{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91844,"databundleVersionId":11361821,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":322698,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":271927,"modelId":292625},{"sourceId":347627,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":271928,"modelId":292625}],"dockerImageVersionId":30918,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Homework 3","metadata":{}},{"cell_type":"markdown","source":"## Imports","metadata":{}},{"cell_type":"code","source":"import os\nimport random\nfrom pathlib import Path\n\nimport cv2\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\n\nimport librosa\n\nimport torch\nfrom torch import nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\n\nimport torchaudio\nfrom torchaudio.transforms import TimeMasking, FrequencyMasking\n\nimport torchvision\nfrom torchvision import models\nfrom torchvision.transforms import functional as F_t\n\nimport timm\n\nfrom sklearn.metrics import roc_auc_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:23.208423Z","iopub.execute_input":"2025-04-20T19:50:23.208672Z","iopub.status.idle":"2025-04-20T19:50:38.085313Z","shell.execute_reply.started":"2025-04-20T19:50:23.208649Z","shell.execute_reply":"2025-04-20T19:50:38.084274Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Config","metadata":{}},{"cell_type":"code","source":"class CFG:\n    SUBMISSION = True\n    num_workers = 4\n\n    OUTPUT_DIR = '/kaggle/working/'\n\n    train_datadir = Path('/kaggle/input/birdclef-2025/train_audio')\n    train_csv = '/kaggle/input/birdclef-2025/train.csv'\n    test_soundscapes = Path('/kaggle/input/birdclef-2025/test_soundscapes')\n    submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n    taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n    # model_path = '/kaggle/input/bird_v1/pytorch/crossentropy_loss/1/model_crossentropy_loss.pt'\n    model_path = '/kaggle/input/bird_v1/pytorch/bceloss/3/model_bce_loss(2).pt'\n\n    model_name = 'efficientnet_b1'\n\n    SR = 32000\n    TARGET_DURATION = 5.0\n    TARGET_SHAPE = (256, 256)\n    \n    N_FFT = 1024\n    HOP_LENGTH = 512\n    N_MELS = 128\n    FMIN = 50\n    FMAX = 14000\n    \n    device = 'cuda' if torch.cuda.is_available() else 'cpu'\n    num_epochs = 10\n    batch_size = 64\n\ncfg = CFG()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.086405Z","iopub.execute_input":"2025-04-20T19:50:38.086913Z","iopub.status.idle":"2025-04-20T19:50:38.096497Z","shell.execute_reply.started":"2025-04-20T19:50:38.086883Z","shell.execute_reply":"2025-04-20T19:50:38.095251Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Read Prepare model","metadata":{}},{"cell_type":"markdown","source":"It's a usual efficient_net model, since it fast, small and shows good results on ImageNet. Also, I wanted to use YOLOv11 for classification and MobileNet, but they showed worse results on ImageNet, so I decided do not waste time.","metadata":{}},{"cell_type":"code","source":"class BirdCLEFModel(nn.Module):\n    def __init__(self, cfg, num_classes):\n        super().__init__()\n        self.cfg = cfg\n        \n        self.backbone = timm.create_model(\n            cfg.model_name,\n            pretrained=not cfg.SUBMISSION,\n            in_chans=1,\n            drop_rate=0.2,    \n            drop_path_rate=0.2\n        )\n        \n        backbone_out = self.backbone.classifier.in_features\n        self.backbone.classifier = nn.Linear(backbone_out, num_classes)\n        \n    def forward(self, x):\n        logits = self.backbone(x)\n        return logits","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.097904Z","iopub.execute_input":"2025-04-20T19:50:38.098346Z","iopub.status.idle":"2025-04-20T19:50:38.124676Z","shell.execute_reply.started":"2025-04-20T19:50:38.098286Z","shell.execute_reply":"2025-04-20T19:50:38.123610Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Prepare dataset","metadata":{}},{"cell_type":"code","source":"taxonomies = pd.read_csv(cfg.taxonomy_csv)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.125759Z","iopub.execute_input":"2025-04-20T19:50:38.126116Z","iopub.status.idle":"2025-04-20T19:50:38.156221Z","shell.execute_reply.started":"2025-04-20T19:50:38.126086Z","shell.execute_reply":"2025-04-20T19:50:38.155102Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tax2id = {t[\"primary_label\"]: i for i, t in taxonomies.iterrows()}\nid2tax = {i: t for t, i in tax2id.items()}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.157215Z","iopub.execute_input":"2025-04-20T19:50:38.157543Z","iopub.status.idle":"2025-04-20T19:50:38.177125Z","shell.execute_reply.started":"2025-04-20T19:50:38.157508Z","shell.execute_reply":"2025-04-20T19:50:38.176083Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def audio2melspec(audio_data, cfg):\n    # Convert raw audio to Log Mel Spectogram and normalize\n    mel_spec = librosa.feature.melspectrogram(\n        y=audio_data,\n        sr=cfg.SR,\n        n_fft=cfg.N_FFT,\n        hop_length=cfg.HOP_LENGTH,\n        n_mels=cfg.N_MELS,\n        fmin=cfg.FMIN,\n        fmax=cfg.FMAX,\n        power=2.0\n    )\n\n    mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n    mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n    \n    return mel_spec_norm\n\n\ndef process_audio_segment(audio_data, cfg):\n    # add padding if needed, if audio is less than 5s\n    if len(audio_data) < cfg.SR * cfg.TARGET_DURATION:\n        audio_data = np.pad(\n            audio_data, \n            (0, int(cfg.SR * cfg.TARGET_DURATION - len(audio_data))), \n            mode='constant'\n        )\n    \n    mel_spec = audio2melspec(audio_data, cfg)\n\n    # most models were trained on 224x224, so resize spectogram to this size\n    if mel_spec.shape != cfg.TARGET_SHAPE:\n        mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n\n    return mel_spec.astype(np.float32)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.180485Z","iopub.execute_input":"2025-04-20T19:50:38.180803Z","iopub.status.idle":"2025-04-20T19:50:38.196541Z","shell.execute_reply.started":"2025-04-20T19:50:38.180762Z","shell.execute_reply":"2025-04-20T19:50:38.195448Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(cfg.train_csv)\ndf.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.198313Z","iopub.execute_input":"2025-04-20T19:50:38.198689Z","iopub.status.idle":"2025-04-20T19:50:38.440728Z","shell.execute_reply.started":"2025-04-20T19:50:38.198660Z","shell.execute_reply":"2025-04-20T19:50:38.439691Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = df[['primary_label', 'filename', 'secondary_labels']]\ndf.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.441871Z","iopub.execute_input":"2025-04-20T19:50:38.442271Z","iopub.status.idle":"2025-04-20T19:50:38.459282Z","shell.execute_reply.started":"2025-04-20T19:50:38.442240Z","shell.execute_reply":"2025-04-20T19:50:38.458392Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"melspecs = {}\n\n\ndef process_item(item):\n    # load audio and take middle 5s (I hope middle 5s is representive)\n    audio_path = cfg.train_datadir / item[\"filename\"]\n    waveform, sample_rate = librosa.load(audio_path, sr=cfg.SR)\n    \n    length = int(cfg.TARGET_DURATION * cfg.SR)\n\n    step = length // 2\n\n    start = max(0, waveform.shape[0] // 2 - length)\n    end = min(waveform.shape[0], waveform.shape[0] // 2 + 1)\n\n    mel_specs = []\n    for i in range(start, end, step):\n        waveform = waveform[i : i + length]\n        mel_spec = process_audio_segment(waveform, cfg)\n        mel_specs.append( mel_spec )\n    \n    secondary_labels = eval(item[\"secondary_labels\"])\n    label = [item[\"primary_label\"]] + secondary_labels\n\n    labels = [tax2id[i] for i in label if i]\n    \n    return item[\"filename\"], mel_specs, labels\n\n\nif not cfg.SUBMISSION:\n    ## use 4 threads to convert audio 2 log mel spectogram\n    from concurrent.futures import ThreadPoolExecutor, as_completed\n\n    with ThreadPoolExecutor(max_workers=cfg.num_workers) as executor:\n        futures = [executor.submit(process_item, item) for _, item in df.iterrows()]\n\n        for future in tqdm(as_completed(futures), total=len(futures)):\n            filename, mel_specs, labels = future.result()\n\n            for i, m in enumerate(mel_specs):\n                melspecs[f\"{filename}_{i}\"] = {\n                    \"mel_spec\": m,\n                    \"labels\": labels\n                }","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.460305Z","iopub.execute_input":"2025-04-20T19:50:38.460697Z","iopub.status.idle":"2025-04-20T19:50:38.481385Z","shell.execute_reply.started":"2025-04-20T19:50:38.460667Z","shell.execute_reply":"2025-04-20T19:50:38.480008Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class BirdDataset(Dataset):\n    def __init__(self, melspecs):\n        self.melspecs = list(melspecs.values())\n\n        self.time_mask = TimeMasking(time_mask_param=50)\n        self.freq_mask = FrequencyMasking(freq_mask_param=30)\n\n    def __len__(self):\n        return len(self.melspecs)\n\n    def random_brightness_contrast(self, mel_spec):\n        # Apply random brightness and contrast\n        mel_spec = F_t.adjust_brightness(mel_spec, random.uniform(0.7, 1.3))\n        mel_spec = F_t.adjust_contrast(mel_spec, random.uniform(0.7, 1.3))\n\n        return mel_spec\n\n    def __getitem__(self, idx):\n        item = self.melspecs[idx]\n\n        # mel spectogram\n        mel_spec = torch.Tensor( item[\"mel_spec\"] ).unsqueeze(0)\n\n        # Augmentation: Time masking\n        if random.random() < 0.5:\n            mel_spec = self.time_mask(mel_spec)\n        \n        # Augmentation: Frequency masking\n        if random.random() < 0.5:\n            mel_spec = self.freq_mask(mel_spec)\n\n        # Augmentation: Random brightness/contrast\n        if random.random() < 0.5:\n            mel_spec = self.random_brightness_contrast(mel_spec)\n\n        labels = item[\"labels\"]\n        \n        targets = np.zeros((len(tax2id), ))\n        targets[labels] = 1.0\n    \n        return mel_spec, targets","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.482346Z","iopub.execute_input":"2025-04-20T19:50:38.482637Z","iopub.status.idle":"2025-04-20T19:50:38.507943Z","shell.execute_reply.started":"2025-04-20T19:50:38.482611Z","shell.execute_reply":"2025-04-20T19:50:38.506944Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if not cfg.SUBMISSION:\n    # create datasets/dataloaders\n    from sklearn.model_selection import train_test_split\n    \n    # train_df, val_df = train_test_split(df, test_size=0.2, random_state=42)\n    \n    # train_df = train_df.reset_index(drop=True)\n    # val_df = val_df.reset_index(drop=True)\n\n    filenames = list(melspecs.keys())\n    train_files, val_files = train_test_split(filenames, test_size=0.2, random_state=42)\n    \n    # Reconstruct train and val dicts\n    train_data = {fname: melspecs[fname] for fname in train_files}\n    val_data = {fname: melspecs[fname] for fname in val_files}\n    \n    train_ds = BirdDataset(train_data)\n    val_ds = BirdDataset(val_data,)\n    \n    train_dl = DataLoader(train_ds, batch_size=cfg.batch_size, shuffle=True, drop_last=True, num_workers=4, pin_memory=True)\n    val_dl = DataLoader(val_ds, batch_size=cfg.batch_size, num_workers=4, pin_memory=True)\n\n    print(len(train_ds), len(train_dl))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.509044Z","iopub.execute_input":"2025-04-20T19:50:38.509386Z","iopub.status.idle":"2025-04-20T19:50:38.535810Z","shell.execute_reply.started":"2025-04-20T19:50:38.509350Z","shell.execute_reply":"2025-04-20T19:50:38.534722Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = BirdCLEFModel(cfg, len(id2tax))\n\nif cfg.SUBMISSION:\n    model.load_state_dict(torch.load(cfg.model_path, weights_only=True))\n    model.eval()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:38.536849Z","iopub.execute_input":"2025-04-20T19:50:38.537172Z","iopub.status.idle":"2025-04-20T19:50:39.413070Z","shell.execute_reply.started":"2025-04-20T19:50:38.537145Z","shell.execute_reply":"2025-04-20T19:50:39.412180Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sum(p.numel() for p in model.parameters()) / 1_000_000","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:39.413942Z","iopub.execute_input":"2025-04-20T19:50:39.414207Z","iopub.status.idle":"2025-04-20T19:50:39.421767Z","shell.execute_reply.started":"2025-04-20T19:50:39.414185Z","shell.execute_reply":"2025-04-20T19:50:39.420527Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if not cfg.SUBMISSION:\n    backbone_params = [p for n, p in model.backbone.named_parameters() if \"classifier\" not in n]\n\n    optimizer = torch.optim.Adam([\n        {\n            'params': backbone_params,\n            'lr': 1e-4\n        },\n        {\n            'params': model.backbone.classifier.parameters(),\n            'lr': 1e-3\n        },\n    ])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:39.422859Z","iopub.execute_input":"2025-04-20T19:50:39.423190Z","iopub.status.idle":"2025-04-20T19:50:39.437543Z","shell.execute_reply.started":"2025-04-20T19:50:39.423151Z","shell.execute_reply":"2025-04-20T19:50:39.436505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sum(p.numel() for p in model.parameters() if p.requires_grad) / 1_000_000","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:39.438582Z","iopub.execute_input":"2025-04-20T19:50:39.438909Z","iopub.status.idle":"2025-04-20T19:50:39.458418Z","shell.execute_reply.started":"2025-04-20T19:50:39.438871Z","shell.execute_reply":"2025-04-20T19:50:39.457450Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def macro_roc_auc_with_positive_labels(y_true: np.ndarray, y_score: np.ndarray) -> float:\n    positive_cols = y_true.sum(axis=0) > 0\n\n    return roc_auc_score(y_true[:, positive_cols],\n                         y_score[:, positive_cols],\n                         average='macro')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:39.459508Z","iopub.execute_input":"2025-04-20T19:50:39.459812Z","iopub.status.idle":"2025-04-20T19:50:39.475855Z","shell.execute_reply.started":"2025-04-20T19:50:39.459785Z","shell.execute_reply":"2025-04-20T19:50:39.474692Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if not cfg.SUBMISSION:\n    model.to(cfg.device)\n\n    # BCELossWithLogits showed better results (expected)\n    # since we need to predict 1 class, but many. And we need to maximize their probs\n    loss_fn = nn.BCEWithLogitsLoss()\n    \n    for epoch in range(1, cfg.num_epochs + 1):\n        model.train()\n        \n        train_loss = 0\n        all_train_true = []\n        all_train_scores = []\n    \n        for x, y in tqdm(train_dl):\n            x, y = x.to(cfg.device), y.to(cfg.device)\n            optimizer.zero_grad()\n    \n            logits = model(x)\n            loss = loss_fn(logits, y)\n            loss.backward()\n            optimizer.step()\n    \n            train_loss += loss.item() * x.size(0)\n    \n            y_true_batch = y\n            probs = torch.sigmoid(logits)\n\n            all_train_true.append(y_true_batch.cpu().detach().numpy())\n            all_train_scores.append(probs.cpu().detach().numpy())\n    \n        train_true = np.vstack(all_train_true)\n        train_scores = np.vstack(all_train_scores)\n        train_auc = macro_roc_auc_with_positive_labels(train_true, train_scores)\n        avg_train_loss = train_loss / len(train_dl.dataset)\n\n        print(f\"[Epoch {epoch}] Train Loss: {avg_train_loss:.4f} — Train AUC: {train_auc:.4f}\")\n\n        ### Validation\n        val_loss = 0\n        all_val_true = []\n        all_val_scores = []\n        model.eval()\n        \n        with torch.no_grad():\n            for x, y in tqdm(val_dl):\n                x, y = x.to(cfg.device), y.to(cfg.device)\n        \n                logits = model(x)\n                loss = loss_fn(logits, y)\n                val_loss += loss.item() * x.size(0)\n                \n                y_true_batch = y\n                probs = torch.sigmoid(logits)\n\n                all_val_true.append(y_true_batch.cpu().detach().numpy())\n                all_val_scores.append(probs.cpu().detach().numpy())\n\n            val_true = np.vstack(all_val_true)\n            val_scores = np.vstack(all_val_scores)\n            val_auc = macro_roc_auc_with_positive_labels(val_true, val_scores)\n            avg_val_loss = val_loss / len(val_dl.dataset)\n    \n            print(f\"[Epoch {epoch}] Val Loss:   {avg_val_loss:.4f} — Val AUC:   {val_auc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:39.476862Z","iopub.execute_input":"2025-04-20T19:50:39.477132Z","iopub.status.idle":"2025-04-20T19:50:39.489433Z","shell.execute_reply.started":"2025-04-20T19:50:39.477110Z","shell.execute_reply":"2025-04-20T19:50:39.488445Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# model.to(\"cpu\")\n# torch.save(model.state_dict(), \"./model_bce_loss.pt\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:39.490417Z","iopub.execute_input":"2025-04-20T19:50:39.491039Z","iopub.status.idle":"2025-04-20T19:50:39.585582Z","shell.execute_reply.started":"2025-04-20T19:50:39.491002Z","shell.execute_reply":"2025-04-20T19:50:39.584713Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_item(audio_path):\n    # now get EACH 5 seconds from sound\n    waveform, sample_rate = librosa.load(audio_path, sr=cfg.SR)\n    \n    length = int(cfg.TARGET_DURATION * cfg.SR)\n\n    mel_specs = []\n    for i in range(0, len(waveform), sample_rate * 5):\n        start = i\n        end = i + sample_rate * 5\n        w = waveform[start : end]\n\n        mel_spec = process_audio_segment(w, cfg)\n        mel_specs.append( mel_spec )\n        \n    return mel_specs","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:39.586605Z","iopub.execute_input":"2025-04-20T19:50:39.586879Z","iopub.status.idle":"2025-04-20T19:50:39.592431Z","shell.execute_reply.started":"2025-04-20T19:50:39.586856Z","shell.execute_reply":"2025-04-20T19:50:39.591383Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# make submission\nif cfg.SUBMISSION:\n    class_labels = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n    \n    test_soundscape_path = '/kaggle/input/birdclef-2025/test_soundscapes/'\n    test_soundscapes = [os.path.join(test_soundscape_path, afile) for afile in sorted(os.listdir(test_soundscape_path)) if afile.endswith('.ogg')]\n\n    if not test_soundscapes:\n        print(\"Test dir is empty. Using first 10 samples from train dir\")\n        test_soundscapes = list(cfg.train_datadir.glob(\"*/*.ogg\"))[:10]\n    \n    predictions = pd.DataFrame(columns=['row_id'] + class_labels)\n    for audio_path in test_soundscapes:\n        mel_specs = process_item(audio_path)\n\n        for k, mel_spec in enumerate(mel_specs):\n            row_id = os.path.basename(audio_path).split('.')[0] + f'_{k * 5 + 5}'\n\n            mel_spec = torch.Tensor( mel_spec ).unsqueeze(0)\n            logits = model( mel_spec.unsqueeze(0) )[0]\n            scores = F.softmax(logits, dim=0).tolist()\n    \n            new_row = pd.DataFrame(\n                [[row_id] + list(scores)],\n                columns=['row_id'] + class_labels\n            )\n\n            predictions = pd.concat([predictions, new_row], axis=0, ignore_index=True)\n\n    \n    sample_submission = pd.read_csv(cfg.submission_csv)\n\n    assert set(sample_submission.columns) == set(predictions.columns)\n    predictions.to_csv(\"submission.csv\", index=False, float_format='%.16f')\n    print(\"CSV saved\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T19:50:39.595533Z","iopub.execute_input":"2025-04-20T19:50:39.595843Z","iopub.status.idle":"2025-04-20T19:51:04.990420Z","shell.execute_reply.started":"2025-04-20T19:50:39.595816Z","shell.execute_reply":"2025-04-20T19:51:04.989494Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Ways to improve\n- maybe, in submission, stick probabilities to 0 or 1 and not to give all distribution (I don't know whether this will show less error and bigger score)\n- Use bigger models. This approaches inferences pretty fast (less than 5 minutes), but we may use 90 minutes. We may use bigger Efficient Nets.\n- Make bigger dataset: take not only middle 5 seconds, but split dataset on 5 seconds. Also, we may somehow use train_soundscaped. We may train a very complex model on GPU on train_set, then label train_soundscaped using this model and after that train Efficient Net on labeled train_soundscaped.\n- Use cross-validation sets (sadly, it's time-consuming).","metadata":{}},{"cell_type":"raw","source":"","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}