{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"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.3"},"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":"markdown","source":"### Import library","metadata":{}},{"cell_type":"code","source":"\nimport numpy as np\nimport pandas as pd\nimport os\nimport re\nimport torch.nn.functional as F\nfrom colorama import Fore, Style\nfrom sklearn.base import clone, BaseEstimator, RegressorMixin\nfrom sklearn.metrics import cohen_kappa_score, accuracy_score, mean_squared_error\nfrom sklearn.model_selection import StratifiedKFold, train_test_split\nfrom sklearn.decomposition import PCA\nfrom sklearn.datasets import make_classification\nfrom scipy.optimize import minimize\nfrom concurrent.futures import ThreadPoolExecutor\nfrom tqdm import tqdm\n\nfrom sklearn.preprocessing import StandardScaler\nimport matplotlib.pyplot as plt\nfrom keras.models import Model\nfrom keras.layers import Input, Dense\nfrom keras.optimizers import Adam\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\n\nfrom IPython.display import clear_output\nimport warnings\nfrom lightgbm import LGBMRegressor\nfrom xgboost import XGBRegressor\nfrom catboost import CatBoostRegressor\nfrom sklearn.ensemble import VotingRegressor, RandomForestRegressor, GradientBoostingRegressor\nfrom sklearn.impute import SimpleImputer, KNNImputer\nfrom sklearn.pipeline import Pipeline\nimport random\nfrom pytorch_tabnet.tab_model import TabNetRegressor\nfrom sklearn.base import BaseEstimator, RegressorMixin\nfrom sklearn.model_selection import train_test_split\nfrom pytorch_tabnet.callbacks import Callback\nimport os\nimport torch\n","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Environment Initialization and Reproducibility Setup\nSetting a fixed seed for reproducibility across Python, NumPy, and PyTorch, ensuring consistent results in machine learning experiments.","metadata":{}},{"cell_type":"code","source":"\nwarnings.filterwarnings('ignore')\npd.options.display.max_columns = None\nSEED = 42\nn_splits = 5\n\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\nseed_everything(2024)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ntrain_featuresCols = ['Basic_Demos-Age', 'Basic_Demos-Sex',\n                'CGAS-CGAS_Score', 'Physical-BMI',\n                'Physical-Height', 'Physical-Weight', 'Physical-Waist_Circumference',\n                'Physical-Diastolic_BP', 'Physical-HeartRate', 'Physical-Systolic_BP',\n                'FGC-FGC_CU', 'FGC-FGC_CU_Zone', 'FGC-FGC_PU',\n                'FGC-FGC_PU_Zone', 'FGC-FGC_SRL', 'FGC-FGC_SRL_Zone', 'FGC-FGC_SRR',\n                'FGC-FGC_SRR_Zone', 'FGC-FGC_TL', 'FGC-FGC_TL_Zone',\n                'BIA-BIA_Activity_Level_num', 'BIA-BIA_BMC', 'BIA-BIA_BMI',\n                'BIA-BIA_BMR', 'BIA-BIA_DEE', 'BIA-BIA_ECW', 'BIA-BIA_FFM',\n                'BIA-BIA_FFMI', 'BIA-BIA_FMI', 'BIA-BIA_Fat', 'BIA-BIA_Frame_num',\n                'BIA-BIA_ICW', 'BIA-BIA_LDM', 'BIA-BIA_LST', 'BIA-BIA_SMM',\n                'BIA-BIA_TBW', 'SDS-SDS_Total_Raw',\n                'SDS-SDS_Total_T',\n                'PreInt_EduHx-computerinternet_hoursday', 'sii', 'BMI_Age','Internet_Hours_Age','BMI_Internet_Hours',\n                'BFP_BMI', 'FFMI_BFP', 'FMI_BFP', 'LST_TBW', 'BFP_BMR', 'BFP_DEE', 'BMR_Weight', 'DEE_Weight',\n                'SMM_Height', 'Muscle_to_Fat', 'Hydration_Status', 'ICW_TBW', 'BMI_PHR']\n\ntest_featuresCols = ['Basic_Demos-Age', 'Basic_Demos-Sex',\n                'CGAS-CGAS_Score', 'Physical-BMI',\n                'Physical-Height', 'Physical-Weight', 'Physical-Waist_Circumference',\n                'Physical-Diastolic_BP', 'Physical-HeartRate', 'Physical-Systolic_BP',\n                'FGC-FGC_CU', 'FGC-FGC_CU_Zone', 'FGC-FGC_PU',\n                'FGC-FGC_PU_Zone', 'FGC-FGC_SRL', 'FGC-FGC_SRL_Zone', 'FGC-FGC_SRR',\n                'FGC-FGC_SRR_Zone', 'FGC-FGC_TL', 'FGC-FGC_TL_Zone',\n                'BIA-BIA_Activity_Level_num', 'BIA-BIA_BMC', 'BIA-BIA_BMI',\n                'BIA-BIA_BMR', 'BIA-BIA_DEE', 'BIA-BIA_ECW', 'BIA-BIA_FFM',\n                'BIA-BIA_FFMI', 'BIA-BIA_FMI', 'BIA-BIA_Fat', 'BIA-BIA_Frame_num',\n                'BIA-BIA_ICW', 'BIA-BIA_LDM', 'BIA-BIA_LST', 'BIA-BIA_SMM',\n                'BIA-BIA_TBW', 'SDS-SDS_Total_Raw',\n                'SDS-SDS_Total_T',\n                'PreInt_EduHx-computerinternet_hoursday', 'BMI_Age','Internet_Hours_Age','BMI_Internet_Hours',\n                'BFP_BMI', 'FFMI_BFP', 'FMI_BFP', 'LST_TBW', 'BFP_BMR', 'BFP_DEE', 'BMR_Weight', 'DEE_Weight',\n                'SMM_Height', 'Muscle_to_Fat', 'Hydration_Status', 'ICW_TBW', 'BMI_PHR']\n","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Additional Feature Calculation for Time series data\nTo computes additional features related to nocturnal, weekend, and weekend night activities from sensor data.\n\n- Feature 'enmoXlight' for focusing on the relationship between physical activity and light as an indirect indicator. 'enmo * light' could be used to assess whether physical activity levels (enmo) in certain light conditions (light) are associated with internet usage habits. For example, low light combined with minimal physical activity might indicate prolonged internet usage, such as when someone sits indoors in front of a computer or phone screen.\n\n- Feature 'is_night': Nighttime is outside the range of 8 AM to 9 PM.\n- Feature 'is_weekend': Weekend days are Saturday (5.5) and Sunday (6).\n- Feature 'is_weekend_night': Combination of weekend and nighttime conditions.\n","metadata":{}},{"cell_type":"code","source":"extra_feature_cols = [\n    'night_enmo_mean','night_enmo_max','night_light_mean','night_light_max','night_enmoXlight_mean','night_enmoXlight_max',\n    'weekend_enmo_mean','weekend_enmo_max','weekend_light_mean','weekend_light_max','weekend_enmoXlight_mean','weekend_enmoXlight_max',\n    'weekend_night_enmo_mean','weekend_night_enmo_max','weekend_night_light_mean','weekend_night_light_max','weekend_night_enmoXlight_mean','weekend_night_enmoXlight_max',\n]\n\ndef time_features(df):\n    \"\"\"\n    Tính các đặc trưng hoạt động (ban đêm, cuối tuần, cuối tuần ban đêm) dựa trên:\n      - cột 'enmo', 'light', 'time_of_day', 'weekday'\n    Trả về danh sách (list) các giá trị đặc trưng.\n    \"\"\"\n\n    df[\"enmo\"] = df[\"enmo\"].rolling(window=10, min_periods=1).mean()\n    df[\"light\"] = df[\"light\"].rolling(window=10, min_periods=1).mean()\n    df['enmoXlight'] = df['enmo'] * df['light']\n\n\n    df[\"time_of_day_hours\"] = df[\"time_of_day\"] // (3_600 * 1_000_000_000)\n\n    features = []\n\n    def compute_features(condition_col, threshold, prefix):\n        \"\"\"\n        - condition_col: cột boolean (0/1) như is_night, is_weekend, ...\n        - threshold: số mẫu tối thiểu để chấp nhận.\n        - prefix: tiền tố cho tên cột (night, weekend, weekend_night).\n        \"\"\"\n\n        df[condition_col] = (df[condition_col].diff() == 1).cumsum() * df[condition_col]\n        df.loc[df[condition_col] > 0, condition_col] = 1\n\n\n        group_des = (\n            df.groupby(condition_col)[['enmo', 'light', 'enmoXlight']]\n              .agg({\n                  'enmo': ['mean','max','count'],\n                  'light': ['mean','max'],\n                  'enmoXlight': ['mean','max']\n              })\n              .reset_index()\n        )\n\n        group_des = group_des[group_des[condition_col] > 0].reset_index(drop=True)\n        \n\n        group_des.columns = [\n            condition_col,\n            f'{prefix}_enmo_mean', f'{prefix}_enmo_max', f'{prefix}_enmo_count',\n            f'{prefix}_light_mean', f'{prefix}_light_max',\n            f'{prefix}_enmoXlight_mean', f'{prefix}_enmoXlight_max'\n        ]\n        \n\n        group_des = group_des[group_des[f'{prefix}_enmo_count'] > threshold]\n        if len(group_des) == 0:\n          \n            return [np.nan] * 6  \n        \n\n        vals = group_des.drop([condition_col, f'{prefix}_enmo_count'], axis=1).mean(axis=0).values\n        return list(vals)\n\n\n    df['is_night'] = np.where((df['time_of_day_hours'] >= 8) & (df['time_of_day_hours'] < 21), 0, 1)\n    features.extend(compute_features('is_night', threshold=500, prefix='night'))\n\n    df['is_weekend'] = np.where(df['weekday'] >= 5.5, 1, 0)\n    features.extend(compute_features('is_weekend', threshold=2000, prefix='weekend'))\n\n    df['is_weekend_night'] = np.where(\n        (df['weekday'] >= 5.5) & ((df['time_of_day_hours'] < 8) | (df['time_of_day_hours'] >= 21)),\n        1, 0\n    )\n    features.extend(compute_features('is_weekend_night', threshold=200, prefix='weekend_night'))\n\n    return features","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_file(file_name, parquet_dir):\n    \"\"\"\n    Đọc file parquet, trả về (tf_list, desc_list, file_id).\n      - tf_list: time_features (list)\n      - desc_list: thống kê describe() (list)\n      - file_id: ID trích từ tên file\n    Nếu lỗi hoặc file không tồn tại -> (None, None, None).\n    \"\"\"\n    file_path = os.path.join(parquet_dir, file_name, 'part-0.parquet')\n    if not os.path.exists(file_path):\n        return None, None, None\n\n    df = pd.read_parquet(file_path)\n    if 'step' in df.columns:\n        df.drop('step', axis=1, inplace=True)\n\n    tf_list = time_features(df)  \n\n    desc_list = df.describe().values.reshape(-1)\n\n    try:\n        file_id = file_name.split('=')[1]\n    except:\n        file_id = file_name \n    return tf_list, desc_list, file_id\n","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_time_series(dirname):\n    \"\"\"\n    Duyệt qua các file/folder trong dirname, xử lý song song.\n    Mỗi file được đọc, tính:\n      - time_features -> tf_list\n      - describe() -> desc_list\n    Kết quả: Trả về (df_time, df_desc).\n    \"\"\"\n    ids = os.listdir(dirname)\n    \n    with ThreadPoolExecutor(max_workers=8) as executor:\n        results = list(\n            tqdm(executor.map(lambda fname: process_file(fname, dirname), ids), total=len(ids))\n        )\n\n\n    valid_results = [(tf, ds, i) for tf, ds, i in results if tf is not None and ds is not None and i is not None]\n    if len(valid_results) == 0:\n\n        return pd.DataFrame(), pd.DataFrame()\n\n\n    time_feat_lists, desc_lists, indexes = zip(*valid_results)\n\n    df_time = pd.DataFrame(time_feat_lists, columns=extra_feature_cols)\n    df_time['id'] = indexes\n\n   \n    desc_len = len(desc_lists[0])\n    desc_cols = [f\"stat_{i}\" for i in range(desc_len)]\n\n    df_desc = pd.DataFrame(desc_lists, columns=desc_cols)\n    df_desc['id'] = indexes\n\n    return df_time, df_desc\n","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ntrain = pd.read_csv('/kaggle/input/child-mind-institute-problematic-internet-use/train.csv')\ntest = pd.read_csv('/kaggle/input/child-mind-institute-problematic-internet-use/test.csv')\nsample = pd.read_csv('/kaggle/input/child-mind-institute-problematic-internet-use/sample_submission.csv')\n\ntrain_ts_time_features, train_ts = load_time_series(\"/kaggle/input/child-mind-institute-problematic-internet-use/series_train.parquet\")\ntest_ts_time_features, test_ts = load_time_series(\"/kaggle/input/child-mind-institute-problematic-internet-use/series_test.parquet\")","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"This code snippet adjusts the sii column for specific rows in the dataset based on a predefined list of IDs. The list of IDs was determined manually after filtering the dataset in Excel.\nThe logic assumes that if the 'PCIAT-PCIAT_Total' value is less than 5 and some PCIAT-PCIAT_* columns have missing values, the response (sii) is invalid and should be set to None.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\n# nếu mà giá trị PCIAT-PCIAT_Total < 5 và một vài PCIAT-PCIAT còn lại bị missing thì sii  = None vì người trả lời trả lời không chính xác \nids_to_update = ['18fdbccc', '053d7d31', '39dd3538', '68fa4631', '6a98537b', '6b9a25e6', '75311a3f', '926bd07e', 'fc8e4de4']\ntrain.loc[train['id'].isin(ids_to_update), 'sii'] = None","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.dropna(subset=['sii'], inplace=True)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"This code uses KNN imputation to fill missing values in specific PCIAT-PCIAT_* columns for rows where sii is not missing. The imputed values are rounded, updated in the dataset, and a new total score, PCIAT-PCIAT_Total_new, is calculated as the sum of these columns.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.impute import KNNImputer\n\ncolumns_to_impute = [\n    'PCIAT-PCIAT_06', 'PCIAT-PCIAT_01', 'PCIAT-PCIAT_15', 'PCIAT-PCIAT_07',\n    'PCIAT-PCIAT_16', 'PCIAT-PCIAT_12', 'PCIAT-PCIAT_09', 'PCIAT-PCIAT_11',\n    'PCIAT-PCIAT_19', 'PCIAT-PCIAT_08', 'PCIAT-PCIAT_17', 'PCIAT-PCIAT_14',\n    'PCIAT-PCIAT_04', 'PCIAT-PCIAT_20', 'PCIAT-PCIAT_03', 'PCIAT-PCIAT_02',\n    'PCIAT-PCIAT_18', 'PCIAT-PCIAT_13', 'PCIAT-PCIAT_10', 'PCIAT-PCIAT_05'\n]\n\ndf_non_nan_sii = train[train['sii'].notna()]\n\nknn_imputer = KNNImputer(n_neighbors=10)\n\nimputed_data = knn_imputer.fit_transform(df_non_nan_sii[columns_to_impute])\n\nimputed_data = imputed_data.round()\n\ntrain.loc[train['sii'].notna(), columns_to_impute] = imputed_data\n\ntrain['PCIAT-PCIAT_Total_new'] = train[columns_to_impute].sum(axis=1)\n","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"This code recalculates the sii values based on the PCIAT-PCIAT_Total score and updates the dataset with the new classification logic:\n\nIf PCIAT-PCIAT_Total is missing, new_sii is set to NaN.\n\nIf the score is ≤ 30, new_sii is 0.\n\nIf the score is between 31 and 49, new_sii is 1.\n\nIf the score is between 50 and 79, new_sii is 2.\n\nIf the score is ≥ 80, new_sii is 3.","metadata":{}},{"cell_type":"code","source":"\ndef recalculate_sii(row):\n    if pd.isna(row['PCIAT-PCIAT_Total']):\n        return np.nan\n    if row['PCIAT-PCIAT_Total'] <= 30:\n        return 0\n    elif 31 <= row['PCIAT-PCIAT_Total'] <= 49:\n        return 1\n    elif 50 <= row['PCIAT-PCIAT_Total'] <= 79:\n        return 2\n    elif row['PCIAT-PCIAT_Total'] >= 80:\n        return 3\n    return np.nan\n\ntrain['new_sii'] = train.apply(recalculate_sii, axis=1)\n\n","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train['sii'] = train['new_sii']\ntrain.drop(['new_sii'], axis=1, inplace=True)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Using an autoencoder to reduce the dimensionality of time-series data for both training and testing datasets.\n\n\n### AutoEncoder Class\nEncoder: Compresses input data into a lower-dimensional space using a series of linear layers and activation functions (LeakyReLU).\n\nDecoder: Reconstructs the input data from the compressed representation, aiming to minimize the difference (loss) between the original and reconstructed data. The final activation function is a Sigmoid to normalize the output between 0 and 1.\n\nScaling: Standardizes the data using StandardScaler.\n\nTraining: Uses Mean Squared Error (MSE) as the loss function and Adam optimizer.\n","metadata":{}},{"cell_type":"code","source":"\nclass AutoEncoder(nn.Module):\n    def __init__(self, input_dim, encoding_dim):\n        super(AutoEncoder, self).__init__()\n        self.encoder = nn.Sequential(\n            nn.Linear(input_dim, encoding_dim*3),\n            nn.LeakyReLU(),\n            nn.Linear(encoding_dim*3, encoding_dim*2+10),\n            nn.LeakyReLU(),\n            nn.Linear(encoding_dim*2+10, encoding_dim),\n            nn.LeakyReLU()\n        )\n\n        self.decoder = nn.Sequential(\n            nn.Linear(encoding_dim, encoding_dim+15),\n            nn.LeakyReLU(),\n            nn.Linear(encoding_dim+15, encoding_dim*3),\n            nn.LeakyReLU(),\n            nn.Linear(encoding_dim*3, input_dim),\n            nn.Sigmoid()\n        )\n    def forward(self, x):\n        encoded = self.encoder(x)\n        decoded = self.decoder(encoded)\n        return decoded\n\n\n# encoder du lieu\ndef autoencoder(df, encoding_dim=50, epochs=50, batch_size=32):\n    scaler = StandardScaler()\n    df_scaled = scaler.fit_transform(df)\n    \n    data_tensor = torch.FloatTensor(df_scaled)\n    \n    input_dim = data_tensor.shape[1]\n    autoencoder = AutoEncoder(input_dim, encoding_dim)\n    \n    criterion = nn.MSELoss()\n    optimizer = optim.Adam(autoencoder.parameters())\n    \n    for epoch in range(epochs):\n        for i in range(0, len(data_tensor), batch_size):\n            batch = data_tensor[i : i + batch_size]\n            optimizer.zero_grad()\n            reconstructed = autoencoder(batch)\n            loss = criterion(reconstructed, batch)\n            loss.backward()\n            optimizer.step()\n            \n        if (epoch + 1) % 10 == 0:\n            print(f'Epoch [{epoch + 1}/{epochs}], Loss: {loss.item():.4f}]')\n\n    with torch.no_grad():\n        encoded_data = autoencoder.encoder(data_tensor).numpy()\n        \n    df_encoded = pd.DataFrame(encoded_data, columns=[f'Enc_{i + 1}' for i in range(encoded_data.shape[1])])\n    \n    return df_encoded","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_ts_id = train_ts['id']\ntest_ts_id = test_ts['id']\ndf_train = train_ts.drop('id', axis=1)\ndf_test = test_ts.drop('id', axis=1)\n\ntrain_ts_encoded = autoencoder(df_train, encoding_dim=60, epochs=100, batch_size=32)\ntest_ts_encoded = autoencoder(df_test, encoding_dim=60, epochs=100, batch_size=32)\n\ntrain_ts_encoded['id'] = train_ts_id\ntest_ts_encoded['id'] = test_ts_id\nmerged_train_ts_df = train_ts_time_features.merge(train_ts_encoded, on='id', how='inner')\nmerged_test_ts_df = test_ts_time_features.merge(test_ts_encoded, on='id', how='inner')\ntime_series_cols = merged_train_ts_df.columns.tolist()\ntime_series_cols.remove('id')","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"merged_train_ts_df['id']","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ntrain = pd.merge(train, merged_train_ts_df, how=\"left\", on='id')\ntest = pd.merge(test, merged_test_ts_df, how=\"left\", on='id')","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Filling missing values in seasonal categorical columns with 'Missing' to handle NaN effectively. It then converts these columns to the category data type for efficient encoding and memory usage.","metadata":{}},{"cell_type":"code","source":"cat_c = ['Basic_Demos-Enroll_Season', 'CGAS-Season', 'Physical-Season', 'Fitness_Endurance-Season', \n          'FGC-Season', 'BIA-Season', 'PAQ_A-Season', 'PAQ_C-Season', 'SDS-Season', 'PreInt_EduHx-Season']\n\ndef update(df):\n    for c in cat_c: \n        df[c] = df[c].fillna('Missing')\n        df[c] = df[c].astype('category')\n    return df\n        \ntrain = update(train)\ntest = update(test)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_mapping(column, dataset):\n    unique_values = dataset[column].unique()\n    return {value: idx for idx, value in enumerate(unique_values)}\n\nfor col in cat_c:\n    mapping_train = create_mapping(col, train)\n    mapping_test = create_mapping(col, test)\n    \n    train[col] = train[col].replace(mapping_train).astype(int)\n    test[col] = test[col].replace(mapping_test).astype(int)\n\nprint(f'Train Shape : {train.shape} || Test Shape : {test.shape}')","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"\n1. **BMI and Blood Pressure Checks:**\n   - Remove rows where `Physical-BMI` is less than or equal to 0.\n   - Remove rows where `Physical-Diastolic_BP` or `Physical-Systolic_BP` are less than or equal to 0.\n   - Remove rows where `Physical-Diastolic_BP` is greater than 160.\n\n2. **Age-Specific Filtering for Children:**\n   - Identify rows where `Basic_Demos-Age` is less than or equal to 12 (children).\n   - For these rows, remove entries where `FGC-FGC_CU` or `FGC-FGC_GSND` exceeds 80.\n\n3. **Bioelectrical Impedance Analysis (BIA) Metrics:**\n   - Remove rows where `BIA-BIA_BMI` is less than or equal to 0.\n   - Remove rows with unusually high values for various BIA measurements, such as:\n     - `BIA-BIA_BMC` > 1000\n     - `BIA-BIA_BMR` > 40000\n     - `BIA-BIA_DEE` > 60000\n     - `BIA-BIA_ECW`, `BIA-BIA_FFM`, `BIA-BIA_ICW`, `BIA-BIA_LDM`, `BIA-BIA_LST`, `BIA-BIA_SMM`, `BIA-BIA_TBW` > 2000","metadata":{}},{"cell_type":"code","source":"def remove_outliers(df):\n    \n    df = df.drop(df[df['Physical-BMI'] <= 0].index)\n    df = df.drop(df[df['Physical-Diastolic_BP'] <= 0].index)\n    df = df.drop(df[df['Physical-Systolic_BP'] <= 0].index)\n    df = df.drop(df[df['Physical-Diastolic_BP'] > 160].index)\n\n    children = df[df['Basic_Demos-Age'] <= 12]\n    df = df.drop(children[children['FGC-FGC_CU'] > 80].index)\n    df = df.drop(children[children['FGC-FGC_GSND'] > 80].index)\n\n    df = df.drop(df[df['BIA-BIA_BMI'] <= 0].index)\n    df = df.drop(df[df['BIA-BIA_BMC'] > 1000].index)\n    df = df.drop(df[df['BIA-BIA_BMR'] > 40000].index)\n    df = df.drop(df[df['BIA-BIA_DEE'] > 60000].index)\n    df = df.drop(df[df['BIA-BIA_ECW'] > 2000].index)\n    df = df.drop(df[df['BIA-BIA_FFM'] > 2000].index)\n    df = df.drop(df[df['BIA-BIA_ICW'] > 2000].index)\n    df = df.drop(df[df['BIA-BIA_LDM'] > 2000].index)\n    df = df.drop(df[df['BIA-BIA_LST'] > 2000].index)\n    df = df.drop(df[df['BIA-BIA_SMM'] > 2000].index)\n    df = df.drop(df[df['BIA-BIA_TBW'] > 2000].index)\n    \n    return df","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = remove_outliers(train)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def preprocess_feature(df):\n    df['BMI_Age'] = df['Physical-BMI'] * df['Basic_Demos-Age']\n    df['Internet_Hours_Age'] = df['PreInt_EduHx-computerinternet_hoursday'] * df['Basic_Demos-Age']\n    df['BMI_Internet_Hours'] = df['Physical-BMI'] * df['PreInt_EduHx-computerinternet_hoursday']\n    df['BFP_BMI'] = df['BIA-BIA_Fat'] / df['BIA-BIA_BMI']\n    df['FFMI_BFP'] = df['BIA-BIA_FFMI'] / df['BIA-BIA_Fat']\n    df['FMI_BFP'] = df['BIA-BIA_FMI'] / df['BIA-BIA_Fat']\n    df['LST_TBW'] = df['BIA-BIA_LST'] / df['BIA-BIA_TBW']\n    df['BFP_BMR'] = df['BIA-BIA_Fat'] * df['BIA-BIA_BMR']\n    df['BFP_DEE'] = df['BIA-BIA_Fat'] * df['BIA-BIA_DEE']\n    df['BMR_Weight'] = df['BIA-BIA_BMR'] / df['Physical-Weight']\n    df['DEE_Weight'] = df['BIA-BIA_DEE'] / df['Physical-Weight']\n    df['SMM_Height'] = df['BIA-BIA_SMM'] / df['Physical-Height']\n    df['Muscle_to_Fat'] = df['BIA-BIA_SMM'] / df['BIA-BIA_FMI']\n    df['Hydration_Status'] = df['BIA-BIA_TBW'] / df['Physical-Weight']\n    df['ICW_TBW'] = df['BIA-BIA_ICW'] / df['BIA-BIA_TBW']\n    df['BMI_PHR'] = df['Physical-BMI'] * df['Physical-HeartRate']\n    \n    return df","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = preprocess_feature(train)\ntrain = train.dropna(thresh=10, axis=0)\ntest = preprocess_feature(test)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train['Basic_Demos-Enroll_Season']","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_featuresCols += time_series_cols\n\ntrain = train[train_featuresCols]\n# drop cac ban ghi co sii nan\ntrain = train.dropna(subset='sii') \n\n\ntest_featuresCols += time_series_cols\ntest = test[test_featuresCols]\n\nif np.any(np.isinf(train)):\n    train = train.replace([np.inf, -np.inf], np.nan)\n\nif np.any(np.isinf(test)):\n    test = test.replace([np.inf, -np.inf], np.nan)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_abnormal(df, rules):\n    for column, (min_val, max_val) in rules.items():\n        if column in df.columns:\n            cond = (df[column] < min_val) | (df[column] > max_val)\n            df.loc[cond, column] = np.nan\n    return df\n\n\nrules = {\n    'BIA-BIA_Fat': (5, 50),\n    'BIA-BIA_FMI': (0.5, float('inf')),\n    'BIA-BIA_FFMI': (12, 25),\n    'BIA-BIA_ECW': (0, 40),\n    'BIA-BIA_DEE': (1200, 3000),\n    'BIA-BIA_BMR': (900, 2500),\n    'BIA-BIA_ICW': (20, 70),\n    'BIA-BIA_SMM': (12, 70),\n    'BIA-BIA_TBW': (30, 80),\n    'Physical-Weight': (40, float('inf'))\n}\ntrain = process_abnormal(train, rules)\ntest = process_abnormal(test, rules)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def feature_engineering(df):\n\n    abnormal_conditions = {\n        'Physical-Diastolic_BP': [(40, 100)],\n        'Physical-Systolic_BP': [(80, 160)]\n    }\n\n    for col, ranges in abnormal_conditions.items():\n        if col in df.columns:\n            for lower, upper in ranges:\n                df.loc[(df[col] < lower) | (df[col] > upper), col] = np.nan\n\n    if {'Fitness_Endurance-Time_Mins', 'Fitness_Endurance-Time_Sec'}.issubset(df.columns):\n        df['Fitness_Endurance_Time'] = (\n            df['Fitness_Endurance-Time_Mins'] * 60 + df['Fitness_Endurance-Time_Sec']\n        )\n    \n    if 'Basic_Demos-Age' in df.columns:\n        df['Age_Group'] = pd.cut(df['Basic_Demos-Age'], bins=[4, 12, 22], labels=[0, 1]).astype(int)\n\n    if {'PAQ_A-PAQ_A_Total', 'PAQ_C-PAQ_C_Total'}.issubset(df.columns):\n        df['PAQ_Total'] = df[['PAQ_A-PAQ_A_Total', 'PAQ_C-PAQ_C_Total']].max(axis=1)\n    if 'PreInt_EduHx-computerinternet_hoursday' in df.columns and 'Basic_Demos-Age' in df.columns:\n        df['Internet_Hours_Age'] = (\n            df['PreInt_EduHx-computerinternet_hoursday'] * df['Basic_Demos-Age']\n        )\n    \n    if 'Physical-BMI' in df.columns and 'Basic_Demos-Age' in df.columns:\n        df['BMI_Age'] = df['Physical-BMI'] * df['Basic_Demos-Age']\n    \n    if 'Physical-Height' in df.columns and 'Basic_Demos-Age' in df.columns:\n        df['Physical-Height_Age'] = df['Physical-Height'] * df['Basic_Demos-Age']\n\n    if 'SDS-SDS_Total_T' in df.columns and 'PreInt_EduHx-computerinternet_hoursday' in df.columns:\n        df['SDS_InternetHours'] = (\n            df['SDS-SDS_Total_T'] * df['PreInt_EduHx-computerinternet_hoursday']\n        )\n    \n    if 'BIA-BIA_BMI' in df.columns and 'SDS-SDS_Total_T' in df.columns:\n        df['SDS_BMI'] = df['BIA-BIA_BMI'] * df['SDS-SDS_Total_T']\n\n    if 'CGAS-CGAS_Score' in df.columns and 'SDS-SDS_Total_T' in df.columns:\n        df['CGAS_SDS'] = df['CGAS-CGAS_Score'] * df['SDS-SDS_Total_T']\n    \n    if 'Physical-Systolic_BP' in df.columns and 'Basic_Demos-Age' in df.columns:\n        df['Age_Systolic_BP'] = df['Physical-Systolic_BP'] * df['Basic_Demos-Age']\n\n    if 'Physical-Systolic_BP' in df.columns and 'PreInt_EduHx-computerinternet_hoursday' in df.columns:\n        df['PreInt_Systolic_BP'] = (\n            df['Physical-Systolic_BP'] * df['PreInt_EduHx-computerinternet_hoursday']\n        )\n\n    if 'BIA-BIA_Activity_Level_num' in df.columns and 'PAQ_Total' in df.columns:\n        df['PAQ_Activity'] = df['BIA-BIA_Activity_Level_num'] * df['PAQ_Total']\n\n    return df\n\n\ntrain = feature_engineering(train)\ntest= feature_engineering(test)\n","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def eval_models(thresholds, y, y_predict_non_rounded):\n    y_predic = np.where(y_predict_non_rounded < thresholds[0], 0,\n                    np.where(y_predict_non_rounded < thresholds[1], 1,\n                             np.where(y_predict_non_rounded < thresholds[2], 2, 3)))\n    return -cohen_kappa_score(y, y_predic, weights='quadratic')\n\ndef train_models(model_class, test_data):\n    X = train.drop(['sii'], axis=1)\n    y = train['sii']\n\n    SKF = StratifiedKFold(n_splits=n_splits, shuffle=True, random_state=SEED)\n    \n    train_S = []\n    test_S = []\n    \n    oof_non_rounded = np.zeros(len(y), dtype=float) \n    oof_rounded = np.zeros(len(y), dtype=int) \n    test_preds = np.zeros((len(test_data), n_splits))\n\n    for fold, (train_idx, test_idx) in enumerate(tqdm(SKF.split(X, y), desc=\"Training Folds\", total=n_splits)):\n        X_train, X_val = X.iloc[train_idx], X.iloc[test_idx]\n        y_train, y_val = y.iloc[train_idx], y.iloc[test_idx]\n\n        model = clone(model_class)\n        model.fit(X_train, y_train)\n\n        y_train_pred = model.predict(X_train)\n        y_val_pred = model.predict(X_val)\n\n        oof_non_rounded[test_idx] = y_val_pred\n        y_val_pred_rounded = y_val_pred.round(0).astype(int)\n        y_train_pred_rounded = y_train_pred.round(0).astype(int)\n        oof_rounded[test_idx] = y_val_pred_rounded\n\n        train_kappa = cohen_kappa_score(y_train, y_train_pred_rounded, weights='quadratic')        \n        val_kappa = cohen_kappa_score(y_val, y_val_pred_rounded, weights='quadratic')\n\n        train_S.append(train_kappa)\n        test_S.append(val_kappa)\n        \n        test_preds[:, fold] = model.predict(test_data)\n\n        print(f\"Fold {fold+1} - Train QWK: {train_kappa:.4f}, Validation QWK: {val_kappa:.4f}\")\n        clear_output(wait=True)\n\n    print(f\"Mean Train QWK --> {np.mean(train_S):.4f}\")\n    print(f\"Mean Validation QWK ---> {np.mean(test_S):.4f}\")\n\n    KappaOPtimizer = minimize(eval_models,\n                              x0=[0.5, 1.5, 2.5], args=(y, oof_non_rounded), \n                              method='Nelder-Mead')\n    assert KappaOPtimizer.success, \"Optimization did not converge.\"\n    \n    oof_tuned = np.where(oof_non_rounded < (KappaOPtimizer.x)[0], 0,\n                    np.where(oof_non_rounded < (KappaOPtimizer.x)[1], 1,\n                             np.where(oof_non_rounded < (KappaOPtimizer.x)[2], 2, 3)))\n    \n    tKappa = cohen_kappa_score(y, oof_tuned, weights='quadratic')\n\n    print(f\"----> || Optimized SCORE :: {Fore.CYAN}{Style.BRIGHT} {tKappa:.3f}{Style.RESET_ALL}\")\n\n    tpm = test_preds.mean(axis=1)\n    tpTuned = np.where(tpm < (KappaOPtimizer.x)[0], 0,\n                    np.where(tpm < (KappaOPtimizer.x)[1], 1,\n                             np.where(tpm < (KappaOPtimizer.x)[2], 2, 3)))\n    \n    submission = pd.DataFrame({\n        'id': sample['id'],\n        'sii': tpTuned\n    })\n\n    return submission","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\nclass TabNetWrapper(BaseEstimator, RegressorMixin):\n    def __init__(self, **kwargs):\n        self.model = TabNetRegressor(**kwargs)\n        self.kwargs = kwargs\n        self.imputer = KNNImputer(n_neighbors=5)\n        #self.imputer = SimpleImputer(strategy='median')\n        self.best_model_path = 'best_tabnet_model.pt'\n\n    def fit(self, X, y):\n        X_imputed = self.imputer.fit_transform(X)\n\n        if hasattr(y, 'values'):\n            y = y.values\n\n        X_train, X_valid, y_train, y_valid = train_test_split(\n            X_imputed,\n            y,\n            test_size=0.2,\n            random_state=42\n        )\n\n        # Train TabNet model\n        history = self.model.fit(\n            X_train=X_train,\n            y_train=y_train.reshape(-1, 1),\n            eval_set=[(X_valid, y_valid.reshape(-1, 1))],\n            eval_name=['valid'],\n            eval_metric=['mse', 'mae', 'rmse'],\n            max_epochs=500,\n            patience=50,\n            batch_size=1024,\n            virtual_batch_size=128,\n            num_workers=0,\n            drop_last=False,\n            callbacks=[\n                TabNetPretrainedModelCheckpoint(\n                    filepath=self.best_model_path,\n                    monitor='valid_mse',\n                    mode='min',\n                    save_best_only=True,\n                    verbose=True\n                )\n            ]\n        )\n\n        # Load the best model\n        if os.path.exists(self.best_model_path):\n            self.model.load_model(self.best_model_path)\n            os.remove(self.best_model_path)  # Remove temporary file\n\n        return self\n\n\n    def predict(self, X):\n        X_imputed = self.imputer.transform(X)\n        return self.model.predict(X_imputed).flatten()\n\n    def __deepcopy__(self, memo):\n        cls = self.__class__\n        result = cls.__new__(cls)\n        memo[id(self)] = result\n        for k, v in self.__dict__.items():\n            setattr(result, k, deepcopy(v, memo))\n        return result\n\nTabNet_Params = {\n    'n_d': 64,\n    'n_a': 64,\n    'n_steps': 5,\n    'gamma': 1.5,\n    'n_independent': 2,\n    'n_shared': 2,\n    'lambda_sparse': 1e-4,\n    'optimizer_fn': torch.optim.Adam,\n    'optimizer_params': dict(lr=1e-4, weight_decay=1e-5),\n    'mask_type': 'entmax',\n    'scheduler_params': dict(mode=\"min\", patience=10, min_lr=1e-5, factor=0.5),\n    'scheduler_fn': torch.optim.lr_scheduler.ReduceLROnPlateau,\n    'verbose': 1,\n    'device_name': 'cuda' if torch.cuda.is_available() else 'cpu'\n}\n\n\nclass TabNetPretrainedModelCheckpoint(Callback):\n    def __init__(self, filepath, monitor='val_loss', mode='min',\n                 save_best_only=True, verbose=1):\n        super().__init__()\n        self.filepath = filepath\n        self.monitor = monitor\n        self.mode = mode\n        self.save_best_only = save_best_only\n        self.verbose = verbose\n        self.best = float('inf') if mode == 'min' else -float('inf')\n\n    def on_train_begin(self, logs=None):\n        self.model = self.trainer\n\n    def on_epoch_end(self, epoch, logs=None):\n        logs = logs or {}\n        current = logs.get(self.monitor)\n        if current is None:\n            return\n\n        if (self.mode == 'min' and current < self.best) or \\\n           (self.mode == 'max' and current > self.best):\n            if self.verbose:\n                print(f'\\nEpoch {epoch}: {self.monitor} improved from {self.best:.4f} to {current:.4f}')\n            self.best = current\n            if self.save_best_only:\n                self.model.save_model(self.filepath)","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Params = {\n    'learning_rate': 0.017862173759615217,\n    'max_depth': 6,\n    'num_leaves': 125,            \n    'min_data_in_leaf': 13,    \n    'feature_fraction':0.6522262873105152,     \n    'bagging_fraction': 0.7654332788287815,   \n    'bagging_freq': 4,\n    'lambda_l1': 9.655325791404717,\n    'lambda_l2': 0.320887274657755,\n          \n    'device': 'cpu',\n    'min_gain_to_split': 0.5,\n    'max_bin': 128\n\n\n}\n\n\nXGB_Params = {\n    'learning_rate': 0.014712430731211663,\n    'max_depth': 4,\n    'n_estimators': 150,\n    'subsample': 0.6802148193485659,\n    'colsample_bytree': 0.7805781852928252,\n    'reg_alpha': 0.04701140593625621,\n    'reg_lambda': 9.583858559926233,\n    'gamma': 0.028582667563424185,\n    'max_bin': 256,\n    'random_state': SEED,\n    'tree_method': 'hist'\n}\n\n\n\nCatBoost_Params = {\n    'learning_rate': 0.03672551139879832,\n    'depth': 8,\n    'iterations': 344,\n    'random_seed': SEED,\n    'verbose': 0,\n    'l2_leaf_reg': 0.001989164174947358,\n    'border_count': 128,\n    'random_strength': 0.3829541667285703,\n    'task_type': 'CPU',\n    'bagging_temperature': 0.28498124222284416\n}\n","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import optuna\nLight = LGBMRegressor(**Params, random_state=SEED, verbose=-1, n_estimators=300)\nXGB_Model = XGBRegressor(**XGB_Params)\nCatBoost_Model = CatBoostRegressor(**CatBoost_Params)\ntabnet = TabNetWrapper(**TabNet_Params)\nvoting_model = VotingRegressor(estimators=[\n    ('lightgbm', Light),\n    ('xgboost', XGB_Model),\n    ('catboost', CatBoost_Model),\n    ('tabnet', tabnet)\n])","metadata":{},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nSubmission1 = train_models(voting_model, test)\n\nSubmission1.to_csv('submission.csv', index=False)","metadata":{},"outputs":[],"execution_count":null}]}