{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"accelerator":"TPU","colab":{"gpuType":"V5E1","provenance":[]},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":25954,"databundleVersionId":2091745,"sourceType":"competition"},{"sourceId":1297722,"sourceType":"datasetVersion","datasetId":750498},{"sourceId":2130303,"sourceType":"datasetVersion","datasetId":1278322}],"dockerImageVersionId":31193,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Подготовка к работе","metadata":{}},{"cell_type":"code","source":"# Установка пользовательского пакета\nimport shutil\nimport os\nshutil.copytree('../input/resnest50-fast-package/resnest-0.0.6b20200701/resnest', 'resnet', dirs_exist_ok=True)\nos.system('pip install \"./resnet\" --no-deps')","metadata":{"id":"hIJYjekCZzDi","outputId":"4a85c9d6-c283-4931-b4f3-ab80b1f32431","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:23:19.596352Z","iopub.execute_input":"2025-12-01T04:23:19.597062Z","iopub.status.idle":"2025-12-01T04:23:23.079627Z","shell.execute_reply.started":"2025-12-01T04:23:19.597037Z","shell.execute_reply":"2025-12-01T04:23:23.079007Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Imports\nimport pandas as pd\nimport numpy as np\nimport librosa as lb\nimport soundfile as sf\nimport cv2\nfrom pathlib import Path\nimport re\nimport torch\nfrom torch import nn\nfrom  torch.utils.data import Dataset, DataLoader\nfrom tqdm.notebook import tqdm\nimport time\nfrom resnest.torch import resnest50\nimport matplotlib.pyplot as plt\nimport IPython.display as ipd","metadata":{"id":"rP2OsInXZzDj","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:23:31.371596Z","iopub.execute_input":"2025-12-01T04:23:31.372129Z","iopub.status.idle":"2025-12-01T04:23:31.376434Z","shell.execute_reply.started":"2025-12-01T04:23:31.372081Z","shell.execute_reply":"2025-12-01T04:23:31.375604Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(device)","metadata":{"id":"4qrejWRQZzDk","outputId":"b0b11895-6dca-4527-dcb0-054a6967a54d","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:23:34.175172Z","iopub.execute_input":"2025-12-01T04:23:34.175682Z","iopub.status.idle":"2025-12-01T04:23:34.223264Z","shell.execute_reply.started":"2025-12-01T04:23:34.175659Z","shell.execute_reply":"2025-12-01T04:23:34.222331Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Переменные для вычислений\nNUM_CLASSES = 397\nSR = 32_000\nDURATION = 5\nTHRESH = 0.28","metadata":{"id":"wismW1b1ZzDk","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T05:07:48.275613Z","iopub.execute_input":"2025-12-01T05:07:48.275885Z","iopub.status.idle":"2025-12-01T05:07:48.280030Z","shell.execute_reply.started":"2025-12-01T05:07:48.275866Z","shell.execute_reply":"2025-12-01T05:07:48.279320Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Пути к файлам\nTEST_AUDIO_ROOT = Path(\"../input/birdclef-2021/test_soundscapes\")\nSAMPLE_SUB_PATH = \"../input/birdclef-2021/sample_submission.csv\"\nTARGET_PATH = None\nif not len(list(TEST_AUDIO_ROOT.glob(\"*.ogg\"))):\n    TEST_AUDIO_ROOT = Path(\"../input/birdclef-2021/train_soundscapes\")\n    SAMPLE_SUB_PATH = None\n    TARGET_PATH = Path(\"../input/birdclef-2021/train_soundscape_labels.csv\")","metadata":{"id":"M-jUpF-pZzDk","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:23:47.922230Z","iopub.execute_input":"2025-12-01T04:23:47.922500Z","iopub.status.idle":"2025-12-01T04:23:47.939615Z","shell.execute_reply.started":"2025-12-01T04:23:47.922482Z","shell.execute_reply":"2025-12-01T04:23:47.939099Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Основная часть","metadata":{}},{"cell_type":"markdown","source":"### Функции для обработки и визуализации данных","metadata":{}},{"cell_type":"code","source":"class MelSpecComputer:\n    # Класс-обёртка для вычисления мел-спектрограмм\n\n    def __init__(self, sr, n_mels, fmin, fmax, n_fft=None, hop_length=None):\n        self.sr = sr\n        self.n_mels = n_mels\n        self.fmin = fmin\n        self.fmax = fmax\n\n        # Параметры STFT — используем простые и управляемые значения\n        self.n_fft = n_fft if n_fft is not None else sr // 10        # ~100ms окно\n        self.hop_length = hop_length if hop_length is not None else sr // 40  # ~25ms сдвиг\n\n    def __call__(self, audio):\n        # Преобразует одномерный аудиосигнал в мел-спектрограмму\n        mel = lb.feature.melspectrogram(\n            y=audio,\n            sr=self.sr,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            fmax=self.fmax,\n        )\n\n        mel_db = lb.power_to_db(mel, ref=np.max).astype(np.float32)\n        return mel_db\n\n\n# Преобразование монохромного массива в 8-битовое изображение\ndef mono_to_color(arr, eps=1e-6, mean=None, std=None):\n    mu = arr.mean() if mean is None else mean\n    sigma = arr.std() if std is None else std\n\n    norm = (arr - mu) / (sigma + eps)\n\n    vmin, vmax = norm.min(), norm.max()\n\n    if abs(vmax - vmin) > eps:\n        img = np.clip(norm, vmin, vmax)\n        img = 255 * (img - vmin) / (vmax - vmin)\n        img = img.astype(np.uint8)\n    else:\n        img = np.zeros_like(arr, dtype=np.uint8)\n\n    return img\n\n\n# Обрезка или дополнение аудиосигнала до фиксированной длины\ndef crop_or_pad(signal, target_len):\n    cur_len = len(signal)\n\n    if cur_len < target_len:\n        pad_amt = target_len - cur_len\n        signal = np.concatenate([signal, np.zeros(pad_amt)])\n    elif cur_len > target_len:\n        signal = signal[:target_len]\n\n    return signal\n","metadata":{"id":"9woVfyAUZzDl","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T05:10:59.980500Z","iopub.execute_input":"2025-12-01T05:10:59.981081Z","iopub.status.idle":"2025-12-01T05:10:59.988543Z","shell.execute_reply.started":"2025-12-01T05:10:59.981057Z","shell.execute_reply":"2025-12-01T05:10:59.987883Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Функция для визуализации waveform\ndef plot_waveform(audio, sr, title=\"Waveform\"):\n    plt.figure(figsize=(12, 4))\n    lb.display.waveshow(audio, sr=sr)\n    plt.title(title)\n    plt.xlabel(\"Time (s)\")\n    plt.ylabel(\"Amplitude\")\n    plt.tight_layout()\n    plt.show()","metadata":{"id":"azdavx-uZzDl","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:23:54.680961Z","iopub.execute_input":"2025-12-01T04:23:54.681791Z","iopub.status.idle":"2025-12-01T04:23:54.686148Z","shell.execute_reply.started":"2025-12-01T04:23:54.681766Z","shell.execute_reply":"2025-12-01T04:23:54.685329Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Функция для визуализации mel-спектрограмм\ndef plot_mel_spectrogram(melspec, sr, hop_length, n_mels, title=\"Mel Spectrogram\"):\n    plt.figure(figsize=(12, 6))\n    lb.display.specshow(melspec, sr=sr, hop_length=hop_length, x_axis='time', y_axis='mel')\n    plt.colorbar(format='%+2.0f dB')\n    plt.title(title)\n    plt.tight_layout()\n    plt.show()","metadata":{"id":"1X8SwAWIZzDm","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:23:56.173119Z","iopub.execute_input":"2025-12-01T04:23:56.173417Z","iopub.status.idle":"2025-12-01T04:23:56.178166Z","shell.execute_reply.started":"2025-12-01T04:23:56.173395Z","shell.execute_reply":"2025-12-01T04:23:56.177154Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Функция для прослушивания аудио\ndef play_audio(audio, sr, title=\"Audio\"):\n    print(f\"Playing: {title}\")\n    display(ipd.Audio(audio, rate=sr))","metadata":{"id":"aOQfaxQoZzDm","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:23:57.996548Z","iopub.execute_input":"2025-12-01T04:23:57.996790Z","iopub.status.idle":"2025-12-01T04:23:58.000373Z","shell.execute_reply.started":"2025-12-01T04:23:57.996774Z","shell.execute_reply":"2025-12-01T04:23:57.999616Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Функция для выполнения визуализации и прослушивания\ndef process_and_visualize(dataset, num_samples=2):\n    for i in tqdm(range(min(len(dataset), num_samples)), desc=\"Processing and visualizing samples\"):\n        filepath = dataset.data.loc[i, \"filepath\"]\n        original_audio, sr = sf.read(filepath, dtype=\"float32\")\n\n        if dataset.resample_flag and sr != dataset.sr:\n            original_audio = lb.resample(original_audio, sr, dataset.sr, res_type=dataset.res_type)\n\n        # Прослушивание аудио\n        play_audio(original_audio, dataset.sr, title=f\"Sample {i+1}: {dataset.data.loc[i, 'filename']}\")\n\n        # Визуализация waveform\n        plot_waveform(original_audio, dataset.sr, title=f\"Waveform for {dataset.data.loc[i, 'filename']}\")\n\n        # Вычисление mel-спектрограммы для визуализации\n        melspec_for_plot = dataset.mel_comp(original_audio)\n        # Визуализация mel-спектрограммы\n        plot_mel_spectrogram(melspec_for_plot, dataset.sr, dataset.mel_comp.hop_length, dataset.n_mels, title=f\"Mel Spectrogram for {dataset.data.loc[i, 'filename']}\")\n","metadata":{"id":"2854Q7OtZzDn","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:23:59.458877Z","iopub.execute_input":"2025-12-01T04:23:59.459516Z","iopub.status.idle":"2025-12-01T04:23:59.464829Z","shell.execute_reply.started":"2025-12-01T04:23:59.459491Z","shell.execute_reply":"2025-12-01T04:23:59.464006Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Dataset для обработки аудиозаписей птиц\nclass BirdCLEFDataset(Dataset):\n    def __init__(\n        self,\n        data,\n        sr=SR,\n        n_mels=128,\n        fmin=0,\n        fmax=None,\n        duration=DURATION,\n        step=None,\n        res_type=\"kaiser_fast\",\n        resample=True,\n        tta=True\n    ):\n        self.data = data\n\n        self.sr = sr\n        self.n_mels = n_mels\n        self.fmin = fmin\n        self.fmax = fmax if fmax is not None else sr // 2\n\n        self.duration = duration\n        self.segment_len = self.duration * self.sr\n        self.step = step if step is not None else self.segment_len\n\n        self.res_type = res_type\n        self.resample_flag = resample\n        self.tta = tta\n        # подготовка мел-спектрографа\n        self.mel_comp = MelSpecComputer(\n            sr=self.sr,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            fmax=self.fmax\n        )\n\n    def __len__(self):\n        return len(self.data)\n    @staticmethod\n    def normalize(img):\n        img = img.astype(\"float32\") / 255.0\n        return np.stack([img, img, img], axis=0)\n\n    def audio_to_image(self, audio_chunk):\n        mel = self.mel_comp(audio_chunk)\n        colored = mono_to_color(mel)\n        return self.normalize(colored)\n\n    def apply_tta(self, audio):\n        # random gain 0.9–1.1\n        gain = np.random.uniform(0.9, 1.1)\n        audio = audio * gain\n\n        return audio\n\n    def read_file(self, filepath):\n        audio, orig_sr = sf.read(filepath, dtype=\"float32\")\n\n        if self.resample_flag and orig_sr != self.sr:\n            audio = lb.resample(audio, orig_sr, self.sr, res_type=self.res_type)\n\n        if self.tta:\n            audio = self.apply_tta(audio)\n\n        # Разделение аудио на фрагменты фиксированной длины\n        chunks = []\n        for pos in range(self.segment_len, len(audio) + self.step, self.step):\n            start_idx = max(0, pos - self.segment_len)\n            end_idx = start_idx + self.segment_len\n            chunks.append(audio[start_idx:end_idx])\n\n        if len(chunks) == 0:\n            chunks = [crop_or_pad(audio, self.segment_len)]\n\n        # конвертация в изображения\n        images = [self.audio_to_image(chunk) for chunk in chunks]\n\n        return np.stack(images, axis=0)\n\n    def __getitem__(self, idx):\n        return self.read_file(self.data.loc[idx, \"filepath\"])\n","metadata":{"id":"soaUTf4JZzDn","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T05:17:24.564558Z","iopub.execute_input":"2025-12-01T05:17:24.565078Z","iopub.status.idle":"2025-12-01T05:17:24.575592Z","shell.execute_reply.started":"2025-12-01T05:17:24.565054Z","shell.execute_reply":"2025-12-01T05:17:24.574654Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = pd.DataFrame(\n     [(path.stem, *path.stem.split(\"_\"), path) for path in Path(TEST_AUDIO_ROOT).glob(\"*.ogg\")],\n    columns = [\"filename\", \"id\", \"site\", \"date\", \"filepath\"]\n)\nprint(data.shape)\ndata.head()","metadata":{"id":"NPqa2Zh2ZzDn","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T05:17:28.991375Z","iopub.execute_input":"2025-12-01T05:17:28.991657Z","iopub.status.idle":"2025-12-01T05:17:29.004836Z","shell.execute_reply.started":"2025-12-01T05:17:28.991636Z","shell.execute_reply":"2025-12-01T05:17:29.004057Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Обучающие данные и информация о лейблах\ndf_train = pd.read_csv(\"../input/birdclef-2021/train_metadata.csv\")\n\nLABEL_IDS = {label: label_id for label_id,label in enumerate(sorted(df_train[\"primary_label\"].unique()))}\nINV_LABEL_IDS = {val: key for key,val in LABEL_IDS.items()}\n\ntest_data = BirdCLEFDataset(data=data)\nlen(test_data), test_data[0].shape","metadata":{"id":"ZEaypQKqZzDo","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T05:17:33.243237Z","iopub.execute_input":"2025-12-01T05:17:33.243740Z","iopub.status.idle":"2025-12-01T05:17:35.559309Z","shell.execute_reply.started":"2025-12-01T05:17:33.243717Z","shell.execute_reply":"2025-12-01T05:17:35.558580Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Функция для визуализации\nprocess_and_visualize(test_data, num_samples=2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:57:14.745819Z","iopub.execute_input":"2025-12-01T04:57:14.746120Z","iopub.status.idle":"2025-12-01T04:57:26.700916Z","shell.execute_reply.started":"2025-12-01T04:57:14.746074Z","shell.execute_reply":"2025-12-01T04:57:26.699795Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Работа с предобученной моделью ResNeSt","metadata":{}},{"cell_type":"code","source":"def load_net(checkpoint_path, num_classes=NUM_CLASSES):\n    # Загружает сверточную сеть ResNeSt50, \n    # модифицирует финальный слой под нужное\n    # количество классов и восстанавливает \n    # веса из чекпоинта.\n\n    # Создаём модель без предобученных параметров\n    model = resnest50(pretrained=False)\n\n    # Меняем последний классификатор на собственный\n    out_features = model.fc.in_features\n    model.fc = nn.Linear(out_features, num_classes)\n\n    # Загружаем веса на CPU\n    saved = torch.load(checkpoint_path, map_location=\"cpu\")\n\n    # Удаляем префикс \"model.\" у ключей, если он присутствует\n    cleaned_state = {}\n    for k, v in saved.items():\n        new_key = k.split(\"model.\")[-1]   # удаляет только ведущий \"model.\"\n        cleaned_state[new_key] = v\n\n    # Применяем обновлённый словарь весов\n    model.load_state_dict(cleaned_state)\n\n    # Отправляем на устройство и ставим в режим inference\n    model = model.to(device)\n    model.eval()\n\n    return model\n","metadata":{"id":"B6ohWTX-ZzDo","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:24:54.964346Z","iopub.execute_input":"2025-12-01T04:24:54.965161Z","iopub.status.idle":"2025-12-01T04:24:54.970240Z","shell.execute_reply.started":"2025-12-01T04:24:54.965134Z","shell.execute_reply":"2025-12-01T04:24:54.969625Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"checkpoint_paths = [\n    Path(\"../input/kkiller-birdclef-models-public/birdclef_resnest50_fold0_epoch_10_f1_val_06471_20210417161101.pth\"),\n]\n\nnets = [\n        load_net(checkpoint_path.as_posix()) for checkpoint_path in checkpoint_paths\n]","metadata":{"id":"rv1bQeqKZzDo","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:25:16.063027Z","iopub.execute_input":"2025-12-01T04:25:16.063754Z","iopub.status.idle":"2025-12-01T04:25:18.463165Z","shell.execute_reply.started":"2025-12-01T04:25:16.063731Z","shell.execute_reply":"2025-12-01T04:25:18.462585Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Постобработка предсказаний\n@torch.no_grad()\ndef get_thresh_preds(out, thresh=None):\n    thresh = thresh or THRESH\n    o = (-out).argsort(1)\n    npreds = (out > thresh).sum(1)\n    preds = []\n    for oo, npred in zip(o, npreds):\n        preds.append(oo[:npred].cpu().numpy().tolist())\n    return preds","metadata":{"id":"GRTQoEeyZzDo","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T05:10:38.315526Z","iopub.execute_input":"2025-12-01T05:10:38.316199Z","iopub.status.idle":"2025-12-01T05:10:38.320958Z","shell.execute_reply.started":"2025-12-01T05:10:38.316175Z","shell.execute_reply":"2025-12-01T05:10:38.320236Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_bird_names(preds):\n    bird_names = []\n    for pred in preds:\n        if not pred:\n            bird_names.append(\"nocall\")\n        else:\n            bird_names.append(\" \".join([INV_LABEL_IDS[bird_id] for bird_id in pred]))\n    return bird_names","metadata":{"id":"Va7ToNbVZzDo","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:57:50.789243Z","iopub.execute_input":"2025-12-01T04:57:50.789569Z","iopub.status.idle":"2025-12-01T04:57:50.794821Z","shell.execute_reply.started":"2025-12-01T04:57:50.789546Z","shell.execute_reply":"2025-12-01T04:57:50.793983Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Функция для предсказания\ndef predict(nets, test_data, names=True):\n    preds = []\n    with torch.no_grad():\n        for idx in  tqdm(list(range(len(test_data)))):\n            xb = torch.from_numpy(test_data[idx]).to(device)\n            pred = 0.\n            for net in nets:\n                o = net(xb)\n                o = torch.sigmoid(o)\n\n                pred += o\n\n            pred /= len(nets)\n\n            if names:\n                pred = get_bird_names(get_thresh_preds(pred))\n\n            preds.append(pred)\n    return preds","metadata":{"id":"KmQ7sQhbZzDp","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:58:02.952313Z","iopub.execute_input":"2025-12-01T04:58:02.952597Z","iopub.status.idle":"2025-12-01T04:58:02.958010Z","shell.execute_reply.started":"2025-12-01T04:58:02.952575Z","shell.execute_reply":"2025-12-01T04:58:02.957119Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred_prob = predict(nets, test_data, names=False)\nprint(len(pred_prob))","metadata":{"id":"xZXC41OJZzDp","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:25:38.433768Z","iopub.execute_input":"2025-12-01T04:25:38.434048Z","iopub.status.idle":"2025-12-01T04:26:22.884236Z","shell.execute_reply.started":"2025-12-01T04:25:38.434025Z","shell.execute_reply":"2025-12-01T04:26:22.883311Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preds = [get_bird_names(get_thresh_preds(pred, thresh=THRESH)) for pred in pred_prob]","metadata":{"id":"S1hqjOB0ZzDp","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:26:29.365571Z","iopub.execute_input":"2025-12-01T04:26:29.365851Z","iopub.status.idle":"2025-12-01T04:26:29.593564Z","shell.execute_reply.started":"2025-12-01T04:26:29.365829Z","shell.execute_reply":"2025-12-01T04:26:29.592706Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def preds_as_df(data, preds):\n    sub = {\n        \"row_id\": [],\n        \"birds\": [],\n    }\n\n    for row, pred in zip(data.itertuples(False), preds):\n        row_id = [f\"{row.id}_{row.site}_{5*i}\" for i in range(1, len(pred)+1)]\n        sub[\"birds\"] += pred\n        sub[\"row_id\"] += row_id\n\n    sub = pd.DataFrame(sub)\n\n    if SAMPLE_SUB_PATH:\n        sample_sub = pd.read_csv(SAMPLE_SUB_PATH, usecols=[\"row_id\"])\n        sub = sample_sub.merge(sub, on=\"row_id\", how=\"left\")\n        sub[\"birds\"] = sub[\"birds\"].fillna(\"nocall\")\n    return sub","metadata":{"id":"vnXnqjdOZzDp","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:26:35.059107Z","iopub.execute_input":"2025-12-01T04:26:35.059420Z","iopub.status.idle":"2025-12-01T04:26:35.064776Z","shell.execute_reply.started":"2025-12-01T04:26:35.059397Z","shell.execute_reply":"2025-12-01T04:26:35.063907Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sub = preds_as_df(data, preds)\nprint(sub.shape)\nsub","metadata":{"id":"PQ7f819bZzDp","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:26:39.346082Z","iopub.execute_input":"2025-12-01T04:26:39.346609Z","iopub.status.idle":"2025-12-01T04:26:39.361992Z","shell.execute_reply.started":"2025-12-01T04:26:39.346584Z","shell.execute_reply":"2025-12-01T04:26:39.361221Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Сохранение результатов\nsub.to_csv(\"submission.csv\", index=False)","metadata":{"id":"rxjL-WnuZzDp","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T04:26:43.241263Z","iopub.execute_input":"2025-12-01T04:26:43.241561Z","iopub.status.idle":"2025-12-01T04:26:43.249593Z","shell.execute_reply.started":"2025-12-01T04:26:43.241541Z","shell.execute_reply":"2025-12-01T04:26:43.248951Z"}},"outputs":[],"execution_count":null}]}