{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":41880,"databundleVersionId":5677426,"sourceType":"competition"}],"dockerImageVersionId":30626,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\n\nfrom matplotlib import pyplot as plt\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom keras import layers","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-02-25T13:24:40.025133Z","iopub.execute_input":"2024-02-25T13:24:40.025419Z","iopub.status.idle":"2024-02-25T13:24:57.952098Z","shell.execute_reply.started":"2024-02-25T13:24:40.025394Z","shell.execute_reply":"2024-02-25T13:24:57.951266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# If TPU is available\ntry:\n    # Detect TPU\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver() \n    print('Running on TPU ', tpu.master())\n\nexcept:\n    tpu = None\n    \n\n# If TPU is defined\nif tpu:\n    # Initialise TPU\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    # Instantiate a TPU distribution strategy\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\n\nelse:\n    # Or instanstiate available strategy\n    strategy = tf.distribute.get_strategy() \n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:25:01.748054Z","iopub.execute_input":"2024-02-25T13:25:01.748705Z","iopub.status.idle":"2024-02-25T13:25:01.762789Z","shell.execute_reply.started":"2024-02-25T13:25:01.748671Z","shell.execute_reply":"2024-02-25T13:25:01.761743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_dir = \"../input/tlvmc-parkinsons-freezing-gait-prediction/\"\ntdcsfog_dir = base_dir + \"train/tdcsfog/\"\n\nsamples = []\n\n# Read in samples\nfor file in os.listdir(tdcsfog_dir):\n    samples.append(pd.read_csv(tdcsfog_dir + file, index_col=0))\n\nm = len(samples)\nprint(f\"Number of sessions: {m}\")","metadata":{"execution":{"iopub.status.busy":"2024-02-25T14:18:55.873024Z","iopub.execute_input":"2024-02-25T14:18:55.873428Z","iopub.status.idle":"2024-02-25T14:19:06.034390Z","shell.execute_reply.started":"2024-02-25T14:18:55.873401Z","shell.execute_reply":"2024-02-25T14:19:06.033407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"patches = []\nwindow = 3000\nstep = 1500\nstride = 1\n\nfor sample in samples:\n    \n    pad_idx = step - (sample.shape[0] - window) % step\n    padded_sample = pd.concat([sample, sample[:pad_idx]])\n\n    for i in range((padded_sample.shape[0] - window) // step):\n        patch = padded_sample[i * step:i * step + window:stride]\n        patches.append(patch)\n\nraw_ds = np.array(patches)\n\nprint(f\"Size of train set: {raw_ds.shape[0]}\")","metadata":{"execution":{"iopub.status.busy":"2024-02-25T14:19:06.035884Z","iopub.execute_input":"2024-02-25T14:19:06.036211Z","iopub.status.idle":"2024-02-25T14:19:07.384560Z","shell.execute_reply.started":"2024-02-25T14:19:06.036184Z","shell.execute_reply":"2024-02-25T14:19:07.383539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Store feature columns into X array\nraw_X = raw_ds[:, :, :3]\n# Store target columns into y array\ny = raw_ds[:, :, 3:]\n\ninput_shape = raw_X[0].shape\nprint(f\"Input Shape: {input_shape}\")","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:44:43.856403Z","iopub.execute_input":"2024-02-25T13:44:43.857135Z","iopub.status.idle":"2024-02-25T13:44:43.862205Z","shell.execute_reply.started":"2024-02-25T13:44:43.857104Z","shell.execute_reply":"2024-02-25T13:44:43.861238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find triplette of minima for every sample\nmin_arr = np.min(raw_X, axis=1, keepdims=True)\n# Find triplette of maxima for every sample\nmax_arr = np.max(raw_X, axis=1, keepdims=True)\n# Normalise with MinMax rescaling\nX = (raw_X - min_arr) / (max_arr - min_arr)\n\nprint(f\"Min and Max before Norm: {np.min(raw_X):.1f} and {np.max(raw_X):.1f}\")\nprint(f\"Min and Max after Norm: {np.min(X)} and {np.max(X)}\")","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:44:47.892347Z","iopub.execute_input":"2024-02-25T13:44:47.892993Z","iopub.status.idle":"2024-02-25T13:44:49.454198Z","shell.execute_reply.started":"2024-02-25T13:44:47.892952Z","shell.execute_reply":"2024-02-25T13:44:49.453218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Input Example:\")\nprint(\"\\n\")\n\nprint(\"Feature series:\")\nprint(X[0])\nprint(\"\\n\")\n\nprint(\"Target series:\")\nprint(y[0])","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:44:57.760715Z","iopub.execute_input":"2024-02-25T13:44:57.761138Z","iopub.status.idle":"2024-02-25T13:44:57.767945Z","shell.execute_reply.started":"2024-02-25T13:44:57.761097Z","shell.execute_reply":"2024-02-25T13:44:57.766924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"devel_fraction = 0.1\n\ndevel_idx = np.random.choice(len(X), int(devel_fraction * len(X)), replace=False)\ntrain_idx = np.setdiff1d(np.arange(len(X)), devel_idx)","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:45:37.898514Z","iopub.execute_input":"2024-02-25T13:45:37.898849Z","iopub.status.idle":"2024-02-25T13:45:38.122738Z","shell.execute_reply.started":"2024-02-25T13:45:37.898825Z","shell.execute_reply":"2024-02-25T13:45:38.121754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds = tf.data.Dataset.from_tensor_slices((X[train_idx], y[train_idx])).batch(32)\ndevel_ds = tf.data.Dataset.from_tensor_slices((X[devel_idx], y[devel_idx])).batch(32)","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:48:25.094665Z","iopub.execute_input":"2024-02-25T13:48:25.095055Z","iopub.status.idle":"2024-02-25T13:48:26.430923Z","shell.execute_reply.started":"2024-02-25T13:48:25.095024Z","shell.execute_reply":"2024-02-25T13:48:26.429827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set up model within scope of tpu strategy\nwith strategy.scope():\n\n    # Design LSTM model with one recurrent layer\n    model = keras.Sequential([\n        layers.Bidirectional(layers.LSTM(32, return_sequences=True, input_shape=input_shape), merge_mode=\"ave\"),\n        layers.Dense(3, activation=\"softmax\")\n    ])\n\n    # Compile model\n    model.compile(\n        optimizer=keras.optimizers.Adam(learning_rate=0.01),\n        loss=\"categorical_crossentropy\",\n        metrics=[\"categorical_accuracy\"]\n    )","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:53:21.016242Z","iopub.execute_input":"2024-02-25T13:53:21.017358Z","iopub.status.idle":"2024-02-25T13:53:21.053920Z","shell.execute_reply.started":"2024-02-25T13:53:21.017313Z","shell.execute_reply":"2024-02-25T13:53:21.053013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learning_scheduler = keras.callbacks.ReduceLROnPlateau(\n    monitor=\"val_loss\",\n    factor=0.1,\n    patience=10\n)\n\nearly_stopping = keras.callbacks.EarlyStopping(\n    monitor=\"val_loss\",\n    patience=20,\n    restore_best_weights=True,\n    mode=\"min\")\n\n\n# Train model\nhistory = model.fit(\n    train_ds,\n    validation_data=devel_ds,\n    epochs=2,\n    callbacks=[learning_scheduler, early_stopping],\n    verbose=True\n)\n\n# Store training history as a dataframe\nhistory_df = pd.DataFrame(history.history)\n\nprint(f\"Train loss: {history_df['loss'].iloc[-1]:.3f}\")\nprint(f\"Train accuracy: {history_df['categorical_accuracy'].iloc[-1]:.3f}\")","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:55:03.937637Z","iopub.execute_input":"2024-02-25T13:55:03.938398Z","iopub.status.idle":"2024-02-25T13:55:32.276428Z","shell.execute_reply.started":"2024-02-25T13:55:03.938361Z","shell.execute_reply":"2024-02-25T13:55:32.275423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(1, 2)\n\nfig.set_figheight(3)\nfig.set_figwidth(10)\n\n# Visualise performance\nhistory_df.loc[:, [\"loss\", \"val_loss\"]].plot(ax=axes[0])\naxes[0].set_xlabel(\"Number of Epochs\")\naxes[0].set_ylabel(\"Crossentropy Loss\")\n\nhistory_df.loc[:, [\"categorical_accuracy\", \"val_categorical_accuracy\"]].plot(ax=axes[1])\naxes[1].set_xlabel(\"Number of Epochs\")\naxes[1].set_ylabel(\"Accuracy\")\n\nplt.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2024-02-25T13:55:38.456613Z","iopub.execute_input":"2024-02-25T13:55:38.457281Z","iopub.status.idle":"2024-02-25T13:55:39.179081Z","shell.execute_reply.started":"2024-02-25T13:55:38.457234Z","shell.execute_reply":"2024-02-25T13:55:39.178171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Store test id\ntest_id = \"003f117e14\"\n# Read in test session\ntest_sample = pd.read_csv(base_dir + \"test/tdcsfog/\" + test_id + \".csv\")\n\n# Predict labels\ny_pred = model.predict(test_sample.drop(\"Time\", axis=1).to_numpy().reshape(1, -1, 3)).reshape(-1, 3)\n\nprint(f\"Predicted time points: {y_pred.shape[1]}\")\nprint(\"Example Predictions:\")\nprint(y_pred)","metadata":{"execution":{"iopub.status.busy":"2024-02-25T14:01:29.868564Z","iopub.execute_input":"2024-02-25T14:01:29.868923Z","iopub.status.idle":"2024-02-25T14:01:30.049755Z","shell.execute_reply.started":"2024-02-25T14:01:29.868895Z","shell.execute_reply":"2024-02-25T14:01:30.048693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Collect predictions into dataframe\nsubmission_df = pd.DataFrame(\n    y_pred,\n    columns=[\"StartHesitation\", \"Turn\", \"Walking\"]\n)\n\n# Produce Id column\nid_col = [test_id + \"_\" + str(i) for i in range(submission_df.shape[0])]\n# Add Id column to dataframe\nsubmission_df.insert(0, \"Id\", id_col)\n\n# Write submission file\nsubmission_df.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2024-02-25T14:27:35.086121Z","iopub.execute_input":"2024-02-25T14:27:35.086569Z","iopub.status.idle":"2024-02-25T14:27:35.128453Z","shell.execute_reply.started":"2024-02-25T14:27:35.086532Z","shell.execute_reply":"2024-02-25T14:27:35.127447Z"},"trusted":true},"execution_count":null,"outputs":[]}]}