{"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":"from pathlib import Path \nimport os \nfrom glob import glob\nfrom PIL import Image\nfrom torchvision import transforms\nimport torch\nfrom torch.utils.data import Dataset, DataLoader, Subset, random_split\nfrom torch.nn import BCEWithLogitsLoss\nfrom torch import nn, optim \nimport numpy as np \nimport pandas as pd \nfrom torch import optim\nfrom sklearn.metrics import log_loss\nfrom tqdm import tqdm\nfrom torchvision import models","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:07.729832Z","iopub.execute_input":"2023-01-28T11:23:07.730611Z","iopub.status.idle":"2023-01-28T11:23:10.371765Z","shell.execute_reply.started":"2023-01-28T11:23:07.730506Z","shell.execute_reply":"2023-01-28T11:23:10.370707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom torch import unique\n ","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:12.679840Z","iopub.execute_input":"2023-01-28T11:23:12.680902Z","iopub.status.idle":"2023-01-28T11:23:12.686216Z","shell.execute_reply.started":"2023-01-28T11:23:12.680852Z","shell.execute_reply":"2023-01-28T11:23:12.684812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set the seed for the random number generator\nseed = 42\ntorch.manual_seed(seed)\nnp.random.seed(seed)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:14.839909Z","iopub.execute_input":"2023-01-28T11:23:14.840835Z","iopub.status.idle":"2023-01-28T11:23:14.848288Z","shell.execute_reply.started":"2023-01-28T11:23:14.840793Z","shell.execute_reply":"2023-01-28T11:23:14.847262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Подготовка данных\n\n1. Распаковка архивов\n2. Написание DataLoader\n3. Написание Transformer - конвейера подготовки изображения\n4. Разделение набора на train и validation set","metadata":{}},{"cell_type":"code","source":"path = Path('/kaggle/input/dogs-vs-cats-redux-kernels-edition')\nos.listdir(path)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T10:59:27.520347Z","iopub.execute_input":"2023-01-28T10:59:27.520693Z","iopub.status.idle":"2023-01-28T10:59:27.532527Z","shell.execute_reply.started":"2023-01-28T10:59:27.520666Z","shell.execute_reply":"2023-01-28T10:59:27.531540Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%time !unzip -q $path/'train.zip'\n%time !unzip -q $path/'test.zip'","metadata":{"execution":{"iopub.status.busy":"2023-01-28T10:59:30.789998Z","iopub.execute_input":"2023-01-28T10:59:30.790349Z","iopub.status.idle":"2023-01-28T10:59:47.061849Z","shell.execute_reply.started":"2023-01-28T10:59:30.790320Z","shell.execute_reply":"2023-01-28T10:59:47.060566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = list(Path('train').glob('*.jpg'))\nlen(images)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:18.102044Z","iopub.execute_input":"2023-01-28T11:23:18.102439Z","iopub.status.idle":"2023-01-28T11:23:18.325541Z","shell.execute_reply.started":"2023-01-28T11:23:18.102404Z","shell.execute_reply":"2023-01-28T11:23:18.324570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# класс для препроцессинга изображений\nget_label = lambda x: x.name.split('.')[0]\n\nclass DogCat_preprocessing(Dataset):\n    def __init__(self, root, transform=None):\n        self.images = list(Path(root).glob('*.jpg'))\n        self.transform = transform\n    def __len__(self):\n        return len(self.images)\n    def __getitem__(self, idx):\n        img_path = self.images[idx]\n        label = get_label(img_path)\n        img = Image.open(img_path)\n        label = 1 if label == 'dog' else 0\n        if self.transform:\n            img = self.transform(img)\n        return img, torch.tensor(label, dtype=torch.float64)\n\n# конвейер для трансформации изображений - ЗНАЧЕНИЯ НИЖЕ ЭТО ГИПЕРПАРАМЕТРЫ ИХ МОЖНО МЕНЯТЬ\n# Resize - изображения разного размера - нужно привести к одному размеру\n# Normalize - нормализация каждого канала\n# CenterCrop - Обрезка изображения по центру\ntfms = transforms.Compose([\n    transforms.Resize(256),\n    transforms.CenterCrop(224),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:21.005908Z","iopub.execute_input":"2023-01-28T11:23:21.006300Z","iopub.status.idle":"2023-01-28T11:23:21.019108Z","shell.execute_reply.started":"2023-01-28T11:23:21.006266Z","shell.execute_reply":"2023-01-28T11:23:21.017575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# препроцессинг всех картинок\nds = DogCat_preprocessing('train', transform=tfms)\n \nlen(ds)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:23.623783Z","iopub.execute_input":"2023-01-28T11:23:23.624170Z","iopub.status.idle":"2023-01-28T11:23:23.709382Z","shell.execute_reply.started":"2023-01-28T11:23:23.624138Z","shell.execute_reply":"2023-01-28T11:23:23.708231Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Небольшой разведочный анализ\n* Просмотр первых изображений\n* Просмотр соотношения количеcтва классов","metadata":{}},{"cell_type":"code","source":"# функция показа картинки из тензора с меткой класса\ndef show_image( image_tensor , label ):\n    NAME =  lambda x: \"Cat\" if x.item() == 0 else \"Dog\"\n    plt.title(  NAME(label))\n    plt.imshow(  image_tensor.permute(1, 2, 0)  ) \n    return 0","metadata":{"execution":{"iopub.status.busy":"2023-01-28T10:59:50.819807Z","iopub.execute_input":"2023-01-28T10:59:50.820686Z","iopub.status.idle":"2023-01-28T10:59:50.827282Z","shell.execute_reply.started":"2023-01-28T10:59:50.820640Z","shell.execute_reply":"2023-01-28T10:59:50.825956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Первые несколько изображений\nplt.figure(figsize=(12,12))\nfor i in range(1, 16):\n    plt.subplot(3,5,i)\n    plt.axis('off')\n    \n    NAME =  lambda x: \"Cat\" if x.item() == 0 else \"Dog\"\n    \n    picture = ds.__getitem__(i)\n    \n    plt.title(  NAME( picture[1] ))\n    plt.imshow(  picture[0].permute(1, 2, 0)  )      ","metadata":{"execution":{"iopub.status.busy":"2023-01-28T09:59:35.624851Z","iopub.execute_input":"2023-01-28T09:59:35.625334Z","iopub.status.idle":"2023-01-28T09:59:37.098861Z","shell.execute_reply.started":"2023-01-28T09:59:35.625298Z","shell.execute_reply":"2023-01-28T09:59:37.097598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Cats = 0\nDogs = 0\nfor i in tqdm( range( len(ds)) ):\n    label_ = ds.__getitem__(i)[1].item() \n    if label_ ==  0 :\n        Cats += 1\n    else: \n        Dogs += 1       \n   ","metadata":{"execution":{"iopub.status.busy":"2023-01-28T10:14:12.554332Z","iopub.execute_input":"2023-01-28T10:14:12.554779Z","iopub.status.idle":"2023-01-28T10:16:55.626685Z","shell.execute_reply.started":"2023-01-28T10:14:12.554744Z","shell.execute_reply":"2023-01-28T10:16:55.625457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Соотношение классов:\\nКошки: {}\\nСобаки: {}\".format(Cats , Dogs))","metadata":{"execution":{"iopub.status.busy":"2023-01-28T10:19:04.001822Z","iopub.execute_input":"2023-01-28T10:19:04.002318Z","iopub.status.idle":"2023-01-28T10:19:04.009557Z","shell.execute_reply.started":"2023-01-28T10:19:04.002284Z","shell.execute_reply":"2023-01-28T10:19:04.008196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Из соотношения выше следует - что выборка сбалансированная","metadata":{"execution":{"iopub.status.busy":"2023-01-28T10:06:09.739322Z","iopub.execute_input":"2023-01-28T10:06:09.739803Z","iopub.status.idle":"2023-01-28T10:06:09.747030Z","shell.execute_reply.started":"2023-01-28T10:06:09.739764Z","shell.execute_reply":"2023-01-28T10:06:09.745869Z"}}},{"cell_type":"markdown","source":"# Разделение данных на Train и Validation для обучения модели","metadata":{}},{"cell_type":"code","source":"# разделение на  train и validation\ntrain_ds, val_ds = random_split(ds, [int(len(ds) * 0.8), len(ds) - int(len(ds) * 0.8)])\n ","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:30.456857Z","iopub.execute_input":"2023-01-28T11:23:30.457253Z","iopub.status.idle":"2023-01-28T11:23:30.465502Z","shell.execute_reply.started":"2023-01-28T11:23:30.457213Z","shell.execute_reply":"2023-01-28T11:23:30.464206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# создание dataloaders\ntrain_dl = DataLoader(train_ds, batch_size=32, shuffle=True)\nval_dl = DataLoader(val_ds, batch_size=32, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:32.272860Z","iopub.execute_input":"2023-01-28T11:23:32.273256Z","iopub.status.idle":"2023-01-28T11:23:32.279265Z","shell.execute_reply.started":"2023-01-28T11:23:32.273222Z","shell.execute_reply":"2023-01-28T11:23:32.278011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"xb, yb = next(iter(train_dl))\nprint(xb.shape, yb)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:35.653142Z","iopub.execute_input":"2023-01-28T11:23:35.653543Z","iopub.status.idle":"2023-01-28T11:23:35.927404Z","shell.execute_reply.started":"2023-01-28T11:23:35.653508Z","shell.execute_reply":"2023-01-28T11:23:35.926293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_default_device():\n    \"\"\"Выбор доступного ускорителя\"\"\"\n    if torch.cuda.is_available():\n        return torch.device('cuda')\n    else:\n        return torch.device('cpu')\n    \ndef to_device(data, device):\n    \"\"\"Перевод тензоров на выбранное устройство\"\"\"\n    if isinstance(data, (list,tuple)):\n        return [to_device(x, device) for x in data]\n    return data.to(device, non_blocking=True)\n\nclass DeviceDataLoader():\n    \"\"\" Включение dataloader  для перевода на ускоритель \"\"\"\n    def __init__(self, dl, device):\n        self.dl = dl\n        self.device = device\n        \n    def __iter__(self):\n        \n        for b in self.dl: \n            yield to_device(b, self.device)\n    \"\"\" Непосредственно перевод dataloader  на ускоритель \"\"\"\n    def __len__(self):\n        \"\"\"Количество батчей\"\"\"\n        return len(self.dl)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:47.545754Z","iopub.execute_input":"2023-01-28T11:23:47.546477Z","iopub.status.idle":"2023-01-28T11:23:47.556498Z","shell.execute_reply.started":"2023-01-28T11:23:47.546437Z","shell.execute_reply":"2023-01-28T11:23:47.555235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dl = DeviceDataLoader(train_dl, get_default_device())\nval_dl = DeviceDataLoader(val_dl, get_default_device())","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:23:50.436585Z","iopub.execute_input":"2023-01-28T11:23:50.437333Z","iopub.status.idle":"2023-01-28T11:23:50.508020Z","shell.execute_reply.started":"2023-01-28T11:23:50.437265Z","shell.execute_reply":"2023-01-28T11:23:50.506829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Раздел построения модели для классификации\n\nМожно создавать модель с нуля или загрузить из подраздела Torchvision","metadata":{}},{"cell_type":"code","source":"# Создание базового класса для модели сети с готовыми методами  обучения и проверки и мониторинга\n\nimport torch.nn as nn\n\nclass ImageClassificationBase(nn.Module):\n    def training_step(self, batch):\n        images, labels = batch\n        out = self(images)\n        loss = loss_fn(out, labels.unsqueeze(1))\n        return loss\n    def validation_step(self, batch):\n        images, labels = batch\n        out = self(images)\n        loss = loss_fn(out, labels.unsqueeze(1))\n        pred = torch.sigmoid(out) > 0.5 \n        y_pred = torch.clip(torch.sigmoid(out), 0.005, 0.995).cpu().detach().numpy()\n        y_true = labels.cpu().numpy()\n        log_losss = torch.tensor(log_loss(y_true, y_pred))\n        return {'val_loss': loss.detach(), 'val_acc': log_losss}\n    def validation_epoch_end(self, outputs):\n        batch_losses = [x['val_loss'] for x in outputs]\n        epoch_loss = torch.stack(batch_losses).mean()\n        batch_acc = [x['val_acc'] for x in outputs]\n        epoch_acc = torch.stack(batch_acc).mean()\n        return {'val_loss': epoch_loss.item(), 'val_acc': epoch_acc.item()}\n    def epoch_end(self, epoch, result):\n        print(\"Epoch [{}], last_lr: {:.5f}, train_loss: {:.4f}, val_loss: {:.4f}, val_log_loss: {:.4f}\".format(epoch, result['lrs'][-1], result['train_loss'], result['val_loss'], result['val_acc']))","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:25:14.077166Z","iopub.execute_input":"2023-01-28T11:25:14.077974Z","iopub.status.idle":"2023-01-28T11:25:14.090438Z","shell.execute_reply.started":"2023-01-28T11:25:14.077933Z","shell.execute_reply":"2023-01-28T11:25:14.089176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Создание модели - используется предобученная сеть ResNet18\nclass Res_Net_18(ImageClassificationBase):\n    def __init__(self):\n        super().__init__()\n        self.network = models.resnet18(pretrained=True)\n        num_features = self.network.fc.in_features\n        self.network.fc = nn.Linear(512, 1)\n    \n    def forward(self, xb):\n        return self.network(xb)\n    \n    def freeze(self):\n       # Заморозка сверток для дообучения\n        for param in self.network.parameters():\n            param.require_grad = False\n        for param in self.network.fc.parameters():\n            param.require_grad = True\n    \n    def unfreeze(self):\n        # Разморозка слоев\n        for param in self.network.parameters():\n            param.require_grad = True\n\nmodel = Res_Net_18()\nmodel = model.to(get_default_device())","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:25:23.029288Z","iopub.execute_input":"2023-01-28T11:25:23.029688Z","iopub.status.idle":"2023-01-28T11:25:26.391783Z","shell.execute_reply.started":"2023-01-28T11:25:23.029650Z","shell.execute_reply":"2023-01-28T11:25:26.390689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Инициализация параметров обучения  сети - количество эпох, скорость обучения, сокращение весов\nepochs = 2\nmax_lr = 0.01\ngrad_clip = 0.1\nweight_decay = 1e-4\n \nloss_fn = BCEWithLogitsLoss()\noptimizer = optim.SGD(model.parameters(),lr=max_lr, momentum=0.9)\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\nmodel = Res_Net_18()\nmodel = model.to(device)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:25:38.621430Z","iopub.execute_input":"2023-01-28T11:25:38.621850Z","iopub.status.idle":"2023-01-28T11:25:38.873356Z","shell.execute_reply.started":"2023-01-28T11:25:38.621812Z","shell.execute_reply":"2023-01-28T11:25:38.872311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Обучение модели","metadata":{}},{"cell_type":"code","source":"# несколько вспомогательных функций\n@torch.no_grad()\ndef evaluate(model, val_loader):\n    model.eval()\n    outputs = [model.validation_step(batch) for batch in val_loader]\n    return model.validation_epoch_end(outputs)\n\ndef get_lr(optimizer):\n    for param_group in optimizer.param_groups:\n        return param_group['lr']\n\ndef fit_one_cycle(epochs, max_lr, model, train_dl, val_dl, grad_clip=None, weight_decay=0, opt_func=optimizer):\n    torch.cuda.empty_cache()\n    history = []\n    optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n    sched = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr, epochs=epochs, steps_per_epoch=len(train_dl))\n    \n    for epoch in range(epochs):\n        #  Фаза обучения\n        model.train()\n        train_losses = []\n        lrs = []\n        for batch in tqdm( train_dl):\n            loss = model.training_step(batch)\n            train_losses.append(loss)\n            loss.backward()\n            \n            #  сокращение градиента\n            if grad_clip:\n                nn.utils.clip_grad_value_(model.parameters(), grad_clip)\n            \n            optimizer.step()\n            optimizer.zero_grad()\n            \n            #  запись и обновление скорости обучения\n            lrs.append(get_lr(optimizer))\n            sched.step()\n        \n        # проверка модели\n        result = evaluate(model, val_dl)\n        result['train_loss'] = torch.stack(train_losses).mean().item()\n        result['lrs'] = lrs\n        model.epoch_end(epoch, result)\n        history.append(result)\n    return history","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:25:50.868381Z","iopub.execute_input":"2023-01-28T11:25:50.868793Z","iopub.status.idle":"2023-01-28T11:25:50.880785Z","shell.execute_reply.started":"2023-01-28T11:25:50.868735Z","shell.execute_reply":"2023-01-28T11:25:50.879681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Оценка модели без тренировки на Validation Set\nhistory = [evaluate(model, val_dl)]\nhistory","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:25:57.327538Z","iopub.execute_input":"2023-01-28T11:25:57.327976Z","iopub.status.idle":"2023-01-28T11:26:40.350543Z","shell.execute_reply.started":"2023-01-28T11:25:57.327936Z","shell.execute_reply":"2023-01-28T11:26:40.349458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# заморозка слоев модели для дообучения\nmodel.freeze()","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:26:40.352458Z","iopub.execute_input":"2023-01-28T11:26:40.354015Z","iopub.status.idle":"2023-01-28T11:26:40.359131Z","shell.execute_reply.started":"2023-01-28T11:26:40.353973Z","shell.execute_reply":"2023-01-28T11:26:40.358121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# дообучение модели на 2 эпохах\n# %%time\nhistory += fit_one_cycle(epochs, max_lr, model, train_dl, val_dl, \n                             grad_clip=grad_clip, \n                             weight_decay=weight_decay, \n                             opt_func=optimizer)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:26:40.360723Z","iopub.execute_input":"2023-01-28T11:26:40.361138Z","iopub.status.idle":"2023-01-28T11:31:44.165095Z","shell.execute_reply.started":"2023-01-28T11:26:40.361101Z","shell.execute_reply":"2023-01-28T11:31:44.163823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Разморозка слоев и дообучение на 4 эпохах\nmodel.unfreeze()\nepochs = 4","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:32:38.235409Z","iopub.execute_input":"2023-01-28T11:32:38.235853Z","iopub.status.idle":"2023-01-28T11:32:38.241711Z","shell.execute_reply.started":"2023-01-28T11:32:38.235813Z","shell.execute_reply":"2023-01-28T11:32:38.240103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history += fit_one_cycle(epochs, max_lr, model, train_dl, val_dl, \n                             grad_clip=grad_clip, \n                             weight_decay=weight_decay, \n                             opt_func=optimizer)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:32:43.452293Z","iopub.execute_input":"2023-01-28T11:32:43.452676Z","iopub.status.idle":"2023-01-28T11:42:35.279814Z","shell.execute_reply.started":"2023-01-28T11:32:43.452644Z","shell.execute_reply":"2023-01-28T11:42:35.278643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Визуализация результатов обучения\n\nНа графиках отображены точность, функция потерь, скорость обучения","metadata":{}},{"cell_type":"code","source":"def plot_accuracies(history):\n    accuracies = [x['val_acc'] for x in history]\n    plt.plot(accuracies, '-x')\n    plt.xlabel('epoch')\n    plt.ylabel('accuracy')\n    plt.title('Accuracy vs. No. of epochs');","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:42:41.624480Z","iopub.execute_input":"2023-01-28T11:42:41.624905Z","iopub.status.idle":"2023-01-28T11:42:41.631177Z","shell.execute_reply.started":"2023-01-28T11:42:41.624867Z","shell.execute_reply":"2023-01-28T11:42:41.630017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nplot_accuracies(history)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:42:45.002272Z","iopub.execute_input":"2023-01-28T11:42:45.003152Z","iopub.status.idle":"2023-01-28T11:42:45.315655Z","shell.execute_reply.started":"2023-01-28T11:42:45.003105Z","shell.execute_reply":"2023-01-28T11:42:45.314492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_losses(history):\n    train_losses = [x.get('train_loss') for x in history]\n    val_losses = [x['val_loss'] for x in history]\n    plt.plot(train_losses, '-bx')\n    plt.plot(val_losses, '-rx')\n    plt.xlabel('epoch')\n    plt.ylabel('loss')\n    plt.legend(['Training', 'Validation'])\n    plt.title('Loss vs. No. of epochs');","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:43:08.369617Z","iopub.execute_input":"2023-01-28T11:43:08.370375Z","iopub.status.idle":"2023-01-28T11:43:08.376994Z","shell.execute_reply.started":"2023-01-28T11:43:08.370334Z","shell.execute_reply":"2023-01-28T11:43:08.375780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_losses(history)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:43:12.748867Z","iopub.execute_input":"2023-01-28T11:43:12.749284Z","iopub.status.idle":"2023-01-28T11:43:12.985862Z","shell.execute_reply.started":"2023-01-28T11:43:12.749250Z","shell.execute_reply":"2023-01-28T11:43:12.984795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_lrs(history):\n    lrs = np.concatenate([x.get('lrs', []) for x in history])\n    plt.plot(lrs)\n    plt.xlabel('Batch no.')\n    plt.ylabel('Learning rate')\n    plt.title('Learning Rate vs. Batch no.');","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:43:35.192034Z","iopub.execute_input":"2023-01-28T11:43:35.192433Z","iopub.status.idle":"2023-01-28T11:43:35.198164Z","shell.execute_reply.started":"2023-01-28T11:43:35.192392Z","shell.execute_reply":"2023-01-28T11:43:35.197141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_lrs(history)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:43:37.429353Z","iopub.execute_input":"2023-01-28T11:43:37.429734Z","iopub.status.idle":"2023-01-28T11:43:37.649715Z","shell.execute_reply.started":"2023-01-28T11:43:37.429702Z","shell.execute_reply":"2023-01-28T11:43:37.648789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Прогноз на одном объекте","metadata":{}},{"cell_type":"code","source":"# Сохранение модели\ntorch.save(model.state_dict(), 'model_res_ner_18.pt')","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:44:51.662897Z","iopub.execute_input":"2023-01-28T11:44:51.663644Z","iopub.status.idle":"2023-01-28T11:44:51.749129Z","shell.execute_reply.started":"2023-01-28T11:44:51.663605Z","shell.execute_reply":"2023-01-28T11:44:51.748052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Загрузка модели\nmodel.load_state_dict(torch.load('model_res_ner_18.pt'))","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:45:33.708640Z","iopub.execute_input":"2023-01-28T11:45:33.709394Z","iopub.status.idle":"2023-01-28T11:45:33.764953Z","shell.execute_reply.started":"2023-01-28T11:45:33.709354Z","shell.execute_reply":"2023-01-28T11:45:33.763811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del model","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# выработка прогнозов на 1 изображении\n@torch.no_grad()\ndef predict(model, img_path):\n    model.eval()\n    img = Image.open(img_path)\n    img = tfms(img)\n    img = img.unsqueeze(0)\n    img = img.to(device)\n    output = model(img)\n    # if pred is 1, then dog, else cat\n    pred = 'dog' if output.data > 0.5 else 'cat' \n    return pred","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:45:41.295340Z","iopub.execute_input":"2023-01-28T11:45:41.296403Z","iopub.status.idle":"2023-01-28T11:45:41.302717Z","shell.execute_reply.started":"2023-01-28T11:45:41.296364Z","shell.execute_reply":"2023-01-28T11:45:41.301532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = images[0]\nImage.open(img)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:46:03.605483Z","iopub.execute_input":"2023-01-28T11:46:03.605913Z","iopub.status.idle":"2023-01-28T11:46:03.663532Z","shell.execute_reply.started":"2023-01-28T11:46:03.605876Z","shell.execute_reply":"2023-01-28T11:46:03.662547Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict(model, img)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:46:07.253812Z","iopub.execute_input":"2023-01-28T11:46:07.254833Z","iopub.status.idle":"2023-01-28T11:46:07.275927Z","shell.execute_reply.started":"2023-01-28T11:46:07.254780Z","shell.execute_reply":"2023-01-28T11:46:07.274788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Выработка прогнозов на тестовом наборе\nВ этой части:\n* Создание DataLoader для Test\n* Выработка прогнозов и сохранение в файл для посылки","metadata":{}},{"cell_type":"code","source":"import pandas as pd \ndf = pd.read_csv('/kaggle/input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:46:43.168524Z","iopub.execute_input":"2023-01-28T11:46:43.169309Z","iopub.status.idle":"2023-01-28T11:46:43.204059Z","shell.execute_reply.started":"2023-01-28T11:46:43.169268Z","shell.execute_reply":"2023-01-28T11:46:43.202830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DogCatTest(Dataset):\n    def __init__(self, df, root, transform=None):\n        self.df = df\n        self.root = root\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        img_id, _ = self.df.iloc[idx]\n        img_path = os.path.join(self.root, str(int(img_id)) + '.jpg')\n        img = Image.open(img_path)\n        if self.transform:\n            img = self.transform(img)\n        return img, torch.tensor(1)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:46:49.970388Z","iopub.execute_input":"2023-01-28T11:46:49.970791Z","iopub.status.idle":"2023-01-28T11:46:49.978348Z","shell.execute_reply.started":"2023-01-28T11:46:49.970747Z","shell.execute_reply":"2023-01-28T11:46:49.977067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_tfms = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n])","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:46:53.423979Z","iopub.execute_input":"2023-01-28T11:46:53.424587Z","iopub.status.idle":"2023-01-28T11:46:53.430368Z","shell.execute_reply.started":"2023-01-28T11:46:53.424543Z","shell.execute_reply":"2023-01-28T11:46:53.429490Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = DogCatTest(df, 'test', transform = test_tfms)\ntest_dl = DataLoader(test_ds, batch_size=32, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:46:57.119804Z","iopub.execute_input":"2023-01-28T11:46:57.120293Z","iopub.status.idle":"2023-01-28T11:46:57.130903Z","shell.execute_reply.started":"2023-01-28T11:46:57.120252Z","shell.execute_reply":"2023-01-28T11:46:57.129655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def prediction(test_dl, model):\n    model = model.eval()\n    preds = []\n    for i, (data, _) in enumerate(tqdm(test_dl)):\n        data = data.to(device)\n        output = model(data)\n        y_pred = torch.clip(torch.sigmoid(output), 0.005, 0.995).cpu().detach().numpy()\n        preds.extend(y_pred)\n    return preds","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:47:00.622382Z","iopub.execute_input":"2023-01-28T11:47:00.622813Z","iopub.status.idle":"2023-01-28T11:47:00.630042Z","shell.execute_reply.started":"2023-01-28T11:47:00.622772Z","shell.execute_reply":"2023-01-28T11:47:00.628694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%time prediction = prediction(test_dl, model)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:47:10.077922Z","iopub.execute_input":"2023-01-28T11:47:10.078974Z","iopub.status.idle":"2023-01-28T11:48:21.216389Z","shell.execute_reply.started":"2023-01-28T11:47:10.078924Z","shell.execute_reply":"2023-01-28T11:48:21.215418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:48:29.233703Z","iopub.execute_input":"2023-01-28T11:48:29.234541Z","iopub.status.idle":"2023-01-28T11:48:29.251787Z","shell.execute_reply.started":"2023-01-28T11:48:29.234481Z","shell.execute_reply":"2023-01-28T11:48:29.250691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['label'] = np.ravel(prediction)\ndf.to_csv('submission_res_net_18.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:48:56.688258Z","iopub.execute_input":"2023-01-28T11:48:56.688653Z","iopub.status.idle":"2023-01-28T11:48:56.719599Z","shell.execute_reply.started":"2023-01-28T11:48:56.688618Z","shell.execute_reply":"2023-01-28T11:48:56.718681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = pd.read_csv('submission_res_net_18.csv')\ntest.head()","metadata":{"execution":{"iopub.status.busy":"2023-01-28T11:49:58.803767Z","iopub.execute_input":"2023-01-28T11:49:58.804797Z","iopub.status.idle":"2023-01-28T11:49:58.821885Z","shell.execute_reply.started":"2023-01-28T11:49:58.804730Z","shell.execute_reply":"2023-01-28T11:49:58.820723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}