{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":53666,"databundleVersionId":6589269,"sourceType":"competition"},{"sourceId":8288280,"sourceType":"datasetVersion","datasetId":4847251}],"dockerImageVersionId":30673,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from math import ceil, exp, log\nfrom datetime import timedelta\nimport warnings\nwarnings.simplefilter(action='ignore', category=FutureWarning)\n\nimport numpy as np\nimport pandas as pd\nimport pyarrow.parquet as pq\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom tqdm.auto import tqdm\nimport torch \nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision.transforms.functional as TF\nfrom torch.optim.lr_scheduler import StepLR\n\nnot_nan_series_ids = [\n    '08db4255286f',\n    '0a96f4993bd7',\n    '0cfc06c129cc',\n    '1087d7b0ff2e',\n    '10f8bc1f7b07',\n    '18b61dd5aae8',\n    '29c75c018220',\n    '31011ade7c0a',\n    '3452b878e596',\n    '349c5562ee2c',\n    '3664fe9233f9',\n    '483d6545417f',\n    '55a47ff9dc8a',\n    '5acc9d63b5fd',\n    '5f94bb3e1bed',\n    '655f19eabf1e',\n    '67f5fc60e494',\n    '72bbd1ac3edf',\n    '76237b9406d5',\n    '7822ee8fe3ec',\n    '89bd631d1769',\n    '8e32047cbc1f',\n    '939932f1822d',\n    '9ee455e4770d',\n    'a596ad0b82aa',\n    'a9a2f7fac455',\n    'a9e5f5314bcb',\n    'af91d9a50547',\n    'b364205aba43',\n    'c535634d7dcd',\n    'c6788e579967',\n    'c68260cc9e8f',\n    'ca730dbf521d',\n    'd150801f3145',\n    'd25e479ecbb7',\n    'd515236bdeec',\n    'd5e47b94477e'\n]\n\ntorch.cuda.is_available()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-05-17T08:40:58.456291Z","iopub.execute_input":"2024-05-17T08:40:58.456664Z","iopub.status.idle":"2024-05-17T08:41:03.062137Z","shell.execute_reply.started":"2024-05-17T08:40:58.456635Z","shell.execute_reply":"2024-05-17T08:41:03.061003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_data_from_pq_to_pd(data_path: str, n_series: int = None):\n    print('Чтение parquet данных')\n    data = pq.read_table(data_path)\n    print('Переводим в DataFrame')\n    data = data.to_pandas(categories=['string', 'int', 'datetime', 'float', 'float'])\n    if n_series is not None:\n        series_ids = data.series_id.unique()\n        data = data[data.series_id.isin(series_ids[:n_series])]\n    print('Переводим в правильный datetime')\n#     data.timestamp = pd.to_datetime(data.timestamp, format=\"%Y-%m-%dT%H:%M:%S%z\")\n    print('Отбираем not Nan временные ряды')\n    data = data[data.series_id.isin(not_nan_series_ids)]\n    \n    print('Types of columns:')\n    print(data.dtypes, end='\\n\\n')\n    print('Shape:', data.shape)\n    return data","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:03.063939Z","iopub.execute_input":"2024-05-17T08:41:03.064386Z","iopub.status.idle":"2024-05-17T08:41:03.071259Z","shell.execute_reply.started":"2024-05-17T08:41:03.064359Z","shell.execute_reply":"2024-05-17T08:41:03.070336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# series_data = get_data_from_pq_to_pd('/kaggle/input/child-mind-institute-detect-sleep-states/train_series.parquet')","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:03.072696Z","iopub.execute_input":"2024-05-17T08:41:03.072977Z","iopub.status.idle":"2024-05-17T08:41:03.093326Z","shell.execute_reply.started":"2024-05-17T08:41:03.072953Z","shell.execute_reply":"2024-05-17T08:41:03.092417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"series_data = pd.read_csv('/kaggle/input/train-series/series_data.csv')\n# series_data[\"timestamp\"] = pd.to_datetime(series_data[\"timestamp\"])\nseries_data.drop(columns=['Unnamed: 0', 'timestamp'], inplace=True)\nprint(series_data.shape)\nseries_data.head()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:03.096003Z","iopub.execute_input":"2024-05-17T08:41:03.096861Z","iopub.status.idle":"2024-05-17T08:41:23.729751Z","shell.execute_reply.started":"2024-05-17T08:41:03.096827Z","shell.execute_reply":"2024-05-17T08:41:23.728812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# series_data.groupby('series_id').step.max()\n# train_series.series_id.unique()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:23.731094Z","iopub.execute_input":"2024-05-17T08:41:23.731455Z","iopub.status.idle":"2024-05-17T08:41:23.736480Z","shell.execute_reply.started":"2024-05-17T08:41:23.731420Z","shell.execute_reply":"2024-05-17T08:41:23.735209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"events_data = pd.read_csv(r'/kaggle/input/train-series/events_data.csv') # r'/kaggle/input/child-mind-institute-detect-sleep-states/train_events.csv')\nevents_data = events_data[events_data.series_id.isin(series_data.series_id.unique())] \nevents_data.drop(columns=['Unnamed: 0', 'timestamp'], inplace=True)\nevents_data.step = events_data[events_data.step.notna()].step.astype(int)\nprint('Shape:', events_data.shape)\nevents_data.head()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:23.737604Z","iopub.execute_input":"2024-05-17T08:41:23.737841Z","iopub.status.idle":"2024-05-17T08:41:24.886316Z","shell.execute_reply.started":"2024-05-17T08:41:23.737820Z","shell.execute_reply":"2024-05-17T08:41:24.885331Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"assert(set(events_data.series_id.unique()) - set(series_data.series_id.unique()) == set())","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:24.887416Z","iopub.execute_input":"2024-05-17T08:41:24.887690Z","iopub.status.idle":"2024-05-17T08:41:26.025770Z","shell.execute_reply.started":"2024-05-17T08:41:24.887666Z","shell.execute_reply":"2024-05-17T08:41:26.024976Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# events_data.groupby('series_id').step.max()\n# train_events.series_id.unique()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:26.026897Z","iopub.execute_input":"2024-05-17T08:41:26.027201Z","iopub.status.idle":"2024-05-17T08:41:26.031139Z","shell.execute_reply.started":"2024-05-17T08:41:26.027175Z","shell.execute_reply":"2024-05-17T08:41:26.030210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"events_data.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:26.032185Z","iopub.execute_input":"2024-05-17T08:41:26.032426Z","iopub.status.idle":"2024-05-17T08:41:26.046769Z","shell.execute_reply.started":"2024-05-17T08:41:26.032403Z","shell.execute_reply":"2024-05-17T08:41:26.045894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Разделим данные на тренировочную и тестовую выборки\ntest_size = round(0.2 * len(not_nan_series_ids))\nprint('Train size:', len(not_nan_series_ids) - test_size)\nprint('Test size:', test_size)\n\ntest_series = series_data[series_data.series_id.isin(not_nan_series_ids[:test_size])]\ntrain_series = series_data[series_data.series_id.isin(not_nan_series_ids[test_size:])]\nprint('Test series shape:', test_series.shape)\nprint('Train series shape:', train_series.shape)\n\ntest_events = events_data[events_data.series_id.isin(not_nan_series_ids[:test_size])]\ntrain_events = events_data[events_data.series_id.isin(not_nan_series_ids[test_size:])]\nprint('Test events shape:', test_events.shape)\nprint('Train events shape:', train_events.shape)\n\ndel(series_data)\ndel(events_data)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:26.049206Z","iopub.execute_input":"2024-05-17T08:41:26.049473Z","iopub.status.idle":"2024-05-17T08:41:28.398445Z","shell.execute_reply.started":"2024-05-17T08:41:26.049450Z","shell.execute_reply":"2024-05-17T08:41:28.397422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"assert(set(test_series.series_id.unique()) & set(train_series.series_id.unique()) == set())\nassert(set(test_events.series_id.unique()) & set(train_events.series_id.unique()) == set())","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:28.399806Z","iopub.execute_input":"2024-05-17T08:41:28.400196Z","iopub.status.idle":"2024-05-17T08:41:29.537081Z","shell.execute_reply.started":"2024-05-17T08:41:28.400161Z","shell.execute_reply":"2024-05-17T08:41:29.536269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Добавим метки и посмотрим на распределение сегментов\n\n(НЕ работает)","metadata":{"_kg_hide-input":false}},{"cell_type":"code","source":"# train_series = get_data_from_pq_to_pd(r'/kaggle/input/child-mind-institute-detect-sleep-states/train_series.parquet', 4)\n# train_series.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def add_class_label_to_train_series(train_series: pd.DataFrame, train_events: pd.DataFrame):\n    prev_step = -1\n    for elem in train_events[['series_id', 'step', 'event']].T.to_dict().values():\n        indexes = train_series[(prev_step < train_series.step) & (train_series.step <= elem['step']) & (train_series.series_id == elem['series_id'])].index\n        train_series.loc[indexes, 'event'] = elem['event']\n        prev_step = elem['step']","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_train_series_with_class_mark(train_series: pd.DataFrame, train_events: pd.DataFrame, y_column_name: str = 'anglez'):\n    na_val = train_series[train_series.event.isna()].iloc[0]['event']\n    palette = {\n        'onset': 'tab:orange',\n        'wakeup': 'tab:green'\n    }\n    fig, axs = plt.subplots(train_series.series_id.nunique(), 1, figsize=(35, 5))\n    plt.subplots_adjust(hspace = 0.5)\n    if train_series.series_id.nunique() != 1:\n        for ax, series_id in zip(axs, train_series.series_id.unique()):\n            plot_data = train_series[train_series.series_id == series_id]\n            sns.lineplot(plot_data, x='step', y=y_column_name, color='blue', ax=ax, label='No data').set(title=series_id)\n            sns.lineplot(plot_data, x='step', y=y_column_name, hue='event', palette=palette, ax=ax)\n    else:\n        plot_data = train_series\n        ax = axs\n        series_id = train_series.series_id.unique()[0]\n        sns.lineplot(plot_data, x='step', y=y_column_name, color='blue', ax=ax, label='No data').set(title=series_id)\n        sns.lineplot(plot_data, x='step', y=y_column_name, hue='event', palette=palette, ax=ax)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Нужно добавить метки классов перед визуализацией\nadd_class_label_to_train_series(train_series, train_events)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_train_series_with_class_mark(train_series, train_events, 'enmo')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_train_series_with_class_mark(train_series, train_events, 'anglez')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Попробуем сегментировать с помощью методов МО","metadata":{}},{"cell_type":"code","source":"enmo_train_series = train_series.enmo.to_frame()\nenmo_train_series['timestamp'] = train_series.timestamp\n# enmo_train_series['event'] = train_series.event\nenmo_train_series = enmo_train_series.set_index('timestamp')\nprint('Shape:', enmo_train_series.shape)\nenmo_train_series.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"downsampled_enmo = enmo_train_series.resample('5min').mean()\nprint('Shape:', downsampled_enmo.shape)\ndownsampled_enmo.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"downsampled_enmo.plot()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install sktime","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sktime.annotation.plotting.utils import plot_time_series_with_change_points\nfrom sktime.annotation.clasp import ClaSPSegmentation, find_dominant_window_sizes\nfrom sktime.annotation.ggs import GreedyGaussianSegmentation","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Реальное распределение меток\ntrain_id = 'a9e5f5314bcb' # '349c5562ee2c'\nplot_time_series_with_change_points('Enmo', train_series[train_series.series_id == train_id].enmo, train_events[train_events.series_id == train_id].step)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"steps = train_events[train_events.step.notna()].step.astype(int)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"temp_data = normalize(train_dataset[0][1])[1].numpy()\ntemp_label = [train_dataset[0][2][0].argmax(), train_dataset[0][2][1].argmax()]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Сегментация с помощью Clasp\nclasp = ClaSPSegmentation(period_length=70, n_cps=2, fmt=\"sparse\")\nfound_cps = clasp.fit_predict(temp_data) #downsampled_enmo.enmo)\nprofiles = clasp.profiles\nscores = clasp.scores\nprint(\"The found change points are\", found_cps.to_numpy())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_time_series_with_change_points('Enmo', pd.Series(temp_data), found_cps)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_time_series_with_change_points('Enmo', pd.Series(temp_data), temp_label)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.argmax(temp_data)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Сегментация с помощью GreedyGaussian\nmodel = GreedyGaussianSegmentation(k_max=45, lamb=0.1)\nmodel.fit_predict(downsampled_enmo.enmo)\nprint(\"The found change points are\", model.change_points_)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Корректируем предсказания GreedyGaussian\nfound_cps = model.change_points_\nfound_cps[-1] -= 1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_time_series_with_change_points('Enmo', downsampled_enmo.enmo, found_cps)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Пробуем вытащить некоторые данные с временного ряда","metadata":{}},{"cell_type":"markdown","source":"Посмотрим на сезонность и тренд","metadata":{}},{"cell_type":"code","source":"from statsmodels.tsa.seasonal import seasonal_decompose","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"decompose = seasonal_decompose(enmo_train_series, period=60*60*24//5)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"decompose.plot()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Как видим, сезонность и тренд отсутствуют. Проверим ряд на стационарность","metadata":{}},{"cell_type":"code","source":"from statsmodels.tsa.stattools import adfuller","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"adf_test = adfuller(enmo_train_series['enmo'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('p-value = ' + str(adf_test[1]))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ряд не стационарен","metadata":{}},{"cell_type":"markdown","source":"## Используем CNN для сегментация\n\nДля этого вначале нужно построить Dataset и DataLoader","metadata":{}},{"cell_type":"code","source":"class ChildMindDataset(Dataset):\n    def __init__(self, series_data: pd.DataFrame, event_data: pd.DataFrame):\n        self.ids, self._data, self._labels = self.__divide_series_into_parts(series_data, event_data)\n        \n    def __divide_series_into_parts(self, series_data: pd.DataFrame, event_data: pd.DataFrame):\n        series_parts_data = []\n        series_parts_labels = []\n        series_parts_ids = []\n        part_size = 17280 # 60*60*24/5 = 17280 - длительность суток\n        # Итерируемся по каждому временному ряду\n        for series_id, series_data in series_data.groupby('series_id'):\n            # Берем вектор 'enmo' и 'anglez' для конкретного временного ряда\n            enmo_anglez_data = series_data[['enmo', 'anglez']]\n            # Делим значения enmo и anglez на куски одного размера \n            parts_data = [enmo_anglez_data.iloc[part_size * i: part_size * (i + 1)] for i in range(ceil(len(enmo_anglez_data) / part_size))]\n            # Поправляем последний кусок, чтобы он был единого со всеми размера \n            if len(parts_data[-1]) < part_size:\n                new_index = np.arange(part_size)\n                parts_data[-1] = parts_data[-1].reindex(new_index, fill_value=0)\n            assert(len(parts_data[-1]) == part_size)\n            parts_data = [torch.from_numpy(df.to_numpy()).float() for df in parts_data]\n            series_parts_data.extend(parts_data)\n            \n            # Берем метки для конкретного временного ряда\n            labels = event_data[event_data.series_id == series_id]\n            # Собираем для каждого куска временные метки\n            for i in range(len(parts_data)):\n                # Сохраняем id временного ряда\n                series_parts_ids.append(series_id)\n                # Собираем метки wakeup, onset для даннного куска временного ряда \n                part_labels = labels[(part_size * i < labels.step) & (labels.step < part_size * (i + 1))]            \n                # Переводим временные метки в вектор heatmap размера (2, 17280)\n                # Отдельно по onset и wakeup\n                heatmaps_onset = []\n                heatmaps_wakeup = []\n                for _, part_label in part_labels.iterrows():\n                    heatmap = self._get_gaussian_heatmap_series(part_label.step % part_size, part_size)\n                    if part_label.event == 'onset':\n                        heatmaps_onset.append(heatmap)\n                    else:\n                        heatmaps_wakeup.append(heatmap)\n                heatmaps_onset = np.array(heatmaps_onset)\n                heatmaps_wakeup = np.array(heatmaps_wakeup)\n                # Если меток для данного временного куска не нашлось,\n                # то оставляем heatmap пустым\n                if len(heatmaps_onset) == 0:\n#                     print('empty onset id:', series_id)\n                    heatmaps_onset = np.zeros((1, part_size))\n                if len(heatmaps_wakeup) == 0:\n#                     print('empty wakeup id:', series_id)\n                    heatmaps_wakeup = np.zeros((1, part_size))\n                \n                # Собираем общий heatmap\n                heatmap_label = np.array([\n                    self._min_max_norm(heatmaps_onset.sum(axis=0)),\n                    self._min_max_norm(heatmaps_wakeup.sum(axis=0))\n                ])\n                # Сохраняем куски с временными метками в общий список данных\n                heatmap_label = torch.from_numpy(heatmap_label.T).float()\n                series_parts_labels.append(heatmap_label)\n        return series_parts_ids, series_parts_data, series_parts_labels\n    \n    def _min_max_norm(self, array: np.array) -> np.array:\n        min_val = np.min(array)\n        max_val = np.max(array)\n        if max_val - min_val == 0:\n            return array\n        else:\n            return (array - min_val) / (max_val - min_val)\n    \n    def _get_gaussian_heatmap_series(self, x_border: int, series_len: int, sigma: int=5) -> list:\n        heatmap = [exp(- (elem - x_border)**2 / (2 * sigma**2)) for elem in range(series_len)]\n        return heatmap\n        \n    def __len__(self) -> int:     \n        return len(self._data)\n    \n    def __getitem__(self, idx):\n        series__part_id = self.ids[idx]\n        series_part_data = self._data[idx]\n        series_part_label = self._labels[idx]\n        return series__part_id, series_part_data, series_part_label","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:52.229957Z","iopub.execute_input":"2024-05-17T08:41:52.230331Z","iopub.status.idle":"2024-05-17T08:41:52.250393Z","shell.execute_reply.started":"2024-05-17T08:41:52.230295Z","shell.execute_reply":"2024-05-17T08:41:52.249392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = ChildMindDataset(train_series, train_events)\ntest_dataset = ChildMindDataset(test_series, test_events)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:41:53.252931Z","iopub.execute_input":"2024-05-17T08:41:53.253304Z","iopub.status.idle":"2024-05-17T08:42:21.905157Z","shell.execute_reply.started":"2024-05-17T08:41:53.253274Z","shell.execute_reply":"2024-05-17T08:42:21.904298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset[0][2].shape","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:42:31.485885Z","iopub.execute_input":"2024-05-17T08:42:31.486515Z","iopub.status.idle":"2024-05-17T08:42:31.492558Z","shell.execute_reply.started":"2024-05-17T08:42:31.486480Z","shell.execute_reply":"2024-05-17T08:42:31.491606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_dataset)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataloader = DataLoader(train_dataset, batch_size=5, shuffle=True)\ntest_dataloader = DataLoader(test_dataset, batch_size=5, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:42:35.877221Z","iopub.execute_input":"2024-05-17T08:42:35.878227Z","iopub.status.idle":"2024-05-17T08:42:35.883415Z","shell.execute_reply.started":"2024-05-17T08:42:35.878183Z","shell.execute_reply":"2024-05-17T08:42:35.882338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_ts_label(label):\n    label = label.cpu().numpy()\n    fig, axs = plt.subplots(ncols=2, figsize=(10, 5))\n    for i in range(2):\n        peak_num = label[i].argmax()\n        left = peak_num - 50 if peak_num - 50 > 0 else 0\n        right = peak_num + 50 if peak_num + 50 < 17280 else 50\n        print(f'left: {left}, right: {right}')\n        axs[i].bar(np.arange(len(label[i, left:right])), label[i, left:right])","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:42:39.813833Z","iopub.execute_input":"2024-05-17T08:42:39.814211Z","iopub.status.idle":"2024-05-17T08:42:39.821313Z","shell.execute_reply.started":"2024-05-17T08:42:39.814180Z","shell.execute_reply":"2024-05-17T08:42:39.820103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_ts_label(train_dataset[0][2])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"temp_series = train_dataset[0][2][:,0]\nfig, ax = plt.subplots()\nleft = 3500 # 7000\nright = 3600 #13200 #\nax.bar(np.arange(len(temp_series[0, left:right])), temp_series[0, left:right])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# temp_series = train_dataset[0][2]\n# fig, ax = plt.subplots()\n# left = 10000\n# right = 10100 \n# ax.bar(np.arange(len(temp_series[1, left:right])), temp_series[1, left:right])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i, data in enumerate(train_dataset):\n#     print(i)\n#     print(data)\n    assert(data[1].shape == (2, 17280))\n    assert(data[2].shape == (2, 17280))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Строим модель сегментации ","metadata":{}},{"cell_type":"code","source":"class SerialSegNet(nn.Module):\n    def __init__(self, in_ch: int=2, out_ch: int=2, layer_ch_num: list[int] = [10, 20, 30]):\n        assert(len(layer_ch_num) >= 3)\n        super(SerialSegNet, self).__init__()\n        self._in_ch = in_ch\n        self._out_ch = out_ch\n                \n        self._max_unpool = nn.MaxUnpool1d(4, stride=4)\n        self._max_pool = nn.MaxPool1d(4, stride=4, return_indices=True)\n        \n        self._layer_enc1 = self._create_enc_block(self._in_ch, layer_ch_num[0])\n        self._layer_enc2 = self._create_enc_block(layer_ch_num[0], layer_ch_num[1])\n        self._layer_enc3 = self._create_enc_block(layer_ch_num[1], layer_ch_num[2])\n        \n        self._layer_dec1 = self._create_dec_block(layer_ch_num[2], layer_ch_num[1])\n        self._layer_dec2 = self._create_dec_block(layer_ch_num[1], layer_ch_num[0])\n        self._layer_dec3 = self._create_dec_block(layer_ch_num[0], self._out_ch)\n        \n        self._bottleneck = self._create_conv_block(layer_ch_num[2], layer_ch_num[2])\n        \n    def _create_conv_block(self, in_ch: int, out_ch: int):\n        return nn.Sequential(\n            nn.Conv1d(in_ch, out_ch, kernel_size=7, padding=3, stride=1),\n            nn.BatchNorm1d(out_ch),\n            nn.ReLU()\n        )\n    \n    def _create_enc_block(self, in_ch: int, out_ch: int):\n        first_conv = self._create_conv_block(in_ch, out_ch)\n        second_conv = self._create_conv_block(out_ch, out_ch)\n        return nn.Sequential(\n            first_conv,\n            second_conv\n        )\n    \n    def _create_dec_block(self, in_ch: int, out_ch: int):\n        first_conv = self._create_conv_block(in_ch, out_ch)\n        second_conv = self._create_conv_block(out_ch, out_ch)\n        return nn.Sequential(\n            first_conv,\n            second_conv\n        )\n    \n    def forward(self, x):\n        x = self._layer_enc1(x)\n        skip1 = x\n        x, ind1 = self._max_pool(x)\n        size1 = x.size()\n        \n        x = self._layer_enc2(x)\n        skip2 = x\n        x, ind2 = self._max_pool(x)\n        size2 = x.size()\n        \n        x = self._layer_enc3(x)\n        skip3 = x\n        x, ind3 = self._max_pool(x)\n        \n        x = self._bottleneck(x)\n        \n        x = torch.cat((skip3, x), dim=1)\n        x = self._max_unpool(x, ind3, output_size=size2)\n        x = self._layer_dec1(x)\n        \n        x = self._max_unpool(x, ind2, output_size=size1)\n        x = self._layer_dec2(x)\n        x = torch.cat((skip2, x), dim=1)\n        \n        x = self._max_unpool(x, ind1)\n        x = self._layer_dec3(x)\n        x = torch.cat((skip1, x), dim=1)\n        \n        x = F.softmax(x, dim=1)\n        \n        return x\n        ","metadata":{"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DoubleConv(nn.Module):\n    def __init__(self, in_channels, out_channels):\n        super(DoubleConv, self).__init__()\n        self.conv = nn.Sequential(\n            nn.Conv1d(in_channels, out_channels, 3, 1, 1, bias=False),\n            nn.BatchNorm1d(out_channels),\n            nn.ReLU(inplace=True),\n            nn.Conv1d(out_channels, out_channels, 3, 1, 1, bias=False),\n            nn.BatchNorm1d(out_channels),\n            nn.ReLU(inplace=True),\n        )\n\n    def forward(self, x):\n        return self.conv(x)\n\nclass UNET(nn.Module):\n    def __init__(\n            self, in_channels=3, out_channels=1, features=[64, 128, 256, 512],\n    ):\n        super(UNET, self).__init__()\n        self.ups = nn.ModuleList()\n        self.downs = nn.ModuleList()\n        self.pool = nn.MaxPool1d(kernel_size=2, stride=2)\n\n        # Down part of UNET\n        for feature in features:\n            self.downs.append(DoubleConv(in_channels, feature))\n            in_channels = feature\n\n        # Up part of UNET\n        for feature in reversed(features):\n            self.ups.append(\n                nn.ConvTranspose1d(\n                    feature*2, feature, kernel_size=2, stride=2,\n                )\n            )\n            self.ups.append(DoubleConv(feature*2, feature))\n\n        self.bottleneck = DoubleConv(features[-1], features[-1]*2)\n        self.final_conv = nn.Conv1d(features[0], out_channels, kernel_size=1)\n\n    def forward(self, x):\n        skip_connections = []\n\n        for down in self.downs:\n            x = down(x)\n            skip_connections.append(x)\n            x = self.pool(x)\n\n        x = self.bottleneck(x)\n        skip_connections = skip_connections[::-1]\n\n        for idx in range(0, len(self.ups), 2):\n            x = self.ups[idx](x)\n            skip_connection = skip_connections[idx//2]\n\n            if x.shape != skip_connection.shape:\n                x = TF.resize(x, size=skip_connection.shape[2:])\n\n            concat_skip = torch.cat((skip_connection, x), dim=1)\n            x = self.ups[idx+1](concat_skip)\n\n        return self.final_conv(x)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:42:42.718505Z","iopub.execute_input":"2024-05-17T08:42:42.718872Z","iopub.status.idle":"2024-05-17T08:42:42.733320Z","shell.execute_reply.started":"2024-05-17T08:42:42.718842Z","shell.execute_reply":"2024-05-17T08:42:42.732420Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ResidualBiGRU(nn.Module):\n    def __init__(self, hidden_size, n_layers=1, bidir=True):\n        super(ResidualBiGRU, self).__init__()\n\n        self.hidden_size = hidden_size\n        self.n_layers = n_layers\n\n        self.gru = nn.GRU(\n            hidden_size,\n            hidden_size,\n            n_layers,\n            batch_first=True,\n            bidirectional=bidir,\n        )\n        dir_factor = 2 if bidir else 1\n        self.fc1 = nn.Linear(\n            hidden_size * dir_factor, hidden_size * dir_factor * 2\n        )\n        self.ln1 = nn.LayerNorm(hidden_size * dir_factor * 2)\n        self.fc2 = nn.Linear(hidden_size * dir_factor * 2, hidden_size)\n        self.ln2 = nn.LayerNorm(hidden_size)\n\n    def forward(self, x, h=None):\n        res, new_h = self.gru(x, h)\n        # res.shape = (batch_size, sequence_size, 2*hidden_size)\n\n        res = self.fc1(res)\n        res = self.ln1(res)\n        res = nn.functional.relu(res)\n\n        res = self.fc2(res)\n        res = self.ln2(res)\n        res = nn.functional.relu(res)\n\n        # skip connection\n        res = res + x\n\n        return res, new_h\n\nclass MultiResidualBiGRU(nn.Module):\n    def __init__(self, input_size, hidden_size, out_size, n_layers, bidir=True):\n        super(MultiResidualBiGRU, self).__init__()\n\n        self.input_size = input_size\n        self.hidden_size = hidden_size\n        self.out_size = out_size\n        self.n_layers = n_layers\n\n        self.fc_in = nn.Linear(input_size, hidden_size)\n        self.ln = nn.LayerNorm(hidden_size)\n        self.res_bigrus = nn.ModuleList(\n            [\n                ResidualBiGRU(hidden_size, n_layers=1, bidir=bidir)\n                for _ in range(n_layers)\n            ]\n        )\n        self.fc_out = nn.Linear(hidden_size, out_size)\n\n    def forward(self, x, h=None):\n        # if we are at the beginning of a sequence (no hidden state)\n        if h is None:\n            # (re)initialize the hidden state\n            h = [None for _ in range(self.n_layers)]\n\n        x = self.fc_in(x)\n        x = self.ln(x)\n        x = nn.functional.relu(x)\n\n        new_h = []\n        for i, res_bigru in enumerate(self.res_bigrus):\n            x, new_hi = res_bigru(x, h[i])\n            new_h.append(new_hi)\n\n        x = self.fc_out(x)\n#         x = F.normalize(x,dim=0)\n        return x, new_h  # log probabilities + hidden states","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:42:43.209710Z","iopub.execute_input":"2024-05-17T08:42:43.210149Z","iopub.status.idle":"2024-05-17T08:42:43.226880Z","shell.execute_reply.started":"2024-05-17T08:42:43.210110Z","shell.execute_reply":"2024-05-17T08:42:43.225800Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def mse_loss_with_border_regularization(output, target):\n#     loss = torch.mean((output - target)**2)\n#     borders_mask = (torch.nonzero(train_dataset[0][2] >= 0.8)*1).float()\n#     predict_mask = (torch.nonzero(train_dataset[0][2] >= 0.8)*1).float()    \n#     loss = torch.mean((predict_mask - borders_mask)**2)\n#     return loss","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:42:43.889215Z","iopub.execute_input":"2024-05-17T08:42:43.889582Z","iopub.status.idle":"2024-05-17T08:42:43.893813Z","shell.execute_reply.started":"2024-05-17T08:42:43.889553Z","shell.execute_reply":"2024-05-17T08:42:43.892884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def normalize(y):\n    mean = y[:,0].mean().item()\n    std = y[:,0].std().item()\n    y[:,0] = (y[:,0]-mean)/(std+1e-16)\n    mean = y[:,1].mean().item()\n    std = y[:,1].std().item()\n    y[:,1] = (y[:,1]-mean)/(std+1e-16)\n    return y","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class WingLoss(nn.Module):\n    def __init__(self, omega=10, epsilon=2):\n        super(WingLoss, self).__init__()\n        self.omega = omega\n        self.epsilon = epsilon\n\n    def forward(self, pred, target):\n        y = target\n        y_hat = pred\n        delta_y = (y - y_hat).abs()\n        delta_y1 = delta_y[delta_y < self.omega]\n        delta_y2 = delta_y[delta_y >= self.omega]\n        loss1 = self.omega * torch.log(1 + delta_y1 / self.epsilon)\n        C = self.omega - self.omega * log(1 + self.omega / self.epsilon)\n        loss2 = delta_y2 - C\n        return (loss1.sum() + loss2.sum()) / (len(loss1) + len(loss2))","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:42:46.997276Z","iopub.execute_input":"2024-05-17T08:42:46.997661Z","iopub.status.idle":"2024-05-17T08:42:47.005558Z","shell.execute_reply.started":"2024-05-17T08:42:46.997632Z","shell.execute_reply":"2024-05-17T08:42:47.004571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def validate_epoch(model, test_loader):\n    model.eval()\n    valid_loss = []\n    tq = tqdm(test_loader)\n    with torch.no_grad():\n        for i, (serial_ids, test_data, test_labels) in enumerate(test_loader):\n            tq.set_description(f'Val Batch: {i+1}')\n            tq.update()\n            if torch.cuda.is_available():\n                test_data = test_data.cuda()\n                test_labels = test_labels.cuda()\n            \n            outputs = model(test_data)\n            loss = loss_fn(outputs, test_labels.float())\n            valid_loss.append(loss.item())\n    return valid_loss","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:43:24.498801Z","iopub.execute_input":"2024-05-17T08:43:24.499316Z","iopub.status.idle":"2024-05-17T08:43:24.506100Z","shell.execute_reply.started":"2024-05-17T08:43:24.499282Z","shell.execute_reply":"2024-05-17T08:43:24.505048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_epoch(model, train_loader, loss_fn, optimizer):\n    model.train()\n    train_loss = []\n    tq = tqdm(train_loader)\n    for i, (serial_ids, train_data, train_labels) in enumerate(train_loader):\n        tq.set_description(f'Train Batch: {i+1}')\n        tq.update()\n        if torch.cuda.is_available():\n            train_data = train_data.cuda()\n            train_labels = train_labels.cuda()\n\n        optimizer.zero_grad()\n        outputs = model(train_data)\n\n        loss = loss_fn(outputs, train_labels.float())\n        loss.backward()\n        optimizer.step()\n        train_loss.append(loss.item())\n    return train_loss","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:43:24.713033Z","iopub.execute_input":"2024-05-17T08:43:24.713363Z","iopub.status.idle":"2024-05-17T08:43:24.720212Z","shell.execute_reply.started":"2024-05-17T08:43:24.713337Z","shell.execute_reply":"2024-05-17T08:43:24.719284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def fit(model, loss_fn, optimizer, train_loader, test_loader, epoch_num: int, scheduler=None):\n    cuda_available = torch.cuda.is_available()\n    print('Cuda available:', cuda_available)\n    if cuda_available:\n        model.cuda()\n    \n    train_loss_collector = []\n    valid_loss_collector = []\n    tq = tqdm(range(epoch_num))\n    for epoch in tq:\n        tq.set_description(f'Epoch: {epoch+1}')\n        train_loss = train_epoch(model, train_loader, loss_fn, optimizer)\n        valid_loss = validate_epoch(model, test_loader)\n        train_loss_collector.append(np.mean(train_loss))\n        valid_loss_collector.append(np.mean(valid_loss))\n        if scheduler is not None:\n            scheduler.step()\n    return train_loss_collector, valid_loss_collector  ","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:43:24.905817Z","iopub.execute_input":"2024-05-17T08:43:24.906182Z","iopub.status.idle":"2024-05-17T08:43:24.913114Z","shell.execute_reply.started":"2024-05-17T08:43:24.906152Z","shell.execute_reply":"2024-05-17T08:43:24.912121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ch_num = 32\n# model = UNET(in_channels=2, out_channels=2, features=[ch_num, ch_num*2, ch_num*4, ch_num*8])\nmodel = MultiResidualBiGRU(input_size=2,hidden_size=5,out_size=2,n_layers=5)\n\nloss_fn = nn.MSELoss() # WingLoss()   \noptimizer = torch.optim.Adam(model.parameters(), lr=3e-4) #3e-4)\nscheduler = StepLR(optimizer, step_size=1, gamma=0.5)\n\ntrain_loss, val_loss = fit(model, loss_fn, optimizer, train_dataloader, test_dataloader, 8, scheduler)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T08:43:25.432205Z","iopub.execute_input":"2024-05-17T08:43:25.433016Z","iopub.status.idle":"2024-05-17T08:43:26.498511Z","shell.execute_reply.started":"2024-05-17T08:43:25.432985Z","shell.execute_reply":"2024-05-17T08:43:26.497114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.lineplot(train_loss)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.lineplot(val_loss)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"temp_data = next(iter(test_dataloader))\ntemp_value = temp_data[1].cuda()\ntemp_label = temp_data[2].cuda()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\nNone","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with torch.no_grad():\n    model.cuda()\n    model_output = model(temp_value)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_output[0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = model_output[0].cpu()\nfig, ax = plt.subplots()\nleft = 0\nright = 11000 \nax.bar(np.arange(len(data[0, left:right])), data[0, left:right])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_ts_label(temp_label[0])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_ts_label(model_output[0])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_fn(normalize(model_output[0]).float(), temp_label[0])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ы","metadata":{},"execution_count":null,"outputs":[]}]}