{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":82611,"databundleVersionId":9553358,"sourceType":"competition"},{"sourceId":10019224,"sourceType":"datasetVersion","datasetId":6169262}],"dockerImageVersionId":30786,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip uninstall pandas -y\n!pip install 'pandas<2'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:39:34.188603Z","iopub.execute_input":"2024-11-26T11:39:34.189011Z","iopub.status.idle":"2024-11-26T11:39:59.336196Z","shell.execute_reply.started":"2024-11-26T11:39:34.188971Z","shell.execute_reply":"2024-11-26T11:39:59.334841Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:39:59.338579Z","iopub.execute_input":"2024-11-26T11:39:59.339023Z","iopub.status.idle":"2024-11-26T11:40:01.002914Z","shell.execute_reply.started":"2024-11-26T11:39:59.338984Z","shell.execute_reply":"2024-11-26T11:40:01.001403Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = pd.read_csv('/kaggle/input/brist1d/train.csv')\ndata.drop('id', axis=1, inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:01.004503Z","iopub.execute_input":"2024-11-26T11:40:01.00509Z","iopub.status.idle":"2024-11-26T11:40:17.186365Z","shell.execute_reply.started":"2024-11-26T11:40:01.005051Z","shell.execute_reply":"2024-11-26T11:40:17.185168Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data.info(show_counts=True,verbose = True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:17.188889Z","iopub.execute_input":"2024-11-26T11:40:17.189257Z","iopub.status.idle":"2024-11-26T11:40:19.094964Z","shell.execute_reply.started":"2024-11-26T11:40:17.189221Z","shell.execute_reply":"2024-11-26T11:40:19.09357Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Average missing data percent: ', np.mean(data.isnull().mean() * 100), '%')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:19.096375Z","iopub.execute_input":"2024-11-26T11:40:19.097477Z","iopub.status.idle":"2024-11-26T11:40:20.966971Z","shell.execute_reply.started":"2024-11-26T11:40:19.097414Z","shell.execute_reply":"2024-11-26T11:40:20.96557Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Get each specific unique feature as separate dataframe\ndef df_of_col (data, col):\n    df = pd.DataFrame()\n    for i in data.columns:\n        if (i.split('-')[0] == col) & (i  not in ['hr','bg+1:00','id','p_num']):\n            df[i] = data[i]\n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:20.968739Z","iopub.execute_input":"2024-11-26T11:40:20.969293Z","iopub.status.idle":"2024-11-26T11:40:20.976807Z","shell.execute_reply.started":"2024-11-26T11:40:20.96925Z","shell.execute_reply":"2024-11-26T11:40:20.975283Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Let's look at mising values and get a method to deal with them.","metadata":{}},{"cell_type":"code","source":"activity = df_of_col(data,'activity')\nactivity.sample(5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:20.978455Z","iopub.execute_input":"2024-11-26T11:40:20.978879Z","iopub.status.idle":"2024-11-26T11:40:21.638271Z","shell.execute_reply.started":"2024-11-26T11:40:20.978844Z","shell.execute_reply":"2024-11-26T11:40:21.63701Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"missing_percentage = activity.isnull().mean() * 100\nprint(f'Mean percentage for missing values is {np.mean(missing_percentage)}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:21.639671Z","iopub.execute_input":"2024-11-26T11:40:21.640121Z","iopub.status.idle":"2024-11-26T11:40:23.365098Z","shell.execute_reply.started":"2024-11-26T11:40:21.640085Z","shell.execute_reply":"2024-11-26T11:40:23.363843Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# We have 98% of missing value on average for activity columns, so let's just drop them.\ndata = data.drop(columns=activity.columns)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:23.366294Z","iopub.execute_input":"2024-11-26T11:40:23.366694Z","iopub.status.idle":"2024-11-26T11:40:23.610832Z","shell.execute_reply.started":"2024-11-26T11:40:23.366659Z","shell.execute_reply":"2024-11-26T11:40:23.609556Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"missing_percentage = df_of_col(data,'carbs').isnull().mean() * 100\nprint(f'Mean percentage for missing values is {np.mean(missing_percentage)}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:23.616276Z","iopub.execute_input":"2024-11-26T11:40:23.61688Z","iopub.status.idle":"2024-11-26T11:40:23.726948Z","shell.execute_reply.started":"2024-11-26T11:40:23.616722Z","shell.execute_reply":"2024-11-26T11:40:23.725833Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# We have 98% of missing value on average for carbs columns, so let's just drop them.\ndata = data.drop(columns=df_of_col(data,'carbs').columns)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:23.728274Z","iopub.execute_input":"2024-11-26T11:40:23.72865Z","iopub.status.idle":"2024-11-26T11:40:23.957343Z","shell.execute_reply.started":"2024-11-26T11:40:23.728615Z","shell.execute_reply":"2024-11-26T11:40:23.956148Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(15, 6))\nsns.heatmap(data.isnull(), cmap='viridis', cbar=False, yticklabels=False)\nplt.title('Тепловая карта пропущенных значений')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:40:23.959042Z","iopub.execute_input":"2024-11-26T11:40:23.959404Z","iopub.status.idle":"2024-11-26T11:41:26.573469Z","shell.execute_reply.started":"2024-11-26T11:40:23.95937Z","shell.execute_reply":"2024-11-26T11:41:26.572132Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Time-dependent features (e.g., bg-X:XX, insulin-X:XX) will require interpolation or forward/backward filling, based on time-series relationships\n\nParticipant-specific features (e.g., p_num, steps-X:XX, cals-X:XX, hr-X:XX) will be filled using participant-related data trends.\n","metadata":{}},{"cell_type":"code","source":"bg_columns = [col for col in data.columns if col.startswith('bg-')]\nhr_columns = [col for col in data.columns if col.startswith('hr-')]\nsteps_columns = [col for col in data.columns if col.startswith('steps-')]\n\n# Combine columns to process together\nfeature_columns = {\n    'bg': bg_columns,\n    'hr': hr_columns,\n    'steps': steps_columns\n}\n\n# Function to apply rolling, forward/backward fill, and group-based median imputation\ndef impute_time_series_features(df, columns, method='median', window=5):\n    for col in columns:\n        # Rolling mean or median imputation for temporal smoothing\n        df[col] = df[col].fillna(df[col].rolling(window=window, min_periods=1).median())\n        \n        # Forward fill for remaining nulls\n        df[col] = df[col].ffill()\n        \n        # Backward fill for any leading nulls\n        df[col] = df[col].bfill()\n        \n        # Group-based median for participant-specific imputation\n        df[col] = df.groupby('p_num')[col].transform(lambda x: x.fillna(x.median()))\n    return df\n\nfor feature, columns in feature_columns.items():\n    data = impute_time_series_features(data, columns)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:41:26.5752Z","iopub.execute_input":"2024-11-26T11:41:26.575708Z","iopub.status.idle":"2024-11-26T11:42:11.565006Z","shell.execute_reply.started":"2024-11-26T11:41:26.575654Z","shell.execute_reply":"2024-11-26T11:42:11.563782Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Identify all insulin and cals columns based on prefixes\ninsulin_columns = [col for col in data.columns if col.startswith('insulin-')]\ncals_columns = [col for col in data.columns if col.startswith('cals-')]\n\n# Combine columns to process together\nfeature_columns_insulin_cals = {\n    'insulin': insulin_columns,\n    'cals': cals_columns\n}\n\n# Function to apply group-based median and rolling median imputation for insulin and cals\ndef impute_non_temporal_features(df, columns, method='median', window=5):\n    for col in columns:\n        # Group-based median for participant-specific imputation\n        df[col] = df.groupby('p_num')[col].transform(lambda x: x.fillna(x.median()))\n        \n        # Rolling median for remaining nulls (temporal smoothing)\n        df[col] = df[col].fillna(df[col].rolling(window=window, min_periods=1).median())\n    return df\n\n# Apply imputation to insulin and cals columns in both datasets\nfor feature, columns in feature_columns_insulin_cals.items():\n    data = impute_non_temporal_features(data, columns, method='median')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:42:11.566436Z","iopub.execute_input":"2024-11-26T11:42:11.56682Z","iopub.status.idle":"2024-11-26T11:42:27.461314Z","shell.execute_reply.started":"2024-11-26T11:42:11.566787Z","shell.execute_reply":"2024-11-26T11:42:27.459769Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"target = data['bg+1:00']\nsns.distplot(target)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:42:27.463134Z","iopub.execute_input":"2024-11-26T11:42:27.463541Z","iopub.status.idle":"2024-11-26T11:42:28.660326Z","shell.execute_reply.started":"2024-11-26T11:42:27.463504Z","shell.execute_reply":"2024-11-26T11:42:28.658886Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data['time'] = pd.to_datetime(data['time'], format='%H:%M:%S', errors='coerce')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:42:28.66171Z","iopub.execute_input":"2024-11-26T11:42:28.662045Z","iopub.status.idle":"2024-11-26T11:42:28.703939Z","shell.execute_reply.started":"2024-11-26T11:42:28.662013Z","shell.execute_reply":"2024-11-26T11:42:28.702886Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = pd.get_dummies(data, columns=['p_num'], prefix='participant')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:42:28.705473Z","iopub.execute_input":"2024-11-26T11:42:28.705954Z","iopub.status.idle":"2024-11-26T11:42:29.431264Z","shell.execute_reply.started":"2024-11-26T11:42:28.705905Z","shell.execute_reply":"2024-11-26T11:42:29.429955Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(15, 6))\nsns.heatmap(data.isnull(), cmap='viridis', cbar=False, yticklabels=False)\nplt.title('Тепловая карта пропущенных значений')\nplt.show()\nprint('Average missing data percent: ', np.mean(data.isnull().mean() * 100), '%')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:42:29.432867Z","iopub.execute_input":"2024-11-26T11:42:29.433188Z","iopub.status.idle":"2024-11-26T11:43:37.765687Z","shell.execute_reply.started":"2024-11-26T11:42:29.433158Z","shell.execute_reply":"2024-11-26T11:43:37.762767Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Пропущенных значений больше нет, данные типизированы, приступим к построению модели.","metadata":{}},{"cell_type":"code","source":"%%capture\n!pip install -U lightautoml==0.3.8b1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:43:37.769521Z","iopub.execute_input":"2024-11-26T11:43:37.770904Z","iopub.status.idle":"2024-11-26T11:44:18.273198Z","shell.execute_reply.started":"2024-11-26T11:43:37.770536Z","shell.execute_reply":"2024-11-26T11:44:18.271448Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Standard python libraries\nimport os\nimport time\n\n# Essential DS libraries\nimport numpy as np\nimport pandas as pd\nfrom sklearn.metrics import mean_absolute_error, mean_squared_error\nfrom sklearn.model_selection import train_test_split\nimport torch\n\n# Visualising tools\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# LightAutoML presets, task and report generation\nfrom lightautoml.automl.presets.tabular_presets import TabularAutoML\nfrom lightautoml.tasks import Task","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:44:18.275556Z","iopub.execute_input":"2024-11-26T11:44:18.276158Z","iopub.status.idle":"2024-11-26T11:44:53.411277Z","shell.execute_reply.started":"2024-11-26T11:44:18.276104Z","shell.execute_reply":"2024-11-26T11:44:53.409796Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"N_THREADS = 4\nN_FOLDS = 5\nRANDOM_STATE = 42\nTEST_SIZE = 0.2\nTIMEOUT = 60 * 30 # equal to 30 minutes\nTARGET_NAME = 'bg+1:00'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:44:53.413039Z","iopub.execute_input":"2024-11-26T11:44:53.413791Z","iopub.status.idle":"2024-11-26T11:44:53.420129Z","shell.execute_reply.started":"2024-11-26T11:44:53.413753Z","shell.execute_reply":"2024-11-26T11:44:53.418662Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"np.random.seed(RANDOM_STATE)\ntorch.set_num_threads(N_THREADS)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:44:53.421905Z","iopub.execute_input":"2024-11-26T11:44:53.422371Z","iopub.status.idle":"2024-11-26T11:44:53.452391Z","shell.execute_reply.started":"2024-11-26T11:44:53.422317Z","shell.execute_reply":"2024-11-26T11:44:53.45096Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tr_data, te_data = train_test_split(\n    data, \n    test_size=TEST_SIZE, \n    random_state=RANDOM_STATE\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:44:53.454204Z","iopub.execute_input":"2024-11-26T11:44:53.454974Z","iopub.status.idle":"2024-11-26T11:44:54.089343Z","shell.execute_reply.started":"2024-11-26T11:44:53.454928Z","shell.execute_reply":"2024-11-26T11:44:54.088199Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"task = Task('reg', loss = 'mse', metric = 'mse')\nroles = {'target': TARGET_NAME,}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:44:54.090752Z","iopub.execute_input":"2024-11-26T11:44:54.091054Z","iopub.status.idle":"2024-11-26T11:44:54.099491Z","shell.execute_reply.started":"2024-11-26T11:44:54.091026Z","shell.execute_reply":"2024-11-26T11:44:54.098124Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = data.dropna(subset=['bg+1:00'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:44:54.100917Z","iopub.execute_input":"2024-11-26T11:44:54.102059Z","iopub.status.idle":"2024-11-26T11:44:54.32199Z","shell.execute_reply.started":"2024-11-26T11:44:54.101996Z","shell.execute_reply":"2024-11-26T11:44:54.320673Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test = pd.read_csv('/kaggle/input/brist1d/test.csv')\ntest.drop('id', axis=1, inplace=True)\ntest = test.drop(columns=activity.columns)\ntest = test.drop(columns=df_of_col(data,'carbs').columns)\n\nfor feature, columns in feature_columns.items():\n    test = impute_time_series_features(test, columns)\n\nfor feature, columns in feature_columns_insulin_cals.items():\n    test = impute_non_temporal_features(test, columns, method='median')\n    \ntest['time'] = pd.to_datetime(test['time'], format='%H:%M:%S', errors='coerce')\ntest = pd.get_dummies(test, columns=['p_num'], prefix='participant')\n# Align columns between train and test to ensure both have the same structure\ndata, test = data.align(test, join='outer', axis=1, fill_value=0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:44:54.324295Z","iopub.execute_input":"2024-11-26T11:44:54.324866Z","iopub.status.idle":"2024-11-26T11:44:59.249955Z","shell.execute_reply.started":"2024-11-26T11:44:54.324811Z","shell.execute_reply":"2024-11-26T11:44:59.248577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"automl = TabularAutoML(\n    task = task, \n    timeout = TIMEOUT,\n    cpu_limit = N_THREADS,\n    reader_params = {'n_jobs': N_THREADS, 'cv': N_FOLDS, 'random_state': RANDOM_STATE})\nautoml.fit_predict(data, roles = roles, verbose = 4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T11:44:59.25157Z","iopub.execute_input":"2024-11-26T11:44:59.251988Z","iopub.status.idle":"2024-11-26T12:05:47.647221Z","shell.execute_reply.started":"2024-11-26T11:44:59.251951Z","shell.execute_reply":"2024-11-26T12:05:47.645829Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred = automl.predict(data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T12:05:47.653864Z","iopub.execute_input":"2024-11-26T12:05:47.65426Z","iopub.status.idle":"2024-11-26T12:06:15.955872Z","shell.execute_reply.started":"2024-11-26T12:05:47.654227Z","shell.execute_reply":"2024-11-26T12:06:15.954788Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f'TRAIN rmse: {mean_squared_error(data[TARGET_NAME].values, pred.data.reshape(-1))**0.5}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T12:06:15.956959Z","iopub.execute_input":"2024-11-26T12:06:15.957296Z","iopub.status.idle":"2024-11-26T12:06:15.97156Z","shell.execute_reply.started":"2024-11-26T12:06:15.957263Z","shell.execute_reply":"2024-11-26T12:06:15.97008Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"output = pd.read_csv('/kaggle/input/brist1d/sample_submission.csv')\n#output.drop('bg+1:00', axis=1, inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T12:06:15.973463Z","iopub.execute_input":"2024-11-26T12:06:15.974065Z","iopub.status.idle":"2024-11-26T12:06:16.002462Z","shell.execute_reply.started":"2024-11-26T12:06:15.974009Z","shell.execute_reply":"2024-11-26T12:06:16.000748Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_pred = automl.predict(test)\noutput['bg+1:00'] = test_pred.data.reshape(-1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T12:11:24.265166Z","iopub.execute_input":"2024-11-26T12:11:24.265743Z","iopub.status.idle":"2024-11-26T12:11:25.845185Z","shell.execute_reply.started":"2024-11-26T12:11:24.265701Z","shell.execute_reply":"2024-11-26T12:11:25.844178Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"output.to_csv('submission.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-26T12:25:09.404672Z","iopub.execute_input":"2024-11-26T12:25:09.405948Z","iopub.status.idle":"2024-11-26T12:25:09.508742Z","shell.execute_reply.started":"2024-11-26T12:25:09.405878Z","shell.execute_reply":"2024-11-26T12:25:09.50685Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}