{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport sys\nsys.path.append('../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master')\nimport warnings\nwarnings.filterwarnings(\"ignore\", category=UserWarning)\nBASE_TEST_DIR = '../input/birdsong-recognition' if os.path.exists('../input/birdsong-recognition/test_audio') else '../input/my-birdcall-datasets'","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport cv2, librosa, random, torch\nimport pandas as pd\nimport torch.nn as nn\nfrom torchvision import models\nfrom efficientnet_pytorch import EfficientNet\nfrom torchvision import transforms\nfrom sklearn.metrics import f1_score\nfrom torch.optim import Adam\nimport torch.nn.functional as F\n\n\nclass Hparams():\n    def __init__(self):\n        #resnet50 resnext50_32x4d mobilenet_v2 efficientnet-b3  densenet121 densenet169 \n        self.models_name = ['resnet50','efficientnet-b0','efficientnet-b0','efficientnet-b0','efficientnet-b0','resnet50']\n        self.chk = ['resnet50_78_0.830_0.666.pt','enet0_101_0.771_0.692.pt','enet0_45_0.558.pt','enet0_133_0.707_0.691.pt',\n                    '150enet0_116_0.707_0.703.pt','2.5resnet50_113_0.715_0.693.pt']\n        self.count_bird = [265,265,265,265,150,265] #count birds|Количество птиц, 264 - all, 265 + nocall\n        self.len_chack = [448,448,448,448,448,224] # The duration of the training files 448 = 5 second|Длительность обучающих файлов\n        \n        self.mel_folder = './mel/'\n        self.n_fft = 892\n        self.sr = 21952 \n        self.hop_length=245\n        self.n_mels =  224\n        self.win_length = self.n_fft\n        self.batch_size = 100 # 3 - b7, 8 - b5,  12 - b3, 25 - b0, 18 - b1 70\n        self.lr = 0.001\n        self.border = 0.5\n        self.save_interval = 200 #Model saving interval\n        # Список из count_bird птиц по пополуярности\n        self.bird_count = pd.read_csv('../input/my-birdcall-datasets/bird_count.csv').ebird_code.to_numpy()        \n        self.BIRD_CODE = {b:i for i,b in enumerate(self.bird_count)}\n        self.INV_BIRD_CODE = {v: k for k, v in self.BIRD_CODE.items()}\n        self.bird_count = self.bird_count[:self.count_bird[0]]\n\n\nhp = Hparams()\ndef mono_to_color(X: np.ndarray,len_chack, mean=0.5, std=0.5, eps=1e-6):\n    trans = transforms.Compose([transforms.ToPILImage(),\n                                        transforms.Resize([hp.n_mels, len_chack]), transforms.ToTensor(),\n                                        transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])\n    X = np.stack([X, X, X], axis=-1)\n    V = (255 * X).astype(np.uint8)\n    V = (trans(V)+1)/2\n    return V\n    \n    \ndef accuracy(y_true, y_pred):\n    y_pred = torch.sigmoid(y_pred)\n    y_pred = y_pred.detach().cpu().numpy()\n    return f1_score(y_true > hp.border, y_pred > hp.border, average=\"samples\")\n    \n    \ndef get_melspectr(train_path):\n    # Load file | Загружаем файл\n    y, _ = librosa.load(train_path,sr=hp.sr,mono=True,res_type=\"kaiser_fast\")\n\n    # Create melspectrogram | Создать Мелспектрограмму\n    spectr = librosa.feature.melspectrogram(y, sr=hp.sr, n_mels=hp.n_mels, n_fft=hp.n_fft, hop_length = hp.hop_length, win_length = hp.win_length, fmin = 300)\n    return spectr.astype(np.float16)\n\n\ndef random_power(images, power = 1.5, c= 0.7):\n    images = images - images.min()\n    images = images/(images.max()+0.0000001)\n    images = images**(random.random()*power + c)\n    return images\n\n    \ndef test_accuracy(preds, log_stat= False, border=0.5):\n    answer = pd.read_csv('../input/my-birdcall-datasets/example_test_audio_summary.csv')\n    preds = answer.merge(preds, how = 'right', left_on='filename_seconds', right_on='row_id')\n    y_true, y_pred = [], []\n    my_bird = 0\n    pred_bird = 0\n    bad_bird = {}    \n    for all in preds.loc[:,['bird','birds']].to_numpy(): \n        y = np.zeros(265)\n        c = np.array(all[0].split())\n        for bird in c:\n            y[hp.BIRD_CODE[bird]]=1\n        y_true.append(y)\n        \n        y = np.zeros(265)\n        d = np.array(all[1].split())\n        for bird in d:\n            y[hp.BIRD_CODE[bird]]=1\n        y_pred.append(y)\n        \n        mask = np.in1d(d, c)\n        #good += mask.sum()\n        if d[0] != 'nocall':\n            pred_bird += len(d)\n        if mask.sum()>0 and d[0] != 'nocall':\n            my_bird += mask.sum()\n        for i in d[~mask]:\n            if i in bad_bird:\n                bad_bird[i] += 1\n            else:\n                bad_bird[i] = 1\n        #all_bird += (len(c)+len(d))/2\n    if not pred_bird: pred_bird = 1\n    f1 = f1_score(y_true, y_pred, average=\"samples\")\n    print(\"border: %.1f bird: %d bird_accuracy: %.3f test_accuracy: %.3f\" % (\n                                border,my_bird, my_bird/pred_bird, f1)) \n    if log_stat:\n        for w in sorted(bad_bird, key=bad_bird.get, reverse=True)[:5]:\n            print (w, bad_bird[w])            \n    \n    return my_bird, my_bird/pred_bird, f1\n\n\nclass BirdcallNet( nn.Module):\n    def __init__(self, name, num_classes=265):\n        super(BirdcallNet, self).__init__()\n        self.model = models.__getattribute__(name)(pretrained=False)\n        if name in [\"resnet50\",\"resnext50_32x4d\"]:\n            self.model.fc = nn.Linear(2048, num_classes)\n        elif name in ['resnet18','resnet34']:\n            self.model.fc = nn.Linear(512, num_classes)\n        elif  name ==\"densenet121\":\n            self.model.classifier = nn.Linear(1024, num_classes)\n        elif name in ['alexnet','vgg16']:\n            self.model.classifier[-1] = nn.Linear(4096, num_classes)\n        elif name ==\"mobilenet_v2\":\n            self.model.classifier[1] = nn.Linear(1280, num_classes)\n        #print(self.model)\n    def forward(self, x):\n        return self.model(x)\n\n        \ndef get_model(model_name,chk,count_bird):\n    best_bird_count,best_score, epochs = 0,0,1\n    all_loss, train_accuracy = [], []\n    f1_scores,t_scores,b_scores = [],[],[]\n    if not chk and model_name in ['efficientnet-b3','efficientnet-b0']:\n        model = EfficientNet.from_pretrained(model_name, num_classes = count_bird).cuda()\n        optimizer = Adam(model.parameters(), lr = hp.lr)\n    else:\n        models_names = ['alexnet','resnet50','resnet18','resnet34','mobilenet_v2','densenet121','resnext50_32x4d','densenet169']\n        if model_name in models_names:\n            model = BirdcallNet(model_name, hp.count_bird[0]).cuda()\n        elif model_name == 'mini':\n            model = Classifier(hp.count_bird[0]).cuda()\n        else:\n            model = EfficientNet.from_name(model_name, override_params={'num_classes': count_bird }).cuda()\n        optimizer = Adam(model.parameters(), lr = hp.lr)\n        # Load a checkpoint | Загрузить чекпоинт\n        if chk:\n            ckpt = torch.load('../input/my-birdcall-datasets/'+chk)\n            model.load_state_dict(ckpt['model'])\n            epochs = int(ckpt['epoch']) + 1\n            train_accuracy =  ckpt['train_accuracy'] \n            all_loss   = ckpt['all_loss'] \n            best_bird_count =  ckpt['best_bird_count'] \n            best_score   = ckpt['best_score']\n            \n            if 'optimizer' in ckpt:\n                optimizer.load_state_dict(ckpt['optimizer'])\n            if 't_scores' in ckpt:\n                t_scores   = ckpt['t_scores']\n            if 'f1_scores' in ckpt:\n                f1_scores   = ckpt['f1_scores']\n            if 'b_scores' in ckpt:\n                b_scores   = ckpt['b_scores']\n            print('Чекпоинт загружен: Эпоха %d Число обнаруженых птиц %d Score %.3f' % (epochs,best_bird_count,best_score))\n    return model,optimizer, epochs, train_accuracy, all_loss, best_bird_count, best_score, t_scores, f1_scores, b_scores\n    ","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nfrom torchvision import models\nimport torch.nn.functional as F\nimport torch.utils.data as data\nfrom torch.utils.data import Dataset\nimport glob, os,time, random, librosa, argparse\nfrom efficientnet_pytorch import EfficientNet\n#from hparams import Hparams, get_model, mono_to_color,random_power, accuracy, get_melspectr, test_accuracy\nimport matplotlib.pyplot as plt\nfrom scipy.ndimage.filters import gaussian_filter1d\nfrom tqdm import tqdm\nfrom scipy.stats.mstats import gmean\n        \ndef preprocess():\n    os.makedirs(hp.mel_folder, exist_ok=True)\n    dataset = glob.glob(os.path.join(\"./short/\", '**/*.wav'), recursive=True)\n    with open('meta.csv', 'w', encoding=\"utf-8\") as output:\n        output.write(\"file,bird\\n\")\n        for train_path in tqdm(dataset):\n            # Only the name of the file | Только название файла\n            wav_name = os.path.basename(train_path) \n            dirname = train_path.split(\"\\\\\")[1]\n            \n            # Create melspectrogram | Получить спектр\n            mel = get_melspectr(train_path)\n            \n            # Translate to torch | Перевести в torch\n            mel = torch.from_numpy(mel)\n            \n            # Getting a new path to the file | Получаем новый путь до файла\n            wav_path = os.path.join(hp.mel_folder, wav_name)\n\n            # Save melspectrogram | Сохраняем иелспектрограмму\n            save_path = wav_path.replace('.mp3', '.amp')\n            torch.save(mel, save_path)\n            output.write(wav_name +',' + dirname + \"\\n\")\n    secondary_labels = pd.read_csv('train1.csv')\n    meta = pd.read_csv('meta.csv')\n    meta = meta.merge(secondary_labels[[\"filename\",'labels_bg']], how = 'left', left_on='file', right_on='filename',copy=False)\n    meta[[\"file\",\"bird\",'labels_bg']].to_csv('meta.csv', index=False)\n    print('Training dataset created / Тренировочный датасет создан')\n    \nclass MelDataset(Dataset):\n    def __init__(self, bird_list, hp):\n        # Initialize the list of melspectrograms | Инициализировать список мелспектрограмм\n        self.bird_list = bird_list\n        self.hp = hp\n        self.noise = pd.read_csv(\"nocall.csv\")\n        self.stop_border = 0.3 # Probability of stopping mixing | Вероятность прервать смешивание\n        self.level_noise = 0.05 # level noise | Уровень шума\n        self.div_coef = 100 # signal amplification during mixing | Усиления сигнала при смешивании\n            \n    def __len__(self):\n        return len(self.bird_list)\n\n    def __getitem__(self, idx):\n        idx2 = random.randint(0, len(self.bird_list)-1) # Second file | Второй файл\n        idx3 = random.randint(0, len(self.bird_list)-1) # Third file | Третий файл\n\n        y = torch.zeros(self.hp.count_bird[0])\n        birds, background = [],[]\n        \n        # Length of the segment | Длительность отрезка\n        self.len_chack = random.randint(self.hp.len_chack[0]-48, self.hp.len_chack[0]+52)\n        #self.len_chack = self.hp.len_chack[0]\n        \n        images = np.zeros((self.hp.n_mels, self.len_chack)).astype(np.float32)            \n        for i,idy in enumerate([idx,idx2,idx3]):\n            # Choosing a record with a bird | Выбираем запись с птицей\n            sample = self.bird_list.loc[idy, :]\n            # Uploading a record with a bird | Загружаем запись с птицей\n            mel = torch.load(self.hp.mel_folder+sample.file.replace(\".mp3\",\".amp\")).numpy()\n\n            # Birds in the file | Птицы в файле\n            labels_bird = sample.bird.split()\n            for bird in labels_bird:\n                if not bird in birds and bird != 264:\n                    birds.append(self.hp.BIRD_CODE[bird])\n            \n            # Birds in the background | Птицы на фоне     \n            if sample.labels_bg:\n                labels_bg = sample.labels_bg.split()\n                for bg in labels_bg:\n                    if not bg in background:\n                        background.append(self.hp.BIRD_CODE[bg])\n            \n            # Select the piece that contains the sound | Выбираем кусок в котором содержится звук\n            if mel.shape[1]>self.len_chack: \n                start = random.randint(0, mel.shape[1] - self.len_chack - 1)\n                mel = mel[:, start : start + random.randint(self.len_chack-48, self.len_chack)]\n            else:\n                len_zero = random.randint(0, self.len_chack-mel.shape[1])\n                mel = np.concatenate((np.zeros((self.hp.n_mels,len_zero)),mel), axis=1)\n            \n            mel = np.concatenate((mel,np.zeros((self.hp.n_mels,self.len_chack-mel.shape[1]))), axis=1)\n            \n            # Change the contrast | Изменить контрастность\n            mel = random_power(mel, power = 3, c= 0.5)\n            #mel = librosa.power_to_db(mel.astype(np.float32), ref=np.max)\n            #mel = (mel+80)/80\n            \n            # Mix the signal | Смешать сигнал\n            images = images + mel*(random.random() * self.div_coef + 1)\n            \n            # Abort accidentally | Случайно прервать \n            if random.random()<self.stop_border:\n                break\n        \n        # Add a different sound without birds | Добавить другой звук без птиц\n        idy = random.randint(0, len(self.noise)-1)\n        sample = self.noise.loc[idy, :]\n        mel = torch.load('./mel/'+sample.file.replace(\".wav\",\".amp\")).numpy()\n        mel = np.concatenate((np.zeros((self.hp.n_mels,self.len_chack)),mel), axis=1)\n        mel = np.concatenate((mel,np.zeros((self.hp.n_mels,self.len_chack))), axis=1)\n        start = random.randint(0, mel.shape[1] - self.len_chack - 1)\n        mel = mel[:, start : start + self.len_chack]\n        mel = random_power(mel)\n        #mel = librosa.power_to_db(mel.astype(np.float32), ref=np.max)\n        #mel = (mel+80)/80\n        images = images + mel/(mel.max()+0.0000001)*(random.random()*1+0.5)*images.max()\n        \n        # In db and normalize | В Дб и нормализовать\n        images = librosa.power_to_db(images.astype(np.float32), ref=np.max)\n        images = (images+80)/80\n        \n        # Add noise | Добавить шум\n        # Add white noise | Добавить белый шум            \n        if random.random()<0.9:\n            images = images + (np.random.sample((self.hp.n_mels,self.len_chack)).astype(np.float32)+9) * images.mean() * self.level_noise * (np.random.sample() + 0.3)\n        \n        # Add pink noise | Добавить розовый шум\n        if random.random()<0.9:\n            r = random.randint(1,self.hp.n_mels)\n            pink_noise = np.array([np.concatenate((1 - np.arange(r)/r,np.zeros(self.hp.n_mels-r)))]).T\n            images = images + (np.random.sample((self.hp.n_mels,self.len_chack)).astype(np.float32)+9) * 2  * images.mean() * self.level_noise * (np.random.sample() + 0.3)\n        \n        # Add bandpass noise | Добавить полосовой шум\n        if random.random()<0.9:\n            a = random.randint(0, self.hp.n_mels//2)\n            b = random.randint(a+20, self.hp.n_mels)\n            images[a:b,:] = images[a:b,:] + (np.random.sample((b-a,self.len_chack)).astype(np.float32)+9) * 0.05 * images.mean() * self.level_noise  * (np.random.sample() + 0.3)\n        \n        \n        # Lower the upper frequencies | Понизить верхние частоты\n        if random.random()<0.5:\n            images = images - images.min()\n            r = random.randint(self.hp.n_mels//2,self.hp.n_mels)\n            x = random.random()/2\n            pink_noise = np.array([np.concatenate((1-np.arange(r)*x/r,np.zeros(self.hp.n_mels-r)-x+1))]).T\n            images = images*pink_noise\n            images = images/images.max()\n        \n        # Change the contrast | Изменить контрастность\n        images = random_power(images, power = 2, c= 0.7)\n        \n        # Expand to 3 channels | Расширить до 3 каналов\n        #images = torch.from_numpy(np.stack([images, images, images])).float()\n        images = mono_to_color(images,hp.len_chack[0])\n\n        # Draw pictures | Рисуем графики\n        if random.random()<0.0001:\n            img = images.numpy()\n            img = img - img.min()\n            img = img/img.max()\n            img = np.moveaxis(img, 0, 2)\n            imgplot = plt.imshow(img)\n            plt.savefig('log/img/'+(\"_\".join(self.hp.INV_BIRD_CODE[x] for x in birds))+'_'+sample.file+'.png')    \n        \n        # If there are no birds, then the background | Усли нет птиц, значит фон\n        if not birds:\n            birds.append(264)        \n        \n        # The background is 0.3, and the marked bird is 1 | Фон это 0.3, а помеченая птица 1\n        for bird in background:\n            if bird < len(y):\n                y[bird]=0.3\n        for bird in birds:\n            #if not bird==264:\n            y[bird]=1\n        return images, y\n\n\n\ndef train(model,optimizer,epochs,train_accuracy,all_loss,best_bird_count,best_score, t_scores, f1_scores, b_scores):\n    # Create a folder for logs | Создать папку для логов\n    save_dir = os.path.join(\"./log\")\n    os.makedirs(save_dir, exist_ok=True)\n    \n    # Upload a list of training files | Загрузить список тренировочных mel meta.csv\n    bird_list = pd.read_csv(\"meta.csv\")\n    bird_list = bird_list[bird_list.bird.isin(hp.bird_count)].reset_index(drop=True)\n    bird_list = bird_list.fillna(0)\n    train_count = len(bird_list)\n    trainset = MelDataset(bird_list, hp)\n    train_loader = data.DataLoader(trainset, batch_size = hp.batch_size, shuffle=True, drop_last=True, num_workers = 2)\n    \n    # Training process | Процесс обучения\n    prediction_dict = {}\n    start = time.time()\n    model.zero_grad() \n    for epoch in range(epochs, 1000):\n        step = 0\n        model.train()\n        start_time = time.time()\n        for (mel, background) in train_loader:\n            step+=1\n            # Consider the network output | Считаем выход сети\n            prediction = model(mel.cuda())\n            \n            # We consider an error | Считаем ошибку\n            train_loss = nn.BCEWithLogitsLoss()(prediction, background.cuda())\n            #train_loss = nn.CrossEntropyLoss()(prediction, np.argmax(background, axis = 1).cuda())\n            \n            # Calculate the gradients and make a step | Вычисляем градиенты и делаем шаг \n            train_loss.backward()\n            if not step % (100//hp.batch_size): \n                optimizer.step()\n                model.zero_grad()\n            \n            # Saving error and accuracy | Сохраняем ошибку и точность\n            train_accuracy.append(accuracy(background, prediction))\n            all_loss.append(train_loss.detach().cpu().numpy())\n            \n            # Every hp.save_interval steps we display statistics | Каждые 100 шагов выводим статистику\n            if not step % hp.save_interval:\n                print(str(epoch)+' '+str(step)+'/'+str(train_count//hp.batch_size), \n                        \"время: %.3f loss: %.3f accuracy: %.3f \" % (\n                        (time.time()-start_time)/hp.save_interval,\n                        np.mean(all_loss[-hp.save_interval:])*10,\n                        np.mean(train_accuracy[-hp.save_interval:])))\n                # Test | Тестируем \n                (bird_count, bird_accuracy, test_accuracy), _ = generate([model],epochs,hp.border,True)\n                if bird_accuracy>0:\n                    t_scores.append(bird_accuracy)\n                    f1_scores.append(test_accuracy)\n                    b_scores.append(bird_count)\n                \n                model.train()\n                \n                # Draw graphs | Рисуем графики\n                plt.clf()\n                plt.plot(gaussian_filter1d(train_accuracy[80:], 20))\n                plt.plot(gaussian_filter1d(all_loss[80:], 20)*10)\n                plt.savefig('log/all_loss.png')        \n                plt.clf()\n                plt.plot(t_scores)\n                plt.savefig('log/t.png') \n                plt.clf()\n                plt.plot(f1_scores)\n                plt.savefig('log/f1.png')\n                plt.clf()\n                plt.plot(b_scores)\n                plt.savefig('log/b.png')\n                # Saving the model | Сохраняем модель\n                if (bird_count>best_bird_count or test_accuracy>best_score or step==hp.save_interval):\n                    if bird_count>best_bird_count:\n                        best_bird_count = bird_count\n                    if test_accuracy>best_score:\n                        best_score = test_accuracy\n                    \n                    torch.save({\n                        'model': model.state_dict(),\n                        'optimizer': optimizer.state_dict(),\n                        'epoch': epoch,\n                        'best_bird_count': bird_count,\n                        'best_score': test_accuracy,\n                        'train_accuracy': train_accuracy,\n                        'all_loss': all_loss,\n                        't_scores': t_scores,\n                        'f1_scores': f1_scores,\n                        'b_scores': b_scores,                        \n                    }, 'log/enet_%d_%.3f_%.3f.pt' % (bird_count,bird_accuracy,test_accuracy))\n                    print(\"Модель сохранена\")\n                start_time = time.time()\n\n\ndef generate(models, epochs, border,log_stat):\n    start = time.time() \n    preds = []\n\n    # Uploading a list of files for testing | Загружаем список файлов для тестирования\n    TEST_FOLDER = f'{BASE_TEST_DIR}/test_audio/'\n    test_info = pd.read_csv(f'{BASE_TEST_DIR}/test.csv')\n    \n    # Looking for all unique audio recordings | Ищем все уникальные аудиозаписи\n    unique_audio_id = test_info.audio_id.unique() \n    \n    # Predict | Предсказываем\n    for model in models:\n        model.eval()\n    with torch.no_grad():    \n        for audio_id in unique_audio_id:\n            # Getting a spectrogram | Получаем спектрограмму\n            melspectr = get_melspectr(TEST_FOLDER + audio_id + \".mp3\")\n            melspectr = librosa.power_to_db(melspectr, amin=1e-7, ref=np.max)\n            melspectr = ((melspectr+80)/80).astype(np.float16)\n            \n            # Looking for all the excerpts for this sound | Ищем все отрывки для данного звука  \n            test_df_for_audio_id = test_info.query(f\"audio_id == '{audio_id}'\").reset_index(drop=True)\n            est_bird =np.zeros((265))\n            probass = {}\n            \n            # Проходим по все отрывкам \n            for index, row in test_df_for_audio_id.iterrows():\n                # Getting the site, start time, and id | Получаем сайт, время начала и id\n                site = row['site']\n                start_time = row['seconds'] - 5\n                row_id = row['row_id']\n                mels = []\n                probas = None\n                \n                # Cut out the desired piece | Вырезаем нужный кусок\n                if site == 'site_1' or site == 'site_2':\n                    start_index = int(hp.sr * start_time/hp.hop_length)\n                    end_index = int(hp.sr * row['seconds']/hp.hop_length)                \n                    y = melspectr[:,start_index:end_index]\n                else:\n                    y = melspectr\n                    \n                # cutting off the tail | отсекаю хвост\n                if (y.shape[1]%hp.len_chack[0]):\n                    y = y[:,:-(y.shape[1]%448)]\n                \n                prob = []\n                for i,model in enumerate(models):\n                    mels = []\n                    probas = None                    \n                    # Split into several chunks with the duration hp.len_chack | Разбиваем на несколько кусков длительностью hp.len_chack\n                    ys = np.reshape(y, (hp.n_mels, -1, hp.len_chack[i]))\n                    ys = np.moveaxis(ys, 1, 0)\n\n                    # For each piece we make transformations | Для каждого куска делаем преобразования\n                    for image in ys:\n                        # Convert to 3 colors and normalize | Переводим в 3 цвета и нормализуем\n                        image = image/image.max()\n                        #image = image**0.85\n                        #image = torch.from_numpy(np.stack([image, image, image])).float()\n                        image = mono_to_color(image,hp.len_chack[i])\n                        mels.append(image)\n\n                    mels = np.stack(mels)                \n                    \n                    # Прохожу по всем batch\n                    for n in range(0,len(mels),hp.batch_size):\n                        if len(mels) == 1:\n                            mel = np.array(mels)\n                        else:\n                            mel = mels[n:n+hp.batch_size]\n\n                        mel = torch.from_numpy(mel).cuda()\n\n                        # Predict | Получить выход модели\n                        prediction = model(mel)\n                        #prediction = F.softmax(prediction, dim=1)\n                        prediction = torch.sigmoid(prediction)\n\n                        # in numpy\n                        proba = prediction.detach().cpu().numpy()\n\n                        # Add zeros up to 265 | Добавить нули до 265\n                        proba = np.concatenate((proba,np.zeros((proba.shape[0],265-proba.shape[1]))), axis=1)\n\n                        # Adding to the array | Добавляю в массив\n                        if not probas is None:\n                            probas = np.append(probas, proba, axis = 0)\n                        else:\n                            probas = proba\n                        if hp.len_chack[i] == 448:\n                            probas = np.append(probas, proba, axis = 0)\n                    prob.append(probas)\n\n                # Averaging the ensemble | Усредняю ансамбль\n                prob = np.stack(prob,axis=0)\n                prob = prob**2\n                proba = prob.mean(axis=0)#gmean(prob)/2 + prob.mean(axis=0)/2\n                proba = proba**(1/2)\n                \n                # If a bird is encountered in one segment, increase its probability in others\n                # Если встретилась птица в одном отрезке, увеличить её вероятность в других\n                for xx in proba:\n                    z = xx.copy()\n                    z[z<0.5] = 0\n                    est_bird = est_bird + z/70\n                    est_bird[(est_bird<0.15)&(est_bird>0)] = 0.15\n      \n                # Dictionary with an array of all passages | Словарь с массивом всех отрывков\n                probass[row_id] = proba\n            \n            est_bird[est_bird>0.3] = 0.3\n            for row_id,probas in probass.items():\n                prediction_dict = []\n                for proba in probas:\n                    proba += est_bird\n                    events = proba > border\n                    labels = np.argwhere(events).reshape(-1).tolist()\n\n                    # To convert in the name of the bird | Преобразовать в название птиц\n                    if len(labels) == 0  or (264 in labels):\n                        continue\n                    else:\n                        labels_str_list = list(map(lambda x: hp.INV_BIRD_CODE[x], labels))\n                        for i in labels_str_list:\n                            if i not in prediction_dict:\n                                prediction_dict.append(i)  \n                    \n                # If birds are not predicted | Если не предсказываются птицы\n                if len(prediction_dict) == 0:\n                    prediction_dict = \"nocall\"\n                else:\n                    prediction_dict = \" \".join(prediction_dict)\n          \n                # To add to the list | Добавить в список\n                preds.append([row_id, prediction_dict])\n\n        # Convert to DataFrame and save | Перевести в DataFrame и сохранить\n        preds = pd.DataFrame(preds, columns=['row_id', 'birds'])\n        preds.to_csv('submission.csv', index=False)\n    \n    return test_accuracy(preds,log_stat,border), time.time() - start\n\n\ndef pseudo(models):\n    files = {}\n    with open('meta_all.csv', 'r', encoding=\"utf-8\") as input:\n        input.readline()\n        for s in input:\n            s = s.strip().split(',')\n            file,bird,background = s[0],s[1],s[2].split(' ')\n            file = file.split('.')[0]\n            files[file] = [bird,background]\n    \n    # Uploading a list of files for marking | Загружаем список файлов для маркирования\n    dataset = glob.glob(os.path.join(\"./mel/\", 'XC*.amp'), recursive=True)\n    #dataset = glob.glob(os.path.join(\"./un_bird/\", '*.wav'), recursive=True)\n    #dataset = ['./clear/osprey/XC27026.mp3']\n    prediction_dict = {}\n    \n    # Predict | Предсказываем\n    for model in models:\n        model.eval()\n    with torch.no_grad():\n        for file_name in tqdm(dataset):\n            #y = get_melspectr(file_name)\n            y = torch.load(file_name).numpy()\n            est_bird =np.zeros((265))\n            mels = []\n            probas = None\n            ys = []\n\n            if y.shape[1]>=hp.len_chack:\n                for i in range(0,(y.shape[1]*5)//hp.len_chack-4,3):\n                    yy = y[:,i*hp.len_chack//5:(i+5)*hp.len_chack//5]\n                    if yy.shape[1]<hp.len_chack:\n                        yy = np.concatenate((yy,np.zeros((hp.n_mels,hp.len_chack-yy.shape[1]))), axis=1)\n                    ys.append(yy)\n                ys = np.stack(ys) \n            else:\n                yy = np.concatenate((y,np.zeros((hp.n_mels,hp.len_chack-y.shape[1]))), axis=1)\n                ys = np.array([yy])\n            \n            for y in ys:\n                y = librosa.power_to_db(y,  amin=1e-7, ref=np.max)\n                y = ((y+80)/80).astype(np.float16)\n                image = torch.from_numpy(np.stack([y, y, y])).float()\n                mels.append(image)\n\n            mels = np.stack(mels) \n            for n in range(0,len(mels),hp.batch_size*2):\n                if len(mels) == 1:\n                    mel = np.array(mels)\n                else:\n                    mel = mels[n:n+hp.batch_size*2]\n\n                mel = torch.from_numpy(mel).cuda()\n                \n                prob = []\n                for model in models:\n                    prediction = model(mel)\n                    prediction = torch.sigmoid(prediction)\n                    proba = prediction.detach().cpu().numpy()\n                    proba = np.concatenate((proba,np.zeros((proba.shape[0],265-proba.shape[1]))), axis=1)\n                    prob.append(proba)\n                    \n                prob = np.stack(prob)\n                proba = prob.mean(axis=0)\n                            \n                if not probas is None:\n                    probas = np.append(probas, proba, axis = 0)\n                else:\n                    probas = proba\n            \n            for sk,proba in enumerate(probas):\n                proba += est_bird\n                file_name1 = os.path.basename(file_name).replace('.mp3','').replace('.wav','').replace('.amp','')\n                sek = file_name1 +'_' + str(sk)+'.amp'\n                events = proba > hp.border\n                labels = np.argwhere(events).reshape(-1).tolist()\n                if len(labels) == 0  or (264 in labels):\n                    continue\n                else:\n                    labels_str_list = list(map(lambda x: hp.INV_BIRD_CODE[x], labels))\n                    if file_name1 in files:\n                        bird = []\n                        background = []\n                        for i in labels_str_list:\n                            if i in files[file_name1][1] or i==files[file_name1][0]:\n                                if not i in bird:\n                                    bird.append(i)\n                            else:\n                                if not i in background:\n                                    background.append(i)\n                        if bird:\n                            torch.save(torch.from_numpy(ys[sk].astype(np.float16)), './mel_p/'+sek)\n                            prediction_dict[sek] = [\" \".join(bird),\" \".join(background)]\n                            \"\"\"\n                            img = np.moveaxis(mels[sk], 0, 2)\n                            #ys[sk] = ys[sk]/ys[sk].max()\n                            #img = np.moveaxis(np.stack([ys[sk],ys[sk],ys[sk]]), 0, 2)\n                            img = np.array(img, dtype = np.float64)\n                            plt.imshow(img)\n                            plt.savefig('./1/'+sek+\" \".join(bird)+'.png') \n                            \"\"\"                            \n\n        preds = pd.DataFrame.from_dict(prediction_dict, orient='index', columns=['birds',\"labels_bg\"])\n        preds.reset_index(inplace=True)\n        preds.columns = ['file', 'bird',\"labels_bg\"]\n        preds.to_csv('meta.csv', index=False)\n\n\n# Loading hp | Загружаем гиперпараметры\nhp = Hparams()\nall_model = []\nfor i in range(len(hp.models_name)):\n    model,optimizer, epochs, train_accuracy, all_loss, best_bird_count, best_score, t_scores, f1_scores, b_scores = get_model(\n                                                                                hp.models_name[i],hp.chk[i],hp.count_bird[i])\n    all_model.append(model)\ngenerate(all_model, epochs, hp.border, True)    \n\"\"\"\nif __name__ == \"__main__\":\n    BASE_TEST_DIR = '.'\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"-r\", \"--run\", default='train', help=\\\n        \"Enter the function you want to run | Введите функцию, которую надо запустить (preprocess, train, generate)\")\n    args = parser.parse_args()\n    \n    if args.run == 'preprocess' or args.run == 'p':\n        preprocess()    \n    else:\n        # to create a model | создать model\n        all_model = []\n        for i in range(len(hp.models_name)):\n            model,optimizer, epochs, train_accuracy, all_loss, best_bird_count, best_score, t_scores, f1_scores, b_scores = get_model(hp.models_name[i],hp.chk[i],hp.count_bird[i])\n            all_model.append(model)\n        if args.run == 'train' or args.run == 't':\n            train(all_model[0],optimizer,epochs,train_accuracy,all_loss,best_bird_count,best_score, t_scores, f1_scores, b_scores)\n        elif args.run == 'pseudotarget' or args.run == 'm':\n            pseudo(all_model)\n        elif args.run == 'generate' or args.run == 'g':\n            for i in [ 0.4, 0.5, 0.6]:\n                print(i, generate(all_model, epochs, i, True))\n        else:\n            print(\"Enter the correct function | Введите корректную функцию (preprocess, train, generate)\") \n\"\"\"            ","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}