{"metadata":{"kernelspec":{"display_name":"child_mind_inst","language":"python","name":"child_mind_inst"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.7"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":81933,"databundleVersionId":9643020,"sourceType":"competition"}],"dockerImageVersionId":30804,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport os\npd.set_option('display.max_columns', None)\nworking_dir = '/kaggle/input/child-mind-institute-problematic-internet-use/'\noutput_dir = '/kaggle/working/'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:22.872035Z","iopub.execute_input":"2024-12-13T01:23:22.872462Z","iopub.status.idle":"2024-12-13T01:23:22.878271Z","shell.execute_reply.started":"2024-12-13T01:23:22.872426Z","shell.execute_reply":"2024-12-13T01:23:22.877108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(working_dir + 'train.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:22.880161Z","iopub.execute_input":"2024-12-13T01:23:22.880525Z","iopub.status.idle":"2024-12-13T01:23:22.935592Z","shell.execute_reply.started":"2024-12-13T01:23:22.880492Z","shell.execute_reply":"2024-12-13T01:23:22.934382Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Dealing with season data\n# Method 1: Dropping\n# df = df.loc[: ,~df.columns.str.contains('season', case=False)]\n\n# Method 2: Encoding\ndisplay(df.head().select_dtypes(exclude='number'))\n\nseason_cols = df.select_dtypes(exclude='number').columns\nseason_cols = [col for col in season_cols if 'id' not in col]\n\n# Encode\nseason_mapping = {\n    'Spring' : 1,\n    'Sumemr' : 2,\n    'Fall'   : 3,\n    'Winter' : 4\n}\n\nfor col in season_cols:\n    df[col] = df[col].apply(lambda x : np.uint8(season_mapping.get(x, 0))).astype(int)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:24.226318Z","iopub.execute_input":"2024-12-13T01:23:24.226660Z","iopub.status.idle":"2024-12-13T01:23:24.579408Z","shell.execute_reply.started":"2024-12-13T01:23:24.226624Z","shell.execute_reply":"2024-12-13T01:23:24.578281Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Trim column by sii and pciat\ndf = df.drop(columns=['id'])\npciat_columns = [col for col in df.columns if col.split(sep='-')[0] == 'PCIAT']\npciat_columns.append('sii')\ndf = df.dropna(subset=pciat_columns)\ndf = df.dropna(subset='sii')\ndf.head(5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:24.581744Z","iopub.execute_input":"2024-12-13T01:23:24.582093Z","iopub.status.idle":"2024-12-13T01:23:24.654376Z","shell.execute_reply.started":"2024-12-13T01:23:24.582060Z","shell.execute_reply":"2024-12-13T01:23:24.653066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Dropping all data with > 40% missing ratio\ndropped_cols = []\ncolumns = df.columns\nfor col in columns:\n    missing_ratio = df[col].isna().sum() / len(df)\n    if missing_ratio > 0.4:\n        df = df.drop(columns=col)\n        dropped_cols.append(col)\n\nprint('Dropped: ')\nprint(dropped_cols)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:24.655883Z","iopub.execute_input":"2024-12-13T01:23:24.656328Z","iopub.status.idle":"2024-12-13T01:23:24.687784Z","shell.execute_reply.started":"2024-12-13T01:23:24.656284Z","shell.execute_reply":"2024-12-13T01:23:24.686593Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_columns = [col for col in df.columns if \n              (col.split(sep='-')[0] != 'PCIAT' and col.split(sep='-')[0] != 'sii'\n                  and col != 'id'\n              )\n          ]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:24.689150Z","iopub.execute_input":"2024-12-13T01:23:24.689552Z","iopub.status.idle":"2024-12-13T01:23:24.695588Z","shell.execute_reply.started":"2024-12-13T01:23:24.689514Z","shell.execute_reply":"2024-12-13T01:23:24.694513Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# General quantile capping\nfeature_cap = {}\nfor col in num_columns:\n    if col == 'id':\n        continue\n    feature_cap[col] = {\n        'lower': df[col].quantile(0.01),\n        'upper': df[col].quantile(0.99)\n    }\n    df[col] = df[col].clip(df[col].quantile(0.01), df[col].quantile(0.99))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:24.696952Z","iopub.execute_input":"2024-12-13T01:23:24.697347Z","iopub.status.idle":"2024-12-13T01:23:24.875126Z","shell.execute_reply.started":"2024-12-13T01:23:24.697311Z","shell.execute_reply":"2024-12-13T01:23:24.874101Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Considering all Physical and BIA data that are <= less than or equal to 0 are errors\n# we will replace it with NaN then impute (Age too)\nphysical_columns = [col for col in df.columns if col.split(sep='-')[0] == 'Physical']\nBIA_columns = [col for col in df.columns if col.split(sep='-')[0] == 'BIA']\ndf[df['Basic_Demos-Age'] == 0] = np.nan\ndf[df[physical_columns + BIA_columns] <= 0] = np.nan","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:24.876362Z","iopub.execute_input":"2024-12-13T01:23:24.876677Z","iopub.status.idle":"2024-12-13T01:23:24.921153Z","shell.execute_reply.started":"2024-12-13T01:23:24.876646Z","shell.execute_reply":"2024-12-13T01:23:24.920122Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Method 1 Using KNN imputer\nfrom sklearn.impute import KNNImputer\nfrom sklearn.impute import SimpleImputer\n\n# Divide into 5 cluster corresponding to 5 groups of PCIAT\n\n# 5 is an intuitive guess, need to find optimal number of k-neighbours later.\nimputer = KNNImputer(\n    n_neighbors=5\n)\n\nfeature_columns = [col for col in df.columns if \n                      col not in pciat_columns and\n                      col != 'sii' and\n                      col != 'id'\n                 ]\n\nX = np.array(df[feature_columns])\nX_imputed = imputer.fit_transform(X)\ndf[feature_columns] = X_imputed","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:24.922352Z","iopub.execute_input":"2024-12-13T01:23:24.922670Z","iopub.status.idle":"2024-12-13T01:23:26.497182Z","shell.execute_reply.started":"2024-12-13T01:23:24.922637Z","shell.execute_reply":"2024-12-13T01:23:26.496054Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# TODO:\n# Dimension reduciton\n# Over sampling\n# Stacking models\n# https://www.analyticsvidhya.com/blog/2021/06/5-techniques-to-handle-imbalanced-data-for-a-classification-problem/\n# Build another RF/XGB classifier with Oversampling to complement the current model in terms of predicint labels 2, 3","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:26.500319Z","iopub.execute_input":"2024-12-13T01:23:26.500681Z","iopub.status.idle":"2024-12-13T01:23:26.505372Z","shell.execute_reply.started":"2024-12-13T01:23:26.500638Z","shell.execute_reply":"2024-12-13T01:23:26.504243Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.ensemble import RandomForestClassifier\nfrom sklearn.ensemble import GradientBoostingClassifier\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import cohen_kappa_score\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.metrics import make_scorer\nfrom sklearn.model_selection import GridSearchCV\nfrom xgboost import XGBClassifier","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:26.507079Z","iopub.execute_input":"2024-12-13T01:23:26.507590Z","iopub.status.idle":"2024-12-13T01:23:26.522321Z","shell.execute_reply.started":"2024-12-13T01:23:26.507544Z","shell.execute_reply":"2024-12-13T01:23:26.520977Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Model 1: Random forest\nX = df[feature_columns]\nY = df['sii']\n\nX_train, X_val, Y_train, Y_val = train_test_split(X, Y, train_size=0.8, test_size=0.2, stratify=Y)\nkappa_scorer = make_scorer(cohen_kappa_score, weights='quadratic')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:26.523758Z","iopub.execute_input":"2024-12-13T01:23:26.524228Z","iopub.status.idle":"2024-12-13T01:23:26.542387Z","shell.execute_reply.started":"2024-12-13T01:23:26.524159Z","shell.execute_reply":"2024-12-13T01:23:26.541253Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Using grid search\nrf_param = {\n        'n_estimators': [120],\n        'max_depth'   : [6],\n        'random_state': [42],\n        'bootstrap'   : [True],\n        'criterion'   : ['entropy'],\n        'max_features': [None, 'sqrt', 'log2'],\n        'class_weight': ['balanced'],\n}\n\nforest = GridSearchCV(RandomForestClassifier(), rf_param, scoring=kappa_scorer, cv=10, verbose=3)\nforest.fit(X_train, Y_train)","metadata":{"scrolled":true,"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:23:26.543690Z","iopub.execute_input":"2024-12-13T01:23:26.544161Z","iopub.status.idle":"2024-12-13T01:24:27.885665Z","shell.execute_reply.started":"2024-12-13T01:23:26.544114Z","shell.execute_reply":"2024-12-13T01:24:27.884419Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"forest.best_params_\n\n# 0.39 kappa\n# {'bootstrap': True,\n#  'class_weight': 'balanced',\n#  'criterion': 'entropy',\n#  'max_depth': 6,\n#  'max_features': None,\n#  'n_estimators': 100,\n#  'random_state': 42}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:24:27.887154Z","iopub.execute_input":"2024-12-13T01:24:27.888188Z","iopub.status.idle":"2024-12-13T01:24:27.895417Z","shell.execute_reply.started":"2024-12-13T01:24:27.888137Z","shell.execute_reply":"2024-12-13T01:24:27.894266Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_for_validation = forest\nplt.figure(figsize=(3,3))\nsns.heatmap(confusion_matrix(Y_train, model_for_validation.predict(X_train)), annot=True, cmap='viridis')\ncohen_kappa_score(Y_train, model_for_validation.predict(X_train), weights='quadratic')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:24:27.896988Z","iopub.execute_input":"2024-12-13T01:24:27.897465Z","iopub.status.idle":"2024-12-13T01:24:28.231105Z","shell.execute_reply.started":"2024-12-13T01:24:27.897417Z","shell.execute_reply":"2024-12-13T01:24:28.229999Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Problem class 3 always get wrong prediction\n# Class 2 get misclassified alot with class \n\n# Class accuracy improved with balanced weight but same problem still persist\nY_pred = model_for_validation.predict(X_val)\nplt.figure(figsize=(3,3))\nsns.heatmap(confusion_matrix(Y_val, Y_pred), annot=True, cmap='viridis')\ncohen_kappa_score(Y_val, Y_pred, weights='quadratic')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:24:28.232631Z","iopub.execute_input":"2024-12-13T01:24:28.233039Z","iopub.status.idle":"2024-12-13T01:24:28.540218Z","shell.execute_reply.started":"2024-12-13T01:24:28.232998Z","shell.execute_reply":"2024-12-13T01:24:28.538983Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<h1>Submission</h1>","metadata":{}},{"cell_type":"code","source":"# Model 1 pipeline\n# Load data\ntest_df = pd.read_csv(working_dir + 'test.csv')\n                 \ndef transform(test_df):\n    # Drop text features\n    test_df = test_df.drop(dropped_cols, axis=1)\n    # test_df = test_df.loc[: ,~test_df.columns.str.contains('season', case=False)]\n\n\n    for col in season_cols:\n        if col in dropped_cols or col == 'PCIAT-Season':\n            continue\n        test_df[col] = test_df[col].apply(lambda x : np.uint8(season_mapping.get(x, 0)).astype(int))\n\n    # Get numeric columns\n    num_columns = [col for col in test_df.columns if \n                      (col.split(sep='-')[0] != 'PCIAT' and col.split(sep='-')[0] != 'sii' and col != 'id')\n                  ]\n\n    # Value capping, use specific cap values acquired from training quantile capping\n    for col in num_columns:\n        if col == 'id':\n            continue\n        test_df[col] = test_df[col].clip(feature_cap[col]['lower'], feature_cap[col]['upper'])\n        \n    # Considering all Physical and BIA data that are <= less than or equal to 0 are errors\n    # we will replace it with NaN then impute (Age too)\n    physical_columns = [col for col in test_df.columns if col.split(sep='-')[0] == 'Physical']\n    BIA_columns = [col for col in test_df.columns if col.split(sep='-')[0] == 'BIA']\n    test_df[test_df['Basic_Demos-Age'] == 0] = np.nan\n    test_df[test_df[physical_columns + BIA_columns] <= 0] = np.nan\n\n\n    imputer = KNNImputer(\n        n_neighbors=5\n    )\n    \n    feature_columns = [col for col in test_df.columns if col != 'id']\n    \n    X = np.array(test_df[feature_columns])\n    X_imputed = imputer.fit_transform(X)\n    test_df[feature_columns] = X_imputed\n\n    return test_df\n\ntest_df = transform(test_df)\nX_test = test_df.drop(columns=['id'])\npred = forest.predict(X_test)\n","metadata":{"scrolled":true,"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:24:28.541682Z","iopub.execute_input":"2024-12-13T01:24:28.542048Z","iopub.status.idle":"2024-12-13T01:24:28.669526Z","shell.execute_reply.started":"2024-12-13T01:24:28.542014Z","shell.execute_reply":"2024-12-13T01:24:28.668173Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"output = pd.DataFrame({'id': test_df.id, 'sii': pred})\noutput.to_csv(output_dir + 'submission.csv', sep=',', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-13T01:24:28.670972Z","iopub.execute_input":"2024-12-13T01:24:28.671342Z","iopub.status.idle":"2024-12-13T01:24:28.678990Z","shell.execute_reply.started":"2024-12-13T01:24:28.671308Z","shell.execute_reply":"2024-12-13T01:24:28.677753Z"}},"outputs":[],"execution_count":null}]}