{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Detect Sleep States DataPrepare\n\n### This notebook is inspired by the following [werus23's](https://www.kaggle.com/werus23) amazing notebooks.\n### see also them.\n\nFinding Critical Points using RNNs\n\n - [Data Prep notebook](https://www.kaggle.com/code/werus23/sleep-critical-point-prepare-data)\n - [Training notebook](https://www.kaggle.com/werus23/sleep-critical-point-train)\n - [Inference Notebook](https://www.kaggle.com/code/werus23/sleep-critical-point-infer)\n\nCredits:\n\n - idea: https://www.kaggle.com/competitions/child-mind-institute-detect-sleep-states/discussion/441470\n - dataloader: https://www.kaggle.com/code/henriupton/efficient-loading-memory-usage-visualizations-cmi\n - arch: https://www.kaggle.com/competitions/tlvmc-parkinsons-freezing-gait-prediction/discussion/416410","metadata":{}},{"cell_type":"markdown","source":"My other works\n- [Data preparation Notebook](https://www.kaggle.com/code/itsuki9180/detect-sleep-states-dataprepare)\n- [Training Notebook](https://www.kaggle.com/code/itsuki9180/detect-sleep-states-train) \n- [Inference Notebook](https://www.kaggle.com/code/itsuki9180/detect-sleep-states-dataprepare) <- you are viewing now","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport gc\nimport time\nimport json\nfrom datetime import datetime\nimport matplotlib.pyplot as plt\nimport os\nimport joblib\nimport random\nimport math\nfrom tqdm import tqdm \n\nfrom scipy.interpolate import interp1d\nfrom scipy import signal\nfrom scipy.signal import argrelmax\n\nfrom math import pi, sqrt, exp\nimport sklearn,sklearn.model_selection\nfrom sklearn.metrics import mean_squared_error\nimport torch\nfrom torch import nn,Tensor\nimport torch.nn.functional as F\nfrom torch.utils.data import DataLoader, Dataset, SubsetRandomSampler\nfrom sklearn.metrics import average_precision_score\nfrom timm.scheduler import CosineLRScheduler\nplt.style.use(\"ggplot\")\n\nfrom pyarrow.parquet import ParquetFile\nimport pyarrow as pa \nimport ctypes\ntorch.set_num_interop_threads(4)\ntorch.set_num_threads(4)\n\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:30.321339Z","iopub.execute_input":"2023-10-23T20:56:30.321660Z","iopub.status.idle":"2023-10-23T20:56:36.679699Z","shell.execute_reply.started":"2023-10-23T20:56:30.321632Z","shell.execute_reply":"2023-10-23T20:56:36.678865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fundamental config\nWORKERS = os.cpu_count()//2\nN_FOLDS = 5\nTRAIN_FOLD = 0","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:36.681038Z","iopub.execute_input":"2023-10-23T20:56:36.682011Z","iopub.status.idle":"2023-10-23T20:56:36.685998Z","shell.execute_reply.started":"2023-10-23T20:56:36.681980Z","shell.execute_reply":"2023-10-23T20:56:36.685261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PATHS:\n    MAIN_DIR = \"/kaggle/input/child-mind-institute-detect-sleep-states/\"\n    # CSV FILES : \n    SUBMISSION = MAIN_DIR + \"sample_submission.csv\"\n    TRAIN_EVENTS = MAIN_DIR + \"train_events.csv\"\n    # PARQUET FILES:\n    TRAIN_SERIES = MAIN_DIR + \"train_series.parquet\"\n    TEST_SERIES = MAIN_DIR + \"test_series.parquet\"\nclass CFG:\n    DEMO_MODE = True\nclass data_reader:\n    def __init__(self, demo_mode):\n        super().__init__()\n        # MAPPING FOR DATA LOADING :\n        self.names_mapping = {\n            \"submission\" : {\"path\" : PATHS.SUBMISSION, \"is_parquet\" : False, \"has_timestamp\" : False}, \n            \"train_events\" : {\"path\" : PATHS.TRAIN_EVENTS, \"is_parquet\" : False, \"has_timestamp\" : True},\n            \"train_series\" : {\"path\" : PATHS.TRAIN_SERIES, \"is_parquet\" : True, \"has_timestamp\" : True},\n            \"test_series\" : {\"path\" : PATHS.TEST_SERIES, \"is_parquet\" : True, \"has_timestamp\" : True}\n        }\n        self.valid_names = [\"submission\", \"train_events\", \"train_series\", \"test_series\"]\n        self.demo_mode = demo_mode\n    \n    def verify(self, data_name):\n        \"function for data name verification\"\n        if data_name not in self.valid_names:\n            print(\"PLEASE ENTER A VALID DATASET NAME, VALID NAMES ARE : \", valid_names)\n        return\n    \n    def cleaning(self, data):\n        \"cleaning function : drop na values\"\n        before_cleaning = len(data)\n        print(\"Number of missing timestamps : \", len(data[data[\"timestamp\"].isna()]))\n        data = data.dropna(subset=[\"timestamp\"])\n        after_cleaning = len(data)\n        print(\"Percentage of removed rows : {:.1f}%\".format(100 * (before_cleaning - after_cleaning) / before_cleaning) )\n#         print(data.isna().any())\n#         data = data.bfill()\n        return data\n    \n    @staticmethod\n    def reduce_memory_usage(data):\n        \"iterate through all the columns of a dataframe and modify the data type to reduce memory usage.\"\n        start_mem = data.memory_usage().sum() / 1024**2\n        print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))\n        for col in data.columns:\n            col_type = data[col].dtype    \n            if col_type != object:\n                c_min = data[col].min()\n                c_max = data[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                        data[col] = data[col].astype(np.int8)\n                    elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                        data[col] = data[col].astype(np.int16)\n                    elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                        data[col] = data[col].astype(np.int32)\n                    elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                        data[col] = data[col].astype(np.int64)  \n                else:\n                    if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                        data[col] = data[col].astype(np.float16)\n                    elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                        data[col] = data[col].astype(np.float32)\n                    else:\n                        data[col] = data[col].astype(np.float64)\n            else:\n                data[col] = data[col].astype('category')\n\n        end_mem = data.memory_usage().sum() / 1024**2\n        print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))\n        print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))\n        return data\n    \n    def load_data(self, data_name):\n        \"function for data loading\"\n        self.verify(data_name)\n        data_props = self.names_mapping[data_name]\n        if data_props[\"is_parquet\"]:\n            if self.demo_mode:\n                pf = ParquetFile(data_props[\"path\"]) \n                demo_rows = next(pf.iter_batches(batch_size=20_000)) \n                data = pa.Table.from_batches([demo_rows]).to_pandas()\n            else:\n                data = pd.read_parquet(data_props[\"path\"])\n        else:\n            if self.demo_mode:\n                data = pd.read_csv(data_props[\"path\"], nrows=20_000)\n            else:\n                data = pd.read_csv(data_props[\"path\"])\n                \n        gc.collect()\n        if data_props[\"has_timestamp\"]:\n            print('cleaning')\n            data = self.cleaning(data)\n            gc.collect()\n        #data = self.reduce_memory_usage(data)\n        return data","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:36.687206Z","iopub.execute_input":"2023-10-23T20:56:36.687804Z","iopub.status.idle":"2023-10-23T20:56:36.711116Z","shell.execute_reply.started":"2023-10-23T20:56:36.687771Z","shell.execute_reply":"2023-10-23T20:56:36.710270Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reader = data_reader(demo_mode=False)\ntest_series = reader.load_data(data_name=\"test_series\")\nids = test_series.series_id.unique()\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:36.713797Z","iopub.execute_input":"2023-10-23T20:56:36.714266Z","iopub.status.idle":"2023-10-23T20:56:37.282334Z","shell.execute_reply.started":"2023-10-23T20:56:36.714228Z","shell.execute_reply":"2023-10-23T20:56:37.281368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seq_block(in_features, out_features, ks=3, drop_rate=0.2, dilation=1):\n    padding = ((ks-1)*dilation)//2\n    return nn.Sequential(\n        nn.Conv1d(in_features, out_features, ks, padding=padding, dilation=dilation),\n        nn.BatchNorm1d(out_features),\n        nn.LeakyReLU(0.2),\n        nn.Dropout(drop_rate)\n    )\n\nclass SimpleConvNet(nn.Module):\n    def __init__(self, in_c=2, out_c=2, hidden=128, emb_dim=8, ks=3, n_blks=3, dropout=0.2):\n        super(SimpleConvNet, self).__init__()\n        \n        self.hr_emb = nn.Embedding(24, emb_dim)\n        self.fc1_hr = nn.Linear(emb_dim, emb_dim)\n        self.fc2_hr = nn.Linear(emb_dim, emb_dim)\n        \n        self.fc_in = nn.Linear(in_c+emb_dim, hidden)\n        self.blks = nn.Sequential(\n            *[seq_block(hidden, hidden, ks, drop_rate=dropout, dilation=2**i) for i in range(n_blks)]\n            )\n        self.fc_out = nn.Linear(hidden, out_c)\n        \n        self.lrelu = nn.LeakyReLU(0.2)\n        \n    def forward(self, x, h):        \n        e = self.hr_emb(h)\n        e = self.fc1_hr(e)\n        e = self.lrelu(e)\n        e = self.fc2_hr(e)\n\n        x = torch.cat([x, e.squeeze(2)], dim=-1)\n        x = self.fc_in(x)\n        \n        x = x.permute(0,2,1)\n        \n        for b in self.blks:\n            x = b(x)\n\n        x = x.permute(0,2,1)\n        \n        x = self.fc_out(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:37.283610Z","iopub.execute_input":"2023-10-23T20:56:37.283856Z","iopub.status.idle":"2023-10-23T20:56:37.294748Z","shell.execute_reply.started":"2023-10-23T20:56:37.283834Z","shell.execute_reply":"2023-10-23T20:56:37.293814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SIGMA = 720 #average length of day is 24*60*12 = 17280 for comparison\nSAMPLE_FREQ = 12 # 1 obs per minute\nclass SleepTestDataset(Dataset):\n    def __init__(\n        self,\n        test_series,\n        test_ids\n    ):\n        self.enmo_mean = np.load('/kaggle/input/detect-sleep-states-dataprepare/enmo_mean.npy')\n        self.enmo_std = np.load('/kaggle/input/detect-sleep-states-dataprepare/enmo_std.npy')\n\n        self.Xs = self.conv_dfs(test_series, test_ids)\n        \n        self.feat_list = np.load('/kaggle/input/detect-sleep-states-train/feature_list.npy')\n        self.label_list = ['onset', 'wakeup']\n        \n        self.hour_feat= ['hour']\n        \n            \n    def conv_dfs(self, series, ids):\n        res = []\n        for j, viz_id in tqdm(enumerate(ids), total=len(ids)):\n            viz_series = series.loc[(series.series_id==viz_id)].copy().reset_index()\n            viz_series['dt'] = pd.to_datetime(viz_series.timestamp,format = '%Y-%m-%dT%H:%M:%S%z').astype(\"datetime64[ns, UTC-04:00]\")\n            viz_series['hour'] = viz_series['dt'].dt.hour\n            new_df = viz_series[['step', 'anglez', 'enmo', 'hour']]\n            res.append(new_df)\n\n        return res\n\n    def norm_feat_eng(self, X, init=False):\n        X['anglez'] = X['anglez'] / 90.0\n        X['enmo'] = (X['enmo']-self.enmo_mean)/ (self.enmo_std+1e-8)\n        \n        for w in [1, 2, 4, 8, 16]:    \n            X['anglez_shift_pos_' + str(w)] = X['anglez'].shift(w).fillna(0)\n            X['anglez_shift_neg_' + str(w)] = X['anglez'].shift(-w).fillna(0)\n            \n            X['enmo_shift_pos_' + str(w)] = X['enmo'].shift(w).fillna(0)\n            X['enmo_shift_neg_' + str(w)] = X['enmo'].shift(-w).fillna(0)\n            \n            if init:\n                self.feat_list.append('anglez_shift_pos_' + str(w))\n                self.feat_list.append('anglez_shift_neg_' + str(w))\n                \n                self.feat_list.append('enmo_shift_pos_' + str(w))\n                self.feat_list.append('enmo_shift_neg_' + str(w))\n            \n        for r in [17, 33, 65]:\n            tmp_anglez = X['anglez'].rolling(r, center=True)\n            X[f'anglez_mean_{r}'] = tmp_anglez.mean()\n            X[f'anglez_std_{r}'] = tmp_anglez.std()            \n            \n            tmp_enmo = X['enmo'].rolling(r, center=True)\n            X[f'enmo_mean_{r}'] = tmp_enmo.mean()\n            X[f'enmo_std_{r}'] = tmp_enmo.std()\n            \n            if init:\n                self.feat_list.append(f'anglez_mean_{r}')\n                self.feat_list.append(f'anglez_std_{r}')\n\n                self.feat_list.append(f'enmo_mean_{r}')\n                self.feat_list.append(f'enmo_std_{r}')\n                \n        X = X.fillna(0)\n        \n        return X.astype(np.float32)\n\n    def gauss(self,n=SIGMA,sigma=SIGMA*0.15):\n        # guassian distribution function\n        r = range(-int(n/2),int(n/2)+1)\n        return [1 / (sigma * sqrt(2*pi)) * exp(-float(x)**2/(2*sigma**2)) for x in r]\n    \n    def __len__(self):\n        return len(self.Xs)\n\n    def __getitem__(self, index):\n        X = self.Xs[index]\n        X = self.norm_feat_eng(X, init=False)\n        x = X[self.feat_list].values.astype(np.float32)     \n        t = X[self.hour_feat].values.astype(np.int32)\n        return x, t\n\ntest_ds = SleepTestDataset(test_series, ids)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:37.296153Z","iopub.execute_input":"2023-10-23T20:56:37.296432Z","iopub.status.idle":"2023-10-23T20:56:37.361592Z","shell.execute_reply.started":"2023-10-23T20:56:37.296388Z","shell.execute_reply":"2023-10-23T20:56:37.360785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds[0][0].shape","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:37.362704Z","iopub.execute_input":"2023-10-23T20:56:37.363064Z","iopub.status.idle":"2023-10-23T20:56:37.400301Z","shell.execute_reply.started":"2023-10-23T20:56:37.363030Z","shell.execute_reply":"2023-10-23T20:56:37.399491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if len(test_ds.Xs)==3:\n    for x in test_ds.Xs:\n        display(x)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:37.401377Z","iopub.execute_input":"2023-10-23T20:56:37.401638Z","iopub.status.idle":"2023-10-23T20:56:37.454443Z","shell.execute_reply.started":"2023-10-23T20:56:37.401615Z","shell.execute_reply":"2023-10-23T20:56:37.453616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if len(test_ds.Xs)==3:\n    for i, x in enumerate(test_ds.Xs):\n        plt.plot(x['enmo'], lw=0.5)\n        plt.title(ids[i])\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:37.455671Z","iopub.execute_input":"2023-10-23T20:56:37.456014Z","iopub.status.idle":"2023-10-23T20:56:38.181043Z","shell.execute_reply.started":"2023-10-23T20:56:37.455988Z","shell.execute_reply":"2023-10-23T20:56:38.180162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del test_series, reader\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:38.184377Z","iopub.execute_input":"2023-10-23T20:56:38.184660Z","iopub.status.idle":"2023-10-23T20:56:38.352431Z","shell.execute_reply.started":"2023-10-23T20:56:38.184636Z","shell.execute_reply":"2023-10-23T20:56:38.351497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model config\nHIDDEN = 256 \nEMB_DIM = 16\nKS = 31 \nN_BLKS = 5 \nDROPOUT = 0.2","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:38.353598Z","iopub.execute_input":"2023-10-23T20:56:38.353904Z","iopub.status.idle":"2023-10-23T20:56:38.362693Z","shell.execute_reply.started":"2023-10-23T20:56:38.353879Z","shell.execute_reply":"2023-10-23T20:56:38.361888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dl = DataLoader(\n    test_ds,\n    batch_size=1,\n    pin_memory=True,\n    num_workers=WORKERS,\n    shuffle=False,\n    drop_last=False\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:38.363730Z","iopub.execute_input":"2023-10-23T20:56:38.364023Z","iopub.status.idle":"2023-10-23T20:56:38.372825Z","shell.execute_reply.started":"2023-10-23T20:56:38.363998Z","shell.execute_reply":"2023-10-23T20:56:38.372061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = SimpleConvNet(in_c=len(test_ds.feat_list), out_c=2, hidden=HIDDEN, emb_dim=EMB_DIM, ks=KS, n_blks=N_BLKS, dropout=DROPOUT).to(device)\nmodel.load_state_dict(torch.load(f'/kaggle/input/detect-sleep-states-train/model_best_fold-{TRAIN_FOLD}.pth',map_location=device))\nmodel.eval().half()","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:38.373901Z","iopub.execute_input":"2023-10-23T20:56:38.374287Z","iopub.status.idle":"2023-10-23T20:56:41.897236Z","shell.execute_reply.started":"2023-10-23T20:56:38.374255Z","shell.execute_reply":"2023-10-23T20:56:41.896342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"autocast = torch.cuda.amp.autocast(enabled=True, dtype=torch.half)\nscaler = torch.cuda.amp.GradScaler(enabled=True, init_scale=4096)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:41.898265Z","iopub.execute_input":"2023-10-23T20:56:41.898512Z","iopub.status.idle":"2023-10-23T20:56:41.903425Z","shell.execute_reply.started":"2023-10-23T20:56:41.898489Z","shell.execute_reply":"2023-10-23T20:56:41.902376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def lpf(wave, fs=12*60*24, fe=60, n=3):\n    nyq = fs / 2.0\n    b, a = signal.butter(1, fe/nyq, btype='low')\n    for i in range(0, n):\n        wave = signal.filtfilt(b, a, wave)\n    return wave","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:41.904603Z","iopub.execute_input":"2023-10-23T20:56:41.904861Z","iopub.status.idle":"2023-10-23T20:56:41.915629Z","shell.execute_reply.started":"2023-10-23T20:56:41.904839Z","shell.execute_reply":"2023-10-23T20:56:41.914745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame()","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:41.916630Z","iopub.execute_input":"2023-10-23T20:56:41.916882Z","iopub.status.idle":"2023-10-23T20:56:41.925811Z","shell.execute_reply.started":"2023-10-23T20:56:41.916860Z","shell.execute_reply":"2023-10-23T20:56:41.924991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with torch.no_grad():\n    with tqdm(test_dl, leave=True) as pbar:\n        for i, (X_batch, hr_batch) in enumerate(pbar):\n            X_batch = X_batch.to(device)\n            hr_batch = hr_batch.to(device)\n            with autocast:\n                y_pred = model(X_batch, hr_batch)\n\n            y_pred = y_pred[0].sigmoid().cpu().numpy().astype(np.float32)\n            \n            before_RMSE = np.sqrt(mean_squared_error(y_pred, np.zeros_like(y_pred)))\n            \n            if len(test_ds.Xs)!=3:\n                y_pred[:,0] = lpf(y_pred[:,0])\n                y_pred[:,1] = lpf(y_pred[:,1])\n            \n            after_RMSE = np.sqrt(mean_squared_error(y_pred, np.zeros_like(y_pred)))\n\n            decay_ratio = before_RMSE/after_RMSE\n            y_pred *= decay_ratio\n            \n            onset_candi = argrelmax(y_pred[:, 0], order=12*60*6) # 12*60*6 = 6hours\n            wakeup_candi = argrelmax(y_pred[:, 1], order=12*60*6) # 12*60*6 = 6hours\n            \n\n            series_id = ids[i]\n            try:                \n                onset_candi = onset_candi[0]\n                onset = pd.DataFrame({'series_id': [series_id]*len(onset_candi),\n                                     'step': onset_candi,\n                                     'score': y_pred[onset_candi, 0].reshape(-1),\n                                     'event': ['onset']*len(onset_candi)})\n            except:\n                 onset = pd.DataFrame()\n            \n            try:\n                wakeup_candi = wakeup_candi[0]\n                wakeup = pd.DataFrame({'series_id': [series_id]*len(wakeup_candi),\n                                     'step': wakeup_candi,\n                                     'score': y_pred[wakeup_candi, 1].reshape(-1),\n                                     'event': ['wakeup']*len(wakeup_candi)})\n            except:\n                wakeup = pd.DataFrame()\n            \n            submission = pd.concat([submission, onset, wakeup], axis=0)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:41.926933Z","iopub.execute_input":"2023-10-23T20:56:41.927230Z","iopub.status.idle":"2023-10-23T20:56:46.996131Z","shell.execute_reply.started":"2023-10-23T20:56:41.927200Z","shell.execute_reply":"2023-10-23T20:56:46.995020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = submission.sort_values(['series_id','step']).reset_index(drop=True)\nsubmission['row_id'] = submission.index.astype(int)\nsubmission['score'] = submission['score'].fillna(submission['score'].mean())\nsubmission = submission[['row_id','series_id','step','event','score']]\nsubmission.to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:46.997825Z","iopub.execute_input":"2023-10-23T20:56:46.998255Z","iopub.status.idle":"2023-10-23T20:56:47.016701Z","shell.execute_reply.started":"2023-10-23T20:56:46.998220Z","shell.execute_reply":"2023-10-23T20:56:47.015679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2023-10-23T20:56:47.018141Z","iopub.execute_input":"2023-10-23T20:56:47.018535Z","iopub.status.idle":"2023-10-23T20:56:47.032416Z","shell.execute_reply.started":"2023-10-23T20:56:47.018499Z","shell.execute_reply":"2023-10-23T20:56:47.031486Z"},"trusted":true},"execution_count":null,"outputs":[]}]}