{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport librosa\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport tqdm\nimport random\nimport os\n\nfrom torch.optim import Adam\n\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import KFold, StratifiedKFold\nimport math\nfrom collections import OrderedDict\n\nfrom PIL import Image\nimport albumentations\nfrom pydub import AudioSegment\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import f1_score\ndevice = torch.device('cuda')\n\nimport warnings\nwarnings.filterwarnings('ignore')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"SEP = 32\n\nMU = 256\nSIGNAL_LENGTH = 160000//SEP\nFOLD = 0\nN_FOLDS = 5\nSEED = 416\nEPOCHS = 3\nNPZ_DIR =  \"../input/birdcall-dataset-for-wavenet/train_npz\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train = pd.read_csv(\"../input/birdsong-recognition/train.csv\")\n\ntrain = train[train[\"filename\"].map(lambda x: x not in [\"XC195038.mp3\"])]\ntrain = train.reset_index(drop=True)\n\n# label encoding for target values\ntrain[\"ebird_label\"] = LabelEncoder().fit_transform(train[\"ebird_code\"].values)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def seed_everything(seed):\n    random.seed(seed)\n    np.random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True \n    torch.backends.cudnn.benchmark = True ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class BirdDataset:\n    def __init__(self, df, is_train):\n        \n        self.filename = df.filename.values\n        self.ebird_label = df.ebird_label.values\n        self.ebird_code = df.ebird_code.values\n        self.is_train = is_train\n\n    def __len__(self):\n        return len(self.filename)\n    \n    def __getitem__(self, item):\n        \n        filename = self.filename[item].split(\".\")[0]\n        ebird_code = self.ebird_code[item]\n        ebird_label = self.ebird_label[item]\n\n        quantized = np.load(f\"{NPZ_DIR}/{ebird_code}/{filename}.wav.npz.npy\").astype(int)\n        \n        if SIGNAL_LENGTH > len(quantized):\n            onehot =  torch.eye(MU)[quantized]\n            onehot = torch.cat([onehot, torch.zeros((SIGNAL_LENGTH - len(quantized), MU))], dim=0)\n        elif self.is_train:\n            head_i = random.sample(range(len(quantized)-SIGNAL_LENGTH), 1)[0]\n            signal = quantized[head_i:head_i+SIGNAL_LENGTH]\n            onehot = torch.eye(MU)[signal]\n        else:\n            signal = quantized[:SIGNAL_LENGTH]\n            onehot = torch.eye(MU)[signal]\n        \n        target = ebird_label\n        \n        return {\n            \"signal\" : torch.tensor(onehot, dtype=torch.float), \n            \"target\" : torch.tensor(target, dtype=torch.long)\n        }","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ref: https://www.kaggle.com/cswwp347724/wavenet-pytorch\n\nclass Wave_Block(nn.Module):\n\n    def __init__(self, in_channels, out_channels, dilation_rates, kernel_size):\n        super(Wave_Block, self).__init__()\n        self.num_rates = dilation_rates\n        self.convs = nn.ModuleList()\n        self.filter_convs = nn.ModuleList()\n        self.gate_convs = nn.ModuleList()\n\n        self.convs.append(nn.Conv1d(in_channels, out_channels, kernel_size=1))\n        dilation_rates = [2 ** i for i in range(dilation_rates)]\n        for dilation_rate in dilation_rates:\n            self.filter_convs.append(\n                nn.Conv1d(out_channels, out_channels, kernel_size=kernel_size, padding=int((dilation_rate*(kernel_size-1))/2), dilation=dilation_rate))\n            self.gate_convs.append(\n                nn.Conv1d(out_channels, out_channels, kernel_size=kernel_size, padding=int((dilation_rate*(kernel_size-1))/2), dilation=dilation_rate))\n            self.convs.append(nn.Conv1d(out_channels, out_channels, kernel_size=1))\n\n    def forward(self, x):\n        x = self.convs[0](x)\n        res = x\n        for i in range(self.num_rates):\n            x = torch.tanh(self.filter_convs[i](x)) * torch.sigmoid(self.gate_convs[i](x))\n            x = self.convs[i + 1](x)\n            res = res + x\n        return res\n# detail \nclass Classifier(nn.Module):\n    def __init__(self, inch=256, kernel_size=3):\n        super().__init__()\n        self.wave_block1 = Wave_Block(inch, 16, 12, kernel_size)\n        self.wave_block2 = Wave_Block(16, 32, 8, kernel_size)\n        self.wave_block3 = Wave_Block(32, 64, 4, kernel_size)\n        self.wave_block4 = Wave_Block(64, 128, 1, kernel_size)\n        self.fc = nn.Linear(128, 1)\n        self.cls = nn.Linear(SIGNAL_LENGTH, 264)\n\n    def forward(self, x):\n        x = x.permute(0, 2, 1)\n\n        x = self.wave_block1(x)\n        x = self.wave_block2(x)\n        x = self.wave_block3(x)\n\n        x = self.wave_block4(x)\n        x = x.permute(0, 2, 1)\n        x = self.fc(x)\n        x = self.cls(x.squeeze(-1))\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"_t = train[\"ebird_label\"].values\nskf = StratifiedKFold(n_splits=N_FOLDS, shuffle=True, random_state=SEED)\ntrn_idx, val_idx = [(trn_idx, val_idx) for trn_idx, val_idx in skf.split(_t, _t)][FOLD]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train = train.sample(frac=1)\ntrn_df = train.iloc[trn_idx].reset_index(drop=True)\nval_df = train.iloc[val_idx].reset_index(drop=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_dataset = BirdDataset(trn_df, True)\ntrain_data_loader = torch.utils.data.DataLoader(\n        dataset = train_dataset,\n        batch_size = 4*SEP,\n        shuffle = True,\n        pin_memory = True,\n        drop_last = True\n)\n\nvalid_dataset = BirdDataset(val_df, False)\nvalid_data_loader = torch.utils.data.DataLoader(\n        dataset = valid_dataset,\n        batch_size = 4*SEP,\n        shuffle = False,\n        pin_memory = True,\n        drop_last = False\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"seed_everything(SEED)\n\nmodel = Classifier()\nmodel.to(device)\noptimizer = Adam(model.parameters(), lr=0.0001)\n\nscores, losses = [], []\nbest_score = 0\nfor epoch in range(EPOCHS):\n    print(f\"*** {epoch} Epoch ***\")\n    model.train()\n    t = tqdm.notebook.tqdm(train_data_loader)\n    for d in t:\n        pred = model(d[\"signal\"].to(device))\n        loss = nn.CrossEntropyLoss()(pred, d[\"target\"].to(device))\n    \n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n    \n        t.set_description(f\"Train Loss = {loss.item()}\")\n        losses.append(loss.item())\n    \n    model.eval()\n    f1_lst = []\n    for d in valid_data_loader:\n        with torch.no_grad():\n            pred = model(d[\"signal\"].to(device))\n            f1 = f1_score(d[\"target\"], pred.argmax(1).cpu(), average=\"micro\")\n            f1_lst.append(f1)\n    score = sum(f1_lst)/len(f1_lst)\n    print(\"valid f1 =\", score)\n    scores.append(score)\n    \n    if best_score < score:\n        best_score = score\n        torch.save(model.state_dict(), f\"birdcall_wavenet_f{FOLD}_best.bin\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(scores)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f\"best score: {best_score}\")\nplt.plot(losses)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}