{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"},{"sourceId":11116340,"sourceType":"datasetVersion","datasetId":6931283}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\nfrom torchvision.transforms import v2\nimport matplotlib.pyplot as plt\nimport torchvision.models as models\n\nfrom torch.utils.data import DataLoader, Dataset\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, classification_report, confusion_matrix\nimport seaborn as sns\nfrom PIL import Image\nimport copy\nimport datetime\nimport random\nimport traceback\nfrom IPython.display import display, clear_output\nimport os\nimport shutil\nfrom torchvision.datasets import ImageFolder\n\nseed = 0\nrandom.seed(seed)\nnp.random.seed(seed)\n\ntorch.random.manual_seed(seed)\ntorch.cuda.manual_seed(seed)\ntorch.backends.cudnn.deterministic=False\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:54:55.426993Z","iopub.execute_input":"2025-05-02T18:54:55.427296Z","iopub.status.idle":"2025-05-02T18:55:03.258395Z","shell.execute_reply.started":"2025-05-02T18:54:55.427238Z","shell.execute_reply":"2025-05-02T18:55:03.257549Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nprint(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:25:39.959421Z","iopub.execute_input":"2025-05-02T17:25:39.959999Z","iopub.status.idle":"2025-05-02T17:25:39.964458Z","shell.execute_reply.started":"2025-05-02T17:25:39.959970Z","shell.execute_reply":"2025-05-02T17:25:39.963567Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_transform = v2.Compose([\n    v2.ToImage(), \n    v2.ToDtype(torch.float32, scale=True),  \n    v2.RandomHorizontalFlip(),\n    v2.RandomVerticalFlip(),\n    v2.RandomCrop(32, padding=4),  \n    v2.Normalize(mean=[0.485, 0.456, 0.406],\n                 std=[0.229, 0.224, 0.225])  \n])\n\ntest_transform = v2.Compose([\n    v2.ToImage(), \n    v2.ToDtype(torch.float32, scale=True),    \n    v2.Normalize(mean=[0.485, 0.456, 0.406],\n                 std=[0.229, 0.224, 0.225])  \n])\n\ntrain_datasets = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=train_transform)\ntest_datasets = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=test_transform)\ntrain_loader = torch.utils.data.DataLoader(train_datasets, batch_size=100, shuffle=True)\ntest_loader = torch.utils.data.DataLoader(test_datasets, batch_size=100, shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:55:17.552417Z","iopub.execute_input":"2025-05-02T18:55:17.553050Z","iopub.status.idle":"2025-05-02T18:55:41.542725Z","shell.execute_reply.started":"2025-05-02T18:55:17.553028Z","shell.execute_reply":"2025-05-02T18:55:41.541919Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"classes = train_datasets.classes\ntrain_datasets.classes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:25:53.873263Z","iopub.execute_input":"2025-05-02T17:25:53.873541Z","iopub.status.idle":"2025-05-02T17:25:53.879266Z","shell.execute_reply.started":"2025-05-02T17:25:53.873522Z","shell.execute_reply":"2025-05-02T17:25:53.878434Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class fc(torch.nn.Module):\n    # Конструктор для класса\n    # Инициализация нейронной сети\n    def __init__(self):\n\n        super(fc, self).__init__()\n        self.conv1 = torch.nn.Conv2d(in_channels = 3, out_channels = 32, kernel_size = (3,3), padding=1)\n        self.mp1 = torch.nn.MaxPool2d(kernel_size = (2,2))\n        #32*16*16\n        self.relu = torch.nn.ReLU()\n        self.conv2 = torch.nn.Conv2d(in_channels = 32, out_channels = 64, kernel_size = (3,3), padding=1)\n        self.mp2 = torch.nn.MaxPool2d(kernel_size = (2,2))\n        #64*8*8\n        self.conv3 = torch.nn.Conv2d(in_channels = 64, out_channels = 128, kernel_size = (3,3), padding=1)\n        #128*8*8\n        self.fc1 = torch.nn.Linear(128*8*8, 512)\n        self.activ1 = torch.nn.ReLU()\n        self.fc2 = torch.nn.Linear(512, 256)\n        self.activ2 = torch.nn.ReLU()\n        self.fc3 = torch.nn.Linear(256, 64)\n        self.activ3 = torch.nn.ReLU()\n        self.fc4 = torch.nn.Linear(64, 32)\n        self.activ4 = torch.nn.ReLU()\n        self.fc5 = torch.nn.Linear(32, 16)\n        self.activ5 = torch.nn.ReLU()\n        self.fc6 = torch.nn.Linear(16, 10)\n        self.reg = torch.nn.Dropout(0.1)\n        self.sm = torch.nn.Softmax(dim=1)\n\n    def forward(self, data_input):\n        x = self.conv1(data_input)\n        x = self.relu(x)\n        x = self.mp1(x)\n        x = self.conv2(x)\n        x = self.relu(x)\n        x = self.mp2(x)\n        x = self.conv3(x)\n        x = self.relu(x)\n        x = x.reshape(-1, 128*8*8)\n        x = self.reg(x)\n        x = self.fc1(x)\n        x = self.activ1(x)\n        x = self.fc2(x)\n        x = self.activ2(x)\n        x = self.fc3(x)\n        x = self.activ3(x)\n        x = self.fc4(x)\n        x = self.activ4(x)\n        x = self.fc5(x)\n        x = self.activ5(x)\n        x = self.fc6(x)\n        return x\n\n    def inference(self, data_input):\n        with torch.no_grad():\n            x = self.forward(data_input)\n            x = self.sm(x)\n        return x","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:25:56.499287Z","iopub.execute_input":"2025-05-02T17:25:56.499818Z","iopub.status.idle":"2025-05-02T17:25:56.509128Z","shell.execute_reply.started":"2025-05-02T17:25:56.499790Z","shell.execute_reply":"2025-05-02T17:25:56.508541Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def copy_data_to_device(data, device):\n    if torch.is_tensor(data):\n        return data.to(device)\n    elif isinstance(data, (list, tuple)):\n        return [copy_data_to_device(elem, device) for elem in data]\n    raise ValueError('Недопустимый тип данных {}'.format(type(data)))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:55:41.543950Z","iopub.execute_input":"2025-05-02T18:55:41.544222Z","iopub.status.idle":"2025-05-02T18:55:41.548559Z","shell.execute_reply.started":"2025-05-02T18:55:41.544199Z","shell.execute_reply":"2025-05-02T18:55:41.547789Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_eval_loop(model, train_dataset, val_dataset, criterion,\n                    lr=1e-4, epoch_n=10, batch_size=32,\n                    device=None, early_stopping_patience=100, l2_reg_alpha=0,\n                    max_batches_per_epoch_train=10000,\n                    max_batches_per_epoch_val=1000,\n                    data_loader_ctor=torch.utils.data.DataLoader,\n                    optimizer_ctor=None,\n                    lr_scheduler_ctor=None,\n                    shuffle_train=True,\n                    dataloader_workers_n=0, \n                    plot=False):\n    if device is None:\n        device = 'cuda' if torch.cuda.is_available() else 'cpu'\n    model.to(device)\n\n    if optimizer_ctor is None:\n        optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=l2_reg_alpha)\n    else:\n        optimizer = optimizer_ctor(model.parameters(), lr=lr)\n\n    if lr_scheduler_ctor is not None:\n        lr_scheduler = lr_scheduler_ctor(optimizer)\n    else:\n        lr_scheduler = None\n\n    train_dataloader = data_loader_ctor(train_dataset, batch_size=batch_size, shuffle=shuffle_train,\n                                        num_workers=dataloader_workers_n)\n    val_dataloader = data_loader_ctor(val_dataset, batch_size=batch_size, shuffle=False,\n                                      num_workers=dataloader_workers_n)\n\n    best_val_loss = float('inf')\n    best_epoch_i = 0\n    best_model = copy.deepcopy(model)\n\n# Dynamic plot\n    if plot:\n        plot_epoch_data = []\n        plot_train_loss = []\n        plot_val_loss = []\n        plot_acc_train = []\n        plot_acc_val = []\n        \n        fig, ax = plt.subplots(2,1, figsize=(10,6))\n        line_train, = ax[0].plot([], [], 'r-')\n        line_val, = ax[0].plot([], [], 'b-')\n        line_acc_train, = ax[1].plot([], [], 'r-')\n        line_acc_val, = ax[1].plot([], [], 'b-')\n        ax[0].legend(['train', 'val'])\n        ax[0].set_xlim(0, epoch_n)\n        ax[1].legend(['train', 'val'])\n        ax[1].set_xlim(0, epoch_n)\n        ax[0].title.set_text('Функции потерь')\n        ax[1].title.set_text('Accuracy')\n\n        def add_point(epoch_i, train_loss, val_loss, acc_train, acc_val):\n            max_loss = max(ax[0].viewLim.y1 / 1.1, train_loss, val_loss)\n            ax[0].set_ylim(0, max_loss * 1.1)\n            ax[1].set_ylim(0, 110)\n            plot_epoch_data.append(epoch_i)\n            plot_train_loss.append(train_loss)\n            plot_val_loss.append(val_loss)\n            plot_acc_train.append(100 * acc_train)\n            plot_acc_val.append(100 * acc_val)\n            line_train.set_data(plot_epoch_data, plot_train_loss)\n            line_val.set_data(plot_epoch_data, plot_val_loss)\n            line_acc_train.set_data(plot_epoch_data, plot_acc_train)\n            line_acc_val.set_data(plot_epoch_data, plot_acc_val)\n            clear_output(wait=True)\n            display(fig)\n\n\n    for epoch_i in range(epoch_n):\n        try:\n            epoch_start = datetime.datetime.now()\n            \n\n            print('Эпоха {}'.format(epoch_i))\n\n            model.train()\n            mean_train_loss = 0\n            mean_train_acc = 0\n            train_batches_n = 0\n            for batch_i, (batch_x, batch_y) in enumerate(train_dataloader):\n                if batch_i > max_batches_per_epoch_train:\n                    break\n                batch_x = copy_data_to_device(batch_x, device)\n                batch_y = copy_data_to_device(batch_y, device)\n\n                pred = model(batch_x)\n                loss = criterion(pred, batch_y)\n                model.zero_grad()\n                loss.backward()\n\n                optimizer.step()\n                temp = []\n                for i in range(len(pred)):\n                    temp.append(torch.argmax(pred[i]).cpu().numpy())\n                acc = accuracy_score(temp, batch_y.cpu().numpy())\n                mean_train_loss += float(loss)\n                mean_train_acc += float(acc)\n                train_batches_n += 1\n                \n            \n            mean_train_loss /= train_batches_n\n            mean_train_acc /= train_batches_n\n\n            print('Эпоха: {} итераций, {:0.2f} сек'.format(train_batches_n,\n                                                           (datetime.datetime.now() - epoch_start).total_seconds()))\n            print('Среднее значение функции потерь на обучении', mean_train_loss)\n            print('Средняя accuracy на обучении', mean_train_acc)\n\n\n\n            model.eval()\n            mean_val_loss = 0\n            mean_val_acc = 0\n            val_batches_n = 0\n\n            with torch.no_grad():\n                for batch_i, (batch_x, batch_y) in enumerate(val_dataloader):\n                    if batch_i > max_batches_per_epoch_val:\n                        break\n\n                    batch_x = copy_data_to_device(batch_x, device)\n                    batch_y = copy_data_to_device(batch_y, device)\n\n                    pred = model(batch_x)\n                    loss = criterion(pred, batch_y)\n                    temp = []\n                    for i in range(len(pred)):\n                        temp.append(torch.argmax(pred[i]).cpu().numpy())\n                    acc = accuracy_score(temp, batch_y.cpu().numpy())\n                    mean_val_loss += float(loss)\n                    mean_val_acc += float(acc)\n                    val_batches_n += 1\n\n            mean_val_loss /= val_batches_n\n            mean_val_acc /= val_batches_n\n\n            if plot:\n                add_point(epoch_i, mean_train_loss, mean_val_loss, mean_train_acc, mean_val_acc)\n            else:\n                pass\n            \n            print('Среднее значение функции потерь на валидации', mean_val_loss)\n            print('Среднее значение accuracy на валидации', mean_val_acc)\n\n            if mean_val_loss < best_val_loss:\n                best_epoch_i = epoch_i\n                best_val_loss = mean_val_loss\n                best_model = copy.deepcopy(model)\n                print('Новая лучшая модель! На эпохе {}'.format(epoch_i))\n            elif epoch_i - best_epoch_i > early_stopping_patience:\n                print('Модель не улучшилась за последние {} эпох, прекращаем обучение'.format(\n                    early_stopping_patience))\n                break\n\n            if lr_scheduler is not None:\n                lr_scheduler.step(mean_val_loss)\n\n            print()\n        except KeyboardInterrupt:\n            print('Досрочно остановлено пользователем')\n            break\n        except Exception as ex:\n            print('Ошибка при обучении: {}\\n{}'.format(ex, traceback.format_exc()))\n            break\n        finally:\n            if plot:\n                plt.close(fig)\n\n    return best_val_loss, best_model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:55:41.549382Z","iopub.execute_input":"2025-05-02T18:55:41.549635Z","iopub.status.idle":"2025-05-02T18:55:41.569411Z","shell.execute_reply.started":"2025-05-02T18:55:41.549613Z","shell.execute_reply":"2025-05-02T18:55:41.568715Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = fc()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:26:09.135099Z","iopub.execute_input":"2025-05-02T17:26:09.135466Z","iopub.status.idle":"2025-05-02T17:26:09.186348Z","shell.execute_reply.started":"2025-05-02T17:26:09.135443Z","shell.execute_reply":"2025-05-02T17:26:09.185804Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_loss, best_model = train_eval_loop(model=model, \n                train_dataset=train_datasets, \n                val_dataset=test_datasets, \n                criterion=torch.nn.CrossEntropyLoss(),\n                lr=1e-3, \n                epoch_n=20, \n                batch_size=16,\n                device=device, \n                l2_reg_alpha=0.5,\n                max_batches_per_epoch_train=10000,\n                max_batches_per_epoch_val=1000,\n                optimizer_ctor=torch.optim.Adam,\n                data_loader_ctor=torch.utils.data.DataLoader,\n                lr_scheduler_ctor=torch.optim.lr_scheduler.ReduceLROnPlateau,\n                shuffle_train=True,\n                dataloader_workers_n=2,\n                plot=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:26:11.495107Z","iopub.execute_input":"2025-05-02T17:26:11.495767Z","iopub.status.idle":"2025-05-02T17:35:34.991076Z","shell.execute_reply.started":"2025-05-02T17:26:11.495738Z","shell.execute_reply":"2025-05-02T17:35:34.990356Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_labels = []\nactual_labels = []\n\nmodel.eval()\nwith torch.inference_mode():\n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = model(images)\n        _, predicted = torch.max(outputs, 1)\n        predicted_labels.extend(predicted.cpu().numpy())\n        actual_labels.extend(labels.cpu().numpy())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:44:19.920827Z","iopub.execute_input":"2025-05-02T17:44:19.921442Z","iopub.status.idle":"2025-05-02T17:44:22.568342Z","shell.execute_reply.started":"2025-05-02T17:44:19.921414Z","shell.execute_reply":"2025-05-02T17:44:22.567593Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy = accuracy_score(actual_labels, predicted_labels)\nprecision = precision_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nrecall = recall_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nf1 = f1_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\n\n# Принт метрик\nprint(f\"Model Accuracy: {accuracy * 100:.2f}%\")\nprint(f\"Model Precision: {precision * 100:.2f}%\")\nprint(f\"Model Recall: {recall * 100:.2f}%\")\nprint(f\"Model F1 Score: {f1 * 100:.2f}%\")\n\ncm = confusion_matrix(actual_labels, predicted_labels)\nclass_names = test_loader.dataset.classes\n\nplt.figure(figsize=(10, 10))\nsns.heatmap(cm, annot=True, fmt='d', xticklabels=class_names, yticklabels=class_names, cmap='Blues', annot_kws={\"size\": 15})\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Labels')\nplt.ylabel('Actual Labels')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:44:25.851284Z","iopub.execute_input":"2025-05-02T17:44:25.851623Z","iopub.status.idle":"2025-05-02T17:44:26.551252Z","shell.execute_reply.started":"2025-05-02T17:44:25.851598Z","shell.execute_reply":"2025-05-02T17:44:26.550533Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.DataFrame({'preds':predicted_labels, 'actual':actual_labels})\ndf['err'] = abs(df.preds - df.actual)\ndf.query('err > 0')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:44:35.409110Z","iopub.execute_input":"2025-05-02T17:44:35.410157Z","iopub.status.idle":"2025-05-02T17:44:35.478073Z","shell.execute_reply.started":"2025-05-02T17:44:35.410118Z","shell.execute_reply":"2025-05-02T17:44:35.477455Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i = 0\nfor el in iter(test_loader):\n    for j in range(16):\n        if i + j in df.query('err > 0').index and i + j < 1000:\n            image = el[0][j]\n            if image.shape[0] == 3:\n                image = image[0, ...]\n            plt.imshow(image)\n            plt.title(f'Предсказали: {df.loc[i+j,\"preds\"]}; Настоящее: {df.loc[i+j,\"actual\"]}')\n    i+=16\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:44:38.706431Z","iopub.execute_input":"2025-05-02T17:44:38.707037Z","iopub.status.idle":"2025-05-02T17:44:55.765573Z","shell.execute_reply.started":"2025-05-02T17:44:38.707016Z","shell.execute_reply":"2025-05-02T17:44:55.764980Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class fc_batch_norm(torch.nn.Module):\n    def __init__(self):\n        super(fc_batch_norm, self).__init__()\n        self.conv1 = torch.nn.Conv2d(in_channels=3, out_channels=32, kernel_size=(3,3), padding=1)\n        self.bn1 = torch.nn.BatchNorm2d(32)\n        self.mp1 = torch.nn.MaxPool2d(kernel_size=(2,2))\n        \n        self.conv2 = torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3,3), padding=1)\n        self.bn2 = torch.nn.BatchNorm2d(64)\n        self.mp2 = torch.nn.MaxPool2d(kernel_size=(2,2))\n\n        self.conv3 = torch.nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3,3), padding=1)\n        self.bn3 = torch.nn.BatchNorm2d(128)\n\n        self.fc1 = torch.nn.Linear(128*8*8, 512)\n        self.bn4 = torch.nn.BatchNorm1d(512)\n        self.fc2 = torch.nn.Linear(512, 256)\n        self.bn5 = torch.nn.BatchNorm1d(256)\n        self.fc3 = torch.nn.Linear(256, 64)\n        self.bn6 = torch.nn.BatchNorm1d(64)\n        self.fc4 = torch.nn.Linear(64, 32)\n        self.bn7 = torch.nn.BatchNorm1d(32)\n        self.fc5 = torch.nn.Linear(32, 16)\n        self.bn8 = torch.nn.BatchNorm1d(16)\n        self.fc6 = torch.nn.Linear(16, 10)\n\n        self.relu = torch.nn.ReLU()\n        self.reg = torch.nn.Dropout(0.1)\n        self.sm = torch.nn.Softmax(dim=1)\n\n    def forward(self, data_input):\n        x = self.conv1(data_input)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.mp1(x)\n\n        x = self.conv2(x)\n        x = self.bn2(x)\n        x = self.relu(x)\n        x = self.mp2(x)\n\n        x = self.conv3(x)\n        x = self.bn3(x)\n        x = self.relu(x)\n\n        x = x.reshape(-1, 128*8*8)\n        x = self.reg(x)\n\n        x = self.fc1(x)\n        x = self.bn4(x)\n        x = self.relu(x)\n\n        x = self.fc2(x)\n        x = self.bn5(x)\n        x = self.relu(x)\n\n        x = self.fc3(x)\n        x = self.bn6(x)\n        x = self.relu(x)\n\n        x = self.fc4(x)\n        x = self.bn7(x)\n        x = self.relu(x)\n\n        x = self.fc5(x)\n        x = self.bn8(x)\n        x = self.relu(x)\n\n        x = self.fc6(x)\n        return x\n\n    def inference(self, data_input):\n        with torch.no_grad():\n            x = self.forward(data_input)\n            x = self.sm(x)\n        return x\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:47:08.956947Z","iopub.execute_input":"2025-05-02T17:47:08.957751Z","iopub.status.idle":"2025-05-02T17:47:08.968983Z","shell.execute_reply.started":"2025-05-02T17:47:08.957722Z","shell.execute_reply":"2025-05-02T17:47:08.968286Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_bn = fc_batch_norm()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:47:11.814888Z","iopub.execute_input":"2025-05-02T17:47:11.815154Z","iopub.status.idle":"2025-05-02T17:47:11.857370Z","shell.execute_reply.started":"2025-05-02T17:47:11.815135Z","shell.execute_reply":"2025-05-02T17:47:11.856585Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_loss, best_model = train_eval_loop(model=model_bn, \n                train_dataset=train_datasets, \n                val_dataset=test_datasets, \n                criterion=torch.nn.CrossEntropyLoss(),\n                lr=1e-3, \n                epoch_n=20, \n                batch_size=16,\n                device=device, \n                l2_reg_alpha=0.5,\n                max_batches_per_epoch_train=10000,\n                max_batches_per_epoch_val=1000,\n                optimizer_ctor=torch.optim.Adam,\n                data_loader_ctor=torch.utils.data.DataLoader,\n                lr_scheduler_ctor=torch.optim.lr_scheduler.ReduceLROnPlateau,\n                shuffle_train=True,\n                dataloader_workers_n=2,\n                plot=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T17:47:57.815709Z","iopub.execute_input":"2025-05-02T17:47:57.815961Z","iopub.status.idle":"2025-05-02T17:59:15.362874Z","shell.execute_reply.started":"2025-05-02T17:47:57.815944Z","shell.execute_reply":"2025-05-02T17:59:15.362031Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_labels = []\nactual_labels = []\n\nmodel_bn.eval()\nwith torch.inference_mode():\n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = model_bn(images)\n        _, predicted = torch.max(outputs, 1)\n        predicted_labels.extend(predicted.cpu().numpy())\n        actual_labels.extend(labels.cpu().numpy())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:16:07.647049Z","iopub.execute_input":"2025-05-02T18:16:07.647595Z","iopub.status.idle":"2025-05-02T18:16:10.185716Z","shell.execute_reply.started":"2025-05-02T18:16:07.647570Z","shell.execute_reply":"2025-05-02T18:16:10.185095Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy = accuracy_score(actual_labels, predicted_labels)\nprecision = precision_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nrecall = recall_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nf1 = f1_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\n\n# Принт метрик\nprint(f\"Model Accuracy: {accuracy * 100:.2f}%\")\nprint(f\"Model Precision: {precision * 100:.2f}%\")\nprint(f\"Model Recall: {recall * 100:.2f}%\")\nprint(f\"Model F1 Score: {f1 * 100:.2f}%\")\n\ncm = confusion_matrix(actual_labels, predicted_labels)\nclass_names = test_loader.dataset.classes\n\nplt.figure(figsize=(10, 10))\nsns.heatmap(cm, annot=True, fmt='d', xticklabels=class_names, yticklabels=class_names, cmap='Blues', annot_kws={\"size\": 15})\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Labels')\nplt.ylabel('Actual Labels')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:16:14.494039Z","iopub.execute_input":"2025-05-02T18:16:14.494618Z","iopub.status.idle":"2025-05-02T18:16:14.917977Z","shell.execute_reply.started":"2025-05-02T18:16:14.494590Z","shell.execute_reply":"2025-05-02T18:16:14.917052Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.DataFrame({'preds':predicted_labels, 'actual':actual_labels})\ndf['err'] = abs(df.preds - df.actual)\ndf.query('err > 0')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:16:20.242222Z","iopub.execute_input":"2025-05-02T18:16:20.242554Z","iopub.status.idle":"2025-05-02T18:16:20.289232Z","shell.execute_reply.started":"2025-05-02T18:16:20.242529Z","shell.execute_reply":"2025-05-02T18:16:20.288552Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i = 0\nfor el in iter(test_loader):\n    for j in range(16):\n        if i + j in df.query('err > 0').index and i + j < 17:\n            image = el[0][j]\n            if image.shape[0] == 3:\n                image = image[0, ...]\n            plt.imshow(image)\n            plt.title(f'Предсказали: {df.loc[i+j,\"preds\"]}; Настоящее: {df.loc[i+j,\"actual\"]}')\n    i+=16\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:16:23.054648Z","iopub.execute_input":"2025-05-02T18:16:23.055513Z","iopub.status.idle":"2025-05-02T18:16:28.498907Z","shell.execute_reply.started":"2025-05-02T18:16:23.055478Z","shell.execute_reply":"2025-05-02T18:16:28.498332Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class fc_layer_norm(torch.nn.Module):\n    def __init__(self):\n        super(fc_layer_norm, self).__init__()\n        self.conv1 = torch.nn.Conv2d(in_channels=3, out_channels=32, kernel_size=(3,3), padding=1)\n        self.ln1 = torch.nn.LayerNorm([32, 32, 32])  # Формат: [C, H, W]\n        self.mp1 = torch.nn.MaxPool2d(kernel_size=(2,2))\n\n        self.conv2 = torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3,3), padding=1)\n        self.ln2 = torch.nn.LayerNorm([64, 16, 16])\n        self.mp2 = torch.nn.MaxPool2d(kernel_size=(2,2))\n\n        self.conv3 = torch.nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3,3), padding=1)\n        self.ln3 = torch.nn.LayerNorm([128, 8, 8])\n\n        self.fc1 = torch.nn.Linear(128*8*8, 512)\n        self.ln4 = torch.nn.LayerNorm(512)\n        self.fc2 = torch.nn.Linear(512, 256)\n        self.ln5 = torch.nn.LayerNorm(256)\n        self.fc3 = torch.nn.Linear(256, 64)\n        self.ln6 = torch.nn.LayerNorm(64)\n        self.fc4 = torch.nn.Linear(64, 32)\n        self.ln7 = torch.nn.LayerNorm(32)\n        self.fc5 = torch.nn.Linear(32, 16)\n        self.ln8 = torch.nn.LayerNorm(16)\n        self.fc6 = torch.nn.Linear(16, 10)\n\n        self.relu = torch.nn.ReLU()\n        self.reg = torch.nn.Dropout(0.1)\n        self.sm = torch.nn.Softmax(dim=1)\n\n    def forward(self, data_input):\n        x = self.conv1(data_input)\n        x = self.ln1(x)\n        x = self.relu(x)\n        x = self.mp1(x)\n\n        x = self.conv2(x)\n        x = self.ln2(x)\n        x = self.relu(x)\n        x = self.mp2(x)\n\n        x = self.conv3(x)\n        x = self.ln3(x)\n        x = self.relu(x)\n\n        x = x.reshape(-1, 128*8*8)\n        x = self.reg(x)\n\n        x = self.fc1(x)\n        x = self.ln4(x)\n        x = self.relu(x)\n\n        x = self.fc2(x)\n        x = self.ln5(x)\n        x = self.relu(x)\n\n        x = self.fc3(x)\n        x = self.ln6(x)\n        x = self.relu(x)\n\n        x = self.fc4(x)\n        x = self.ln7(x)\n        x = self.relu(x)\n\n        x = self.fc5(x)\n        x = self.ln8(x)\n        x = self.relu(x)\n\n        x = self.fc6(x)\n        return x\n\n    def inference(self, data_input):\n        with torch.no_grad():\n            x = self.forward(data_input)\n            x = self.sm(x)\n        return x\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:03:00.851320Z","iopub.execute_input":"2025-05-02T18:03:00.851623Z","iopub.status.idle":"2025-05-02T18:03:00.862790Z","shell.execute_reply.started":"2025-05-02T18:03:00.851603Z","shell.execute_reply":"2025-05-02T18:03:00.862146Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_ln = fc_layer_norm()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:03:05.445942Z","iopub.execute_input":"2025-05-02T18:03:05.446549Z","iopub.status.idle":"2025-05-02T18:03:05.486260Z","shell.execute_reply.started":"2025-05-02T18:03:05.446525Z","shell.execute_reply":"2025-05-02T18:03:05.485720Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_loss, best_model = train_eval_loop(model=model_ln, \n                train_dataset=train_datasets, \n                val_dataset=test_datasets, \n                criterion=torch.nn.CrossEntropyLoss(),\n                lr=1e-3, \n                epoch_n=20, \n                batch_size=16,\n                device=device, \n                l2_reg_alpha=0.5,\n                max_batches_per_epoch_train=10000,\n                max_batches_per_epoch_val=1000,\n                optimizer_ctor=torch.optim.Adam,\n                data_loader_ctor=torch.utils.data.DataLoader,\n                lr_scheduler_ctor=torch.optim.lr_scheduler.ReduceLROnPlateau,\n                shuffle_train=True,\n                dataloader_workers_n=2,\n                plot=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:03:09.233932Z","iopub.execute_input":"2025-05-02T18:03:09.234497Z","iopub.status.idle":"2025-05-02T18:13:45.622934Z","shell.execute_reply.started":"2025-05-02T18:03:09.234471Z","shell.execute_reply":"2025-05-02T18:13:45.622190Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_labels = []\nactual_labels = []\n\nmodel_ln.eval()\nwith torch.inference_mode():\n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = model_ln(images)\n        _, predicted = torch.max(outputs, 1)\n        predicted_labels.extend(predicted.cpu().numpy())\n        actual_labels.extend(labels.cpu().numpy())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:16:39.196684Z","iopub.execute_input":"2025-05-02T18:16:39.197284Z","iopub.status.idle":"2025-05-02T18:16:41.698018Z","shell.execute_reply.started":"2025-05-02T18:16:39.197256Z","shell.execute_reply":"2025-05-02T18:16:41.697453Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy = accuracy_score(actual_labels, predicted_labels)\nprecision = precision_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nrecall = recall_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nf1 = f1_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\n\n# Принт метрик\nprint(f\"Model Accuracy: {accuracy * 100:.2f}%\")\nprint(f\"Model Precision: {precision * 100:.2f}%\")\nprint(f\"Model Recall: {recall * 100:.2f}%\")\nprint(f\"Model F1 Score: {f1 * 100:.2f}%\")\n\ncm = confusion_matrix(actual_labels, predicted_labels)\nclass_names = test_loader.dataset.classes\n\nplt.figure(figsize=(10, 10))\nsns.heatmap(cm, annot=True, fmt='d', xticklabels=class_names, yticklabels=class_names, cmap='Blues', annot_kws={\"size\": 15})\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Labels')\nplt.ylabel('Actual Labels')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:16:44.170784Z","iopub.execute_input":"2025-05-02T18:16:44.171335Z","iopub.status.idle":"2025-05-02T18:16:44.660713Z","shell.execute_reply.started":"2025-05-02T18:16:44.171283Z","shell.execute_reply":"2025-05-02T18:16:44.658751Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.DataFrame({'preds':predicted_labels, 'actual':actual_labels})\ndf['err'] = abs(df.preds - df.actual)\ndf.query('err > 0')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:16:48.058844Z","iopub.execute_input":"2025-05-02T18:16:48.059504Z","iopub.status.idle":"2025-05-02T18:16:48.104833Z","shell.execute_reply.started":"2025-05-02T18:16:48.059477Z","shell.execute_reply":"2025-05-02T18:16:48.104089Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i = 0\nfor el in iter(test_loader):\n    for j in range(16):\n        if i + j in df.query('err > 0').index and i + j < 17:\n            image = el[0][j]\n            if image.shape[0] == 3:\n                image = image[0, ...]\n            plt.imshow(image)\n            plt.title(f'Предсказали: {df.loc[i+j,\"preds\"]}; Настоящее: {df.loc[i+j,\"actual\"]}')\n    i+=16\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:16:52.093352Z","iopub.execute_input":"2025-05-02T18:16:52.093639Z","iopub.status.idle":"2025-05-02T18:16:57.740342Z","shell.execute_reply.started":"2025-05-02T18:16:52.093619Z","shell.execute_reply":"2025-05-02T18:16:57.739772Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class fc_dropout(torch.nn.Module):\n    def __init__(self):\n        super(fc_dropout, self).__init__()\n        self.conv1 = torch.nn.Conv2d(in_channels=3, out_channels=32, kernel_size=(3,3), padding=1)\n        self.drop1 = torch.nn.Dropout2d(0.1)  # Dropout после conv1\n        self.mp1 = torch.nn.MaxPool2d(kernel_size=(2,2))\n\n        self.conv2 = torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3,3), padding=1)\n        self.drop2 = torch.nn.Dropout2d(0.1)  # Dropout после conv2\n        self.mp2 = torch.nn.MaxPool2d(kernel_size=(2,2))\n\n        self.conv3 = torch.nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3,3), padding=1)\n        self.drop3 = torch.nn.Dropout2d(0.1)  # Dropout после conv3\n\n        self.fc1 = torch.nn.Linear(128*8*8, 512)\n        self.drop4 = torch.nn.Dropout(0.1)\n        self.fc2 = torch.nn.Linear(512, 256)\n        self.drop5 = torch.nn.Dropout(0.1)\n        self.fc3 = torch.nn.Linear(256, 64)\n        self.drop6 = torch.nn.Dropout(0.1)\n        self.fc4 = torch.nn.Linear(64, 32)\n        self.drop7 = torch.nn.Dropout(0.1)\n        self.fc5 = torch.nn.Linear(32, 16)\n        self.drop8 = torch.nn.Dropout(0.1)\n        self.fc6 = torch.nn.Linear(16, 10)\n\n        self.relu = torch.nn.ReLU()\n        self.sm = torch.nn.Softmax(dim=1)\n\n    def forward(self, data_input):\n        x = self.conv1(data_input)\n        x = self.relu(x)\n        x = self.drop1(x)\n        x = self.mp1(x)\n\n        x = self.conv2(x)\n        x = self.relu(x)\n        x = self.drop2(x)\n        x = self.mp2(x)\n\n        x = self.conv3(x)\n        x = self.relu(x)\n        x = self.drop3(x)\n\n        x = x.reshape(-1, 128*8*8)\n\n        x = self.fc1(x)\n        x = self.relu(x)\n        x = self.drop4(x)\n\n        x = self.fc2(x)\n        x = self.relu(x)\n        x = self.drop5(x)\n\n        x = self.fc3(x)\n        x = self.relu(x)\n        x = self.drop6(x)\n\n        x = self.fc4(x)\n        x = self.relu(x)\n        x = self.drop7(x)\n\n        x = self.fc5(x)\n        x = self.relu(x)\n        x = self.drop8(x)\n\n        x = self.fc6(x)\n        return x\n\n    def inference(self, data_input):\n        with torch.no_grad():\n            self.eval()\n            x = self.forward(data_input)\n            x = self.sm(x)\n        return x\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:20:51.504368Z","iopub.execute_input":"2025-05-02T18:20:51.504919Z","iopub.status.idle":"2025-05-02T18:20:51.516204Z","shell.execute_reply.started":"2025-05-02T18:20:51.504899Z","shell.execute_reply":"2025-05-02T18:20:51.515460Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_dropout = fc_dropout()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:20:55.419836Z","iopub.execute_input":"2025-05-02T18:20:55.420123Z","iopub.status.idle":"2025-05-02T18:20:55.464568Z","shell.execute_reply.started":"2025-05-02T18:20:55.420102Z","shell.execute_reply":"2025-05-02T18:20:55.463883Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_loss, best_model = train_eval_loop(model=model_dropout, \n                train_dataset=train_datasets, \n                val_dataset=test_datasets, \n                criterion=torch.nn.CrossEntropyLoss(),\n                lr=1e-3, \n                epoch_n=20, \n                batch_size=16,\n                device=device, \n                l2_reg_alpha=0.5,\n                max_batches_per_epoch_train=10000,\n                max_batches_per_epoch_val=1000,\n                optimizer_ctor=torch.optim.Adam,\n                data_loader_ctor=torch.utils.data.DataLoader,\n                lr_scheduler_ctor=torch.optim.lr_scheduler.ReduceLROnPlateau,\n                shuffle_train=True,\n                dataloader_workers_n=2,\n                plot=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:20:58.070680Z","iopub.execute_input":"2025-05-02T18:20:58.071197Z","iopub.status.idle":"2025-05-02T18:30:59.482972Z","shell.execute_reply.started":"2025-05-02T18:20:58.071171Z","shell.execute_reply":"2025-05-02T18:30:59.482088Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_labels = []\nactual_labels = []\n\nmodel_dropout.eval()\nwith torch.inference_mode():\n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = model_dropout(images)\n        _, predicted = torch.max(outputs, 1)\n        predicted_labels.extend(predicted.cpu().numpy())\n        actual_labels.extend(labels.cpu().numpy())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:30:59.484468Z","iopub.execute_input":"2025-05-02T18:30:59.484706Z","iopub.status.idle":"2025-05-02T18:31:02.031584Z","shell.execute_reply.started":"2025-05-02T18:30:59.484685Z","shell.execute_reply":"2025-05-02T18:31:02.030775Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy = accuracy_score(actual_labels, predicted_labels)\nprecision = precision_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nrecall = recall_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nf1 = f1_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\n\n# Принт метрик\nprint(f\"Model Accuracy: {accuracy * 100:.2f}%\")\nprint(f\"Model Precision: {precision * 100:.2f}%\")\nprint(f\"Model Recall: {recall * 100:.2f}%\")\nprint(f\"Model F1 Score: {f1 * 100:.2f}%\")\n\ncm = confusion_matrix(actual_labels, predicted_labels)\nclass_names = test_loader.dataset.classes\n\nplt.figure(figsize=(10, 10))\nsns.heatmap(cm, annot=True, fmt='d', xticklabels=class_names, yticklabels=class_names, cmap='Blues', annot_kws={\"size\": 15})\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Labels')\nplt.ylabel('Actual Labels')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:31:14.890941Z","iopub.execute_input":"2025-05-02T18:31:14.891227Z","iopub.status.idle":"2025-05-02T18:31:15.328082Z","shell.execute_reply.started":"2025-05-02T18:31:14.891205Z","shell.execute_reply":"2025-05-02T18:31:15.327245Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.DataFrame({'preds':predicted_labels, 'actual':actual_labels})\ndf['err'] = abs(df.preds - df.actual)\ndf.query('err > 0')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:31:20.757436Z","iopub.execute_input":"2025-05-02T18:31:20.757719Z","iopub.status.idle":"2025-05-02T18:31:20.808373Z","shell.execute_reply.started":"2025-05-02T18:31:20.757698Z","shell.execute_reply":"2025-05-02T18:31:20.807571Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i = 0\nfor el in iter(test_loader):\n    for j in range(16):\n        if i + j in df.query('err > 0').index and i + j < 17:\n            image = el[0][j]\n            if image.shape[0] == 3:\n                image = image[0, ...]\n            plt.imshow(image)\n            plt.title(f'Предсказали: {df.loc[i+j,\"preds\"]}; Настоящее: {df.loc[i+j,\"actual\"]}')\n    i+=16\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:31:23.531216Z","iopub.execute_input":"2025-05-02T18:31:23.531548Z","iopub.status.idle":"2025-05-02T18:31:28.961066Z","shell.execute_reply.started":"2025-05-02T18:31:23.531525Z","shell.execute_reply":"2025-05-02T18:31:28.960346Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_transform = v2.Compose([\n    v2.ToImage(), \n    v2.ToDtype(torch.float32, scale=True),  \n    v2.RandomHorizontalFlip(),\n    v2.RandomVerticalFlip(),\n    v2.Resize((224,224)),  \n    v2.Normalize(mean=[0.485, 0.456, 0.406],\n                 std=[0.229, 0.224, 0.225])  \n])\n\ntest_transform = v2.Compose([\n    v2.ToImage(),\n    v2.ToDtype(torch.float32, scale=True),\n    v2.Resize((224,224)), \n    v2.Normalize(mean=[0.485, 0.456, 0.406],\n                 std=[0.229, 0.224, 0.225])  \n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:38:30.679892Z","iopub.execute_input":"2025-05-02T18:38:30.680489Z","iopub.status.idle":"2025-05-02T18:38:30.685774Z","shell.execute_reply.started":"2025-05-02T18:38:30.680466Z","shell.execute_reply":"2025-05-02T18:38:30.685191Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"batch_size = 64","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:55:55.428469Z","iopub.execute_input":"2025-05-02T18:55:55.429052Z","iopub.status.idle":"2025-05-02T18:55:55.432316Z","shell.execute_reply.started":"2025-05-02T18:55:55.429029Z","shell.execute_reply":"2025-05-02T18:55:55.431511Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"vgg19 = models.vgg19(pretrained=True)\nresnet50 = models.resnet50(pretrained=True)\nmobilenetv3_small = models.mobilenet_v3_small(pretrained=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:56:03.040900Z","iopub.execute_input":"2025-05-02T18:56:03.041381Z","iopub.status.idle":"2025-05-02T18:56:08.707940Z","shell.execute_reply.started":"2025-05-02T18:56:03.041360Z","shell.execute_reply":"2025-05-02T18:56:08.707321Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_classes = 10\nvgg19.classifier[6] = torch.nn.Linear(vgg19.classifier[6].in_features, num_classes)\nresnet50.fc = torch.nn.Linear(resnet50.fc.in_features, num_classes)\nmobilenetv3_small.classifier[3] = torch.nn.Linear(mobilenetv3_small.classifier[3].in_features, num_classes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T18:56:12.083722Z","iopub.execute_input":"2025-05-02T18:56:12.084265Z","iopub.status.idle":"2025-05-02T18:56:12.089537Z","shell.execute_reply.started":"2025-05-02T18:56:12.084228Z","shell.execute_reply":"2025-05-02T18:56:12.088858Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_loss, best_model = train_eval_loop(model=vgg19, \n                train_dataset=train_datasets, \n                val_dataset=test_datasets, \n                criterion=torch.nn.CrossEntropyLoss(),\n                lr=1e-3, \n                epoch_n=20, \n                batch_size=batch_size,\n                device=device, \n                l2_reg_alpha=0.5,\n                max_batches_per_epoch_train=10000,\n                max_batches_per_epoch_val=1000,\n                optimizer_ctor=torch.optim.Adam,\n                data_loader_ctor=torch.utils.data.DataLoader,\n                lr_scheduler_ctor=torch.optim.lr_scheduler.ReduceLROnPlateau,\n                shuffle_train=True,\n                dataloader_workers_n=2,\n                plot=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T19:44:16.079441Z","iopub.execute_input":"2025-05-02T19:44:16.080055Z","iopub.status.idle":"2025-05-02T20:00:54.397037Z","shell.execute_reply.started":"2025-05-02T19:44:16.080032Z","shell.execute_reply":"2025-05-02T20:00:54.396208Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_labels = []\nactual_labels = []\n\nvgg19.eval()\nwith torch.inference_mode():\n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = vgg19(images)\n        _, predicted = torch.max(outputs, 1)\n        predicted_labels.extend(predicted.cpu().numpy())\n        actual_labels.extend(labels.cpu().numpy())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T20:01:13.444316Z","iopub.execute_input":"2025-05-02T20:01:13.444591Z","iopub.status.idle":"2025-05-02T20:01:18.134001Z","shell.execute_reply.started":"2025-05-02T20:01:13.444570Z","shell.execute_reply":"2025-05-02T20:01:18.133192Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy = accuracy_score(actual_labels, predicted_labels)\nprecision = precision_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nrecall = recall_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nf1 = f1_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\n\n# Принт метрик\nprint(f\"Model Accuracy: {accuracy * 100:.2f}%\")\nprint(f\"Model Precision: {precision * 100:.2f}%\")\nprint(f\"Model Recall: {recall * 100:.2f}%\")\nprint(f\"Model F1 Score: {f1 * 100:.2f}%\")\n\ncm = confusion_matrix(actual_labels, predicted_labels)\nclass_names = test_loader.dataset.classes\n\nplt.figure(figsize=(10, 10))\nsns.heatmap(cm, annot=True, fmt='d', xticklabels=class_names, yticklabels=class_names, cmap='Blues', annot_kws={\"size\": 15})\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Labels')\nplt.ylabel('Actual Labels')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T20:01:19.255885Z","iopub.execute_input":"2025-05-02T20:01:19.256495Z","iopub.status.idle":"2025-05-02T20:01:19.693181Z","shell.execute_reply.started":"2025-05-02T20:01:19.256464Z","shell.execute_reply":"2025-05-02T20:01:19.692446Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.DataFrame({'preds':predicted_labels, 'actual':actual_labels})\ndf['err'] = abs(df.preds - df.actual)\ndf.query('err > 0')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T20:01:24.720382Z","iopub.execute_input":"2025-05-02T20:01:24.720851Z","iopub.status.idle":"2025-05-02T20:01:24.777046Z","shell.execute_reply.started":"2025-05-02T20:01:24.720827Z","shell.execute_reply":"2025-05-02T20:01:24.776300Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i = 0\nfor el in iter(test_loader):\n    for j in range(16):\n        if i + j in df.query('err > 0').index and i + j < 10:\n            image = el[0][j]\n            if image.shape[0] == 3:\n                image = image[0, ...]\n            plt.imshow(image)\n            plt.title(f'Предсказали: {df.loc[i+j,\"preds\"]}; Настоящее: {df.loc[i+j,\"actual\"]}')\n    i+=16\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T20:01:27.853393Z","iopub.execute_input":"2025-05-02T20:01:27.853980Z","iopub.status.idle":"2025-05-02T20:01:33.976865Z","shell.execute_reply.started":"2025-05-02T20:01:27.853959Z","shell.execute_reply":"2025-05-02T20:01:33.976308Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_loss, best_model = train_eval_loop(model=resnet50, \n                train_dataset=train_datasets, \n                val_dataset=test_datasets, \n                criterion=torch.nn.CrossEntropyLoss(),\n                lr=1e-3, \n                epoch_n=20, \n                batch_size=batch_size,\n                device=device, \n                l2_reg_alpha=0.5,\n                max_batches_per_epoch_train=10000,\n                max_batches_per_epoch_val=1000,\n                optimizer_ctor=torch.optim.Adam,\n                data_loader_ctor=torch.utils.data.DataLoader,\n                lr_scheduler_ctor=torch.optim.lr_scheduler.ReduceLROnPlateau,\n                shuffle_train=True,\n                dataloader_workers_n=2,\n                plot=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T19:16:18.673419Z","iopub.execute_input":"2025-05-02T19:16:18.674162Z","iopub.status.idle":"2025-05-02T19:30:55.604760Z","shell.execute_reply.started":"2025-05-02T19:16:18.674136Z","shell.execute_reply":"2025-05-02T19:30:55.604032Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_labels = []\nactual_labels = []\n\nresnet50.eval()\nwith torch.inference_mode():\n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = resnet50(images)\n        _, predicted = torch.max(outputs, 1)\n        predicted_labels.extend(predicted.cpu().numpy())\n        actual_labels.extend(labels.cpu().numpy())","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy = accuracy_score(actual_labels, predicted_labels)\nprecision = precision_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nrecall = recall_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nf1 = f1_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\n\n# Принт метрик\nprint(f\"Model Accuracy: {accuracy * 100:.2f}%\")\nprint(f\"Model Precision: {precision * 100:.2f}%\")\nprint(f\"Model Recall: {recall * 100:.2f}%\")\nprint(f\"Model F1 Score: {f1 * 100:.2f}%\")\n\ncm = confusion_matrix(actual_labels, predicted_labels)\nclass_names = test_loader.dataset.classes\n\nplt.figure(figsize=(10, 10))\nsns.heatmap(cm, annot=True, fmt='d', xticklabels=class_names, yticklabels=class_names, cmap='Blues', annot_kws={\"size\": 15})\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Labels')\nplt.ylabel('Actual Labels')\nplt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.DataFrame({'preds':predicted_labels, 'actual':actual_labels})\ndf['err'] = abs(df.preds - df.actual)\ndf.query('err > 0')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i = 0\nfor el in iter(test_loader):\n    for j in range(16):\n        if i + j in df.query('err > 0').index and i + j < 10:\n            image = el[0][j]\n            if image.shape[0] == 3:\n                image = image[0, ...]\n            plt.imshow(image)\n            plt.title(f'Предсказали: {df.loc[i+j,\"preds\"]}; Настоящее: {df.loc[i+j,\"actual\"]}')\n    i+=16\n    plt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_loss, best_model = train_eval_loop(model=mobilenetv3_small, \n                train_dataset=train_datasets, \n                val_dataset=test_datasets, \n                criterion=torch.nn.CrossEntropyLoss(),\n                lr=1e-3, \n                epoch_n=20, \n                batch_size=batch_size,\n                device=device, \n                l2_reg_alpha=0.5,\n                max_batches_per_epoch_train=10000,\n                max_batches_per_epoch_val=1000,\n                optimizer_ctor=torch.optim.Adam,\n                data_loader_ctor=torch.utils.data.DataLoader,\n                lr_scheduler_ctor=torch.optim.lr_scheduler.ReduceLROnPlateau,\n                shuffle_train=True,\n                dataloader_workers_n=2,\n                plot=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T19:34:19.802759Z","iopub.execute_input":"2025-05-02T19:34:19.803508Z","iopub.status.idle":"2025-05-02T19:43:19.468198Z","shell.execute_reply.started":"2025-05-02T19:34:19.803482Z","shell.execute_reply":"2025-05-02T19:43:19.467189Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_labels = []\nactual_labels = []\n\nmobilenetv3_small.eval()\nwith torch.inference_mode():\n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = mobilenetv3_small(images)\n        _, predicted = torch.max(outputs, 1)\n        predicted_labels.extend(predicted.cpu().numpy())\n        actual_labels.extend(labels.cpu().numpy())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T19:43:49.779690Z","iopub.execute_input":"2025-05-02T19:43:49.779994Z","iopub.status.idle":"2025-05-02T19:43:53.004291Z","shell.execute_reply.started":"2025-05-02T19:43:49.779968Z","shell.execute_reply":"2025-05-02T19:43:53.003451Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy = accuracy_score(actual_labels, predicted_labels)\nprecision = precision_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nrecall = recall_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\nf1 = f1_score(actual_labels, predicted_labels, average='weighted', zero_division=0)\n\n# Принт метрик\nprint(f\"Model Accuracy: {accuracy * 100:.2f}%\")\nprint(f\"Model Precision: {precision * 100:.2f}%\")\nprint(f\"Model Recall: {recall * 100:.2f}%\")\nprint(f\"Model F1 Score: {f1 * 100:.2f}%\")\n\ncm = confusion_matrix(actual_labels, predicted_labels)\nclass_names = test_loader.dataset.classes\n\nplt.figure(figsize=(10, 10))\nsns.heatmap(cm, annot=True, fmt='d', xticklabels=class_names, yticklabels=class_names, cmap='Blues', annot_kws={\"size\": 15})\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Labels')\nplt.ylabel('Actual Labels')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T19:43:54.445146Z","iopub.execute_input":"2025-05-02T19:43:54.445875Z","iopub.status.idle":"2025-05-02T19:43:54.885969Z","shell.execute_reply.started":"2025-05-02T19:43:54.445850Z","shell.execute_reply":"2025-05-02T19:43:54.885287Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.DataFrame({'preds':predicted_labels, 'actual':actual_labels})\ndf['err'] = abs(df.preds - df.actual)\ndf.query('err > 0')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T19:43:59.950215Z","iopub.execute_input":"2025-05-02T19:43:59.950800Z","iopub.status.idle":"2025-05-02T19:43:59.998154Z","shell.execute_reply.started":"2025-05-02T19:43:59.950779Z","shell.execute_reply":"2025-05-02T19:43:59.997491Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i = 0\nfor el in iter(test_loader):\n    for j in range(16):\n        if i + j in df.query('err > 0').index and i + j < 10:\n            image = el[0][j]\n            if image.shape[0] == 3:\n                image = image[0, ...]\n            plt.imshow(image)\n            plt.title(f'Предсказали: {df.loc[i+j,\"preds\"]}; Настоящее: {df.loc[i+j,\"actual\"]}')\n    i+=16\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-02T19:44:02.777401Z","iopub.execute_input":"2025-05-02T19:44:02.777689Z","iopub.status.idle":"2025-05-02T19:44:08.275602Z","shell.execute_reply.started":"2025-05-02T19:44:02.777669Z","shell.execute_reply":"2025-05-02T19:44:08.275046Z"}},"outputs":[],"execution_count":null}]}