import os import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.preprocessing import StandardScaler, LabelEncoder from sklearn.metrics import confusion_matrix, classification_report, accuracy_score, precision_score, recall_score, f1_score from tensorflow.keras.models import Model, Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout, Input, Attention, LayerNormalization, Concatenate, GlobalAveragePooling1D, multiply, Layer, Reshape from tensorflow.keras.utils import to_categorical from tensorflow.keras.optimizers import Adam from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping # Suppress TensorFlow GPU warnings os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # Paths to the dataset files dataset_dir_path = r'C:\Users\LENOVO LEGION\Downloads\human+activity+recognition+using+smartphones\UCI HAR Dataset\UCI HAR Dataset' # Load and preprocess data def load_data(): # Load the feature labels features = pd.read_csv(os.path.join(dataset_dir_path, 'features.txt'), delim_whitespace=True, header=None, names=['index', 'feature']) # Load the activity labels activity_labels = pd.read_csv(os.path.join(dataset_dir_path, 'activity_labels.txt'), delim_whitespace=True, header=None, names=['index', 'activity']) # Load training data X_train = pd.read_csv(os.path.join(dataset_dir_path, 'train', 'X_train.txt'), delim_whitespace=True, header=None) y_train = pd.read_csv(os.path.join(dataset_dir_path, 'train', 'y_train.txt'), delim_whitespace=True, header=None, names=['activity']) # Load test data X_test = pd.read_csv(os.path.join(dataset_dir_path, 'test', 'X_test.txt'), delim_whitespace=True, header=None) y_test = pd.read_csv(os.path.join(dataset_dir_path, 'test', 'y_test.txt'), delim_whitespace=True, header=None, names=['activity']) # Label the columns X_train.columns = features['feature'] X_test.columns = features['feature'] # Normalize the feature data scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # Reshape the data for LSTM (samples, time steps, features) X_train_reshaped = X_train_scaled.reshape((X_train_scaled.shape[0], 1, X_train_scaled.shape[1])) X_test_reshaped = X_test_scaled.reshape((X_test_scaled.shape[0], 1, X_test_scaled.shape[1])) # Encode activity labels encoder = LabelEncoder() y_train_encoded = encoder.fit_transform(y_train['activity']) y_test_encoded = encoder.transform(y_test['activity']) # Convert to categorical y_train_categorical = to_categorical(y_train_encoded) y_test_categorical = to_categorical(y_test_encoded) return X_train_reshaped, y_train_categorical, X_test_reshaped, y_test_categorical, activity_labels, X_train_scaled # Load data X_train, y_train, X_test, y_test, activity_labels, X_train_scaled = load_data() # Define model architectures # 1. Simple LSTM def simple_lstm(input_shape, num_classes): model = Sequential() model.add(LSTM(100, input_shape=input_shape, return_sequences=False)) model.add(Dropout(0.5)) model.add(Dense(num_classes, activation='softmax')) return model # 2. Deep LSTM def deep_lstm(input_shape, num_classes): model = Sequential() model.add(LSTM(100, input_shape=input_shape, return_sequences=True)) model.add(Dropout(0.5)) model.add(LSTM(100, return_sequences=False)) model.add(Dropout(0.5)) model.add(Dense(num_classes, activation='softmax')) return model # 3. LSTM with Attention def lstm_attention(input_shape, num_classes): inputs = Input(shape=input_shape) x = LSTM(100, return_sequences=True)(inputs) x = Dropout(0.5)(x) x = LSTM(100, return_sequences=True)(x) x = Dropout(0.5)(x) attention = Attention()([x, x]) attention = LayerNormalization()(attention) x = Concatenate()([x, attention]) x = GlobalAveragePooling1D()(x) x = Dense(100, activation='relu')(x) x = Dropout(0.5)(x) outputs = Dense(num_classes, activation='softmax')(x) return Model(inputs, outputs) # 4. Multi-Head LSTM with Attention def multi_head_lstm_attention(input_shape, num_classes, num_heads=3): inputs = Input(shape=input_shape) lstm_outs = [] for _ in range(num_heads): lstm = LSTM(50, return_sequences=True)(inputs) lstm_outs.append(lstm) x = Concatenate()(lstm_outs) x = Dropout(0.5)(x) attention = Attention()([x, x]) attention = LayerNormalization()(attention) x = Concatenate()([x, attention]) x = GlobalAveragePooling1D()(x) x = Dense(100, activation='relu')(x) x = Dropout(0.5)(x) outputs = Dense(num_classes, activation='softmax')(x) return Model(inputs, outputs) # 5. Multi-Head LSTM with SE blocks class SqueezeExciteBlock(Layer): def __init__(self, ratio=16, **kwargs): super(SqueezeExciteBlock, self).__init__(**kwargs) self.ratio = ratio def build(self, input_shape): self.global_avg_pool = GlobalAveragePooling1D() self.dense1 = Dense(input_shape[-1] // self.ratio, activation='relu', kernel_initializer='he_normal', use_bias=False) self.dense2 = Dense(input_shape[-1], activation='sigmoid', kernel_initializer='he_normal', use_bias=False) super(SqueezeExciteBlock, self).build(input_shape) def call(self, inputs): x = self.global_avg_pool(inputs) x = Reshape((1, inputs.shape[-1]))(x) x = self.dense1(x) x = self.dense2(x) x = multiply([inputs, x]) return x def get_config(self): config = super(SqueezeExciteBlock, self).get_config() config.update({"ratio": self.ratio}) return config def multi_head_lstm_se(input_shape, num_classes, num_heads=3): inputs = Input(shape=input_shape) lstm_outs = [] for _ in range(num_heads): lstm = LSTM(100, return_sequences=True)(inputs) lstm = Dropout(0.5)(lstm) lstm = SqueezeExciteBlock()(lstm) lstm_outs.append(lstm) x = Concatenate()(lstm_outs) x = GlobalAveragePooling1D()(x) x = Dense(100, activation='relu')(x) x = Dropout(0.5)(x) outputs = Dense(num_classes, activation='softmax')(x) return Model(inputs, outputs) # Function to train and evaluate models def train_and_evaluate(model, X_train, y_train, X_test, y_test, model_name): model.compile(optimizer=Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy']) reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5, min_lr=0.00001) early_stopping = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True) history = model.fit(X_train, y_train, epochs=20, batch_size=64, validation_split=0.2, verbose=1, callbacks=[reduce_lr, early_stopping]) loss, accuracy = model.evaluate(X_test, y_test, verbose=0) y_pred = model.predict(X_test) y_pred_classes = np.argmax(y_pred, axis=1) y_true = np.argmax(y_test, axis=1) precision = precision_score(y_true, y_pred_classes, average='weighted') recall = recall_score(y_true, y_pred_classes, average='weighted') f1 = f1_score(y_true, y_pred_classes, average='weighted') print(f'{model_name} Test Accuracy: {accuracy*100:.2f}%') return history, accuracy, precision, recall, f1, y_true, y_pred_classes # Define and train models input_shape = (X_train.shape[1], X_train.shape[2]) num_classes = y_train.shape[1] models = { 'Simple LSTM': simple_lstm(input_shape, num_classes), 'Deep LSTM': deep_lstm(input_shape, num_classes), 'LSTM with Attention': lstm_attention(input_shape, num_classes), 'Multi-Head LSTM with Attention': multi_head_lstm_attention(input_shape, num_classes), 'Multi-Head LSTM with SE': multi_head_lstm_se(input_shape, num_classes) } results = {} for name, model in models.items(): results[name] = train_and_evaluate(model, X_train, y_train, X_test, y_test, name) # Visualization functions def plot_accuracy_epochs(histories): plt.figure(figsize=(12, 6)) for name, history in histories.items(): plt.plot(history.history['accuracy'], label=f'{name} - Training') plt.plot(history.history['val_accuracy'], label=f'{name} - Validation') plt.title('Accuracy vs Epochs') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend() plt.show() def plot_loss_epochs(histories): plt.figure(figsize=(12, 6)) for name, history in histories.items(): plt.plot(history.history['loss'], label=f'{name} - Training') plt.plot(history.history['val_loss'], label=f'{name} - Validation') plt.title('Loss vs Epochs') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.show() def plot_confusion_matrix(y_true, y_pred, labels, title): cm = confusion_matrix(y_true, y_pred) plt.figure(figsize=(10, 8)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.title(f'Confusion Matrix - {title}') plt.ylabel('True label') plt.xlabel('Predicted label') plt.xticks(ticks=np.arange(len(labels)) + 0.5, labels=labels, rotation=45) plt.yticks(ticks=np.arange(len(labels)) + 0.5, labels=labels, rotation=0) plt.tight_layout() plt.show() def plot_metrics_comparison(results): metrics = ['Accuracy', 'Precision', 'Recall', 'F1 Score'] model_names = list(results.keys()) values = np.array([[res[1], res[2], res[3], res[4]] for res in results.values()]) plt.figure(figsize=(12, 8)) sns.heatmap(values.T, annot=True, fmt='.3f', cmap='YlOrRd', xticklabels=model_names, yticklabels=metrics) plt.title('Model Performance Metrics Heatmap') plt.tight_layout() plt.show() # Generate visualizations histories = {name: res[0] for name, res in results.items()} plot_accuracy_epochs(histories) plot_loss_epochs(histories) for name, res in results.items(): plot_confusion_matrix(res[5], res[6], activity_labels['activity'], name) plot_metrics_comparison(results) # Box plot of accuracies plt.figure(figsize=(10, 6)) accuracies = [res[0].history['val_accuracy'] for res in results.values()] plt.boxplot(accuracies, labels=list(results.keys())) plt.title('Validation Accuracy Comparison') plt.ylabel('Accuracy') plt.xticks(rotation=45) plt.tight_layout() plt.show() # Recognition error over time plt.figure(figsize=(12, 6)) for name, history in histories.items(): recognition_error = 1 - np.array(history.history['accuracy']) plt.plot(recognition_error, label=name) plt.title('Recognition Error Over Time') plt.ylabel('Recognition Error') plt.xlabel('Epoch') plt.legend() plt.show() # Correlation matrix correlation_matrix = pd.DataFrame(X_train_scaled).corr() plt.figure(figsize=(12, 10)) sns.heatmap(correlation_matrix, cmap='coolwarm', annot=False) plt.title('Correlation Matrix of Features') plt.show() # Comparison between accuracy and epoch plt.figure(figsize=(12, 6)) for name, history in histories.items(): plt.plot(history.history['accuracy'], label=f'{name} - Training') plt.plot(history.history['val_accuracy'], label=f'{name} - Validation') plt.title('Comparison between Accuracy and Epoch') plt.xlabel('Epoch') plt.ylabel('Accuracy') plt.legend() plt.show() # Print classification reports for name, res in results.items(): print(f"\nClassification Report for {name}:") print(classification_report(res[5], res[6], target_names=activity_labels['activity'])) # F1 Score, Precision, and Recall comparison plt.figure(figsize=(12, 6)) metrics = ['Precision', 'Recall', 'F1 Score'] x = np.arange(len(models)) width = 0.25 for i, metric in enumerate(metrics): values = [res[i+2] for res in results.values()] plt.bar(x + i*width, values, width, label=metric) plt.xlabel('Models') plt.ylabel('Score') plt.title('Precision, Recall, and F1 Score Comparison') plt.xticks(x + width, list(models.keys()), rotation=45, ha='right') plt.legend() plt.tight_layout() plt.show() # Training and Validation loss figure for each model for name, history in histories.items(): plt.figure(figsize=(10, 6)) plt.plot(history.history['loss'], label='Training Loss') plt.plot(history.history['val_loss'], label='Validation Loss') plt.title(f'Training and Validation Loss - {name}') plt.xlabel('Epoch') plt.ylabel('Loss') plt.legend() plt.show() # Main execution block if __name__ == "__main__": print("Human Activity Recognition Model Comparison") print("===========================================") # Print overall results for name, res in results.items(): print(f"\n{name}:") print(f" Accuracy: {res[1]:.4f}") print(f" Precision: {res[2]:.4f}") print(f" Recall: {res[3]:.4f}") print(f" F1 Score: {res[4]:.4f}") print("\nVisualization Summary:") print("1. Accuracy vs Epochs plot") print("2. Loss vs Epochs plot") print("3. Confusion Matrix for each model") print("4. Model Performance Metrics Heatmap") print("5. Validation Accuracy Comparison (Box Plot)") print("6. Recognition Error Over Time") print("7. Correlation Matrix of Features") print("8. Comparison between Accuracy and Epoch") print("9. Precision, Recall, and F1 Score Comparison") print("10. Training and Validation Loss for each model") print("\nClassification Reports:") for name, res in results.items(): print(f"\nClassification Report for {name}:") print(classification_report(res[5], res[6], target_names=activity_labels['activity'])) # Save results to file with open('har_model_comparison_results.txt', 'w') as f: for name, res in results.items(): f.write(f"\n{name}:\n") f.write(f" Accuracy: {res[1]:.4f}\n") f.write(f" Precision: {res[2]:.4f}\n") f.write(f" Recall: {res[3]:.4f}\n") f.write(f" F1 Score: {res[4]:.4f}\n") f.write("\nClassification Report:\n") f.write(classification_report(res[5], res[6], target_names=activity_labels['activity'])) f.write("\n" + "="*50 + "\n") print("\nResults have been saved to 'har_model_comparison_results.txt'")