{"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":"code","source":"# Reduce Memory Usage\n# reference : https://www.kaggle.com/code/arjanso/reducing-dataframe-memory-size-by-65 @ARJANGROEN\n\ndef 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        print(col)\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                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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-05-22T10:44:38.812102Z","iopub.execute_input":"2023-05-22T10:44:38.812487Z","iopub.status.idle":"2023-05-22T10:44:38.852941Z","shell.execute_reply.started":"2023-05-22T10:44:38.812455Z","shell.execute_reply":"2023-05-22T10:44:38.851832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Importing libraries \nimport numpy as np\nimport pandas as pd\nimport glob\nimport random\nfrom sklearn import *\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom os import path\nfrom pathlib import Path\nfrom tqdm.auto import tqdm\n\nfrom sklearn.model_selection import GroupKFold, GridSearchCV\nfrom sklearn.preprocessing import PolynomialFeatures\nimport lightgbm as lgb\nfrom sklearn.multioutput import MultiOutputRegressor\nfrom sklearn.base import clone\nfrom sklearn.metrics import average_precision_score","metadata":{"execution":{"iopub.status.busy":"2023-05-22T10:44:38.854793Z","iopub.execute_input":"2023-05-22T10:44:38.855328Z","iopub.status.idle":"2023-05-22T10:44:42.817916Z","shell.execute_reply.started":"2023-05-22T10:44:38.855298Z","shell.execute_reply":"2023-05-22T10:44:42.816708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Install tsflex and seglearn\n!pip install tsflex --no-index --find-links=file:///kaggle/input/time-series-tools\n!pip install seglearn --no-index --find-links=file:///kaggle/input/time-series-tools","metadata":{"execution":{"iopub.status.busy":"2023-05-22T10:44:42.820993Z","iopub.execute_input":"2023-05-22T10:44:42.821467Z","iopub.status.idle":"2023-05-22T10:45:10.913167Z","shell.execute_reply.started":"2023-05-22T10:44:42.821423Z","shell.execute_reply":"2023-05-22T10:45:10.911906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from seglearn.feature_functions import base_features, emg_features\nfrom tsflex.features import FeatureCollection, MultipleFeatureDescriptors\nfrom tsflex.features.integrations import seglearn_feature_dict_wrapper","metadata":{"execution":{"iopub.status.busy":"2023-05-22T10:45:10.916204Z","iopub.execute_input":"2023-05-22T10:45:10.916545Z","iopub.status.idle":"2023-05-22T10:45:11.166186Z","shell.execute_reply.started":"2023-05-22T10:45:10.916514Z","shell.execute_reply":"2023-05-22T10:45:11.165279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"root = '/kaggle/input/tlvmc-parkinsons-freezing-gait-prediction/'\n\ntrain = glob.glob(path.join(root, 'train/**/**'))\ntest = glob.glob(path.join(root, 'test/**/**'))\n\nsubjects = pd.read_csv(path.join(root, 'subjects.csv'))\ntasks = pd.read_csv(path.join(root, 'tasks.csv'))\nevents = pd.read_csv(path.join(root, 'events.csv'))\n\ntdcsfog_metadata = pd.read_csv(path.join(root, 'tdcsfog_metadata.csv'))\ndefog_metadata = pd.read_csv(path.join(root, 'defog_metadata.csv')) \n\ntdcsfog_metadata['Module'] = 'tdcsfog'\ndefog_metadata['Module'] = 'defog'\n\nfull_metadata = pd.concat([tdcsfog_metadata, defog_metadata])\n","metadata":{"execution":{"iopub.status.busy":"2023-05-22T10:45:11.168812Z","iopub.execute_input":"2023-05-22T10:45:11.169841Z","iopub.status.idle":"2023-05-22T10:45:11.417926Z","shell.execute_reply.started":"2023-05-22T10:45:11.169794Z","shell.execute_reply":"2023-05-22T10:45:11.416927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subjects.loc[subjects['Subject'] == 'fe5d84', 'Sex'] = 'F'","metadata":{"execution":{"iopub.status.busy":"2023-05-22T09:36:24.700855Z","iopub.execute_input":"2023-05-22T09:36:24.701776Z","iopub.status.idle":"2023-05-22T09:36:24.712113Z","shell.execute_reply.started":"2023-05-22T09:36:24.701733Z","shell.execute_reply":"2023-05-22T09:36:24.710760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seed = 100\ncluster_size = 8","metadata":{"execution":{"iopub.status.busy":"2023-05-22T09:36:24.713797Z","iopub.execute_input":"2023-05-22T09:36:24.714245Z","iopub.status.idle":"2023-05-22T09:36:24.726599Z","shell.execute_reply.started":"2023-05-22T09:36:24.714206Z","shell.execute_reply":"2023-05-22T09:36:24.725323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subjects['Sex'] = subjects['Sex'].factorize()[0]\nsubjects = subjects.fillna(0).groupby('Subject').median() #why median?\nsubjects['s_group'] = cluster.KMeans(n_clusters = cluster_size, random_state = seed).fit_predict(subjects[subjects.columns[1:]])\nnew_names = {'Visit':'s_visit','Age':'s_age','YearsSinceDx':'s_years','UPDRSIII_On':'s_on','UPDRSIII_Off':'s_off','NFOGQ':'s_NFOGQ', 'Sex': 's_sex'}\nsubjects = subjects.rename(columns = new_names)\nsubjects","metadata":{"execution":{"iopub.status.busy":"2023-05-22T09:36:24.728319Z","iopub.execute_input":"2023-05-22T09:36:24.728793Z","iopub.status.idle":"2023-05-22T09:36:25.558332Z","shell.execute_reply.started":"2023-05-22T09:36:24.728752Z","shell.execute_reply":"2023-05-22T09:36:25.557090Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tasks['Duration'] = tasks['End'] - tasks['Begin']\ntasks = pd.pivot_table(tasks, values=['Duration'], index=['Id'], columns=['Task'], aggfunc='sum', fill_value=0)\ntasks.columns = [c[1] for c in tasks.columns]\ntasks = tasks.reset_index()\ntasks['t_group'] = cluster.KMeans(n_clusters = cluster_size, random_state = seed).fit_predict(tasks[tasks.columns[1:]])\ntasks","metadata":{"execution":{"iopub.status.busy":"2023-05-22T09:36:25.559869Z","iopub.execute_input":"2023-05-22T09:36:25.560713Z","iopub.status.idle":"2023-05-22T09:36:25.687489Z","shell.execute_reply.started":"2023-05-22T09:36:25.560675Z","shell.execute_reply":"2023-05-22T09:36:25.686370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# merge the subjects with the metadata\nmetadata_w_subjects = full_metadata.merge(subjects, how='left', on='Subject').copy()\nfeatures = metadata_w_subjects.columns","metadata":{"execution":{"iopub.status.busy":"2023-05-22T09:36:25.688872Z","iopub.execute_input":"2023-05-22T09:36:25.689308Z","iopub.status.idle":"2023-05-22T09:36:25.705804Z","shell.execute_reply.started":"2023-05-22T09:36:25.689278Z","shell.execute_reply":"2023-05-22T09:36:25.704677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"metadata_w_subjects['Medication'] = metadata_w_subjects['Medication'].factorize()[0]\nmetadata_w_subjects","metadata":{"execution":{"iopub.status.busy":"2023-05-22T09:36:25.708758Z","iopub.execute_input":"2023-05-22T09:36:25.709214Z","iopub.status.idle":"2023-05-22T09:36:25.752266Z","shell.execute_reply.started":"2023-05-22T09:36:25.709184Z","shell.execute_reply":"2023-05-22T09:36:25.750960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"basic_feats = MultipleFeatureDescriptors(\n    functions=seglearn_feature_dict_wrapper(base_features()),\n    series_names=['AccV', 'AccML', 'AccAP'],\n    windows=[5000],\n    strides=[5000],\n)\n\nemg_feats = emg_features()\ndel emg_feats['simple square integral'] # is same as abs_energy (which is in base_features)\n\nemg_feats = MultipleFeatureDescriptors(\n    functions=seglearn_feature_dict_wrapper(emg_feats),\n    series_names=['AccV', 'AccML', 'AccAP'],\n    windows=[5000],\n    strides=[5000],\n)\n\nfc = FeatureCollection([basic_feats, emg_feats])","metadata":{"execution":{"iopub.status.busy":"2023-05-22T10:45:11.419237Z","iopub.execute_input":"2023-05-22T10:45:11.419545Z","iopub.status.idle":"2023-05-22T10:45:11.429729Z","shell.execute_reply.started":"2023-05-22T10:45:11.419520Z","shell.execute_reply":"2023-05-22T10:45:11.428613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def reader(file):\n    try:\n        df = pd.read_csv(file, index_col='Time', usecols=['Time', 'AccV', 'AccML', 'AccAP', 'StartHesitation', 'Turn' , 'Walking'])\n\n        path_split = file.split('/')\n        df['Id'] = path_split[-1].split('.')[0]\n        dataset = Path(file).parts[-2]\n        df['Module'] = dataset\n        \n        # Used to be commented out\n        #this is done because the speeds are at different rates for the datasets\n        if dataset == 'tdcsfog':\n            df.AccV = df.AccV / 9.80665\n            df.AccML = df.AccML / 9.80665\n            df.AccAP = df.AccAP / 9.80665\n\n        df['Time_frac']=(df.index/df.index.max()).values\n        \n        df = pd.merge(df, tasks[['Id','t_group']], how='left', on='Id').fillna(-1)\n        \n        df = pd.merge(df, metadata_w_subjects[['Id','Subject', 'Visit','Test','Medication','s_group']], how='left', on='Id').fillna(-1)\n        \n        # Adding Feature Extraction\n        df_feats = fc.calculate(df, return_df=True, include_final_window=True, approve_sparsity=True, window_idx=\"begin\").astype(np.float32)\n        df = df.merge(df_feats, how=\"left\", left_index=True, right_index=True)\n        \n        # Adding stride\n        df[\"Stride\"] = df[\"AccV\"] + df[\"AccML\"] + df[\"AccAP\"]\n        \n        # Adding step\n        df[\"Step\"] = np.sqrt(abs(df[\"Stride\"]))\n    \n        df.fillna(method=\"ffill\", inplace=True)\n        # Generating polynomial features\n        selected_features = ['AccV', 'AccML', 'AccAP']\n        poly = PolynomialFeatures(degree=2, include_bias=False)\n        poly_features = poly.fit_transform(df[selected_features])\n        feature_names = poly.get_feature_names_out(input_features=selected_features)\n        poly_features_df = pd.DataFrame(poly_features, columns=feature_names)\n\n        # Concatenate polynomial features with the original DataFrame\n        df = pd.concat([df, poly_features_df], axis=1)\n        return df\n    except: pass\n\ntrain = pd.concat([reader(f) for f in tqdm(train)]).fillna(0); print(train.shape)\n#train = reduce_memory_usage(train)\ncols = [c for c in train.columns if c not in ['Id','Subject','Module', 'Time', 'StartHesitation', 'Turn' , 'Walking', 'Valid', 'Task','Event']]\npcols = ['StartHesitation', 'Turn' , 'Walking']\nscols = ['Id', 'StartHesitation', 'Turn' , 'Walking']\ntrain=train.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2023-05-22T10:45:11.431552Z","iopub.execute_input":"2023-05-22T10:45:11.432035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"best_params_ = {'colsample_bytree': 0.5282057895135501,\n 'learning_rate': 0.22659963168004743,\n 'max_depth': 8,\n 'min_child_weight': 3.1233911067827616,\n 'n_estimators': 291,\n 'subsample': 0.9961057796456088,\n }\n\ndef custom_average_precision(y_true, y_pred):\n    score = average_precision_score(y_true, y_pred)\n    return 'average_precision', score, True\n\nclass LGBMMultiOutputRegressor(MultiOutputRegressor):\n    def fit(self, X, y, eval_set=None, **fit_params):\n        self.estimators_ = [clone(self.estimator) for _ in range(y.shape[1])]\n        \n        for i, estimator in enumerate(self.estimators_):\n            if eval_set:\n                fit_params['eval_set'] = [(eval_set[0], eval_set[1][:, i])]\n            estimator.fit(X, y[:, i], **fit_params)\n        \n        return self","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# For Grid search the hyperparameters\n\"\"\"# Define a set of hyperparameters for grid search\nparam_grid = {\n    'estimator__learning_rate': [0.01, 0.05, 0.1],\n    'estimator__n_estimators': [100,150],\n    'estimator__max_depth': [7],\n    #'estimator__colsample_bytree': [0.6, 0.8, 1],\n    'estimator__subsample': [0.6, 0.8, 1]\n    #'estimator__min_child_weight': [1, 3, 6]\n}\n\n# Create a base model\nlgbm_base = lgb.LGBMRegressor(random_state=42)\n\n# Create the MultiOutputRegressor instance wrapping the base model\nlgbm_multi = LGBMMultiOutputRegressor(lgbm_base)\n\n# Define a GroupKFold cross-validation\ngkf = GroupKFold(n_splits=3)\n\n# Create the GridSearchCV instance\ngrid_search = GridSearchCV(estimator=lgbm_multi, param_grid=param_grid, cv=gkf, n_jobs=-1, verbose=2, scoring='average_precision')\n\n# Define features, targets, and groups\nX = train[cols].values\ny = train[pcols].values\ngroups = train.Subject.values\n\n# Perform grid search\ngrid_search.fit(X, y, groups=groups)\n\n# Print the best parameters\nprint(\"Best parameters found: \", grid_search.best_params_)\n\n# Use the best model from grid search for further analysis\nbest_grid = grid_search.best_estimator_\"\"\"\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kfold = GroupKFold(5)\ngroups = kfold.split(train, groups=train.Subject)\n\nregs = []\ncvs = []\n\nfor _, (tr_idx, te_idx) in enumerate(tqdm(groups, total=5, desc=\"Folds\")):\n    \n    tr_idx = pd.Series(tr_idx).sample(n=2000000,random_state=42).values\n\n    multioutput_regressor = LGBMMultiOutputRegressor(lgb.LGBMRegressor(**best_params_))\n\n    x_train = train.loc[tr_idx, cols].to_numpy()\n    y_train = train.loc[tr_idx, pcols].to_numpy()\n    \n    x_test = train.loc[te_idx, cols].to_numpy()\n    y_test = train.loc[te_idx, pcols].to_numpy()\n\n    multioutput_regressor.fit(\n        x_train, y_train,\n        eval_set=(x_test, y_test),\n        eval_metric=custom_average_precision,\n        early_stopping_rounds=15,\n        verbose = 0,\n    )\n    \n    regs.append(multioutput_regressor)\n    \n    cv = metrics.average_precision_score(y_test, multioutput_regressor.predict(x_test).clip(0.0,1.0))\n    \n    cvs.append(cv)\n    \nprint(cvs)\nprint(np.mean(cvs))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub = pd.read_csv(path.join(root, 'sample_submission.csv'))\nsubmission = []\n\nfor f in test:\n    df = pd.read_csv(f)\n    df.set_index('Time', drop=True, inplace=True)\n\n    df['Id'] = f.split('/')[-1].split('.')[0]\n\n    dataset = Path(f).parts[-2]\n        \n    if dataset == 'tdcsfog':\n        df.AccV = df.AccV / 9.80665\n        df.AccML = df.AccML / 9.80665\n        df.AccAP = df.AccAP / 9.80665\n            \n    df['Time_frac']=(df.index/df.index.max()).values\n    df = pd.merge(df, tasks[['Id','t_group']], how='left', on='Id').fillna(-1)\n\n    df = pd.merge(df, metadata_w_subjects[['Id','Subject', 'Visit','Test','Medication','s_group']], how='left', on='Id').fillna(-1)\n    df_feats = fc.calculate(df, return_df=True, include_final_window=True, approve_sparsity=True, window_idx=\"begin\")\n    df = df.merge(df_feats, how=\"left\", left_index=True, right_index=True)\n    df.fillna(method=\"ffill\", inplace=True)\n\n    # stride\n    df[\"Stride\"] = df[\"AccV\"] + df[\"AccML\"] + df[\"AccAP\"]\n\n    # step\n    df[\"Step\"] = np.sqrt(abs(df[\"Stride\"]))\n    \n    # Generating polynomial features\n    selected_features = ['AccV', 'AccML', 'AccAP']\n    poly = PolynomialFeatures(degree=2, include_bias=False)\n    poly_features = poly.fit_transform(df[selected_features])\n    feature_names = poly.get_feature_names_out(input_features=selected_features)\n    poly_features_df = pd.DataFrame(poly_features, columns=feature_names)\n\n    # Concatenate polynomial features with the original DataFrame\n    df = pd.concat([df, poly_features_df], axis=1)\n    \n    res_vals = []\n    \n    for i_fold in range(5):\n        \n        pred = regs[i_fold].predict(df[cols]).clip(0.0,1.0)\n        res_vals.append(np.expand_dims(np.round(pred, 3), axis = 2))\n        \n    res_vals = np.mean(np.concatenate(res_vals, axis = 2), axis = 2)\n    res = pd.DataFrame(res_vals, columns=pcols)\n    \n    df = pd.concat([df,res], axis=1)\n    df['Id'] = df['Id'].astype(str) + '_' + df.index.astype(str)\n    submission.append(df[scols])\n    \nsubmission = pd.concat(submission)\nsubmission = pd.merge(sub[['Id']], submission, how='left', on='Id').fillna(0.0)\nsubmission[scols].to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}