changed leaky relu syntax to remove keras bug

This commit is contained in:
Michael Weig 2026-03-04 17:59:05 +01:00
parent 3169c29319
commit 537b452449

View File

@ -20,10 +20,10 @@
"from pathlib import Path\n",
"import sys\n",
"import os\n",
"import tensorflow as tf\n",
"\n",
"base_dir = os.path.abspath(os.path.join(os.getcwd(), \"..\"))\n",
"sys.path.append(base_dir)\n",
"print(base_dir)\n",
"\n",
"from sklearn.pipeline import Pipeline\n",
"from sklearn.svm import OneClassSVM\n",
@ -31,7 +31,7 @@
"import matplotlib.pyplot as plt\n",
"import tensorflow as tf\n",
"import pickle\n",
"from tools import evaluation_tools, scaler\n",
"from Fahrsimulator_MSY2526_AI.model_training.tools import evaluation_tools, scaler\n",
"from sklearn.metrics import (balanced_accuracy_score, accuracy_score, precision_score, \n",
" recall_score, f1_score, confusion_matrix, classification_report) "
]
@ -44,6 +44,17 @@
"### Load data"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "30a4c885",
"metadata": {},
"outputs": [],
"source": [
"enconder_path = Path(\".keras\")\n",
"model_path = Path(\".pkl\")"
]
},
{
"cell_type": "code",
"execution_count": null,
@ -51,7 +62,7 @@
"metadata": {},
"outputs": [],
"source": [
"data_path = Path(r\"/home/jovyan/data-paulusjafahrsimulator-gpu/first_AU_dataset/output_windowed.parquet\")"
"data_path = Path(r\".parquet\")"
]
},
{
@ -61,7 +72,8 @@
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_parquet(path=data_path)"
"df = pd.read_parquet(path=data_path)\n",
"df = df.dropna()"
]
},
{
@ -150,20 +162,29 @@
"metadata": {},
"outputs": [],
"source": [
"au_columns = [col for col in low_all.columns if col.startswith('AU')]\n",
"au_columns = [col for col in low_all.columns if \"face\" in col.lower()] \n",
"\n",
"eye_columns = [ \n",
" 'Fix_count_short_66_150','Fix_count_medium_300_500','Fix_count_long_gt_1000', \n",
" 'Fix_count_100','Fix_mean_duration','Fix_median_duration', \n",
" 'Sac_count','Sac_mean_amp','Sac_mean_dur','Sac_median_dur', \n",
" 'Blink_count','Blink_mean_dur','Blink_median_dur', \n",
" 'Pupil_mean','Pupil_IPA' \n",
"] \n",
"cols = au_columns +eye_columns\n",
"\n",
"# Prepare training data (only normal/low data)\n",
"train_data = low_all[low_all['subjectID'].isin(train_subjects)][['subjectID'] + au_columns].copy()\n",
"train_data = low_all[low_all['subjectID'].isin(train_subjects)][['subjectID'] + cols].copy()\n",
"\n",
"# Prepare validation data (normal and anomaly) \n",
"val_normal_data = low_all[low_all['subjectID'].isin(val_subjects)][['subjectID'] + au_columns].copy()\n",
"val_high_data = high_all[high_all['subjectID'].isin(val_subjects)][['subjectID'] + au_columns].copy()\n",
"val_normal_data = val_normal_data.sample(n=1000, random_state=42)\n",
"val_high_data = val_high_data.sample(n=1000, random_state=42)\n",
"val_normal_data = low_all[low_all['subjectID'].isin(val_subjects)][['subjectID'] + cols].copy()\n",
"val_high_data = high_all[high_all['subjectID'].isin(val_subjects)][['subjectID'] + cols].copy()\n",
"val_normal_data = val_normal_data.sample(n=500, random_state=42)\n",
"val_high_data = val_high_data.sample(n=500, random_state=42)\n",
"\n",
"# Prepare test data (normal and anomaly) - 1000 samples each\n",
"test_normal_data = low_all[low_all['subjectID'].isin(test_subjects)][['subjectID'] + au_columns].copy()\n",
"test_high_data = high_all[high_all['subjectID'].isin(test_subjects)][['subjectID'] + au_columns].copy()\n",
"test_normal_data = low_all[low_all['subjectID'].isin(test_subjects)][['subjectID'] + cols].copy()\n",
"test_high_data = high_all[high_all['subjectID'].isin(test_subjects)][['subjectID'] + cols].copy()\n",
"test_normal_data = test_normal_data.sample(n=500, random_state=42)\n",
"test_high_data = test_high_data.sample(n=500, random_state=42)\n",
"\n",
@ -186,7 +207,7 @@
"outputs": [],
"source": [
"# Cell 3: Fit normalizer on training data\n",
"normalizer = scaler.fit_normalizer(train_data, au_columns, method='minmax', scope='global')\n",
"normalizer = scaler.fit_normalizer(train_data, cols, method='minmax', scope='global')\n",
"print(\"Normalizer fitted on training data\")"
]
},
@ -198,11 +219,11 @@
"outputs": [],
"source": [
"# Cell 4: Apply normalization to all datasets\n",
"train_normalized = scaler.apply_normalizer(train_data, au_columns, normalizer)\n",
"val_normal_normalized = scaler.apply_normalizer(val_normal_data, au_columns, normalizer)\n",
"val_high_normalized = scaler.apply_normalizer(val_high_data, au_columns, normalizer)\n",
"test_normal_normalized = scaler.apply_normalizer(test_normal_data, au_columns, normalizer)\n",
"test_high_normalized = scaler.apply_normalizer(test_high_data, au_columns, normalizer)\n",
"train_normalized = scaler.apply_normalizer(train_data, cols, normalizer)\n",
"val_normal_normalized = scaler.apply_normalizer(val_normal_data, cols, normalizer)\n",
"val_high_normalized = scaler.apply_normalizer(val_high_data, cols, normalizer)\n",
"test_normal_normalized = scaler.apply_normalizer(test_normal_data, cols, normalizer)\n",
"test_high_normalized = scaler.apply_normalizer(test_high_data, cols, normalizer)\n",
"\n",
"print(\"Normalization applied to all datasets\")"
]
@ -214,13 +235,11 @@
"metadata": {},
"outputs": [],
"source": [
"# Cell 5: Extract AU columns and create labels for grid search\n",
"# Extract only AU columns (drop subjectID)\n",
"X_train = train_normalized[au_columns].copy()\n",
"X_val_normal = val_normal_normalized[au_columns].copy()\n",
"X_val_high = val_high_normalized[au_columns].copy()\n",
"X_test_high = test_high_normalized[au_columns].copy()\n",
"X_test_normal = test_normal_normalized[au_columns].copy()\n",
"X_train = train_normalized[cols].copy()\n",
"X_val_normal = val_normal_normalized[cols].copy()\n",
"X_val_high = val_high_normalized[cols].copy()\n",
"X_test_high = test_high_normalized[cols].copy()\n",
"X_test_normal = test_normal_normalized[cols].copy()\n",
"\n",
"\n",
"# Create labels for grid search\n",
@ -241,116 +260,12 @@
"X_train.shape"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "50fc80dc-fe16-4917-aad6-0dbaa1ce5ef9",
"metadata": {},
"outputs": [],
"source": [
"!pip install keras-tuner --quiet # nur einmal nötig\n",
"\n",
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"from kerastuner import HyperModel\n",
"from kerastuner.tuners import RandomSearch\n",
"\n",
"# 1⃣ HyperModel definieren\n",
"class AutoencoderHyperModel(HyperModel):\n",
" def __init__(self, input_dim):\n",
" self.input_dim = input_dim\n",
"\n",
" def build(self, hp):\n",
" reg = hp.Float(\"l2_reg\", min_value=1e-5, max_value=0.01, sampling=\"log\")\n",
" lr = hp.Float(\"learning_rate\", 1e-4, 1e-2, sampling=\"log\")\n",
"\n",
" # Encoder\n",
" encoder = keras.Sequential([\n",
" keras.layers.Dense(\n",
" units=hp.Int(\"enc_units1\", min_value=10, max_value=self.input_dim, step=10),\n",
" activation=None,\n",
" kernel_regularizer=keras.regularizers.l2(reg)\n",
" ),\n",
" keras.layers.LeakyReLU(alpha=0.1),\n",
" keras.layers.Dense(\n",
" units=hp.Int(\"enc_units2\", min_value=5, max_value=20, step=1),\n",
" activation=tf.keras.layers.LeakyReLU(alpha=0.1),\n",
" kernel_regularizer=keras.regularizers.l2(reg)\n",
" ),\n",
" keras.layers.Dense(\n",
" units=2, # Bottleneck\n",
" activation='linear',\n",
" kernel_regularizer=keras.regularizers.l2(reg)\n",
" ),\n",
" ])\n",
"\n",
" # Decoder\n",
" decoder = keras.Sequential([\n",
" keras.layers.Dense(\n",
" units=hp.Int(\"dec_units1\", min_value=5, max_value=20, step=1),\n",
" activation=tf.keras.layers.LeakyReLU(alpha=0.1),\n",
" kernel_regularizer=keras.regularizers.l2(reg)\n",
" ),\n",
" keras.layers.Dense(\n",
" units=hp.Int(\"dec_units2\", min_value=10, max_value=self.input_dim, step=10),\n",
" activation=tf.keras.layers.LeakyReLU(alpha=0.1),\n",
" kernel_regularizer=keras.regularizers.l2(reg)\n",
" ),\n",
" keras.layers.Dense(\n",
" units=self.input_dim,\n",
" activation='linear',\n",
" kernel_regularizer=keras.regularizers.l2(reg)\n",
" ),\n",
" ])\n",
"\n",
" # Autoencoder\n",
" inputs = keras.Input(shape=(self.input_dim,))\n",
" encoded = encoder(inputs)\n",
" decoded = decoder(encoded)\n",
" autoencoder = keras.Model(inputs, decoded)\n",
"\n",
" autoencoder.compile(\n",
" optimizer=keras.optimizers.Adam(learning_rate=lr),\n",
" loss='mse'\n",
" )\n",
"\n",
" return autoencoder\n",
"\n",
"# 2⃣ RandomSearch-Tuner\n",
"hypermodel = AutoencoderHyperModel(input_dim=X_train.shape[1])\n",
"\n",
"tuner = RandomSearch(\n",
" hypermodel,\n",
" objective='val_loss',\n",
" max_trials=10, # Anzahl der getesteten Kombinationen\n",
" executions_per_trial=1, # Anzahl Trainings pro Kombination\n",
" directory='tuner_dir',\n",
" project_name='oc_ae'\n",
")\n",
"\n",
"# 3⃣ Hyperparameter-Tuning starten\n",
"tuner.search(\n",
" X_train, X_train,\n",
" epochs=100,\n",
" batch_size=64,\n",
" validation_data=(X_val_normal, X_val_normal),\n",
" verbose=0\n",
")\n",
"\n",
"# 4⃣ Beste Architektur holen\n",
"best_model = tuner.get_best_models(num_models=1)[0]\n",
"best_hyperparameters = tuner.get_best_hyperparameters(1)[0]\n",
"\n",
"print(\"Beste Hyperparameter:\", best_hyperparameters.values)\n"
]
},
{
"cell_type": "markdown",
"id": "362c0a6f",
"metadata": {},
"source": [
"\n",
"Beste Hyperparameter: {'l2_reg': 1.3757411430582133e-05, 'learning_rate': 0.007321002854350309, 'enc_units1': 20, 'enc_units2': 16, 'dec_units1': 14, 'dec_units2': 10}"
"Build model"
]
},
{
@ -360,26 +275,6 @@
"metadata": {},
"outputs": [],
"source": [
"# reg = 0.1\n",
"# encoder = tf.keras.Sequential(\n",
"# [\n",
"# tf.keras.layers.Dense(units=X_train.shape[1], activation='relu', kernel_regularizer=tf.keras.regularizers.l2(reg)),\n",
"# tf.keras.layers.Dense(units=10, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(reg)),\n",
"# tf.keras.layers.Dense(units=5, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(reg)),\n",
" \n",
"# ]\n",
"# )\n",
"\n",
"# decoder = tf.keras.Sequential(\n",
"# [\n",
"# tf.keras.layers.Dense(units=5,activation='relu', kernel_regularizer=tf.keras.regularizers.l2(reg)),\n",
"# tf.keras.layers.Dense(units=10, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(reg)),\n",
"# tf.keras.layers.Dense(units=X_train.shape[1], activation='linear', kernel_regularizer=tf.keras.regularizers.l2(reg))\n",
"# ]\n",
"# )\n",
"\n",
"\n",
"\n",
"reg = 1e-5\n",
"\n",
"# ENCODER\n",
@ -389,14 +284,15 @@
" activation=None,\n",
" kernel_regularizer=tf.keras.regularizers.l2(reg)\n",
" ),\n",
" tf.keras.layers.LeakyReLU(alpha=0.1),\n",
" \n",
" tf.keras.layers.LeakyReLU(negative_slope=0.1),\n",
"\n",
" tf.keras.layers.Dense(\n",
" units=12,\n",
" activation=tf.keras.layers.LeakyReLU(negative_slope=0.1),\n",
" activation=None,\n",
" kernel_regularizer=tf.keras.regularizers.l2(reg)\n",
" ),\n",
" \n",
" tf.keras.layers.LeakyReLU(negative_slope=0.1),\n",
"\n",
" tf.keras.layers.Dense(\n",
" units=8,\n",
" activation='linear', # Bottleneck stays linear\n",
@ -408,20 +304,24 @@
"decoder = tf.keras.Sequential([\n",
" tf.keras.layers.Dense(\n",
" units=8,\n",
" activation=tf.keras.layers.LeakyReLU(negative_slope=0.1),\n",
" activation=None,\n",
" kernel_regularizer=tf.keras.regularizers.l2(reg)\n",
" ),\n",
" tf.keras.layers.LeakyReLU(negative_slope=0.1),\n",
"\n",
" tf.keras.layers.Dense(\n",
" units=12,\n",
" activation=tf.keras.layers.LeakyReLU(negative_slope=0.1),\n",
" activation=None,\n",
" kernel_regularizer=tf.keras.regularizers.l2(reg)\n",
" ),\n",
" tf.keras.layers.LeakyReLU(negative_slope=0.1),\n",
"\n",
" tf.keras.layers.Dense(\n",
" units=X_train.shape[1],\n",
" activation='linear',\n",
" kernel_regularizer=tf.keras.regularizers.l2(reg)\n",
" ),\n",
"])\n"
"])"
]
},
{
@ -456,7 +356,7 @@
"source": [
"history = autoencoder.fit(\n",
" X_train, X_train, # Input and target are the same for autoencoder\n",
" epochs=200,\n",
" epochs=50,\n",
" batch_size=64,\n",
" validation_data=(X_val_normal, X_val_normal),\n",
" verbose=1\n",
@ -470,8 +370,7 @@
"metadata": {},
"outputs": [],
"source": [
"save_path = Path(\"/home/jovyan/data-paulusjafahrsimulator-gpu/saved_models/encoder_model_2_neurons_minmax.keras\")\n",
"encoder.save(save_path)"
"encoder.save(enconder_path)"
]
},
{
@ -489,8 +388,7 @@
"metadata": {},
"outputs": [],
"source": [
"load_path = Path(\"/home/jovyan/data-paulusjafahrsimulator-gpu/saved_models/encoder_model_2_neurons_minmax.keras\")\n",
"encoder = tf.keras.models.load_model(load_path)"
"encoder = tf.keras.models.load_model(enconder_path)"
]
},
{
@ -541,25 +439,6 @@
"test_predictions.shape"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "759118d8-989d-489c-9d35-331454b4795e",
"metadata": {},
"outputs": [],
"source": [
"all_zero = {\n",
" \"X_train_encoded\": np.all(X_train_encoded == 0),\n",
" \"X_val_normal_encoded\": np.all(X_val_normal_encoded == 0),\n",
" \"X_val_high_encoded\": np.all(X_val_high_encoded == 0),\n",
" \"X_test_normal_encoded\": np.all(X_test_normal_encoded == 0),\n",
" \"X_test_high_encoded\": np.all(X_test_high_encoded == 0),\n",
"}\n",
"\n",
"print(all_zero)\n",
"print(X_train_encoded.shape)"
]
},
{
"cell_type": "code",
"execution_count": null,
@ -567,81 +446,49 @@
"metadata": {},
"outputs": [],
"source": [
"# fig, axes = plt.subplots(1, 3, figsize=(18, 5))\n",
"fig, axes = plt.subplots(1, 3, figsize=(18, 5))\n",
"\n",
"# # Subplot A: Normal\n",
"# axes[0].scatter(\n",
"# X_val_normal_encoded[:, 0],\n",
"# X_val_normal_encoded[:, 1],\n",
"# color=\"blue\",\n",
"# label=\"Normal\"\n",
"# )\n",
"# axes[0].set_title(\"Val Normal (encoded)\")\n",
"# axes[0].set_xlabel(\"latent feature 1\")\n",
"# axes[0].set_ylabel(\"latent feature 2\")\n",
"# axes[0].legend()\n",
"\n",
"# # Subplot B: High\n",
"# axes[1].scatter(\n",
"# X_val_high_encoded[:, 0],\n",
"# X_val_high_encoded[:, 1],\n",
"# color=\"orange\",\n",
"# label=\"High\"\n",
"# )\n",
"# axes[1].set_title(\"ValHigh (encoded)\")\n",
"# axes[1].set_xlabel(\"latent feature 1\")\n",
"# axes[1].set_ylabel(\"latent feature 2\")\n",
"# axes[1].legend()\n",
"\n",
"# # Subplot C: Both\n",
"# axes[2].scatter(\n",
"# X_val_normal_encoded[:, 0],\n",
"# X_val_normal_encoded[:, 1],\n",
"# color=\"blue\",\n",
"# label=\"Normal\"\n",
"# )\n",
"# axes[2].scatter(\n",
"# X_val_high_encoded[:, 0],\n",
"# X_val_high_encoded[:, 1],\n",
"# color=\"orange\",\n",
"# label=\"High\"\n",
"# )\n",
"# axes[2].set_title(\"Normal vs High (encoded)\")\n",
"# axes[2].set_xlabel(\"latent feature 1\")\n",
"# axes[2].set_ylabel(\"latent feature 2\")\n",
"# axes[2].legend()\n",
"\n",
"\n",
"\n",
"latent_dim = 8\n",
"fig, axes = plt.subplots(2, 4, figsize=(20, 10))\n",
"axes = axes.flatten() # flatten to index easily\n",
"\n",
"for i in range(latent_dim):\n",
" axes[i].scatter(\n",
" X_val_normal_encoded[:, i],\n",
" [0]*X_val_normal_encoded.shape[0], # optional: place on a line for 1D visualization\n",
" color='blue',\n",
" label='Normal',\n",
" alpha=0.6\n",
" )\n",
" axes[i].scatter(\n",
" X_val_high_encoded[:, i],\n",
" [0]*X_val_high_encoded.shape[0], # same for High\n",
" color='orange',\n",
" label='High',\n",
" alpha=0.6\n",
" )\n",
" axes[i].set_title(f'Latent dim {i+1}')\n",
" axes[i].set_xlabel(f'Feature {i+1}')\n",
" axes[i].set_yticks([]) # hide y-axis as it's just a 1D comparison\n",
" axes[i].legend()\n",
" axes[i].grid(True)\n",
"\n",
"plt.tight_layout()\n",
"plt.show()\n",
"# Subplot A: Normal\n",
"axes[0].scatter(\n",
" X_val_normal_encoded[:, 0],\n",
" X_val_normal_encoded[:, 1],\n",
" color=\"blue\",\n",
" label=\"Normal\"\n",
")\n",
"axes[0].set_title(\"Val Normal (encoded)\")\n",
"axes[0].set_xlabel(\"latent feature 1\")\n",
"axes[0].set_ylabel(\"latent feature 2\")\n",
"axes[0].legend()\n",
"\n",
"# Subplot B: High\n",
"axes[1].scatter(\n",
" X_val_high_encoded[:, 0],\n",
" X_val_high_encoded[:, 1],\n",
" color=\"orange\",\n",
" label=\"High\"\n",
")\n",
"axes[1].set_title(\"ValHigh (encoded)\")\n",
"axes[1].set_xlabel(\"latent feature 1\")\n",
"axes[1].set_ylabel(\"latent feature 2\")\n",
"axes[1].legend()\n",
"\n",
"# Subplot C: Both\n",
"axes[2].scatter(\n",
" X_val_normal_encoded[:, 0],\n",
" X_val_normal_encoded[:, 1],\n",
" color=\"blue\",\n",
" label=\"Normal\"\n",
")\n",
"axes[2].scatter(\n",
" X_val_high_encoded[:, 0],\n",
" X_val_high_encoded[:, 1],\n",
" color=\"orange\",\n",
" label=\"High\"\n",
")\n",
"axes[2].set_title(\"Normal vs High (encoded)\")\n",
"axes[2].set_xlabel(\"latent feature 1\")\n",
"axes[2].set_ylabel(\"latent feature 2\")\n",
"axes[2].legend()\n",
"\n",
"plt.tight_layout()\n",
"plt.show()\n",
@ -708,11 +555,11 @@
"outputs": [],
"source": [
"# Save\n",
"with open('ocsvm_model.pkl', 'wb') as f:\n",
"with open(model_path, \"wb\") as f:\n",
" pickle.dump(ocsvm, f)\n",
"\n",
"# Load later\n",
"with open('ocsvm_model.pkl', 'rb') as f:\n",
"with open(model_path, \"rb\") as f:\n",
" ocsvm_loaded = pickle.load(f)"
]
},
@ -731,11 +578,6 @@
"metadata": {},
"outputs": [],
"source": [
"# X_combined = np.concatenate([X_train_encoded, X_val_normal_encoded, X_val_high_encoded], axis=0)\n",
"# y_combined = np.concatenate([\n",
"# np.ones(X_train_encoded.shape[0]+X_val_normal_encoded.shape[0]), # normal = 1\n",
"# -np.ones(X_val_high_encoded.shape[0]) # anomaly = -1\n",
"# ], axis=0)\n",
"X_combined = np.concatenate([X_train_encoded, X_val_high_encoded], axis=0)\n",
"y_combined = np.concatenate([\n",
" np.ones(X_train_encoded.shape[0]), # normal = 1\n",
@ -856,14 +698,6 @@
"source": [
"f1_score(y_true=np.concatenate([y_test_normal, y_test_high]), y_pred=predictions)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9e412041-7534-40fe-8486-ee97349a6168",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {