{"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":"code","source":"pip install holidays","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-10-10T13:20:48.687041Z","iopub.execute_input":"2023-10-10T13:20:48.687450Z","iopub.status.idle":"2023-10-10T13:21:25.059344Z","shell.execute_reply.started":"2023-10-10T13:20:48.687417Z","shell.execute_reply":"2023-10-10T13:21:25.058053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Imports","metadata":{}},{"cell_type":"code","source":"import polars as pl\nimport pandas as pd\nimport numpy as np\n\nimport matplotlib.pyplot as plt\n\nfrom datetime import date\nimport holidays\n\nfrom sklearn.model_selection import train_test_split\nimport lightgbm as lgb\nfrom sklearn.metrics import classification_report","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:21:25.061986Z","iopub.execute_input":"2023-10-10T13:21:25.063250Z","iopub.status.idle":"2023-10-10T13:21:27.903745Z","shell.execute_reply.started":"2023-10-10T13:21:25.063203Z","shell.execute_reply":"2023-10-10T13:21:27.902407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Cel\n\nCelem tego konkursu jest wykrywanie początku snu oraz momentu przebudzenia się. Uczestnicy konkursu rozwijają modele trenowane na danych z akcelerometrów noszonych na nadgarstkach, aby określić stan snu danej osoby.\n\nData zakończenia: 6.120.2023","metadata":{}},{"cell_type":"markdown","source":"Mamy  wykryć te zdarzenia:\n* onset - początek snu\n* wakeup - koniec snu\n\nZasady:\n1. Jednokrotny okres snu musi trwać co najmniej 30 minut.\n2. Jednokrotny okres snu może być przerywany epizodami aktywności, które nie przekraczają 30 kolejnych minut.\n3. Nie można wykryć okienka snu, chyba że zegarek jest noszony przez cały ten czas (opisane poniżej).\n4. Najdłuższe okno snu w nocy jest jedynym, które jest rejestrowane.\n5. Jeśli nie można zidentyfikować żadnego ważnego okresu snu, nie rejestruje się ani początku, ani zakończenia snu tej nocy.\n6. Wydarzenia snu nie muszą przecinać się z linią czasu, dlatego nie ma twardej reguły, ile ich może wystąpić w określonym okresie. Niemniej jednak nie więcej niż jedno okno powinno być przypisane na noc. Na przykład osoba może mieć okno snu od 01:00 do 06:00 i od 19:00 do 23:30 w tym samym dniu kalendarzowym, choć przypisane do kolejnych nocy.\n7. Pomimo że każda seria jest ciągłym zapisem, mogą wystąpić okresy, gdy urządzenie z akcelerometrem było zdejmowane. Oznacza to okresy, w których występuje podejrzanie mała zmienność sygnałów z akcelerometru przez dłuższy okres czasu, co jest nierealistyczne dla typowych uczestników. Wydarzenia nie są oznaczane w tych okresach, a ty powinieneś powstrzymać się od prognozowania zdarzeń podczas tych okresów: prognoza zdarzenia zostanie oceniona jako fałszywy pozytyw.","metadata":{}},{"cell_type":"markdown","source":"# Upload train","metadata":{}},{"cell_type":"code","source":"merged_train = (\n    pd.read_parquet('/kaggle/input/detect-sleep-states-memory-decrease/train_series.parquet')\n    .merge(pd.read_parquet('/kaggle/input/detect-sleep-states-memory-decrease/train_events.parquet'), \n           on=['id_map', 'step'], how='left')\n    .drop(['timestamp_y'], axis=1)\n    .fillna({'night': 0, 'event': 0})\n    .assign(\n        # year=lambda x: x['timestamp_x'].dt.year.astype('uint16'),\n        month=lambda x: x['timestamp_x'].dt.month.astype('uint8'),\n        # day=lambda x: x['timestamp_x'].dt.day.astype('uint8'),\n        hour=lambda x: x['timestamp_x'].dt.hour.astype('uint8'),\n        # minute=lambda x: x['timestamp_x'].dt.minute.astype('uint8'),\n        # second=lambda x: x['timestamp_x'].dt.second.astype('uint8'),\n        day_name=lambda x: x['timestamp_x'].dt.dayofweek.astype('uint8'))\n\n)\nmerged_train.set_index('id_map', inplace=True)\n\nmerged_train.head(6)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:25:48.696582Z","iopub.execute_input":"2023-10-10T13:25:48.697044Z","iopub.status.idle":"2023-10-10T13:28:51.527739Z","shell.execute_reply.started":"2023-10-10T13:25:48.697014Z","shell.execute_reply":"2023-10-10T13:28:51.525483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* series_id - Unikalny identyfikator każdej serii akcelerometru.\n* step - Liczba całkowita oznaczająca krok czasowy dla każdej obserwacji w serii.\n* timestamp - Odpowiadająca daty i godzinie w formacie ISO 8601 %Y-%m-%dT%H:%M:%S%z.\n* anglez - Obliczony i opisany przez pakiet GGIR, miara pochodząca z poszczególnych składników akcelerometru, która jest powszechnie używana do wykrywania snu i odnosi się do kąta ręki względem osi pionowej ciała.\n* enmo - Obliczony i opisany przez pakiet GGIR, ENMO to norma euklidesowa minus jeden ze wszystkich sygnałów akcelerometru, przy czym wartości ujemne zaokrąglane są do zera. Choć w tej przestrzeni nie istnieje standardowa miara przyspieszenia, to jest to jedna z kilku powszechnie obliczanych cech.","metadata":{}},{"cell_type":"code","source":"merged_train.info()","metadata":{"execution":{"iopub.status.busy":"2023-10-09T19:54:02.721844Z","iopub.execute_input":"2023-10-09T19:54:02.722320Z","iopub.status.idle":"2023-10-09T19:54:02.747156Z","shell.execute_reply.started":"2023-10-09T19:54:02.722278Z","shell.execute_reply":"2023-10-09T19:54:02.745661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# zmienne kat_sin i kat_cos reprezentują dzień tygodnia \n#kat_sin odpowiada za pozycję w kierunku północ-południe, \n# a kat_cos w kierunku wschód-zachód. \n#Razem te dwie wartości tworzą wektor w przestrzeni dwuwymiarowej, \n#który precyzyjnie określa pozycję na okręgu\n\n# Zamiana nazw dni tygodnia na liczby i przypisanie ich do nowych kolumn\nmerged_train['day_sin'] = np.sin(2 * np.pi * merged_train['day_name'] / 7).astype('float32')\nmerged_train['day_cos'] = np.cos(2 * np.pi * merged_train['day_name'] / 7).astype('float32')\nmerged_train.drop(['day_name'], axis = 1, inplace = True)\nmerged_train.head(2)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:28:51.531740Z","iopub.execute_input":"2023-10-10T13:28:51.532319Z","iopub.status.idle":"2023-10-10T13:29:06.252959Z","shell.execute_reply.started":"2023-10-10T13:28:51.532278Z","shell.execute_reply":"2023-10-10T13:29:06.251775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"merged_train['date'] = merged_train['timestamp_x'].dt.date\nmerged_train.head(2)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:48:29.921287Z","iopub.execute_input":"2023-10-10T13:48:29.921792Z","iopub.status.idle":"2023-10-10T13:49:11.623887Z","shell.execute_reply.started":"2023-10-10T13:48:29.921756Z","shell.execute_reply":"2023-10-10T13:49:11.622355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"event_counts = merged_train['event'].value_counts()\n\ncount_1 = event_counts.get(1, 0)  \ncount_2 = event_counts.get(2, 0)  \n\ntotal_samples = len(merged_train)\npercentage_1 = (count_1 / total_samples) * 100\npercentage_2 = (count_2 / total_samples) * 100\n\nprint(f\"Procentowy udział etykiety 1: {percentage_1:}%\")\nprint(f\"Procentowy udział etykiety 2: {percentage_2:}%\")","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:29:06.254357Z","iopub.execute_input":"2023-10-10T13:29:06.254661Z","iopub.status.idle":"2023-10-10T13:29:06.984016Z","shell.execute_reply.started":"2023-10-10T13:29:06.254635Z","shell.execute_reply":"2023-10-10T13:29:06.982857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# dodanie kolumny 'holidays', gdzie wartość 1 oznacza, że tego dnia jest święto\n\nus_holidays = holidays.US()\nmerged_train['holidays'] = merged_train['timestamp_x'].dt.date.isin(us_holidays)\nmerged_train.head(2)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:38:12.317829Z","iopub.execute_input":"2023-10-10T13:38:12.318255Z","iopub.status.idle":"2023-10-10T13:39:00.557777Z","shell.execute_reply.started":"2023-10-10T13:38:12.318227Z","shell.execute_reply":"2023-10-10T13:39:00.556502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f' Data początkowa:', merged_train['timestamp_x'].min())\nprint(f' Data końcowa: ', merged_train['timestamp_x'].max())","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:37:57.862645Z","iopub.execute_input":"2023-10-10T13:37:57.863095Z","iopub.status.idle":"2023-10-10T13:37:58.662225Z","shell.execute_reply.started":"2023-10-10T13:37:57.863064Z","shell.execute_reply":"2023-10-10T13:37:58.661417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"merged_train[merged_train['date'] == '2019-01-02']","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:51:21.801869Z","iopub.execute_input":"2023-10-10T13:51:21.802336Z","iopub.status.idle":"2023-10-10T13:51:32.609034Z","shell.execute_reply.started":"2023-10-10T13:51:21.802298Z","shell.execute_reply":"2023-10-10T13:51:32.607801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'2018-01-01' in us_holidays","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:40:04.168476Z","iopub.execute_input":"2023-10-10T13:40:04.168944Z","iopub.status.idle":"2023-10-10T13:40:04.177467Z","shell.execute_reply.started":"2023-10-10T13:40:04.168909Z","shell.execute_reply":"2023-10-10T13:40:04.175994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"merged_train[merged_train['holidays'] == True]","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:39:00.559840Z","iopub.execute_input":"2023-10-10T13:39:00.560204Z","iopub.status.idle":"2023-10-10T13:39:00.775765Z","shell.execute_reply.started":"2023-10-10T13:39:00.560177Z","shell.execute_reply":"2023-10-10T13:39:00.774661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"holidays_counts = merged_train['holidays'].value_counts()\n \ncount = holidays_counts.get(1, 0)  \n\n# total_samples = len(merged_train)\npercentage = (count / total_samples) * 100\n\nprint(f\"Procentowy dni świątecznych holidays = 1: {percentage:}%\")","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:29:50.895210Z","iopub.execute_input":"2023-10-10T13:29:50.895795Z","iopub.status.idle":"2023-10-10T13:29:51.603618Z","shell.execute_reply.started":"2023-10-10T13:29:50.895758Z","shell.execute_reply":"2023-10-10T13:29:51.602727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:31:22.538622Z","iopub.execute_input":"2023-10-10T13:31:22.539060Z","iopub.status.idle":"2023-10-10T13:31:22.544951Z","shell.execute_reply.started":"2023-10-10T13:31:22.539030Z","shell.execute_reply":"2023-10-10T13:31:22.543325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"merged_train[merged_train['holidays'] == 1]","metadata":{"execution":{"iopub.status.busy":"2023-10-10T13:30:40.037423Z","iopub.execute_input":"2023-10-10T13:30:40.037858Z","iopub.status.idle":"2023-10-10T13:30:40.137597Z","shell.execute_reply.started":"2023-10-10T13:30:40.037828Z","shell.execute_reply":"2023-10-10T13:30:40.136390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## lag\nObliczamy różnicę między wartościami w danej kolumnie (anglez lub enmo) a wartościami opóźnionymi o jedną pozycję w dół w tej samej kolumnie. Duża różnica może pomóc w wykryciu wybudzenia.","metadata":{}},{"cell_type":"code","source":"merged_train['anglez_diff'] = merged_train['anglez'] - merged_train['anglez'].shift(1)\nmerged_train['enmo_diff'] = merged_train['enmo'] - merged_train['enmo'].shift(1)\nmerged_train.head(2)","metadata":{"execution":{"iopub.status.busy":"2023-10-09T19:54:57.237106Z","iopub.execute_input":"2023-10-09T19:54:57.237498Z","iopub.status.idle":"2023-10-09T19:54:58.487655Z","shell.execute_reply.started":"2023-10-09T19:54:57.237470Z","shell.execute_reply":"2023-10-09T19:54:58.486508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"def feature_extraction(data):\n\n    data['day_sin'] = np.sin(2 * np.pi * data['day_name'] / 7).astype('float32')\n    data['day_cos'] = np.cos(2 * np.pi * data['day_name'] / 7).astype('float32')\n    data.drop(['day_name'], axis=1, inplace=True)\n\n    # Sprawdzenie, czy data to amerykańskie święto\n    us_holidays = holidays.US()\n    data['holidays'] = data['timestamp'].dt.date.isin(us_holidays).astype('uint8')\n\n    # Obliczenie różnicy między kolumnami 'anglez' i 'enmo' oraz ich opóźnieniem\n    data['anglez_diff'] = data['anglez'] - data['anglez'].shift(1)\n    data['enmo_diff'] = data['enmo'] - data['enmo'].shift(1)\n\n    return data","metadata":{"execution":{"iopub.status.busy":"2023-10-09T19:54:58.489461Z","iopub.execute_input":"2023-10-09T19:54:58.489897Z","iopub.status.idle":"2023-10-09T19:54:58.498070Z","shell.execute_reply.started":"2023-10-09T19:54:58.489858Z","shell.execute_reply":"2023-10-09T19:54:58.496784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"columns = ['anglez', 'enmo', 'month', 'hour', 'day_sin', 'day_cos', 'holidays', 'anglez_diff', \n           'enmo_diff']\n\nX = merged_train.drop(['timestamp_x', 'event', 'night', 'step'], axis = 1)\ny = merged_train['event']\nX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42, shuffle = False)","metadata":{"execution":{"iopub.status.busy":"2023-10-09T19:54:58.499763Z","iopub.execute_input":"2023-10-09T19:54:58.500488Z","iopub.status.idle":"2023-10-09T19:55:15.436103Z","shell.execute_reply.started":"2023-10-09T19:54:58.500450Z","shell.execute_reply":"2023-10-09T19:55:15.434558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lgb_model = lgb.LGBMClassifier(\n    objective='multiclass',\n    num_class=3,\n    class_weight='balanced',  # Dostosowanie wag klas\n    random_state=42\n)\n\n# Trenowanie modelu\nlgb_model.fit(X_train, y_train)\n\ny_pred = lgb_model.predict(X_val)\n\n# Raport klasyfikacji\nreport = classification_report(y_val, y_pred)\nreport","metadata":{"execution":{"iopub.status.busy":"2023-10-09T19:55:35.623593Z","iopub.execute_input":"2023-10-09T19:55:35.623998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Link do metryki konkursu: https://www.kaggle.com/code/metric/event-detection-ap/notebook\n\n'This leaderboard is calculated with approximately 25% of the test data. The final results will be based on the other 75%, so the final standings may be different.'","metadata":{}},{"cell_type":"code","source":"test = (pl.scan_parquet('/kaggle/input/child-mind-institute-detect-sleep-states/test_series.parquet')\n                .with_columns(\n                    (\n                        (pl.col(\"timestamp\").str.strptime(pl.Datetime, \"%Y-%m-%dT%H:%M:%S%Z\")),\n                        (pl.col(\"timestamp\").str.strptime(pl.Datetime, \"%Y-%m-%dT%H:%M:%S%Z\").dt.year().alias(\"year\")),\n                        (pl.col(\"timestamp\").str.strptime(pl.Datetime, \"%Y-%m-%dT%H:%M:%S%Z\").dt.month().alias(\"month\")),\n                        (pl.col(\"timestamp\").str.strptime(pl.Datetime, \"%Y-%m-%dT%H:%M:%S%Z\").dt.day().alias(\"day\")),\n                        (pl.col(\"timestamp\").str.strptime(pl.Datetime, \"%Y-%m-%dT%H:%M:%S%Z\").dt.hour().alias(\"hour\")),\n                        (pl.col(\"timestamp\").str.strptime(pl.Datetime, \"%Y-%m-%dT%H:%M:%S%Z\").dt.minute().alias(\"minute\")),\n                        (pl.col(\"timestamp\").str.strptime(pl.Datetime, \"%Y-%m-%dT%H:%M:%S%Z\").dt.second().alias(\"second\")),\n                    )\n                )\n                .collect()\n                .to_pandas()\n               )\n\ntest","metadata":{"execution":{"iopub.status.busy":"2023-09-25T11:24:43.672562Z","iopub.execute_input":"2023-09-25T11:24:43.673261Z","iopub.status.idle":"2023-09-25T11:24:43.863476Z","shell.execute_reply.started":"2023-09-25T11:24:43.673224Z","shell.execute_reply":"2023-09-25T11:24:43.862279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test['day_name']=test['timestamp'].dt.dayofweek.astype('uint8')","metadata":{"execution":{"iopub.status.busy":"2023-09-25T11:24:43.864882Z","iopub.execute_input":"2023-09-25T11:24:43.865405Z","iopub.status.idle":"2023-09-25T11:24:43.873135Z","shell.execute_reply.started":"2023-09-25T11:24:43.865369Z","shell.execute_reply":"2023-09-25T11:24:43.871689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = feature_extraction(test)\ntest.head()","metadata":{"execution":{"iopub.status.busy":"2023-09-25T11:24:43.874713Z","iopub.execute_input":"2023-09-25T11:24:43.875167Z","iopub.status.idle":"2023-09-25T11:24:43.917415Z","shell.execute_reply.started":"2023-09-25T11:24:43.875124Z","shell.execute_reply":"2023-09-25T11:24:43.916159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"columns = ['anglez', 'enmo', 'month', 'hour', 'day_sin', 'day_cos', 'holidays', 'anglez_diff', \n           'enmo_diff']\n\nX_test = test[columns]\ny_pred_test = lgb_model.predict(X_test)\ny_prob_test = lgb_model.predict_proba(X_test)\n\nresults_df = pd.DataFrame({\n    'series_id': test['series_id'],          \n    'step': test['step'],            \n    'event': y_pred_test,                \n    'score': y_prob_test.max(axis=1)     \n})\n\nresults_df","metadata":{"execution":{"iopub.status.busy":"2023-09-25T11:24:43.918921Z","iopub.execute_input":"2023-09-25T11:24:43.919406Z","iopub.status.idle":"2023-09-25T11:24:43.950796Z","shell.execute_reply.started":"2023-09-25T11:24:43.919364Z","shell.execute_reply":"2023-09-25T11:24:43.949262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results_df = results_df[results_df['event'] != 0]\nresults_df = results_df.sort_values(by='score', ascending=False)\nresults_df.reset_index(drop=True, inplace=True)\nresults_df","metadata":{"execution":{"iopub.status.busy":"2023-09-25T11:24:43.952523Z","iopub.execute_input":"2023-09-25T11:24:43.953133Z","iopub.status.idle":"2023-09-25T11:24:43.975925Z","shell.execute_reply.started":"2023-09-25T11:24:43.953059Z","shell.execute_reply":"2023-09-25T11:24:43.974995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results_df['event'] = results_df['event'].map({1: 'onset', 2: 'wakeup'})\nresults_df['row_id'] = range(len(results_df))\nresults_df = results_df[['row_id', 'series_id', 'step', 'event', 'score']]\nresults_df","metadata":{"execution":{"iopub.status.busy":"2023-09-25T11:24:43.977256Z","iopub.execute_input":"2023-09-25T11:24:43.977594Z","iopub.status.idle":"2023-09-25T11:24:43.999478Z","shell.execute_reply.started":"2023-09-25T11:24:43.977564Z","shell.execute_reply":"2023-09-25T11:24:43.998429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-25T11:28:39.214665Z","iopub.execute_input":"2023-09-25T11:28:39.215138Z","iopub.status.idle":"2023-09-25T11:28:39.236139Z","shell.execute_reply.started":"2023-09-25T11:28:39.215102Z","shell.execute_reply":"2023-09-25T11:28:39.234821Z"},"trusted":true},"execution_count":null,"outputs":[]}]}