{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<h1>Predicting Parkinson's Freezing of Gait Episodes: A Comprehensive Step-by-Step Approach</h1>\n\nObjective: the development of a model to predict Parkinson's freezing-of-gait episodes\n<br>\n<br>\n<h3><b>Table of Contents</b></h3>\n\n\n1. [Introduction](#section-1) <br>\n2. [The Big Picture](#section-2) <br>\n3. [Data Collection](#section-3) <br>\n4. [Data Exploration](#section-4) <br>\n5. [Data Preprocessing](#section-5) <br>\n    5.1. [Handling Missing Data](#section-6) <br>\n    5.2. [Handling Categorical Variables](#section-7) <br>\n    5.3. [Data Normalization](#section-15) <br>\n    5.3. [Outlier Detection](#section-8) <br>\n6. [Feature Engineering](#section-9) <br>\n7. [Model](#section-10) <br>\n   7.1. [Model Selection](#section-11)<br>\n   7.2. [Model Training](#section-12)<br>\n   7.3. [Model Evaluation](#section-13)<br>\n8. [Prediction and Submission](#section-14) <br>","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h3>1. Introduction</b></h3>\n\n\n<div style=\"text-align: justify\"> Freezing of gait (FOG) is a debilitating symptom that affects individuals diagnosed with Parkinson’s disease, which significantly impacting their ability to walk and limiting their mobility and independence. Machine learning (ML) techniques can provide valuable insights into the occurrence and causes of FOG episodes. By leveraging ML, medical professionals can enhance their evaluation, monitoring, and prevention of FOG events.\n\n\nThis notebook is based on <a href=https://www.kaggle.com/competitions/tlvmc-parkinsons-freezing-gait-prediction> Parkinson's Freezing of Gait Prediction competition</a> dataset which includes data collected from a wearable 3D lower back sensor. The goal of this project is detecting the start and stop of each freezing episode, as well as identifying three types of FOG events: Start Hesitation, Turn, and Walking.\n\n</div>","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-2\"></a>\n<h3>2. The Big Picture</b></h3>\n\n<div style=\"text-align: justify\">The objective is to develop a model to detect and predict Parkinson's FOG episodes. These episodes will be predicted based on time series data that was recorded for each patient during the execution of a specific protocol in addition to some provided patient characteristics.</div>\n\n<div style=\"text-align: justify\">Given the availability of labeled targets in the dataset, a supervised learning approach is suitable for addressing this problem. Since there are multiple targets (Start Hesitation, Turn, and Walking), the problem is a <b>multi-class classification</b>. The evaluation metric in this project is the mean average precision, which measures the average precision of predictions for each event class. Thus, accurate predictions of correct event types are more important than predicting all events correctly.<br>\nConsidering these requirements, this notebook presents a LightGBM (Light Gradient Boosting Model) model developed specifically to optimize the desired evaluation metric.</div>","metadata":{"execution":{"iopub.status.busy":"2023-07-09T14:45:43.506483Z","iopub.status.idle":"2023-07-09T14:45:43.507431Z","shell.execute_reply.started":"2023-07-09T14:45:43.507195Z","shell.execute_reply":"2023-07-09T14:45:43.507222Z"}}},{"cell_type":"markdown","source":"<a id=\"section-3\"></a>\n<h3>3. Data Collection</h3>\n\n<div style=\"text-align: justify\">Each patient in the dataset is considered as a subject. The dataset includes two types of experiments conducted to assess conditions of the patient:\n\n1. TDCSFOG dataset: This dataset consists of data series collected in a lab, where subjects completed a FOG-provoking protocol.\n1. DeFOG dataset: This dataset comprises data series collected in the subject's home, where the subject also completed a FOG-provoking protocol.\n    \n\n<div style=\"text-align: justify\">The identification of each series in the TDCSFOG dataset is provided in the \"tdcsfog_metadata.csv\" file. Each series is uniquely identified by the Subject, Visit, Test, and Medication condition. Similarly, the identification of each series in the DeFOG dataset is given in the \"defog_metadata.csv\" file, supplied by unique identifiers for Subject, Visit, and Medication condition. For further details, the reader may refer to the <a href= https://www.kaggle.com/competitions/tlvmc-parkinsons-freezing-gait-prediction/data>dataset description page</a>. </div>","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-07-16T06:00:27.803969Z","iopub.execute_input":"2023-07-16T06:00:27.804479Z","iopub.status.idle":"2023-07-16T06:00:27.844717Z","shell.execute_reply.started":"2023-07-16T06:00:27.804442Z","shell.execute_reply":"2023-07-16T06:00:27.843432Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport glob\nimport math\nimport seaborn as sns\nimport lightgbm as lgb\nimport matplotlib.cm as cm\nimport matplotlib.colors as mcolors\nimport matplotlib.pyplot as plt\nimport matplotlib.gridspec as gridspec\n\nfrom tqdm.auto import tqdm\nfrom os import path\nfrom pathlib import Path\n\nfrom sklearn.model_selection import GroupKFold\nfrom sklearn.base import clone\nfrom sklearn.metrics import average_precision_score","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.344945Z","iopub.execute_input":"2023-07-15T19:32:32.345357Z","iopub.status.idle":"2023-07-15T19:32:32.352667Z","shell.execute_reply.started":"2023-07-15T19:32:32.345323Z","shell.execute_reply":"2023-07-15T19:32:32.351712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def reduce_memory_usage(df):\n    \n    start_mem = df.memory_usage().sum() / 1024**2\n    print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))\n    \n    for col in df.columns:\n        col_type = df[col].dtype.name\n        if ((col_type != 'datetime64[ns]') & (col_type != 'category')):\n            if (col_type != 'object'):\n                c_min = df[col].min()\n                c_max = df[col].max()\n\n                if str(col_type)[:3] == 'int':\n                    if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n                        df[col] = df[col].astype(np.int8)\n                    elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                        df[col] = df[col].astype(np.int16)\n                    elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                        df[col] = df[col].astype(np.int32)\n                    elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                        df[col] = df[col].astype(np.int64)\n\n                else:\n                    if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                        df[col] = df[col].astype(np.float16)\n                    elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                        df[col] = df[col].astype(np.float32)\n                    else:\n                        pass\n            else:\n                df[col] = df[col].astype('category')\n    mem_usg = df.memory_usage().sum() / 1024**2 \n    print(\"Memory usage became: \",mem_usg,\" MB\")\n    \n    return df","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-07-15T19:32:32.360253Z","iopub.execute_input":"2023-07-15T19:32:32.361362Z","iopub.status.idle":"2023-07-15T19:32:32.373983Z","shell.execute_reply.started":"2023-07-15T19:32:32.36132Z","shell.execute_reply":"2023-07-15T19:32:32.372564Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# utility functions\ndef get_num_cols(df):\n    numeric_columns = df.select_dtypes(include=[np.number]).columns\n    return numeric_columns\n\n\ndef factorize_column(column):\n    if column.dtype == \"category\" or column.dtype == \"object\":\n        return pd.factorize(column)[0]\n    return column\n","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.375792Z","iopub.execute_input":"2023-07-15T19:32:32.376445Z","iopub.status.idle":"2023-07-15T19:32:32.394258Z","shell.execute_reply.started":"2023-07-15T19:32:32.376408Z","shell.execute_reply":"2023-07-15T19:32:32.393265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"root = \"/kaggle/input/tlvmc-parkinsons-freezing-gait-prediction/\"\n\ntrain_defog = glob.glob(os.path.join(root, \"train\", \"defog\", \"**\"))\ntrain_tdcsfog = glob.glob(os.path.join(root, \"train\", \"tdcsfog\", \"**\"))\ntest_defog = glob.glob(os.path.join(root, \"test\", \"defog\", \"**\"))\ntest_tdcsfog = glob.glob(os.path.join(root, \"test\", \"tdcsfog\", \"**\"))\n\nsubjects_df = pd.read_csv(os.path.join(root, \"subjects.csv\"))\n\ntdcsfog_metadata = pd.read_csv(os.path.join(root, \"tdcsfog_metadata.csv\"))\ndefog_metadata = pd.read_csv(os.path.join(root, \"defog_metadata.csv\"))\n\n#  events data which shows information of every FOG episodes\nevents_df = pd.read_csv(os.path.join(root, \"events.csv\"))","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.396011Z","iopub.execute_input":"2023-07-15T19:32:32.396558Z","iopub.status.idle":"2023-07-15T19:32:32.432792Z","shell.execute_reply.started":"2023-07-15T19:32:32.396524Z","shell.execute_reply":"2023-07-15T19:32:32.431733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tdcsfog_metadata = tdcsfog_metadata.rename(\n    columns={\n        \"Subject\": \"subject\",\n        \"Visit\": \"visit\",\n        \"Test\": \"test\",\n        \"Medication\": \"medication\",\n    }\n)\ndefog_metadata = defog_metadata.rename(\n    columns={\"Subject\": \"subject\", \"Visit\": \"visit\", \"Medication\": \"medication\"}\n)\nsubjects_df = subjects_df.rename(\n    columns={\n        \"Subject\": \"subject\",\n        \"Visit\": \"visit\",\n        \"Age\": \"age\",\n        \"Sex\": \"sex\",\n        \"YearsSinceDx\": \"years_since_dx\",\n    }\n)\n","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.44071Z","iopub.execute_input":"2023-07-15T19:32:32.441045Z","iopub.status.idle":"2023-07-15T19:32:32.455009Z","shell.execute_reply.started":"2023-07-15T19:32:32.441016Z","shell.execute_reply":"2023-07-15T19:32:32.453918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"defog_metadata_subjects = subjects_df.merge(\n    defog_metadata, on=[\"subject\", \"visit\"], how=\"inner\"\n)\n\ntdcsfog_subjects = subjects_df.drop(\"visit\", axis=1)\ntdcsfog_metadata_subjects = tdcsfog_subjects.merge(\n    tdcsfog_metadata, on=[\"subject\"], how=\"inner\"\n)\ntdcsfog_metadata_subjects = tdcsfog_metadata_subjects.drop(\"visit\", axis=1)\n","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.462979Z","iopub.execute_input":"2023-07-15T19:32:32.463396Z","iopub.status.idle":"2023-07-15T19:32:32.47892Z","shell.execute_reply.started":"2023-07-15T19:32:32.463361Z","shell.execute_reply":"2023-07-15T19:32:32.477981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-4\"></a>\n<h3>4. Data Exploration</h3>\n\nWe first look at the subjects dataset.\n","metadata":{}},{"cell_type":"code","source":"subjects_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.570087Z","iopub.execute_input":"2023-07-15T19:32:32.570928Z","iopub.status.idle":"2023-07-15T19:32:32.587188Z","shell.execute_reply.started":"2023-07-15T19:32:32.570888Z","shell.execute_reply":"2023-07-15T19:32:32.585809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* \"visit\" is only available for subjects in the defog datasets.<br>\n* \"years_since_dx\" represents years since the Parkinson's diagnosis.<br>\n* UPDRSIIIOn (resp., UPDRSIIIOff) is Unified Parkinson's Disease Rating Scale score during on (resp., off) medication.<br>\n* NFOGQ is a self-report FoG questionnaire score. <br>","metadata":{}},{"cell_type":"code","source":"defog_metadata_subjects","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.724576Z","iopub.execute_input":"2023-07-15T19:32:32.725051Z","iopub.status.idle":"2023-07-15T19:32:32.74724Z","shell.execute_reply.started":"2023-07-15T19:32:32.72501Z","shell.execute_reply":"2023-07-15T19:32:32.745996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tdcsfog_metadata_subjects","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.873064Z","iopub.execute_input":"2023-07-15T19:32:32.874028Z","iopub.status.idle":"2023-07-15T19:32:32.891802Z","shell.execute_reply.started":"2023-07-15T19:32:32.87398Z","shell.execute_reply":"2023-07-15T19:32:32.89091Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Since different tests were conducted in each visit, the metadata size for TDCSFOG is around 6 times larger than the DeFOG metadata.","metadata":{}},{"cell_type":"code","source":"print(\"The number of patients in DeFog metada:\" ,\n      len(pd.unique(defog_metadata_subjects[\"subject\"])))","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.896691Z","iopub.execute_input":"2023-07-15T19:32:32.897764Z","iopub.status.idle":"2023-07-15T19:32:32.904371Z","shell.execute_reply.started":"2023-07-15T19:32:32.897726Z","shell.execute_reply":"2023-07-15T19:32:32.903536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"The number of patients in TDCSFog metada:\" ,\n      len(pd.unique(tdcsfog_metadata_subjects[\"subject\"])))","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.912524Z","iopub.execute_input":"2023-07-15T19:32:32.913792Z","iopub.status.idle":"2023-07-15T19:32:32.919666Z","shell.execute_reply.started":"2023-07-15T19:32:32.913751Z","shell.execute_reply":"2023-07-15T19:32:32.918593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"For analyzing the information of all 107 patients, both defog and tdcsfog metadata are joined.\n","metadata":{}},{"cell_type":"code","source":"full_metadata = pd.concat([defog_metadata_subjects, tdcsfog_metadata_subjects], axis=0)\n\nfull_metadata.drop([\"visit\", \"test\"], axis=1, inplace=True)\n\nfull_metadata[\"sex\"] = full_metadata[\"sex\"].map({\"F\": 0, \"M\": 1})\nfull_metadata[\"medication\"] = full_metadata[\"medication\"].map({\"on\": 0, \"off\": 1})","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.92449Z","iopub.execute_input":"2023-07-15T19:32:32.925353Z","iopub.status.idle":"2023-07-15T19:32:32.940271Z","shell.execute_reply.started":"2023-07-15T19:32:32.925312Z","shell.execute_reply":"2023-07-15T19:32:32.939089Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(full_metadata[[\"age\",\"years_since_dx\",\"UPDRSIII_On\",\"UPDRSIII_Off\",\"NFOGQ\"]].describe())\n\ndf=full_metadata[[\"age\",\"years_since_dx\",\"UPDRSIII_On\",\"UPDRSIII_Off\",\"NFOGQ\"]].copy()\nplt.figure(figsize=(8,5), dpi= 80)\nsns.boxplot( data=df, notch=False)\n\nplt.title('Box Plot of the full metadata', fontsize=10)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:32.946556Z","iopub.execute_input":"2023-07-15T19:32:32.946961Z","iopub.status.idle":"2023-07-15T19:32:33.209679Z","shell.execute_reply.started":"2023-07-15T19:32:32.946926Z","shell.execute_reply":"2023-07-15T19:32:33.20868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('default')\n\ntemp= full_metadata.copy()\ntemp.dropna(inplace=True)\ntemp=temp[temp['age']!=28]\ntemp.rename(columns={\"years_since_dx\":\"Years Since Diagnosis\"}, inplace=True)\ntemp['Age']=temp['age'].astype(\"int64\")\ntemp['Years Since Diagnosis']=temp['Years Since Diagnosis'].astype(\"int64\")\ncolumns = ['Age', 'Years Since Diagnosis']\n\ncolors_gender = ['#c2c2f0','#ffb3e6']\nfig, axes = plt.subplots(1, 3, figsize=(12, 4))\n\ncounts = temp[\"sex\"].value_counts()\ngender_labels=[\"Male\",\"Female\"]\naxes[0].pie(counts, labels=gender_labels,counterclock=False,startangle=90,autopct='%1.1f%%',\n                 colors=colors_gender, wedgeprops={'edgecolor': 'white', 'linewidth': 0.7})\naxes[0].set_title('Distribution of Sex', pad=20,fontdict={'fontsize': 10,'fontfamily':'Tahoma'})\n\nfor i, column in enumerate(columns):\n    # Get the minimum and maximum values of the column\n    min_value = temp[column].min()\n    max_value = temp[column].max()\n\n    min_value=5 * math.floor(min_value / 5)\n    # Create age ranges using pd.cut()\n    age_ranges = pd.cut(temp[column], bins=np.arange(min_value, max_value+5, 5), right=False,\n                        labels=[f'{i}-{i+5}' for i in range(min_value, max_value, 5)])\n\n    temp['Age Range'] = age_ranges\n\n    counts = temp['Age Range'].value_counts()\n    counts = counts.sort_values(ascending=False)\n    \n    # Sort the sizes_gender variable based on the sorting order of counts\n    sizes_gender = temp.groupby('Age Range')['sex'].value_counts().reindex(counts.index, level=0)\n    \n    gender_counts = sizes_gender.index.get_level_values('sex')\n\n    # Define the color map and assign colors based on gender counts\n    colors = [colors_gender[0] if gender == 1 else colors_gender[1] for gender in gender_counts]\n\n    wedges, texts, autotexts =axes[i+1].pie(counts, labels=counts.index,counterclock=False,startangle=90,\n                  autopct='%1.0f%%',wedgeprops={'edgecolor': 'white', 'linewidth': 0.5})\n    for autotext in autotexts:\n        autotext.set_horizontalalignment('center') \n        autotext.set_verticalalignment('center')  \n        autotext.set_position((1.5 * autotext.get_position()[0],1.5*autotext.get_position()[1]))\n        autotext.set_fontsize(8)\n        autotext.set_color('white')\n    \n    axes[i+1].set_title(f'Distribution of {column} and \\n Sex ', pad=15,  fontdict={'fontsize': 10,'fontfamily':'Tahoma'})\n    axes[i+1].pie(sizes_gender,colors=colors,radius=0.75,counterclock=False,startangle=90,\n               wedgeprops={'edgecolor': 'white', 'linewidth': 0.5})\n    \n    centre_circle = plt.Circle((0,0),0.55,fc='white')\n    axes[i+1].add_artist(centre_circle)\n    # Equal aspect ratio ensures that pie is drawn as a circle\n    axes[i+1].axis('equal')  \n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:33.211518Z","iopub.execute_input":"2023-07-15T19:32:33.212138Z","iopub.status.idle":"2023-07-15T19:32:33.936758Z","shell.execute_reply.started":"2023-07-15T19:32:33.2121Z","shell.execute_reply":"2023-07-15T19:32:33.935811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n* Approximately 80% of the participants are men.\n* More than 66% of the participants are between 65-75 years old.\n* Around 60% of the participants were diagnosed 5-15 years ago.\n* Among participants aged between 80-85, the majority are women.","metadata":{}},{"cell_type":"code","source":"import seaborn as sns\nimport matplotlib.pyplot as plt\nimport matplotlib.cm as cm\nimport matplotlib.colors as mcolors\n\nfull_metadata[\"diff\"] = full_metadata[\"UPDRSIII_Off\"]-full_metadata[\"UPDRSIII_On\"]\n\nplt.figure(figsize=(6, 4))\n\n# Compute the correlation matrix\nnumberic_columns= get_num_cols(full_metadata)\ncorr_matrix = full_metadata[numberic_columns].corr()\n\n# Mask the diagonal elements\nmask = np.zeros_like(corr_matrix, dtype=bool)\nmask[np.triu_indices_from(mask)] = True\n\nheatmap = sns.heatmap(corr_matrix, cmap='RdBu', annot=True, fmt='.2f', linewidths=0.15,\n                      square=True,\n                      mask=mask\n                     )\nplt.title('Full metadata pairwise Correlation Heatmap', fontsize=9)\n\nheatmap.set_xticklabels(heatmap.get_xticklabels(), fontsize=8)\nheatmap.set_yticklabels(heatmap.get_yticklabels(), fontsize=8)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:33.938195Z","iopub.execute_input":"2023-07-15T19:32:33.938747Z","iopub.status.idle":"2023-07-15T19:32:34.396686Z","shell.execute_reply.started":"2023-07-15T19:32:33.938712Z","shell.execute_reply":"2023-07-15T19:32:34.395726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A 'diff' column is added to display the difference between UPDRSIII_Off and UPDRSIII_On.\n\n* There is a relationship between diff and age, which will be analyzed.\n* Additionally, it seems reasonable to fill the missing values of UPDRSIII_Off (presented in the preprocessing part) since it has a strong relationship with UPDRSIII_On. It is also slightly correlated with years_since_dx, age, and sex.","metadata":{}},{"cell_type":"code","source":"\ntemp = full_metadata[~full_metadata['UPDRSIII_On'].isna()].sort_values(\"diff\").copy()\n\nage = temp['age']\ndiff = temp['diff']\nfrequency = temp['age'].value_counts()\n\ncmap = plt.colormaps['Oranges']\n\n\nfig = plt.figure(figsize=(10, 4))\n# Define a custom grid layout for the subplots\ngrid = gridspec.GridSpec(1, 2, width_ratios=[1, 1])\n# Create the first subplot with a specific width\nax1 = plt.subplot(grid[0])\n\n\n# Create a subplot for the scatter plot or line plot\nplt.scatter(full_metadata['UPDRSIII_Off'], full_metadata['UPDRSIII_On'], c=full_metadata['age'], cmap='Oranges')\nplt.xlabel('UPDRSIII_Off')\nplt.ylabel('UPDRSIII_On')\nplt.title('Scatter Plot of UPDRSIII_Off vs UPDRSIII_On', fontsize=9, pad=15)\nplt.colorbar(label='Age')\n\nplt.plot([0, 90], [0, 90], 'r--')  # Add a red dashed line from (0, 0) to (90, 90)\n\n\n\nax2 = plt.subplot(grid[1])\nplt.subplot(1, 2, 2)\nm=plt.scatter(age, diff, c=frequency[age].values, cmap=cmap, s=frequency[age].values*5, alpha=0.8)\nplt.xlabel('age')\nplt.ylabel('diff')\nplt.title('Relationship between Age and the difference of\\n UPDRSIII_On and UPDRSIII_Off', fontsize=9, pad=15)\nplt.colorbar(mappable=m, label='Frequency')\n\n# Add a horizontal line at y=0\nplt.axhline(0, color='black', linestyle='--')  \n\nplt.tight_layout() \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:34.399089Z","iopub.execute_input":"2023-07-15T19:32:34.399688Z","iopub.status.idle":"2023-07-15T19:32:35.086568Z","shell.execute_reply.started":"2023-07-15T19:32:34.39965Z","shell.execute_reply":"2023-07-15T19:32:35.08559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"text-align: justify\">As the plot above depicts, for the majority of cases, medication is effective in controlling UPDRSIII. However, in some cases, medication not only fails to be effective but also worsens the situation.<br>\nIn the next chart, the difference between UPDRSIII, when medication is on and when it is off, is calculated and compared to age. <b>For ages below 60, medication is almost universally effective</b>. However, for ages above 60, the effects vary greatly in a case-by-case manner. The most diversity is observed in the age range of 65-75 (as we saw before, 66% of patients are in this age group). In this age range, medication can either worsen the symptoms or be even more effective compared to other age ranges.</div>\n\n\nThe following trends can be observed with respect to the role of sex:\n","metadata":{}},{"cell_type":"code","source":"# women full metadata\ntemp = full_metadata.copy()\ntemp = temp[temp[\"sex\"]==0]\ntemp[\"diff\"]=temp[\"UPDRSIII_Off\"]-temp[\"UPDRSIII_On\"]\n\nprint(\"Average of UPDRSIII_Off in women: {:.2f}\".format(temp[\"UPDRSIII_Off\"].mean()))\nprint(\"Average of UPDRSIII_On in women: {:.2f}\".format(temp[\"UPDRSIII_On\"].mean()))\n\nprint(\"Average of difference between UPDRSIII_On and UPDRSIII_Off in women: {:.2f}\".format(temp[\"diff\"].mean()))\nprint(\"Ineffective medication cases in women: {:.2f} \".format((len(temp[temp[\"diff\"]<0])/len(temp))*100))","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:35.088174Z","iopub.execute_input":"2023-07-15T19:32:35.088782Z","iopub.status.idle":"2023-07-15T19:32:35.099347Z","shell.execute_reply.started":"2023-07-15T19:32:35.088744Z","shell.execute_reply":"2023-07-15T19:32:35.098113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# men full metadata\ntemp = full_metadata.copy()\ntemp = temp[temp[\"sex\"]==1]\ntemp[\"diff\"]=temp[\"UPDRSIII_Off\"]-temp[\"UPDRSIII_On\"]\n\nprint(\"Average of UPDRSIII_Off in men: {:.2f}\".format(temp[\"UPDRSIII_Off\"].mean()))\nprint(\"Average of UPDRSIII_On in men: {:.2f}\".format(temp[\"UPDRSIII_On\"].mean()))\nprint(\"Average of difference between UPDRSIII_On and UPDRSIII_Off in men: {:.2f}\".format(temp[\"diff\"].mean()))\nprint(\"Ineffective medication cases in men: {:.2f}\".format((len(temp[temp[\"diff\"]<0])/len(temp))*100))","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:35.101357Z","iopub.execute_input":"2023-07-15T19:32:35.101808Z","iopub.status.idle":"2023-07-15T19:32:35.114542Z","shell.execute_reply.started":"2023-07-15T19:32:35.101766Z","shell.execute_reply":"2023-07-15T19:32:35.113411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This analysis reveals the following insights:\n\n* **Women generally exhibit a slightly better condition in Parkinson's disease.**\n* **On the other hand, medication tends to be trivially more effective in men.**","metadata":{}},{"cell_type":"markdown","source":"Now, we investigate a time series dataset that includes all three types of FOG, i.e., Start Hesitation, Turn, and Walking.","metadata":{}},{"cell_type":"code","source":"# get file series Id that includes all three FOG episodes\ndesired_id = events_df.groupby(\"Id\").filter(lambda x: all(item in x[\"Type\"].values for item in [\"StartHesitation\", \"Turn\", \"Walking\"]))[\"Id\"]\ndesired_id=pd.unique(desired_id)\n \nsample_Id=[]\nfor file in train_tdcsfog:\n        Id = file.split('/')[-1].split('.')[0]\n        if Id in desired_id:\n            sample_Id.append(Id)\n\nsample_train_tdcsfog_series = pd.read_csv(root + '/train/tdcsfog/' + str(sample_Id[0]) + '.csv')\nsample_train_tdcsfog_series","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:35.116099Z","iopub.execute_input":"2023-07-15T19:32:35.116805Z","iopub.status.idle":"2023-07-15T19:32:35.200468Z","shell.execute_reply.started":"2023-07-15T19:32:35.116761Z","shell.execute_reply":"2023-07-15T19:32:35.199113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This dataset is comprised of lower-back 3D accelerometer data which captures the following features related to FOG detection:\n\n* AccV: acceleration measured by a vertical sensor\n* AccML: acceleration measured by a mediolateral sensor\n* AccAP: acceleration measured by an anteroposterior sensor\n\n<img src=\"attachment:b814d398-b973-40bd-8f04-265c0612dee5.png\" alt=\"axis of movement\" width=\"500\">\nThese three characteristics are the main feautures to detect FOG.\n","metadata":{},"attachments":{"b814d398-b973-40bd-8f04-265c0612dee5.png":{"image/png":"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+OGH5d133xU3AlXaHYceeqj07NlTbr75ZilbtmzIeojmIoAAAggggAACCOS6AAGmXO9h2ocAAgiEQMCtANOaNWukV69eMmbMGNcCS7H8NWrUkCeeeEIuvfTS2Eu8RwABBBBAAAEEEEAgsAIEmALbdVQcAQQQQMAWcCPANHHiRLn++uvlzz//tIv19PWiiy6SESNGSOXKlT19DoUjgAACCCCAAAIIIJANAQJM2VDmGQgggAACngpkEmDat2+f3HnnnfLUU095Wsd4hdesWdOahnfsscfGu8w5BBBAAAEEEEAAAQQCI0CAKTBdRUURQAABBBIJpBtg2rlzp3Tu3FnefPPNREV7fr5SpUoyadIkadmypefP4gEIIIAAAggggAACCHglQIDJK1nKRQABBBDImkA6AaY9e/ZYO7u9//77WatnogeVKVNGpk6dKmeccUaiLJxHAAEEEEAAAQQQQMDXAsV9XTsqhwACCCCAgEcCN910k/ghuKTN27Fjh1xwwQXy3XffedRaikUAAQQQQAABBBBAwFsBAkze+lI6AggggIAPBYYNGyYvv/yyr2q2ceNG6dChg2zatMlX9aIyCCCAAAIIIIAAAggkI8AUuWSUyIMAAggg4GuBVKbIzZ8/X5o3by66/pIfU8eOHWXcuHF+rBp1QgABBBBAAAEEEEAgoQABpoQ0XEAAAQQQCIpAsgEm3THupJNOkq+//trXTXv33XelXbt2vq4jlUMAAQQQQAABBBBAIFqAKXLRGhwjgAACCOS0wIgRI3wfXNIO6Nmzp29HWOX0B4TGIYAAAggggAACCKQtQIApbTpuRAABBBAIksCuXbukf//+gajysmXLZOTIkYGoK5VEAAEEEEAAAQQQQEAFCDDxOUAAAQQQCIXAa6+9Jr/88ktg2vr444/L3r17A1NfKooAAggggAACCCAQbgECTOHuf1qPAAIIhEbg2WefDVRbf/75Z5k6dWqg6kxlEUAAAQQQQAABBMIrQIApvH1PyxFAAIHQCPz000+BWHsptkPGjh0be4r3CCCAAAIIIIAAAgj4UoAAky+7hUohgAACCLgpMGHCBDeLy1pZupvcnj17svY8HoQAAggggAACCCCAQLoCBJjSleM+BBBAAIHACHz++eeBqWt0RTdv3izz5s2LPsUxAggggAACCCCAAAK+FCDA5MtuoVIIIIAAAm4J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IIAAAggggAACGQgwgikDPG5FAAEE/CywYcMGqVu3rqxdu9bP1aRu/xWoVKmSLFmyRKpWrYoJAggggAACCCCAAAKBE2AEU+C6jAojgAACyQk8+uijBJeSo/JFro0bN0rv3r19URcqgQACCCCAAAIIIIBAqgKMYEpVjPwIIIBAAAR27dolhx12mPznP/8JQG2poi1QrFgx+fLLL+Wkk06yT/GKAAIIIIAAAggggEAgBBjBFIhuopIIIIBAagKzZs0iuJQamS9y60LsLMjui66gEggggAACCCCAAAIpChBgShGM7AgggEAQBKZPnx6EakqpUqXkqquukgYNGgSivtmo5OzZs2XkyJHZeBTPQAABBBBAAAEEEEDANQECTK5RUhACCCDgH4F58+b5pzJxalK9enXp37+/rFq1SkaPHi2///57nFzhPdW3b1/RNZlICCCAAAIIIIAAAggERYAAU1B6inoigAACKQh88803KeTOXtbmzZvLa6+9JitXrpT77rtPqlWrJosWLZL169dnrxIBeNIff/wh999/fwBqShURQAABBBBAAAEEEPh/AQJMfBIQQACBHBPYsGGDrFixwjetsqfBzZkzR3RtqCuuuEJKlizp1G/mzJnOMQf/E3j22Wdl4cKF/zvBEQIIIIAAAggggAACPhYo4eO6UTUEEEAAgTQE/DJ6SafBdevWTbp27WqNVErUlH/961+JLoX6/J49e+S2226TTz75JNQONB4BBBBAAAEEEEAgGAKMYApGP1FLBBBAIGmBog4w6TS4sWPH5pkGV1DlCTAl1vn000/lzTffTJyBKwgggAACCCCAAAII+ESAAJNPOoJqIIAAAm4JFEWASafBde7cWexpcJ06dcozDS5R29auXStLly5NdJnzRuCuu+6Sbdu2YYEAAggggAACCCCAgK8FCDD5unuoHAIIIJC6wPz581O/Kc07Dj30UBkwYICsXr3a2g2uWbNmKZXE6KXCuXSnvUceeaTwjORAAAEEEEAAAQQQQKAIBQgwFSE+j0YAAQTcFtixY4f8+OOPbhebr7xTTjlFxo0bZy0m3q9fP6latWq+PMmcIMCUjJLI448/LsuXL08uM7kQQAABBBBAAAEEECgCAQJMRYDOIxFAAAGvBL777jvRxaG9SKVLl5arr77amganO7917NgxqWlwBdWFAFNBOv+7poHD22+/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yvev3333nbRv31527tyZp67XX3+9LF68WK677jopVqxYnmv2m19//VUuuugiK0j1888/26d5RQABBBBAAAEEEEAgaQECTElTkREBBBBAwBbwywgmrwJM2s4aNWpYQabKlSvbzfb96xdffCFXXXVVvgW8NWA2cuRImTFjhjRu3DhhOzSo1qhRIxk8eLDs2rUrYT4uIIAAAggggAACCCAQK0CAKVaE9wgggAAChQr4YQSTjsapWbNmoXXNJIMGWyZNmiSlS5fOpJis3vvWW29Jjx494j6zRYsW1sLejzzyiJQrVy5uHl04vHfv3nLcccfJ559/HjcPJxFAAAEEEEAAAQQQiBUgwBQrwnsEEEAAgUIF/DCCqXr16lkJ/Jxxxhny2muvSfHiwfmW+cwzz4gGkeKlEiVKWAGkRYsWyfnnnx8vi3Xuxx9/lDPPPFNuuOEGWbt2bcJ8XEAAAQQQQAABBBBAQAWC89My/YUAAggg4BsBP4xg8nJ6XCz0xRdfLE8//XTsaV+/79u3r4waNSphHY844gh5//33rRFaepwo6dQ6XTD85Zdflkgkkigb5xFAAAEEEEAAAQRCLkCAKeQfAJqPAAIIpCPghxFM2QwwqdGtt94qGrQJUurSpYt8+OGHBVb5ggsuEB3N1LNnT9HRTfHS+vXrRRcLP+2000QXEychgAACCCCAAAIIIBArQIApVoT3CCCAAAIFCvzxxx+ybdu2AvNk42KtWrWy8Zg8z3jooYfk2muvzXPOz2/27Nkjl156qcyZM6fAaup6TEOGDLHWZ9J1mhKlmTNnStOmTaVPnz6ydevWRNk4jwACCCCAAAIIIBBCAQJMIex0mowAAghkIuCH6XFa/2yPYLLNXnrpJWnbtq391vevGghq166d/Prrr4XWVXeY053mnn/+eTnggAPi5teg1aBBg+SYY46RyZMnx83DSQQQQAABBBBAAIHwCRBgCl+f02IEEEAgIwE/TI/TBhRVgEmnkb355pty4oknZuSYzZt///13ayTT7t27C32s7s7XrVs30UW+r7zyyoT5V61aJX/961+lffv2osckBBBAAAEEEEAAgXALEGAKd//TegQQQCBlAb+MYCqKKXI2lk4p09E7Rx99tH3K9686vW3YsGFJ1/Pggw+WMWPGyOeffy4NGjRIeN+7775rjWZ68sknRUc3kRBAAAEEEEAA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"}}},{"cell_type":"code","source":"sample_train_tdcsfog_series.describe()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:35.202336Z","iopub.execute_input":"2023-07-15T19:32:35.202804Z","iopub.status.idle":"2023-07-15T19:32:35.240501Z","shell.execute_reply.started":"2023-07-15T19:32:35.202761Z","shell.execute_reply":"2023-07-15T19:32:35.239142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Since the range of acceleration data is different, a suitable normalization process may improve the model performance (presented in the preprocessing part).","metadata":{}},{"cell_type":"code","source":"# Turn series\nsample_tdcsfog_Turn= sample_train_tdcsfog_series[sample_train_tdcsfog_series[\"Turn\"]==1]\n\n# StartHesitation series\nsample_tdcsfog_StartHesitation= sample_train_tdcsfog_series[sample_train_tdcsfog_series[\"StartHesitation\"]==1]\n\n# Walking series\nsample_tdcsfog_Walking= sample_train_tdcsfog_series[sample_train_tdcsfog_series[\"Walking\"]==1]\n\n# None Event series\nsample_tdcsfog_None= sample_train_tdcsfog_series[~((sample_train_tdcsfog_series[\"Walking\"]==1) |\n                                                    (sample_train_tdcsfog_series[\"StartHesitation\"]==1)|\n                                                    (sample_train_tdcsfog_series[\"Turn\"]==1))]\n\n# # Create the 4*2 grid of subplots\ngrid = (4, 2)\nfig = plt.figure(figsize=(10, 5))\n\n# # Create the first pie chart spanning cells (1,1) and (2,1) and (3,1) and(4,1)\nax1 = plt.subplot2grid(grid, (0, 0), rowspan=4, colspan=1)\n\nax1.plot(sample_train_tdcsfog_series[\"Time\"], sample_train_tdcsfog_series[\"AccV\"], label=\"AccV\")\nax1.plot(sample_train_tdcsfog_series[\"Time\"], sample_train_tdcsfog_series[\"AccML\"], label=\"AccML\")\nax1.plot(sample_train_tdcsfog_series[\"Time\"], sample_train_tdcsfog_series[\"AccAP\"], label=\"AccAP\")\n\nax1.legend()\n\nax1.set_title(\"TDCSFog series sample\")\n\nax2 = plt.subplot2grid(grid, (0, 1))\n\n# Plot sample_tdcsfog_Turn in the second column\nax2.plot(sample_tdcsfog_Turn[\"Time\"], sample_tdcsfog_Turn[[\"AccV\", \"AccML\", \"AccAP\"]])\nax2.set_title(\"Turn\")\n\nax3 = plt.subplot2grid(grid, (1, 1))\n# Plot sample_tdcsfog_StartHesitation in the second column\nax3.plot(sample_tdcsfog_StartHesitation[\"Time\"], sample_tdcsfog_StartHesitation[[\"AccV\", \"AccML\", \"AccAP\"]])\nax3.set_title(\"StartHesitation\")\n\nax4 = plt.subplot2grid(grid, (2, 1))\n# Plot sample_tdcsfog_Walking in the second column\nax4.plot(sample_tdcsfog_Walking[\"Time\"], sample_tdcsfog_Walking[[\"AccV\", \"AccML\", \"AccAP\"]])\nax4.set_title(\"Walking\")\n\nax4 = plt.subplot2grid(grid, (3, 1))\n# Plot sample_tdcsfog_None in the second column\nax4.plot(sample_tdcsfog_None[\"Time\"], sample_tdcsfog_None[[\"AccV\", \"AccML\", \"AccAP\"]])\nax4.set_title(\"None\")\n\n# Adjust spacing between subplots\nplt.tight_layout()\n\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:35.244484Z","iopub.execute_input":"2023-07-15T19:32:35.244916Z","iopub.status.idle":"2023-07-15T19:32:36.40535Z","shell.execute_reply.started":"2023-07-15T19:32:35.244882Z","shell.execute_reply":"2023-07-15T19:32:36.404017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"text-align: justify\">In a particular time series, we observe that the variation of acceleration data during the Turn episode is at its maximum, which is a reasonable expectation. However, what makes the prediction challenging is the observation of non-trivial variations even in the absence of Turn, Walking, or Start Hesitation episodes. This variability in the data adds complexity to the prediction task.</div>","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-5\"></a>\n<h3>5. Data Preprocessing</h3>","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-6\"></a>\n<h4>5.1. Handling Missing Data</h4>","metadata":{}},{"cell_type":"code","source":"print(\"Null values in Subjects dataset:\")\nsubjects_df.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.410926Z","iopub.execute_input":"2023-07-15T19:32:36.411444Z","iopub.status.idle":"2023-07-15T19:32:36.422091Z","shell.execute_reply.started":"2023-07-15T19:32:36.411394Z","shell.execute_reply":"2023-07-15T19:32:36.420834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"It is mentioned in the data description that visit column was filled just for deFOG series, so no action is required for this field. But UPDRSIII_Off and UPDRSIII_On columns have to be filled with suitable data.","metadata":{}},{"cell_type":"code","source":"full_metadata","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.423694Z","iopub.execute_input":"2023-07-15T19:32:36.424208Z","iopub.status.idle":"2023-07-15T19:32:36.450969Z","shell.execute_reply.started":"2023-07-15T19:32:36.424163Z","shell.execute_reply":"2023-07-15T19:32:36.449435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"The null percentage of UPDRSIII_Off:{:.2f}%\".format(full_metadata[\"UPDRSIII_Off\"].isna().sum()/len(full_metadata)*100))","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.452638Z","iopub.execute_input":"2023-07-15T19:32:36.453142Z","iopub.status.idle":"2023-07-15T19:32:36.46512Z","shell.execute_reply.started":"2023-07-15T19:32:36.453078Z","shell.execute_reply":"2023-07-15T19:32:36.463917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_metadata.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.466938Z","iopub.execute_input":"2023-07-15T19:32:36.467331Z","iopub.status.idle":"2023-07-15T19:32:36.479931Z","shell.execute_reply.started":"2023-07-15T19:32:36.467297Z","shell.execute_reply":"2023-07-15T19:32:36.478719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"text-align: justify\">As we saw in the correlation matrix, UPDRSIII_Off strongly correlates with UPDRSIII_On. It is also slightly correlated with years_since_dx, age, and sex. So, filling missing values of UPDRSIII_Off and UPDRSIII_On using an imputation scheme seems to be reasonable. For this porpose, we employ the MICE (Multivariate Imputation by Chained Equations) algorithm that considers relationships between variables.","metadata":{}},{"cell_type":"code","source":"# Imputing using MICE\nfrom sklearn.experimental import enable_iterative_imputer\nfrom sklearn.impute import IterativeImputer\nfrom sklearn import linear_model\n\nfull_metadata_temp= full_metadata.loc[:,['Id','UPDRSIII_Off',\"UPDRSIII_On\",\"years_since_dx\",\"age\",\"sex\"]].copy()\n\ncolumns_to_update=['UPDRSIII_Off','UPDRSIII_On']\ndf_mice = full_metadata_temp.filter(columns_to_update, axis=1).copy()\n\n# Define MICE imputer and fill missing values\nmice_imputer = IterativeImputer(estimator=linear_model.BayesianRidge(), n_nearest_features=None,\n                                imputation_order='ascending')\n\ndf_mice_imputed = pd.DataFrame(mice_imputer.fit_transform(df_mice), columns=df_mice.columns)\n# Update the columns in the original DataFrame with the imputed values\nfull_metadata_temp.update(df_mice_imputed[columns_to_update])","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.482029Z","iopub.execute_input":"2023-07-15T19:32:36.482512Z","iopub.status.idle":"2023-07-15T19:32:36.514416Z","shell.execute_reply.started":"2023-07-15T19:32:36.482468Z","shell.execute_reply":"2023-07-15T19:32:36.512923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tdcsfog_metadata_subjects.copy()\ntemp=tdcsfog_metadata_subjects.drop([\"UPDRSIII_Off\",\"UPDRSIII_On\"], axis=1)\n\nmerged_df = temp.merge(full_metadata_temp, on='Id', how='left')\n\n# Fill the null values in column 'c1' of df1 with the values from merged_df\ntdcsfog_metadata_subjects['UPDRSIII_Off'].fillna(merged_df['UPDRSIII_Off'], inplace=True)\ntdcsfog_metadata_subjects['UPDRSIII_On'].fillna(merged_df['UPDRSIII_On'], inplace=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.516255Z","iopub.execute_input":"2023-07-15T19:32:36.516751Z","iopub.status.idle":"2023-07-15T19:32:36.531781Z","shell.execute_reply.started":"2023-07-15T19:32:36.516705Z","shell.execute_reply":"2023-07-15T19:32:36.530739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tdcsfog_metadata_subjects.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.533163Z","iopub.execute_input":"2023-07-15T19:32:36.533967Z","iopub.status.idle":"2023-07-15T19:32:36.545951Z","shell.execute_reply.started":"2023-07-15T19:32:36.53393Z","shell.execute_reply":"2023-07-15T19:32:36.544642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"defog_metadata_subjects.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.547378Z","iopub.execute_input":"2023-07-15T19:32:36.547956Z","iopub.status.idle":"2023-07-15T19:32:36.556096Z","shell.execute_reply.started":"2023-07-15T19:32:36.547919Z","shell.execute_reply":"2023-07-15T19:32:36.555237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-7\"></a>\n<h4>5.2. Converting Categorical Features</h4>","metadata":{}},{"cell_type":"code","source":"full_metadata.dtypes","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.557395Z","iopub.execute_input":"2023-07-15T19:32:36.557943Z","iopub.status.idle":"2023-07-15T19:32:36.570206Z","shell.execute_reply.started":"2023-07-15T19:32:36.55791Z","shell.execute_reply":"2023-07-15T19:32:36.569047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"defog_metadata_subjects[\"sex\"] = defog_metadata_subjects[\"sex\"].map({'F' :0, 'M' :1})\ntdcsfog_metadata_subjects[\"sex\"]= tdcsfog_metadata_subjects[\"sex\"].map({'F' :0, 'M' :1})\n\ndefog_metadata_subjects[\"medication\"] = defog_metadata_subjects[\"medication\"].map({'on' :0, 'off' :1})\ntdcsfog_metadata_subjects[\"medication\"] = tdcsfog_metadata_subjects[\"medication\"].map({'on' :0, 'off' :1})\n","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.571934Z","iopub.execute_input":"2023-07-15T19:32:36.572634Z","iopub.status.idle":"2023-07-15T19:32:36.589527Z","shell.execute_reply.started":"2023-07-15T19:32:36.572598Z","shell.execute_reply":"2023-07-15T19:32:36.588543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Since real values of 'subject' and 'Id' are needed in the next part, they will be converted later.","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-16\"></a>\n<h4>5.3. Normalizing Data</h4>","metadata":{}},{"cell_type":"markdown","source":"The acceleration data needs to be normalized. The normalization takes place in the model method for the purpose of achieving a better performance.","metadata":{}},{"cell_type":"code","source":"def normalize_columns(df, columns):\n    min_values = df[columns].min()\n    max_values = df[columns].max()\n\n    normalized_df = (df[columns] - min_values) / (max_values - min_values)\n    return normalized_df","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.590975Z","iopub.execute_input":"2023-07-15T19:32:36.591513Z","iopub.status.idle":"2023-07-15T19:32:36.604222Z","shell.execute_reply.started":"2023-07-15T19:32:36.591481Z","shell.execute_reply":"2023-07-15T19:32:36.603092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-8\"></a>\n<h4>5.4. Outliers</h4>\n\nTo find the event that takes more than usual time, the distributaion of each FOG event is illustrated by a boxplot.","metadata":{}},{"cell_type":"code","source":"events_df['duration'] = events_df['Completion'] - events_df['Init']","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.606118Z","iopub.execute_input":"2023-07-15T19:32:36.606471Z","iopub.status.idle":"2023-07-15T19:32:36.61764Z","shell.execute_reply.started":"2023-07-15T19:32:36.606442Z","shell.execute_reply":"2023-07-15T19:32:36.616701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('default')\n\nevents_arr = events_df['Type'].unique()\n# Remove NaN values\nseries = pd.Series(events_arr)\nseries_without_nan = series.dropna()\nevents_arr = series_without_nan.to_numpy()\n\nplt.figure(figsize=(6, 6))\nbox_plot=plt.boxplot([events_df[events_df['Type'] == t]['duration'] for t in events_arr],\n            labels=events_arr)\nplt.xlabel('Type')\nplt.ylabel('duration')\nplt.title('Box Plot of Event Durations by Event Type', fontsize=9, pad=10)\n\n# Annotate the minimum and maximum values for each box plot\nfor i, box in enumerate(box_plot['boxes']):\n\n    max_val = box_plot['whiskers'][i*2 + 1].get_ydata()[1]\n    \n    plt.annotate(f\"Max: {max_val:.0f}\", (i+1, max_val), xytext=(10+25, +5), textcoords='offset points', ha='center')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:36.619032Z","iopub.execute_input":"2023-07-15T19:32:36.619388Z","iopub.status.idle":"2023-07-15T19:32:37.22571Z","shell.execute_reply.started":"2023-07-15T19:32:36.619357Z","shell.execute_reply":"2023-07-15T19:32:37.223491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Data points that fall outside the whiskers can be considered as outliers. However, during the fine-tuning of the model, a temporal threshold larger than 200 seconds, to detect event outliers, seems to be ideal.","metadata":{}},{"cell_type":"code","source":"#  delete outliers\n\n# Get the maximum value for each type from the box plot\nmax_values = {t: item.get_ydata()[1] for t, item in zip(events_df['Type'].unique(), box_plot['whiskers'][1::2])}\n\n# Drop rows with durations greater than the maximum value for each type\nevents_filtered = events_df.groupby('Type').apply(lambda x: x[x['duration'] >= (max_values[x['Type'].unique()[0]])+200]).reset_index(drop=True)\n","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:37.227803Z","iopub.execute_input":"2023-07-15T19:32:37.228287Z","iopub.status.idle":"2023-07-15T19:32:37.246111Z","shell.execute_reply.started":"2023-07-15T19:32:37.228247Z","shell.execute_reply":"2023-07-15T19:32:37.244133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-9\"></a>\n<h3>6. Feature Engineering</h3>\n\n<div style=\"text-align: justify\">Because acceleration data are the most important feautures to detect an event, some new features related to these features are added to the data. Some statistics can be calculated for time series data based on a sliding window that moves along the data range. The size of this window is considered 1024.\n\nThese new features are:\n\n* **acc_sum**: Sum of the \"AccV\", \"AccML\", and \"AccAP\" features\n* **time_frac**: The fraction of time relative to the maximum time value in the series\n* **cum_sum**: The cumulative sum of Acc features\n\nRolling features of each Acc features associated with a specified window length are as follows.\n* **rolling_sum**\n* **rolling_min**\n* **rolling_max**\n* **rolling_mean**\n* **rolling_std**\n* **rolling_delta**: The difference between the rolling maximum and the rolling minimum <br>\n    \nLead and lag differences for each Acc feature are listed below.  \n* **acc_lead_diff**: The time difference between the current data point and the previous data point \n* **acc_lag_diff**:The time difference between the current data point and the next data point\n\n","metadata":{}},{"cell_type":"code","source":"\ndef reader(file, module, pre_type=None):\n    if module==\"tdcsfog\":\n        window_length =4048\n    elif module==\"defog\":\n        window_length=4048\n    try:\n\n        df = pd.read_csv(file)\n\n        path_split = file.split('/')\n        Id = path_split[-1].split('.')[0]\n        df['Id'] = Id\n        \n        if module==\"defog\":\n            data= df.merge(defog_metadata_subjects,how=\"left\",on=\"Id\")\n            if 'Valid' in data.columns and 'Task' in data.columns and pre_type==\"train\":\n                data = data.loc[(data['Valid'] == True) & (data[\"Task\"] == True)]\n                data.drop([\"Valid\", \"Task\"], axis=1, inplace=True)\n            elif 'Valid' in data.columns and 'Task' in data.columns:\n                data.drop([\"Valid\", \"Task\"], axis=1, inplace=True)\n\n        elif module == \"tdcsfog\":\n            data= df.merge(tdcsfog_metadata_subjects,how=\"left\",on=\"Id\")\n\n        data[\"acc_sum\"]= data[\"AccV\"]+data[\"AccML\"]+data[\"AccAP\"]\n        data['time_frac']=(data[\"Time\"]/data[\"Time\"].max()).values\n        acc_columns=[\"AccV\",\"AccML\",\"AccAP\"]\n        \n        columns_to_normalize = ['AccV', 'AccML', 'AccAP']\n        data[columns_to_normalize] = normalize_columns(data, columns_to_normalize)   \n        \n        for acc in acc_columns:\n            data[f'{acc}_cumsum'] = data[acc].cumsum()\n            data[f'{acc}_rolling_sum'] = data[acc].rolling(window=window_length, min_periods=1).sum()\n            data[f'{acc}_rolling_min'] = data[acc].rolling(window=window_length, min_periods=1).min()\n            data[f'{acc}_rolling_max'] = data[acc].rolling(window=window_length, min_periods=1).max()\n            data[f'{acc}_rolling_mean'] = data[acc].rolling(window=window_length, min_periods=1).mean()\n            data[f'{acc}_rolling_std'] = data[acc].rolling(window=window_length, min_periods=1).std()\n            data[f'{acc}_rolling_delta'] = data[f'{acc}_rolling_max'] - data[f'{acc}_rolling_min']        \n            data[f'{acc}_EWMA_02'] = data[acc].ewm(alpha=0.2).mean()\n        \n        for c in acc_columns:\n            data[f\"{c}_lead_diff\"] = data[c].diff(-1)\n            data[f\"{c}_lag_diff\"] = data[c].diff()\n\n\n        data.fillna(method='backfill', inplace=True)\n        \n#         for train data \n        events_id = events_filtered[events_filtered[\"Id\"] == Id]\n\n        events_rows = pd.DataFrame()\n        if len(events_id)>0:\n            return None\n                \n        return data\n    except: pass","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:37.262559Z","iopub.execute_input":"2023-07-15T19:32:37.262991Z","iopub.status.idle":"2023-07-15T19:32:37.28824Z","shell.execute_reply.started":"2023-07-15T19:32:37.262952Z","shell.execute_reply":"2023-07-15T19:32:37.284962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_defog_df = pd.concat([reader(f,\"defog\",\"train\") for f in tqdm(train_defog)]).fillna(-1); print(train_defog_df.shape)","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:32:37.290258Z","iopub.execute_input":"2023-07-15T19:32:37.290762Z","iopub.status.idle":"2023-07-15T19:33:08.006339Z","shell.execute_reply.started":"2023-07-15T19:32:37.290712Z","shell.execute_reply":"2023-07-15T19:33:08.005178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_defog_df =reduce_memory_usage(train_defog_df)","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:33:08.007806Z","iopub.execute_input":"2023-07-15T19:33:08.008158Z","iopub.status.idle":"2023-07-15T19:33:20.248311Z","shell.execute_reply.started":"2023-07-15T19:33:08.008128Z","shell.execute_reply":"2023-07-15T19:33:20.247118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_tdcsfog_df = pd.concat([reader(f,\"tdcsfog\") for f in tqdm(train_tdcsfog)]).fillna(0); print(train_tdcsfog_df.shape)","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:33:20.253277Z","iopub.execute_input":"2023-07-15T19:33:20.253679Z","iopub.status.idle":"2023-07-15T19:34:15.1679Z","shell.execute_reply.started":"2023-07-15T19:33:20.253647Z","shell.execute_reply":"2023-07-15T19:34:15.166644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_tdcsfog_df =reduce_memory_usage(train_tdcsfog_df)","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:34:15.169186Z","iopub.execute_input":"2023-07-15T19:34:15.169541Z","iopub.status.idle":"2023-07-15T19:34:34.650047Z","shell.execute_reply.started":"2023-07-15T19:34:15.169511Z","shell.execute_reply":"2023-07-15T19:34:34.649061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-10\"></a>\n<h3>7. Model</h3>\n\n<div style=\"text-align: justify\">\nGiven the availability of labeled targets in the dataset, a supervised learning approach is suitable for addressing this problem. Since there are multiple targets (Start Hesitation, Turn, and Walking), the problem is a multi-class classification.\n<br>\nThe evaluation metric in this project is the mean average precision, which measures the average precision of predictions for each event class. Thus, accurate predictions of correct event types are more important than predicting all events correctly.\n","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-11\"></a>\n<h4>7.1. Model Selection</h4>\n\n<div style=\"text-align: justify\">\n    \nFor this project, after tuning different ML algorithms, LightGBM algorithm is taken into account for the following reasons.\n\n* The dataset is large including many features, so a highly-effiecient model is required.\n* The task involves multi-class classification.\n* The multi-class problem exhibits imbalanced classes.\n* It is crucial to capture complex and non-linear relationships in the data.\n    ","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-12\"></a>\n<h4>7.2. Model Training</h4>\n<div style=\"text-align: justify\">   \nTo find the best parameters for LightGBM algorithm, GridSearchCV is performed according to the following parameter grid:\n    \n    param_grid = {\n      'max_depth': [6,8,10],\n      'learning_rate': [0.15,0.1,0.01],\n      'n_estimators': [50,70,90]\n    } \n  \nThe best parameter values selected are: max_depth=8, learning_rate=0.1, n_estimators=70.\n\nAdditionally, during the fine-tuning process, UPDRSIII_On and UPDRSIII_Off were removed from the tdcsfog dataframe.\n","metadata":{}},{"cell_type":"code","source":"targets = [\"StartHesitation\", \"Turn\", 'Walking']","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:34:34.651347Z","iopub.execute_input":"2023-07-15T19:34:34.651784Z","iopub.status.idle":"2023-07-15T19:34:34.657197Z","shell.execute_reply.started":"2023-07-15T19:34:34.651752Z","shell.execute_reply":"2023-07-15T19:34:34.656046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def model(df, module):\n    \n    df = df.apply(factorize_column)\n\n    y_train = df.loc[:, targets]\n\n    if module == \"defog\":\n        X_train = df.drop(targets, axis=1)\n\n    elif module == \"tdcsfog\":\n        X_train = df.drop([\"StartHesitation\", \"Turn\", 'Walking', 'UPDRSIII_On', 'UPDRSIII_Off'], axis=1)\n      \n    models = []\n    aps=[]\n\n    # Get Ids from X_train\n    Ids = X_train['Id']\n\n    # Create the GroupKFold object based on 'Id' column\n    group_cv = GroupKFold(n_splits=5)\n    \n    for label in targets:\n        y_train_l = y_train[label]\n\n        # LightGBM classifier\n        lgbm = lgb.LGBMClassifier(objective=\"binary\", scale_pos_weight=np.sqrt(y_train_l.value_counts()[0] / y_train_l.value_counts()[1]),\n                                  max_depth=8, learning_rate=0.1, n_estimators=70)\n        \n        aps_l = []\n        # Perform group-based cross-validation\n        for train_idx, val_idx in group_cv.split(X_train, y_train_l, groups=Ids):\n            X_train_fold, X_val_fold = X_train.iloc[train_idx], X_train.iloc[val_idx]\n            y_train_fold, y_val_fold = y_train_l.iloc[train_idx], y_train_l.iloc[val_idx]\n\n            # Fit the model on the training fold\n            lgbm.fit(X_train_fold, y_train_fold)\n\n            # Calculate average precision for the validation fold\n            ap_val = average_precision_score(y_val_fold, lgbm.predict_proba(X_val_fold)[:, 1])\n            aps_l.append(ap_val)\n        print(\"Average precision of {} associated with all folds: {:.4f}\".format(label, np.mean(aps_l)))\n        aps.append(aps_l)    \n    print(\"Overall precision of all folds: {:.4f}\".format( np.mean(aps)))\n#     main model trained on entired data\n    for label in targets:\n        y_train_l = y_train[label]\n\n        # LightGBM classifier\n        lgbm = lgb.LGBMClassifier(objective=\"binary\", scale_pos_weight=np.sqrt(y_train_l.value_counts()[0] / y_train_l.value_counts()[1]),\n                              max_depth=8, learning_rate=0.1, n_estimators=70)\n        lgbm.fit(X_train, y_train_l)\n        models.append(lgbm)\n    return models","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:34:34.65866Z","iopub.execute_input":"2023-07-15T19:34:34.659354Z","iopub.status.idle":"2023-07-15T19:34:34.672623Z","shell.execute_reply.started":"2023-07-15T19:34:34.659315Z","shell.execute_reply":"2023-07-15T19:34:34.671333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-13\"></a>\n<h4>7.3. Model Evaluation</h4>\n<div style=\"text-align: justify\">\nTo achieve an accurate evaluation of the model, a $k$-fold cross-validation based on 'Id' column is used. This group-based cross-valiadation provides a more realistic evaluation of the model's performance.","metadata":{}},{"cell_type":"code","source":"defog_models=model(train_defog_df,\"defog\")","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:34:34.674124Z","iopub.execute_input":"2023-07-15T19:34:34.674568Z","iopub.status.idle":"2023-07-15T19:46:00.682815Z","shell.execute_reply.started":"2023-07-15T19:34:34.674499Z","shell.execute_reply":"2023-07-15T19:46:00.681867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"If outliers are not deleted, the results would be as follows:<br>\n*Average precision of StartHesitation in all folds: 0.7138<br>\nAverage precision of Turn in all folds: 0.8231<br>\nAverage precision of Walking in all folds: 0.2530<br>\nTotal average precision of all folds: 0.5967<br>*\n<br>\nThese results significantly differ from the test evaluation, indicating the potential inaccuracy of the evaluation if that data were included.","metadata":{}},{"cell_type":"code","source":"# tdcsfog model\ntdcsfog_models=model(train_tdcsfog_df,\"tdcsfog\")","metadata":{"execution":{"iopub.status.busy":"2023-07-15T19:46:00.684245Z","iopub.execute_input":"2023-07-15T19:46:00.684813Z","iopub.status.idle":"2023-07-15T20:05:33.688226Z","shell.execute_reply.started":"2023-07-15T19:46:00.684779Z","shell.execute_reply":"2023-07-15T20:05:33.686941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Considering the chart of acceleration data for StartHesitation and the sparse occurrence of this event, detecting this event is challenging, as already predicted.","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-14\"></a>\n<h4>8. Prediction and Submission</h4>\n<div style=\"text-align: justify\">\nBoth the defog and tdcsfog models are evaluated based on their corresponding test data, and the resulting predictions are submitted to the competition. These submissions achieved a placement within the <b>top 20%</b> of participants in the competition.","metadata":{}},{"cell_type":"code","source":"def predict(models, test_df, module):\n    X_test = test_df.apply(factorize_column)\n\n    if module == \"tdcsfog\":\n        X_test= X_test.drop(['UPDRSIII_On', 'UPDRSIII_Off'], axis=1)\n    \n    y_predict = pd.DataFrame()\n    \n    \n    for index, label in enumerate(targets):\n         y_predict[label] = models[index].predict_proba(X_test)[:, 1]\n            \n    test_df[\"Time\"] = test_df[\"Time\"].astype(str)\n    test_df=test_df.reset_index(drop=True)\n    y_predict.insert(0, 'Id', test_df[\"Id\"] + \"_\" + test_df[\"Time\"])\n    return y_predict","metadata":{"execution":{"iopub.status.busy":"2023-07-15T20:05:33.690388Z","iopub.execute_input":"2023-07-15T20:05:33.691279Z","iopub.status.idle":"2023-07-15T20:05:33.699114Z","shell.execute_reply.started":"2023-07-15T20:05:33.691241Z","shell.execute_reply":"2023-07-15T20:05:33.697911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_defog_df = pd.concat([reader(f,\"defog\") for f in tqdm(test_defog)]).fillna(-1); print(test_defog_df.shape)\ntest_tdcsfog_df = pd.concat([reader(f,\"tdcsfog\") for f in tqdm(test_tdcsfog)]).fillna(-1); print(test_tdcsfog_df.shape)\n\n# predict defog test df\ny_defog_predict = predict(defog_models, test_defog_df,\"defog\")\n# predict tdcsfog test df\ny_tdcsfog_predict = predict(tdcsfog_models,test_tdcsfog_df, \"tdcsfog\")","metadata":{"execution":{"iopub.status.busy":"2023-07-15T20:05:33.700524Z","iopub.execute_input":"2023-07-15T20:05:33.70089Z","iopub.status.idle":"2023-07-15T20:05:36.202312Z","shell.execute_reply.started":"2023-07-15T20:05:33.700858Z","shell.execute_reply":"2023-07-15T20:05:36.20127Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission=pd.concat([y_tdcsfog_predict, y_defog_predict])\nsubmission[\"StartHesitation\"]=np.round(submission[\"StartHesitation\"].clip(0.0,1.0),8)\nsubmission[\"Turn\"]=np.round(submission[\"Turn\"].clip(0.0,1.0),8)\nsubmission[\"Walking\"]=np.round(submission[\"Walking\"].clip(0.0,1.0),8)\nsubmission.to_csv('submission.csv', index=False)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2023-07-15T20:05:36.203797Z","iopub.execute_input":"2023-07-15T20:05:36.205085Z","iopub.status.idle":"2023-07-15T20:05:37.425682Z","shell.execute_reply.started":"2023-07-15T20:05:36.205029Z","shell.execute_reply":"2023-07-15T20:05:37.424406Z"},"trusted":true},"execution_count":null,"outputs":[]}]}