{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":53666,"databundleVersionId":6589269,"sourceType":"competition"},{"sourceId":6507308,"sourceType":"datasetVersion","datasetId":3706667},{"sourceId":151583600,"sourceType":"kernelVersion"}],"dockerImageVersionId":30558,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom itertools import groupby\nfrom sklearn.model_selection import train_test_split\nfrom pandas.api.types import is_datetime64_ns_dtype\nimport numba\n\nfrom sklearn.ensemble import RandomForestClassifier\nimport xgboost as xgb\nfrom sklearn.ensemble import GradientBoostingClassifier\nfrom sklearn.preprocessing import MinMaxScaler\nimport lightgbm as lgb\nfrom imblearn.under_sampling import RandomUnderSampler\nfrom joblib import Parallel, delayed\nimport gc\nimport plotly.express as px\nfrom metric import score \n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:19:59.050520Z","iopub.execute_input":"2023-11-28T15:19:59.051016Z","iopub.status.idle":"2023-11-28T15:19:59.063944Z","shell.execute_reply.started":"2023-11-28T15:19:59.050970Z","shell.execute_reply":"2023-11-28T15:19:59.062933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"column_names = {\n    'series_id_column_name': 'series_id',\n    'time_column_name': 'step',\n    'event_column_name': 'event',\n    'score_column_name': 'score',\n}\n\ntolerances = {\n    'onset': [12, 36, 60, 90, 120, 150, 180, 240, 300, 360], \n    'wakeup': [12, 36, 60, 90, 120, 150, 180, 240, 300, 360]\n}","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:19:59.065693Z","iopub.execute_input":"2023-11-28T15:19:59.066736Z","iopub.status.idle":"2023-11-28T15:19:59.085588Z","shell.execute_reply.started":"2023-11-28T15:19:59.066696Z","shell.execute_reply":"2023-11-28T15:19:59.084543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def reduce_mem_usage(df):\n    \n    \"\"\" \n    Iterate through all numeric columns of a dataframe and modify the data type\n    to reduce memory usage.        \n    \"\"\"\n    \n    for col in df.columns:\n        col_type = df[col].dtype\n\n        if col_type != object and not is_datetime64_ns_dtype(df[col]) and not 'category':\n            c_min = df[col].min()\n            c_max = df[col].max()\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.int32)  \n            else:\n                df[col] = df[col].astype(np.float16)\n        \n    return df","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:19:59.087155Z","iopub.execute_input":"2023-11-28T15:19:59.087841Z","iopub.status.idle":"2023-11-28T15:19:59.099991Z","shell.execute_reply.started":"2023-11-28T15:19:59.087808Z","shell.execute_reply":"2023-11-28T15:19:59.098699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_macd(s, hfast=4, hslow=48, macd=15, center=False):\n    \n    sma_fast = s.rolling(hfast*12*60, min_periods=1, center=center).agg('mean')\n    sma_slow = s.rolling(hslow*12*60, min_periods=1, center=center).agg('mean')\n    macd = (sma_fast - sma_slow).rolling(12*macd, min_periods=1, center=center).mean().astype(np.float32)\n    \n    return macd\n\n\ndef cls_zone(df, col='anglezdiffabs'):\n    \n    s = df[f'{col}']\n    df['anglezdiffabs_macd'] = get_macd(s)\n\n    s = df[f'{col}'].sort_index(ascending=False)\n    df['anglezdiffabs_macd_rev'] = get_macd(s).sort_index()\n    \n    df['macd_spred'] = df['anglezdiffabs_macd']-df['anglezdiffabs_macd_rev']\n    df['macd_spread_diff'] =df['macd_spred'].diff(60)\n    \n    df.loc[df['macd_spred']<3, 'wakeup_zone'] = 1\n    df['wakeup_zone'].fillna(0, inplace=True)\n    df.loc[df['macd_spred']>-3, 'onset_zone'] = 1\n    df['onset_zone'].fillna(0, inplace=True)\n    \n    return df\n\n\ndef feat_eng(df):\n    \n    df['series_id'] = df['series_id'].astype('category')\n    df['timestamp'] = pd.to_datetime(df['timestamp']).apply(lambda t: t.tz_localize(None))\n    df['hour'] = df[\"timestamp\"].dt.hour\n    df['month'] = df[\"timestamp\"].dt.month\n    \n    df.sort_values(['timestamp'], inplace=True)\n    df.set_index('timestamp', inplace=True)\n    \n    # limit outiliers in enmo\n    df['enmo'] = df['enmo'].clip(upper=4)\n    \n    df['lids'] = np.maximum(0., df['enmo'] - 0.02)\n    df['lids'] = df['lids'].rolling(f'{120*5}s', center=True, min_periods=1).agg('sum')\n    df['lids'] = 100 / (df['lids'] + 1)\n    df['lids'] = df['lids'].rolling(f'{360*5}s', center=True, min_periods=1).agg('mean').astype(np.float32)\n    \n    df['lids_sma_fast'] = df['lids'].rolling('2h', center=True, min_periods=1).agg('mean').astype(np.float32)\n    df['lids_sma_macd'] = (df['lids'].rolling('18h', center=True, min_periods=1).agg('mean') - df['lids_sma_fast']\n                                 ).rolling(f'1h', center=True, min_periods=1).agg('mean').astype(np.float32)\n    \n    df[\"enmo\"] = (df[\"enmo\"]*1000).astype(np.int16)\n    df[\"anglez\"] = df[\"anglez\"].astype(np.int16)\n    df[\"anglezdiffabs\"] = df[\"anglez\"].diff().abs().astype(np.float32)\n    \n    df = cls_zone(df, col='anglezdiffabs')\n\n    for col in ['enmo', 'anglez', 'anglezdiffabs']:\n        \n        df[f'{col}_sma_fast'] = df[f'{col}'].rolling(f'4h', center=True, min_periods=1).agg('mean').astype(np.float32)\n        df[f'{col}_sf_macd'] = (df[f'{col}_sma_fast'] - df[f'{col}'].rolling(f'48h', center=True, min_periods=1).agg('mean')\n                                   ).rolling(f'1h', center=True, min_periods=1).agg('mean').astype(np.float32)\n        \n        # periods in seconds        \n        periods = [60, 300, 720, 1440, 3600] \n        \n        for n in periods:\n            \n            rol_args = {'window':f'{n+5}s', 'min_periods':10, 'center':True}\n            \n            for agg in ['median', 'mean', 'max', 'min', 'var']:\n                df[f'{col}_{agg}_{n}'] = df[col].rolling(**rol_args).agg(agg).astype(np.float32).values\n                gc.collect()\n            \n            if n == max(periods):\n                df[f'{col}_mad_{n}'] = (df[col] - df[f'{col}_median_{n}']).abs().rolling(**rol_args).median().astype(np.float32)\n            \n            df[f'{col}_amplit_{n}'] = df[f'{col}_max_{n}']-df[f'{col}_min_{n}']\n            df[f'{col}_amplit_{n}_min'] = df[f'{col}_amplit_{n}'].rolling(**rol_args).min().astype(np.float32).values\n            \n            df[f'{col}_diff_{n}_max'] = df[f'{col}_max_{n}'].diff().abs().rolling(**rol_args).max().astype(np.float32)\n            df[f'{col}_diff_{n}_mean'] = df[f'{col}_max_{n}'].diff().abs().rolling(**rol_args).mean().astype(np.float32)\n\n    \n            gc.collect()\n        \n    df.drop(columns=[\n            'anglezdiffabs_min_720', 'anglezdiffabs_min_3600',\n            'anglezdiffabs_amplit_720', 'anglezdiffabs_min_60', 'anglezdiffabs_diff_60_max',\n            'anglezdiffabs','enmo_diff_60_max',\n            'anglez_median_60', 'anglezdiffabs_amplit_3600',\n            'enmo_max_60', 'enmo_amplit_720',\n            'anglezdiffabs_diff_60_mean', 'anglezdiffabs_max_720', 'enmo_median_60',\n            'anglez_amplit_720', 'enmo_mean_60', \n            'anglez_mean_720', 'anglez_mean_60',\n            'anglez_var_720', 'anglez_diff_60_max', 'anglez_diff_720_max',\n            'enmo_min_60', 'enmo_max_720', 'enmo_min_720', 'anglez_diff_720_mean',\n            'anglez_diff_60_mean', 'anglez_max_720', 'anglezdiffabs_var_720',\n            'anglezdiffabs_diff_720_mean', 'enmo_diff_720_mean', 'anglezdiffabs_min_1440', 'anglezdiffabs_min_300',\n            'anglezdiffabs_amplit_1440', 'anglezdiffabs_amplit_300',\n            'anglezdiffabs_diff_300_mean', 'enmo_diff_300_mean',\n            'anglezdiffabs_max_300', 'anglezdiffabs_diff_300_max',\n            'anglez_diff_300_max', 'enmo_diff_300_max', 'anglez_amplit_300',\n            'anglez_diff_300_mean', 'enmo_amplit_300', 'anglezdiffabs_var_300',\n            'enmo_diff_60_mean', 'anglez_mean_300', 'anglez_max_60', 'enmo_var_300',\n            'anglez_median_300', 'enmo_median_300', 'enmo_amplit_1440',\n            'enmo_median_720', 'anglez_amplit_1440', 'anglez_mean_1440',\n            'enmo_max_1440', 'enmo_max_300', 'anglez_max_300', 'enmo_min_1440',\n            'anglez_var_300', 'enmo_min_3600'\n                    ], inplace=True)\n    \n    df.reset_index(inplace=True)\n    df.dropna(inplace=True)\n    \n    df = df[(df['wakeup_zone']==1)|(df['onset_zone']==1)]\n\n    return df","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:19:59.102398Z","iopub.execute_input":"2023-11-28T15:19:59.103046Z","iopub.status.idle":"2023-11-28T15:19:59.138253Z","shell.execute_reply.started":"2023-11-28T15:19:59.103012Z","shell.execute_reply":"2023-11-28T15:19:59.136912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file = '/kaggle/input/zzzs-lightweight-training-dataset-target/Zzzs_train.parquet'\n\ndef feat_eng_by_id(idx):\n    \n    from warnings import simplefilter \n    simplefilter(action=\"ignore\", category=pd.errors.PerformanceWarning)\n    \n    df  = pd.read_parquet(file, filters=[('series_id','=',idx)])\n    df['awake'] = df['awake'].astype(np.int8)\n    df = feat_eng(df)\n    \n    return df","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:19:59.139704Z","iopub.execute_input":"2023-11-28T15:19:59.140072Z","iopub.status.idle":"2023-11-28T15:19:59.158167Z","shell.execute_reply.started":"2023-11-28T15:19:59.140039Z","shell.execute_reply":"2023-11-28T15:19:59.157196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DEV = False\n\nseries_id  = pd.read_parquet(file, columns=['series_id'])\nseries_id = series_id.series_id.unique()\n\nprint(len(series_id))\n\nif DEV:\n    series_id = series_id[::10]\n    print('DEV ids:', len(series_id))","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:19:59.238690Z","iopub.execute_input":"2023-11-28T15:19:59.239474Z","iopub.status.idle":"2023-11-28T15:20:02.207617Z","shell.execute_reply.started":"2023-11-28T15:19:59.239429Z","shell.execute_reply":"2023-11-28T15:20:02.206675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"weird_series = ['31011ade7c0a', 'a596ad0b82aa']\n\nseries_id = [s for s in series_id if s not in weird_series]","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:20:02.210225Z","iopub.execute_input":"2023-11-28T15:20:02.210613Z","iopub.status.idle":"2023-11-28T15:20:02.219173Z","shell.execute_reply.started":"2023-11-28T15:20:02.210562Z","shell.execute_reply":"2023-11-28T15:20:02.217994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\ntrain = Parallel(n_jobs=-1)(delayed(feat_eng_by_id)(i) for i in series_id)\ntrain = pd.concat(train, ignore_index=True)","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:20:02.222895Z","iopub.execute_input":"2023-11-28T15:20:02.223263Z","iopub.status.idle":"2023-11-28T15:37:58.117961Z","shell.execute_reply.started":"2023-11-28T15:20:02.223232Z","shell.execute_reply":"2023-11-28T15:37:58.116580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.shape","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:37:58.119445Z","iopub.execute_input":"2023-11-28T15:37:58.119819Z","iopub.status.idle":"2023-11-28T15:37:58.127401Z","shell.execute_reply.started":"2023-11-28T15:37:58.119787Z","shell.execute_reply":"2023-11-28T15:37:58.126202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"drop_cols = ['series_id', 'step', 'timestamp']\n\nX, y = train.drop(columns=drop_cols+['awake']), train['awake']\n# reduce train dataset by half\nstep=360 if DEV else 60\nX, y = X.iloc[::step], y[::step]\nstep","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:37:58.130609Z","iopub.execute_input":"2023-11-28T15:37:58.130980Z","iopub.status.idle":"2023-11-28T15:38:00.713542Z","shell.execute_reply.started":"2023-11-28T15:37:58.130949Z","shell.execute_reply":"2023-11-28T15:38:00.712356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y.value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:38:00.714823Z","iopub.execute_input":"2023-11-28T15:38:00.715172Z","iopub.status.idle":"2023-11-28T15:38:00.728336Z","shell.execute_reply.started":"2023-11-28T15:38:00.715134Z","shell.execute_reply":"2023-11-28T15:38:00.727217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del train\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:38:00.729580Z","iopub.execute_input":"2023-11-28T15:38:00.729930Z","iopub.status.idle":"2023-11-28T15:38:00.961400Z","shell.execute_reply.started":"2023-11-28T15:38:00.729896Z","shell.execute_reply":"2023-11-28T15:38:00.960030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Ensemble Model","metadata":{}},{"cell_type":"code","source":"class EnsembleAvgProba():\n    \n    def __init__(self, classifiers):\n        \n        self.classifiers = classifiers\n    \n    def fit(self,X,y):\n        \n        for classifier in self.classifiers:                \n            classifier.fit(X, y)\n            gc.collect()\n     \n    def predict_proba(self, X):\n        \n        probs = []\n        \n        for m in self.classifiers:\n            probs.append(m.predict_proba(X))\n        \n        probabilities = np.stack(probs)\n        p = np.mean(probabilities, axis=0)\n        \n        return p\n    \n    def predict(self, X):\n        \n        probs = []\n        \n        for m in self.classifiers:\n            probs.append(m.predict(X))\n        \n        probabilities = np.stack(probs)\n        p = np.median(probabilities, axis=0)\n        \n        return p.round()","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:38:00.962939Z","iopub.execute_input":"2023-11-28T15:38:00.963292Z","iopub.status.idle":"2023-11-28T15:38:00.973262Z","shell.execute_reply.started":"2023-11-28T15:38:00.963265Z","shell.execute_reply":"2023-11-28T15:38:00.972354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X.head()","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:38:00.974942Z","iopub.execute_input":"2023-11-28T15:38:00.975289Z","iopub.status.idle":"2023-11-28T15:38:01.012230Z","shell.execute_reply.started":"2023-11-28T15:38:00.975261Z","shell.execute_reply":"2023-11-28T15:38:01.011054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.neural_network import MLPClassifier\nfrom sklearn.linear_model import SGDClassifier\nimport lightgbm as lgb\nfrom sklearn.ensemble import GradientBoostingClassifier, RandomForestClassifier\nimport xgboost as xgb\n\nlgb_params1 = {    \n    'boosting_type':'gbdt',\n    'num_leaves':31,\n    'max_depth':6,\n    'learning_rate':0.03,\n    'n_estimators':500,\n    'subsample_for_bin':200000,\n    'min_child_weight':0.001,\n    'min_child_samples':20,\n    'subsample':0.6,\n    'reg_alpha':0.025,\n    'reg_lambda':0.025,\n}\n\n# สร้างโมเดล\nlgb_model = lgb.LGBMClassifier(random_state=42, **lgb_params1)\nmlp_model = MLPClassifier(random_state=42)\nsgd_model = SGDClassifier(random_state=42)\n\n# เพิ่มโมเดลใน EnsembleAvgProba\nmodel = EnsembleAvgProba(classifiers=[\n    lgb_model,\n#     mlp_model,\n#     sgd_model\n])\n","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:38:01.013886Z","iopub.execute_input":"2023-11-28T15:38:01.014222Z","iopub.status.idle":"2023-11-28T15:38:01.024588Z","shell.execute_reply.started":"2023-11-28T15:38:01.014195Z","shell.execute_reply":"2023-11-28T15:38:01.023509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nmodel.fit(X, y)","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:38:01.026505Z","iopub.execute_input":"2023-11-28T15:38:01.026959Z","iopub.status.idle":"2023-11-28T15:38:38.906673Z","shell.execute_reply.started":"2023-11-28T15:38:01.026920Z","shell.execute_reply":"2023-11-28T15:38:38.905474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, roc_curve, auc, confusion_matrix\nfrom sklearn.neural_network import MLPClassifier\nimport matplotlib.pyplot as plt\n\n# Assuming you have your features X and labels y\n\n# Define your model (replace this with your actual model)\nmodel = MLPClassifier(random_state=100)\n\n# Initialize StratifiedKFold with 5 folds\nkfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=1)\n\n# Lists to store results\naccuracy_scores = []\nconf_matrices = []\nmean_fpr = np.linspace(0, 1, 100)\nmean_tpr = 0\n\n# Initialize plot for ROC curves and confusion matrices\nplt.figure(figsize=(12, 8))\n\n# Iterate over the folds\ntotal = 0\nfor fold_num, (train_idx, test_idx) in enumerate(kfold.split(X, y)):\n    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]\n    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]\n\n    # Fit the model on the training data\n    model.fit(X_train, y_train)\n\n    # Make predictions on the test data\n    y_pred = model.predict(X_test)\n\n    # Evaluate the accuracy\n    accuracy = accuracy_score(y_test, y_pred)\n    accuracy_scores.append(accuracy)\n\n    # Compute ROC curve and area under the curve\n    fpr, tpr, thresholds = roc_curve(y_test, model.predict_proba(X_test)[:, 1])\n    mean_tpr += np.interp(mean_fpr, fpr, tpr)\n    roc_auc = auc(fpr, tpr)\n\n    # Calculate and store the confusion matrix\n    conf_matrix = confusion_matrix(y_test, y_pred)\n    conf_matrices.append(conf_matrix)\n\n    # Plot ROC curve for each fold\n    plt.subplot(2, 6, fold_num + 1)\n    plt.plot(fpr, tpr, label=f'Fold {fold_num + 1} (AUC = {roc_auc:.5f})')\n    plt.title(f'Fold {fold_num + 1}')\n\n    # Plot confusion matrix as heatmap\n    plt.subplot(2, 6, fold_num + 7)  # Adjusted the index here\n    plt.title(f'Fold {fold_num + 1} Confusion Matrix')\n    plt.imshow(conf_matrix, interpolation='nearest', cmap=plt.cm.Blues)\n    plt.colorbar()\n    plt.xticks([0, 1], [0, 1])\n    plt.yticks([0, 1], [0, 1])\n    plt.xlabel('Predicted Label')\n    plt.ylabel('True Label')\n    for i in range(2):\n        for j in range(2):\n            plt.text(j, i, str(conf_matrix[i, j]), ha='center', va='center', color='red')\n\n    total += accuracy\n    recall = recall_score(y_test, y_pred, average='binary')\n    precision = precision_score(y_test, y_pred, average='binary')\n    f1 = f1_score(y_test, y_pred)\n    specificity = conf_matrix[0, 0] / (conf_matrix[0, 0] + conf_matrix[0, 1])\n\n    # Print the evaluation metrics\n    print(f'Fold {fold_num + 1} Accuracy: {accuracy:.4f}')\n    print(f'Fold {fold_num + 1} Recall: {recall:.4f}')\n    print(f'Fold {fold_num + 1} Precision: {precision:.4f}')\n    print(f'Fold {fold_num + 1} Specificity: {specificity:.4f}')\n    print(f'Fold {fold_num + 1} F1 Score: {f1:.4f}')\n    print(f'Fold {fold_num + 1} Confusion Matrix:\\n{conf_matrix}\\n')\n\n# Calculate and print the average accuracy across all folds\naverage_accuracy = total / kfold.get_n_splits(X, y)\nprint(f'Average Accuracy: {average_accuracy:.4f}')\n\n# Calculate and plot the average ROC curve\nmean_tpr /= kfold.get_n_splits(X, y)\nmean_auc = total / 5\nplt.subplot(2, 6, 12)\nplt.plot(mean_fpr, mean_tpr, color='b', linestyle='--', label=f'Mean ROC (AUC = {mean_auc:.5f})')\nplt.title('Mean ROC')\n\n# Add labels and legend to the ROC plot\nfor i in range(1, 13):\n    plt.subplot(2, 6, i)\n    plt.plot([0, 1], [0, 1], color='grey', linestyle='--')\n    plt.xlabel('False Positive Rate')\n    plt.ylabel('True Positive Rate')\n    plt.legend(loc='lower right')\n\n# Show the plots\n","metadata":{"execution":{"iopub.status.busy":"2023-11-28T17:55:26.553314Z","iopub.execute_input":"2023-11-28T17:55:26.553840Z","iopub.status.idle":"2023-11-28T19:00:23.785655Z","shell.execute_reply.started":"2023-11-28T17:55:26.553803Z","shell.execute_reply":"2023-11-28T19:00:23.784448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Features importance\n\nWe can vizualize all fetures in this [notebook](https://www.kaggle.com/code/renatoreggiani/zzzs-interactive-plot-all-feat-ideas), is helpfull to get more insights","metadata":{}},{"cell_type":"code","source":"feats = []\n\nfor m in model.classifiers:\n    feat_imp = m.feature_importances_\n    \n    feat_imp = MinMaxScaler().fit_transform(feat_imp.reshape(-1, 1))\n    feat_imp = pd.Series(pd.Series(feat_imp.reshape(1, -1)[0], index=X.columns).sort_values(), index=X.columns).sort_values()\n    feats.append(feat_imp)","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:13.804785Z","iopub.execute_input":"2023-11-28T15:40:13.805131Z","iopub.status.idle":"2023-11-28T15:40:14.505704Z","shell.execute_reply.started":"2023-11-28T15:40:13.805087Z","shell.execute_reply":"2023-11-28T15:40:14.503289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feat_imp = pd.Series(pd.concat(feats, axis=1).mean(axis=1), index=feats[0].index).sort_values()\nprint('Columns with poor contribution', feat_imp[feat_imp<0.005].index, sep='\\n')\nfig = px.bar(x=feat_imp, y=feat_imp.index, orientation='h')\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:14.506932Z","iopub.status.idle":"2023-11-28T15:40:14.507355Z","shell.execute_reply.started":"2023-11-28T15:40:14.507151Z","shell.execute_reply":"2023-11-28T15:40:14.507179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feat_imp.sort_values().head(10)","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:14.508795Z","iopub.status.idle":"2023-11-28T15:40:14.509200Z","shell.execute_reply.started":"2023-11-28T15:40:14.509000Z","shell.execute_reply":"2023-11-28T15:40:14.509019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# del X, y\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:14.511050Z","iopub.status.idle":"2023-11-28T15:40:14.511702Z","shell.execute_reply.started":"2023-11-28T15:40:14.511459Z","shell.execute_reply":"2023-11-28T15:40:14.511489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Function to get events","metadata":{}},{"cell_type":"code","source":"def get_events(idx, classifier, file='test_series.parquet') :\n    \n    test  = pd.read_parquet(f'/kaggle/input/child-mind-institute-detect-sleep-states/{file}',\n                    filters=[('series_id','=',idx)])\n    \n    test = feat_eng(test)\n    \n    test_daily = test.groupby(test['timestamp'].dt.date)[['anglez', 'enmo']].std()\n    min_daily_enmo = test_daily['enmo']<5\n    days_to_drop = test_daily[min_daily_enmo].index\n    \n    test = test[~test['timestamp'].dt.date.isin(days_to_drop)]\n        \n#     test = test[test['enmo_max_360']>2]\n#     test = test[test['anglez_std_360']>2]\n    \n    X_test = test.drop(columns=drop_cols)\n    test = test[drop_cols]\n    \n    if test.shape[0]>0:\n\n        preds, probs = classifier.predict(X_test), classifier.predict_proba(X_test)[:, 1]\n\n        test['prediction'] = preds\n        test['prediction'] = test['prediction'].rolling(120+1, center=True).median()\n        test['probability'] = probs\n\n#         test = test[test['prediction']!=2]\n\n        test.loc[test['prediction']==0, 'probability'] = 1-test.loc[test['prediction']==0, 'probability']\n        test['score'] = test['probability'].rolling(60*12*5, center=True, min_periods=10).mean().bfill().ffill()\n        test['pred_diff'] = test['prediction'].diff()\n        test['event'] = test['pred_diff'].replace({1:'wakeup', -1:'onset', 0:np.nan})\n\n        test_wakeup = test[test['event']=='wakeup'].groupby(test['timestamp'].dt.date).agg('first')\n        test_onset = test[test['event']=='onset'].groupby(test['timestamp'].dt.date).agg('last')\n        test = pd.concat([test_wakeup, test_onset], ignore_index=True).sort_values('timestamp')\n        if test.shape[0]>0:\n            if test['event'].values[0]=='wakeup':\n                test = test[1:]\n\n    return test\n\n# get_events(series_id[0], model)","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:14.512706Z","iopub.status.idle":"2023-11-28T15:40:14.513457Z","shell.execute_reply.started":"2023-11-28T15:40:14.513246Z","shell.execute_reply":"2023-11-28T15:40:14.513268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_events(idx, classifier, file='test_series.parquet') :\n    \n    test  = pd.read_parquet(f'/kaggle/input/child-mind-institute-detect-sleep-states/{file}',\n                    filters=[('series_id','=',idx)])\n    \n    test = feat_eng(test)\n    \n    X_test = test.drop(columns=drop_cols)\n    \n    if test.shape[0]>0:\n\n        preds, probs = classifier.predict(X_test), classifier.predict_proba(X_test)[:, 1]\n\n        test['prediction'] = preds\n        test['probability'] = probs\n\n        test = test[test['prediction']!=2]\n\n        test.loc[test['prediction']==0, 'probability'] = 1-test.loc[test['prediction']==0, 'probability']\n        test['score'] = test['probability'].rolling(60*12*5, center=True, min_periods=10).mean().bfill().ffill()\n        test['pred_diff'] = test['prediction'].diff()\n        test['event'] = test['pred_diff'].replace({1:'wakeup', -1:'onset', 0:np.nan})\n        test.dropna(subset='event', inplace=True)\n        test['step_diff'] = test['step'].diff()\n        test.sort_values('step_diff', inplace=True)\n        \n\n        test['day'] = ((test['step']//17280)+1).astype(np.int32)\n        \n        \n        mask_wk= (test['event']=='wakeup') & (test['wakeup_zone']==1)\n        test_wakeup = test[mask_wk].groupby('day', as_index=False).agg('last')\n        \n        mask_os= (test['event']=='onset') & (test['onset_zone']==1)\n        test_onset = test[mask_os].groupby('day', as_index=False).agg('last')\n\n        \n        df_events = pd.concat([test_wakeup, test_onset], ignore_index=True).sort_values('step')\n        \n        \n        if df_events.shape[0]>0:\n    \n            if df_events.iloc[0]['event'] == 'wakeup':\n                df_events = df_events.iloc[1:]\n\n    return df_events\n","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:14.514793Z","iopub.status.idle":"2023-11-28T15:40:14.515770Z","shell.execute_reply.started":"2023-11-28T15:40:14.515539Z","shell.execute_reply":"2023-11-28T15:40:14.515561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\ncols_sub = ['series_id','step','event','score']\n\nseries_id  = pd.read_parquet('/kaggle/input/child-mind-institute-detect-sleep-states/test_series.parquet', columns=['series_id'])\nseries_id = series_id.series_id.unique()\n\ntests = Parallel(n_jobs=-1)(delayed(get_events)(i, model) for i in series_id)","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:14.517058Z","iopub.status.idle":"2023-11-28T15:40:14.517465Z","shell.execute_reply.started":"2023-11-28T15:40:14.517267Z","shell.execute_reply":"2023-11-28T15:40:14.517287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"submission = pd.concat(tests, ignore_index=True)\nsubmission = submission[cols_sub].reset_index(names='row_id')\nsubmission.to_csv('submission.csv', index=False)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:14.518832Z","iopub.status.idle":"2023-11-28T15:40:14.519209Z","shell.execute_reply.started":"2023-11-28T15:40:14.519016Z","shell.execute_reply":"2023-11-28T15:40:14.519033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# %%time\n\n# if DEV:\n    \n#     print('validation')\n\n#     series_id  = pd.read_parquet('/kaggle/input/child-mind-institute-detect-sleep-states/train_series.parquet', columns=['series_id'])\n#     series_id = series_id.series_id.unique()\n\n#     path = '/kaggle/input/child-mind-institute-detect-sleep-states/'\n\n#     train_events = pd.read_csv(path + 'train_events.csv')\n#     train_events['timestamp'] = pd.to_datetime(train_events['timestamp']).apply(lambda t: t.tz_localize(None))\n\n#     val_solution = train_events[train_events['series_id'].isin(series_id)]\n\n#     vals = Parallel(n_jobs=-1)(delayed(get_events)(i, model, file='train_series.parquet') for i in series_id)\n\n#     val=pd.concat(vals, ignore_index=True).reset_index(names='row_id')\n\n#     print(f\"LGBM score: {score(val_solution, val, tolerances, **column_names)}\")\n\n#     val['score'] = 1\n#     print(f\"LGBM score: {score(val_solution, val, tolerances, **column_names)}\")","metadata":{"execution":{"iopub.status.busy":"2023-11-28T15:40:14.520668Z","iopub.status.idle":"2023-11-28T15:40:14.521050Z","shell.execute_reply.started":"2023-11-28T15:40:14.520855Z","shell.execute_reply":"2023-11-28T15:40:14.520873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}