{"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":"import csv\nimport math\nimport os\nfrom pathlib import Path\nimport random\nimport shutil\nimport time\nimport uuid\n\nimport IPython.display as ipd\nimport numpy as np\nimport librosa\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchaudio\nfrom torch.utils.data import Dataset, DataLoader, RandomSampler, TensorDataset\nfrom tqdm.notebook import tqdm\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import StratifiedKFold\n\ntorchaudio.set_audio_backend(\"sox_io\")\n\nSAMPLE_RATE = 48000\nRECORDING_LENGTH = 2880000","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-12-15T17:26:13.110633Z","iopub.execute_input":"2021-12-15T17:26:13.110989Z","iopub.status.idle":"2021-12-15T17:26:16.349496Z","shell.execute_reply.started":"2021-12-15T17:26:13.110958Z","shell.execute_reply":"2021-12-15T17:26:16.348543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install git+https://github.com/facebookresearch/fvcore.git","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:02.375267Z","iopub.execute_input":"2021-12-15T17:36:02.375594Z","iopub.status.idle":"2021-12-15T17:36:12.314682Z","shell.execute_reply.started":"2021-12-15T17:36:02.375562Z","shell.execute_reply":"2021-12-15T17:36:12.313860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rng_seed = 37\nrandom.seed(rng_seed)\nnp.random.seed(rng_seed)\nos.environ['PYTHONHASHSEED'] = str(rng_seed)\ntorch.manual_seed(rng_seed)\ntorch.cuda.manual_seed(rng_seed)\ntorch.backends.cudnn.deterministic = True\ntorch.backends.cudnn.benchmark = False","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:12.317679Z","iopub.execute_input":"2021-12-15T17:36:12.318206Z","iopub.status.idle":"2021-12-15T17:36:12.327427Z","shell.execute_reply.started":"2021-12-15T17:36:12.318165Z","shell.execute_reply":"2021-12-15T17:36:12.326626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATA_DIR = Path('/kaggle/input/rfcx-species-audio-detection')\nOUTPUT_DIR = Path('/kaggle/working')\n\nTRAIN_DIR = DATA_DIR / 'train'\nTEST_DIR = DATA_DIR / 'test'\nMODEL_PATH = Path('../input/timm-resnest-weights/resnest50-528c19ca.pth')\ndest = OUTPUT_DIR / 'waveform-tensors'\nweights_dir = OUTPUT_DIR / 'weights'\n\nPath.mkdir(dest, exist_ok=True)\nPath.mkdir(weights_dir, exist_ok=True)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:12.331305Z","iopub.execute_input":"2021-12-15T17:36:12.331633Z","iopub.status.idle":"2021-12-15T17:36:12.338597Z","shell.execute_reply.started":"2021-12-15T17:36:12.331607Z","shell.execute_reply":"2021-12-15T17:36:12.337688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(DATA_DIR / 'train_tp.csv')","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:12.340132Z","iopub.execute_input":"2021-12-15T17:36:12.340656Z","iopub.status.idle":"2021-12-15T17:36:12.356875Z","shell.execute_reply.started":"2021-12-15T17:36:12.340616Z","shell.execute_reply":"2021-12-15T17:36:12.356101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:12.360218Z","iopub.execute_input":"2021-12-15T17:36:12.360560Z","iopub.status.idle":"2021-12-15T17:36:12.374521Z","shell.execute_reply.started":"2021-12-15T17:36:12.360530Z","shell.execute_reply":"2021-12-15T17:36:12.373351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f_min_df = int(min(df['f_min']) * 0.9)\nf_max_df = int(max(df['f_max']) * 1.1)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:12.376487Z","iopub.execute_input":"2021-12-15T17:36:12.377310Z","iopub.status.idle":"2021-12-15T17:36:12.383780Z","shell.execute_reply.started":"2021-12-15T17:36:12.377265Z","shell.execute_reply":"2021-12-15T17:36:12.382599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f_max_df","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:12.385467Z","iopub.execute_input":"2021-12-15T17:36:12.386262Z","iopub.status.idle":"2021-12-15T17:36:12.395607Z","shell.execute_reply.started":"2021-12-15T17:36:12.386217Z","shell.execute_reply":"2021-12-15T17:36:12.394696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AudioResNest(nn.Module):\n    def __init__(self, n_outputs):\n        super().__init__()\n        self.preprocess = nn.Sequential(\n            torchaudio.transforms.MelSpectrogram(\n                sample_rate=48000,\n                n_fft=4096,\n                hop_length=512,\n                f_min=f_min_df,\n                f_max=f_max_df,\n                n_mels=64,\n                power=2.,\n            ),\n            torchaudio.transforms.AmplitudeToDB(stype='power'),\n        )\n#         self.resnest = torch.hub.load('pytorch/vision', 'resnet50', pretrained=True)\n#         self.resnest = models.resnet18(pretrained=True)\n#         self.resnest = torch.hub.load('pytorch/vision', 'resnet18', pretrained=True)\n#         self.resnest = torch.hub.load('zhanghang1989/ResNeSt', 'resnest50', pretrained=False\n        self.resnest = torch.hub.load('zhanghang1989/ResNeSt', 'resnest50', pretrained=True)\n        self.resnest.load_state_dict(torch.load(MODEL_PATH))\n        self.resnest.fc = nn.Sequential(\n            nn.Linear(2048, 1024),\n            nn.ReLU(),\n            nn.Dropout(p=0.2),\n            nn.Linear(1024, 1024),\n            nn.ReLU(),\n            nn.Dropout(p=0.2),\n            nn.Linear(1024, n_outputs)\n        )\n\n    def forward(self, x):\n        x -= torch.mean(x)\n        x /= torch.max(torch.abs(x))\n        mel_spec = self.preprocess(x)\n        mel_spec -= torch.mean(mel_spec)\n        mel_spec /= torch.std(mel_spec)\n        mel_spec = torch.stack((mel_spec, mel_spec, mel_spec), dim=1)\n        logits = self.resnest(mel_spec)\n        return logits","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:12.397315Z","iopub.execute_input":"2021-12-15T17:36:12.397804Z","iopub.status.idle":"2021-12-15T17:36:12.410224Z","shell.execute_reply.started":"2021-12-15T17:36:12.397751Z","shell.execute_reply":"2021-12-15T17:36:12.409072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", message=\"PySoundFile failed. Trying audioread instead.\")\n\ndef get_segment(audio, sr, t_min, t_max):\n    start_idx = int(sr * t_min)\n    end_idx = int(sr * t_max)\n    seg = audio[start_idx:end_idx]\n    seg -= np.mean(seg)\n    seg /= np.max(np.abs(seg))\n    return seg\n\ndef get_stft(audio, sr, f_min, f_max, n_fft, hop_len):\n    f_min_bin = int(np.floor(f_min / sr * n_fft))\n    f_max_bin = int(np.ceil(f_max / sr * n_fft))\n    stft = np.abs(librosa.stft(audio, n_fft=n_fft, hop_length=hop_len))\n    stft = stft[f_min_bin:f_max_bin + 1, :]\n    return stft\n\ndef find_call_segments(arr, window_size=50, hop_len=50):\n    start_idx = 0\n    segment_energies = []\n    segment_indices = []\n    call_segment_indices = []\n    if len(arr) > window_size:\n        while start_idx + window_size < len(arr):\n            segment_energies.append(np.sum(arr[start_idx:(start_idx+window_size)]))\n            segment_indices.append((start_idx, start_idx + window_size))\n            start_idx += hop_len\n\n        mean_segment_energy = np.mean(segment_energies)\n        large_segment_indices = [ind for ind, en in zip(segment_indices, segment_energies) if en >= mean_segment_energy]\n        for ind in large_segment_indices:\n            call_segment_indices.append(ind[0] + np.argmax(arr[ind[0]:ind[1]]))\n            \n    else:\n        call_segment_indices.append(np.argmax(arr))\n\n    return call_segment_indices\n\ndef get_call_indices(stft, sr, t_min, n_fft, hop_length):\n    start_idx = int(t_min * sr)\n    call_intensity = np.mean(stft, axis=0)\n    call_frame_ind = find_call_segments(call_intensity)\n    call_audio_ind = [start_idx + librosa.frames_to_samples(ind, hop_length=hop_length, n_fft=n_fft) for ind in call_frame_ind]\n    return call_audio_ind\n\ndef get_audio_segment(audio, sr, mid_idx, segment_len_samples):\n    if len(audio) > segment_len_samples:\n        start_idx = int(mid_idx - segment_len_samples / 2)\n        end_idx = int(mid_idx + segment_len_samples / 2)\n        if start_idx < 0:\n            start_idx = 0\n            end_idx = segment_len_samples\n        if end_idx > len(audio) - 1:\n            end_idx = len(audio)\n            start_idx = int(len(audio) - segment_len_samples)\n    else:\n        start_idx = 0\n        end_idx = len(audio) - 1\n    return audio[start_idx:end_idx]\n\nCALL_LEN_SECONDS = 1.0\nCALL_LEN_SAMPLES = int(CALL_LEN_SECONDS * SAMPLE_RATE)\n\nINPUT_LEN_SECONDS = 0.5\nINPUT_LEN_SAMPLES = int(INPUT_LEN_SECONDS * SAMPLE_RATE)\n\n# data = []\n# for row_idx, row in tqdm(df.iterrows(), total=df.shape[0]):\n#     fpath = TRAIN_DIR / (row['recording_id'] + '.flac')\n#     audio, sr = librosa.load(fpath, sr=SAMPLE_RATE)\n#     seg = get_segment(audio, sr, row['t_min'], row['t_max'])\n#     n_fft = 1024\n#     hop_length = 512\n#     stft = get_stft(seg, sr, row['f_min'], row['f_max'], n_fft, hop_length)\n#     call_mid_indices = get_call_indices(stft, sr, row['t_min'], n_fft, hop_length)\n#     fnames = []\n#     for call_mid_idx in call_mid_indices:\n#         call = get_audio_segment(audio, sr, call_mid_idx, CALL_LEN_SAMPLES)\n#         assert len(call) == CALL_LEN_SAMPLES\n#         fname = str(uuid.uuid4()) + '.pt'\n#         torch.save(torch.from_numpy(call), dest / fname)\n#         fnames.append(fname)\n#     data.append((row['recording_id'], row['species_id'], fnames))\n\ndata = []\nfor row_idx, row in tqdm(df.iterrows(), total=df.shape[0]):\n    fpath = TRAIN_DIR / (row['recording_id'] + '.flac')\n    audio, sr = librosa.load(fpath, sr=SAMPLE_RATE)\n    seg = get_segment(audio, sr, row['t_min'], row['t_max'])\n    n_fft = 1024\n    hop_length = 512\n    stft = get_stft(seg, sr, row['f_min'], row['f_max'], n_fft, hop_length)\n    call_mid_indices = get_call_indices(stft, sr, row['t_min'], n_fft, hop_length)\n    for call_mid_idx in call_mid_indices:\n        call = get_audio_segment(audio, sr, call_mid_idx, CALL_LEN_SAMPLES)\n        assert len(call) == CALL_LEN_SAMPLES\n        fname = str(uuid.uuid4()) + '.pt'\n        torch.save(torch.from_numpy(call), dest / fname)\n        data.append((row['recording_id'], row['species_id'], fname))\n\ndf_segmented = pd.DataFrame(data, columns=['recording_id', 'species_id', 'filename'])","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:36:12.412050Z","iopub.execute_input":"2021-12-15T17:36:12.412862Z","iopub.status.idle":"2021-12-15T17:37:54.431505Z","shell.execute_reply.started":"2021-12-15T17:36:12.412815Z","shell.execute_reply":"2021-12-15T17:37:54.430673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_segmented.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:37:54.433018Z","iopub.execute_input":"2021-12-15T17:37:54.433588Z","iopub.status.idle":"2021-12-15T17:37:54.444362Z","shell.execute_reply.started":"2021-12-15T17:37:54.433545Z","shell.execute_reply":"2021-12-15T17:37:54.443181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RainforestDataset(Dataset):\n    def __init__(self, dataframe):\n        self.waveforms = []\n        self.labels = []\n        self.n_species = len(set(list(dataframe['species_id'])))\n        for idx, row in dataframe.iterrows():\n#             label = row['species_id']\n#             label_array = torch.zeros(self.n_species, dtype=torch.long)\n#             label_array[label] = 1.\n#             self.labels.append(label_array)\n            self.labels.append(row['species_id'])\n#             segments = []\n#             for fname in row['filenames']:\n#                 audio_segment = torch.load(dest / fname)\n#                 segments.append(audio_segment)\n            audio = torch.load(dest / row['filename'])\n            self.waveforms.append(audio)\n\n        self.preprocess = nn.Sequential(\n            torchaudio.transforms.MelSpectrogram(\n                sample_rate=48000,\n                n_fft=4096,\n                hop_length=512,\n                f_min=f_min_df,\n                f_max=f_max_df,\n                n_mels=65,\n                power=2.,\n            ),\n            torchaudio.transforms.AmplitudeToDB(stype='power'),\n        )\n\n    def get_n_species(self):\n        return self.n_species\n\n    def __len__(self):\n        return len(self.waveforms)\n\n    def __getitem__(self, idx):\n        # waveform = random.choice(self.waveforms[idx])\n        waveform = self.waveforms[idx]\n        offset = random.randrange(CALL_LEN_SAMPLES - INPUT_LEN_SAMPLES)\n        waveform = waveform[offset:offset+INPUT_LEN_SAMPLES]\n        return waveform, self.labels[idx]\n    \n    def show_sample(self, idx):\n        seg = self.waveforms[idx]\n        # for seg in segments:\n        seg -= torch.mean(seg)\n        seg /= torch.max(torch.abs(seg))\n        ipd.display(ipd.Audio(seg, rate=SAMPLE_RATE))\n        specgram = self.preprocess(seg)\n        specgram -= torch.mean(specgram)\n        specgram /= torch.std(specgram)\n        print(specgram.shape)\n        plt.figure()\n        plt.imshow(specgram)\n        plt.title(f'something')\n\n    def show_random_sample(self):\n        idx = random.randrange(len(self))\n        self.show_sample(idx)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:37:54.446305Z","iopub.execute_input":"2021-12-15T17:37:54.447046Z","iopub.status.idle":"2021-12-15T17:37:54.462357Z","shell.execute_reply.started":"2021-12-15T17:37:54.446993Z","shell.execute_reply":"2021-12-15T17:37:54.461546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds = RainforestDataset(df_segmented)\nds.show_random_sample()","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:37:54.463913Z","iopub.execute_input":"2021-12-15T17:37:54.464310Z","iopub.status.idle":"2021-12-15T17:37:55.931009Z","shell.execute_reply.started":"2021-12-15T17:37:54.464267Z","shell.execute_reply":"2021-12-15T17:37:55.930118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2021-12-15T13:48:46.198521Z","iopub.execute_input":"2021-12-15T13:48:46.199241Z","iopub.status.idle":"2021-12-15T13:48:46.205280Z","shell.execute_reply.started":"2021-12-15T13:48:46.199195Z","shell.execute_reply":"2021-12-15T13:48:46.204093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds","metadata":{"execution":{"iopub.status.busy":"2021-12-15T15:50:35.020022Z","iopub.execute_input":"2021-12-15T15:50:35.020391Z","iopub.status.idle":"2021-12-15T15:50:35.027929Z","shell.execute_reply.started":"2021-12-15T15:50:35.020359Z","shell.execute_reply":"2021-12-15T15:50:35.026531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 16\nn_epochs = 40\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\nskf = StratifiedKFold(n_splits=5, shuffle=True)\ntargets = df_segmented.species_id\nfor fold_idx, (train_idx, val_idx) in enumerate(skf.split(np.zeros(len(targets)), targets)):\n    print(f'Training with fold {fold_idx}')\n    weights_path = weights_dir / f'weights_{fold_idx}.pt'\n    train_ds = RainforestDataset(df_segmented.loc[train_idx])\n    val_ds = RainforestDataset(df_segmented.loc[val_idx])\n    train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True)\n    val_dl = DataLoader(val_ds, batch_size=batch_size)\n\n    model = AudioResNest(train_ds.get_n_species())\n\n    optimizer = torch.optim.Adam(params=model.parameters(), lr=1e-3, amsgrad=False, weight_decay=1e-4)\n    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=4, verbose=True, factor=0.1)\n\n    # criterion = nn.BCEWithLogitsLoss()\n    criterion = nn.CrossEntropyLoss()\n\n    model = model.to(device)\n    criterion = criterion.to(device)\n\n    best_val_acc = 0.\n    best_val_loss = math.inf\n\n    for epoch in tqdm(range(n_epochs), desc='Training'):\n        start_time = time.time()\n        model.train()\n        train_loss = 0.\n        train_acc = 0.\n\n        for x_batch, y_batch in train_dl:\n\n            logits = model(x_batch.to(device))\n            loss = criterion(logits, y_batch.to(device))\n            optimizer.zero_grad()\n            loss.backward()\n            optimizer.step()\n            train_loss += loss.item()\n            # train_acc += torch.sum(torch.argmax(logits, dim=1) == torch.argmax(y_batch.to(device), dim=1))\n            train_acc += torch.sum(torch.argmax(logits, dim=1) == y_batch.to(device))\n\n        train_loss /= len(train_dl)\n        train_acc /= len(train_ds)\n\n        with torch.no_grad():\n            val_loss = 0.\n            val_acc = 0.\n            model.eval()\n            for x_batch, y_batch in val_dl:\n                \n                logits = model(x_batch.to(device))\n                loss = criterion(logits, y_batch.to(device))\n                val_loss += loss.item()\n                # val_acc += torch.sum(torch.argmax(logits, dim=1) == torch.argmax(y_batch.to(device), dim=1))\n                val_acc += torch.sum(torch.argmax(logits, dim=1) == y_batch.to(device))\n\n            val_loss /= len(val_dl)\n            val_acc /= len(val_ds)\n\n        elapsed = time.time() - start_time\n        print(f'Epoch {epoch} (time: {elapsed:.0f}s): train_loss: {train_loss}, train_acc: {train_acc}, val_loss: {val_loss}, val_acc: {val_acc}')\n\n        if val_acc > best_val_acc:\n            print(f'Saving new best model at epoch {epoch} (val_acc improved from {best_val_acc} to {val_acc})')\n            torch.save(model, weights_path)\n            best_val_acc = val_acc\n\n        scheduler.step(val_loss)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T13:48:46.207080Z","iopub.execute_input":"2021-12-15T13:48:46.207829Z","iopub.status.idle":"2021-12-15T14:48:36.754676Z","shell.execute_reply.started":"2021-12-15T13:48:46.207782Z","shell.execute_reply":"2021-12-15T14:48:36.753121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # using ResNeSt-50 as an example\n# from resnest.torch import resnest50\n# net = resnest50(pretrained=True)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T14:48:36.756713Z","iopub.execute_input":"2021-12-15T14:48:36.757568Z","iopub.status.idle":"2021-12-15T14:48:36.763671Z","shell.execute_reply.started":"2021-12-15T14:48:36.757509Z","shell.execute_reply":"2021-12-15T14:48:36.761979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import torchvision.models as models\n# resnet18 = models.resnet18(pretrained=True)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T14:48:36.765716Z","iopub.execute_input":"2021-12-15T14:48:36.766626Z","iopub.status.idle":"2021-12-15T14:48:36.775708Z","shell.execute_reply.started":"2021-12-15T14:48:36.766579Z","shell.execute_reply":"2021-12-15T14:48:36.774600Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shutil.rmtree(dest)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T14:48:36.777556Z","iopub.execute_input":"2021-12-15T14:48:36.778122Z","iopub.status.idle":"2021-12-15T14:48:36.973074Z","shell.execute_reply.started":"2021-12-15T14:48:36.778076Z","shell.execute_reply":"2021-12-15T14:48:36.972102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_test_file(fpath):\n    audio, sr = librosa.load(fpath, sr=None)\n    audio -= np.mean(audio)\n    audio /= np.max(np.abs(audio))\n    hop_len = int(INPUT_LEN_SAMPLES / 2)\n#     waveforms = []\n#     start_idx = 0\n#     while start_idx + INPUT_LEN_SAMPLES < len(audio):\n#         audio_segment = audio[start_idx:start_idx+INPUT_LEN_SAMPLES]\n#         waveforms.append(torch.from_numpy(audio_segment))\n#         start_idx += hop_len\n    chunks = [audio[i : i + INPUT_LEN_SAMPLES] for i in range(0, len(audio)-INPUT_LEN_SAMPLES, hop_len)]\n    chunks.append(audio[-INPUT_LEN_SAMPLES:])\n    signal_chunks = sorted(chunks, key=lambda x: np.sum(x**2), reverse=True)[:5]\n    signal_chunks = [torch.from_numpy(chunk) for chunk in signal_chunks]\n    # could also do energy filtering here\n    # max_energy = np.max([np.sum(chunk**2) for chunk in chunks])\n    # signal_chunks = [torch.from_numpy(chunk) for chunk in chunks if np.sum(chunk**2) > 0.8*max_energy]\n    return torch.stack(signal_chunks)\n\ndef get_probabilities(melspecs, weights_dir, device, n_classes, batch_size=512):\n    ds = TensorDataset(melspecs)\n    dl = DataLoader(ds, batch_size=batch_size)\n    probs = torch.zeros((len(melspecs), n_classes))\n    ws = [w for w in weights_dir.iterdir()]\n    for w in ws:\n        model = torch.load(w)\n        model.to(device)\n        model.eval()\n        fold_probs = []\n        for batch in dl:\n            x = batch[0].to(device)\n            logits = model(x).detach().cpu()\n            ###\n            logits = F.softmax(logits, dim=1)\n            ###\n            fold_probs.append(logits)\n        fold_probs = torch.vstack(fold_probs)\n        probs += fold_probs\n    max_prob_per_class, _ = probs.max(dim=0)\n    return list(max_prob_per_class.numpy())","metadata":{"execution":{"iopub.status.busy":"2021-12-15T14:48:36.975625Z","iopub.execute_input":"2021-12-15T14:48:36.975931Z","iopub.status.idle":"2021-12-15T14:48:36.990719Z","shell.execute_reply.started":"2021-12-15T14:48:36.975900Z","shell.execute_reply":"2021-12-15T14:48:36.989040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open('submission.csv', 'w', newline='') as csvfile:\n    submission_writer = csv.writer(csvfile, delimiter=',')\n    submission_writer.writerow(['recording_id','s0','s1','s2','s3','s4','s5','s6','s7','s8','s9','s10','s11',\n                               's12','s13','s14','s15','s16','s17','s18','s19','s20','s21','s22','s23'])\n\n        for fpath in tqdm(list(TEST_DIR.iterdir())):\n            data = load_test_file(fpath)\n        maxed_output = get_probabilities(data, weights_dir, device, train_ds.get_n_species())\n        write_array = [fpath.stem]\n        for out in maxed_output:\n            write_array.append(out.item())\n        submission_writer.writerow(write_array)\n\nprint('Submission generated')","metadata":{"execution":{"iopub.status.busy":"2021-12-15T14:48:36.993055Z","iopub.execute_input":"2021-12-15T14:48:36.993615Z","iopub.status.idle":"2021-12-15T15:25:34.380426Z","shell.execute_reply.started":"2021-12-15T14:48:36.993567Z","shell.execute_reply":"2021-12-15T15:25:34.379087Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test demo","metadata":{}},{"cell_type":"code","source":"paths_train = ['/kaggle/input/rfcx-species-audio-detection/train/00204008d.flac',\n               '/kaggle/input/rfcx-species-audio-detection/train/003b04435.flac',\n               '/kaggle/input/rfcx-species-audio-detection/train/0079ff47b.flac']","metadata":{"execution":{"iopub.status.busy":"2021-12-15T16:40:31.305019Z","iopub.execute_input":"2021-12-15T16:40:31.305433Z","iopub.status.idle":"2021-12-15T16:40:31.310685Z","shell.execute_reply.started":"2021-12-15T16:40:31.305402Z","shell.execute_reply":"2021-12-15T16:40:31.309205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fpath = '/kaggle/input/rfcx-species-audio-detection/train/006ab765f.flac'\n# for fpath in paths_train:\nprint(fpath)\ndata_train = load_test_file(fpath)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T16:59:51.797995Z","iopub.execute_input":"2021-12-15T16:59:51.798456Z","iopub.status.idle":"2021-12-15T16:59:51.982936Z","shell.execute_reply.started":"2021-12-15T16:59:51.798424Z","shell.execute_reply":"2021-12-15T16:59:51.981613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"maxed_output = get_probabilities(data_train, weights_dir, device, train_ds.get_n_species())","metadata":{"execution":{"iopub.status.busy":"2021-12-15T16:59:52.672548Z","iopub.execute_input":"2021-12-15T16:59:52.672903Z","iopub.status.idle":"2021-12-15T16:59:53.595067Z","shell.execute_reply.started":"2021-12-15T16:59:52.672870Z","shell.execute_reply":"2021-12-15T16:59:53.593948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.argmax(maxed_output)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T16:59:54.129911Z","iopub.execute_input":"2021-12-15T16:59:54.130333Z","iopub.status.idle":"2021-12-15T16:59:54.137073Z","shell.execute_reply.started":"2021-12-15T16:59:54.130299Z","shell.execute_reply":"2021-12-15T16:59:54.135860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mapping_tp = pd.read_csv('/kaggle/input/rfcx-species-audio-detection/train_tp.csv')\nmapping_fp = pd.read_csv('/kaggle/input/rfcx-species-audio-detection/train_fp.csv')","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:26:22.776667Z","iopub.execute_input":"2021-12-15T17:26:22.777022Z","iopub.status.idle":"2021-12-15T17:26:22.811374Z","shell.execute_reply.started":"2021-12-15T17:26:22.776992Z","shell.execute_reply":"2021-12-15T17:26:22.810588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mapping_tp.species_id.unique()","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:01:14.515942Z","iopub.execute_input":"2021-12-15T17:01:14.516333Z","iopub.status.idle":"2021-12-15T17:01:14.526351Z","shell.execute_reply.started":"2021-12-15T17:01:14.516299Z","shell.execute_reply":"2021-12-15T17:01:14.525083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds.show_sample(1)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:37:55.932920Z","iopub.execute_input":"2021-12-15T17:37:55.933428Z","iopub.status.idle":"2021-12-15T17:37:56.077662Z","shell.execute_reply.started":"2021-12-15T17:37:55.933388Z","shell.execute_reply":"2021-12-15T17:37:56.076825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mapping_tp.loc[mapping_tp.recording_id == '006ab765f'].index[0]","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:35:26.546120Z","iopub.execute_input":"2021-12-15T17:35:26.546546Z","iopub.status.idle":"2021-12-15T17:35:26.554518Z","shell.execute_reply.started":"2021-12-15T17:35:26.546473Z","shell.execute_reply":"2021-12-15T17:35:26.553358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mapping_tp.iloc[:5]","metadata":{"execution":{"iopub.status.busy":"2021-12-15T16:48:06.967726Z","iopub.execute_input":"2021-12-15T16:48:06.968139Z","iopub.status.idle":"2021-12-15T16:48:06.984092Z","shell.execute_reply.started":"2021-12-15T16:48:06.968106Z","shell.execute_reply":"2021-12-15T16:48:06.982630Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mapping_fp.loc[mapping_fp.recording_id == '003b04435']","metadata":{"execution":{"iopub.status.busy":"2021-12-15T16:47:42.962897Z","iopub.execute_input":"2021-12-15T16:47:42.963424Z","iopub.status.idle":"2021-12-15T16:47:42.994493Z","shell.execute_reply.started":"2021-12-15T16:47:42.963378Z","shell.execute_reply":"2021-12-15T16:47:42.993299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}