{"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":"markdown","source":"Kaggle link: https://www.kaggle.com/c/dogs-vs-cats-redux-kernels-edition","metadata":{}},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-04T14:27:55.609241Z","iopub.execute_input":"2022-01-04T14:27:55.609909Z","iopub.status.idle":"2022-01-04T14:27:55.618572Z","shell.execute_reply.started":"2022-01-04T14:27:55.609872Z","shell.execute_reply":"2022-01-04T14:27:55.617854Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Import everything needed","metadata":{}},{"cell_type":"code","source":"import zipfile\nimport glob\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n\nfrom sklearn.model_selection import train_test_split\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import datasets, transforms\nnp.random.seed(0)\ntorch.manual_seed(0)\n#CUDA_LAUNCH_BLOCKING=1\ntorch.cuda.manual_seed(0)\n","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:27:55.620435Z","iopub.execute_input":"2022-01-04T14:27:55.620934Z","iopub.status.idle":"2022-01-04T14:27:58.103458Z","shell.execute_reply.started":"2022-01-04T14:27:55.620897Z","shell.execute_reply":"2022-01-04T14:27:58.102725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\nfrom kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\nsecret_value_0 = user_secrets.get_secret(\"WANDB_KEY\")\nwandb.login(key=secret_value_0)\nwandb.init(project='Cats_vs_dogs', save_code=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:27:58.104655Z","iopub.execute_input":"2022-01-04T14:27:58.106160Z","iopub.status.idle":"2022-01-04T14:28:08.348400Z","shell.execute_reply.started":"2022-01-04T14:27:58.106121Z","shell.execute_reply":"2022-01-04T14:28:08.347595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Unzip datasets","metadata":{}},{"cell_type":"code","source":"UNZIP = True\nif UNZIP:\n    train_dir = 'train'\n    test_dir = 'test'\n    with zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip') as train_zip:\n        train_zip.extractall('')\n\n    with zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip') as test_zip:\n        test_zip.extractall('')\n    train_list = glob.glob(os.path.join(train_dir,'*.jpg'))\n    test_list = glob.glob(os.path.join(test_dir, '*.jpg'))\n    print(f\"Train Data: {len(train_list)}\")\n    print(f\"Test Data: {len(test_list)}\")","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:08.350319Z","iopub.execute_input":"2022-01-04T14:28:08.350594Z","iopub.status.idle":"2022-01-04T14:28:27.877096Z","shell.execute_reply.started":"2022-01-04T14:28:08.350556Z","shell.execute_reply":"2022-01-04T14:28:27.876263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = [path.split('/')[-1].split('.')[0] for path in train_list]","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:27.880414Z","iopub.execute_input":"2022-01-04T14:28:27.880681Z","iopub.status.idle":"2022-01-04T14:28:28.840618Z","shell.execute_reply.started":"2022-01-04T14:28:27.880644Z","shell.execute_reply":"2022-01-04T14:28:28.839926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Plot random image with their label","metadata":{}},{"cell_type":"code","source":"random_idx = np.random.randint(1, len(train_list), size=9)\nfig, axes = plt.subplots(3, 3, figsize=(16, 12))\n\nfor idx, ax in enumerate(axes.ravel()):\n    img = Image.open(train_list[idx])\n    ax.set_title(labels[idx])\n    ax.imshow(img)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:28.842849Z","iopub.execute_input":"2022-01-04T14:28:28.843269Z","iopub.status.idle":"2022-01-04T14:28:31.063482Z","shell.execute_reply.started":"2022-01-04T14:28:28.843229Z","shell.execute_reply":"2022-01-04T14:28:31.062605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Use Sklearn to split data","metadata":{}},{"cell_type":"code","source":"train_list, valid_list = train_test_split(train_list, \n                                          test_size=0.2,\n                                          stratify=labels,\n                                          random_state=0)\nprint(f\"Train Data: {len(train_list)}\")\nprint(f\"Validation Data: {len(valid_list)}\")\nprint(f\"Test Data: {len(test_list)}\")","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:31.066541Z","iopub.execute_input":"2022-01-04T14:28:31.067097Z","iopub.status.idle":"2022-01-04T14:28:32.236311Z","shell.execute_reply.started":"2022-01-04T14:28:31.067051Z","shell.execute_reply":"2022-01-04T14:28:32.235593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We will discuss this in more detail in a near future...","metadata":{}},{"cell_type":"code","source":"train_transforms = transforms.Compose([\n        transforms.Resize(128), # makes it easier for the GPU\n        transforms.RandomResizedCrop(112),\n        transforms.RandomHorizontalFlip(),\n        transforms.ToTensor()])\n\nval_transforms = transforms.Compose([\n        transforms.Resize(128),\n        transforms.CenterCrop(112),\n        transforms.ToTensor()])\n\ntest_transforms = transforms.Compose([\n        transforms.Resize(128),\n        transforms.CenterCrop(112),\n        transforms.ToTensor()])","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:32.237699Z","iopub.execute_input":"2022-01-04T14:28:32.237966Z","iopub.status.idle":"2022-01-04T14:28:33.107967Z","shell.execute_reply.started":"2022-01-04T14:28:32.237931Z","shell.execute_reply":"2022-01-04T14:28:33.104979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Define the dataset using PIL to read image","metadata":{}},{"cell_type":"code","source":"class CatsDogsDataset(Dataset):\n    def __init__(self, file_list, transform=None):\n        self.file_list = file_list\n        self.transform = transform\n        self.filelength = len(file_list)\n\n    def __len__(self):\n        return self.filelength\n\n    def __getitem__(self, idx):\n        img_path = self.file_list[idx]\n        img = Image.open(img_path)\n        img_transformed = self.transform(img)\n        label = img_path.split(\"/\")[-1].split(\".\")[0]\n        label = 1 if label == \"dog\" else 0\n        return img_transformed, label","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:33.110013Z","iopub.execute_input":"2022-01-04T14:28:33.110300Z","iopub.status.idle":"2022-01-04T14:28:33.863095Z","shell.execute_reply.started":"2022-01-04T14:28:33.110263Z","shell.execute_reply":"2022-01-04T14:28:33.862392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = CatsDogsDataset(train_list, transform=train_transforms)\nvalid_data = CatsDogsDataset(valid_list, transform=test_transforms)\ntest_data = CatsDogsDataset(test_list, transform=test_transforms)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:33.864388Z","iopub.execute_input":"2022-01-04T14:28:33.864628Z","iopub.status.idle":"2022-01-04T14:28:34.602457Z","shell.execute_reply.started":"2022-01-04T14:28:33.864593Z","shell.execute_reply":"2022-01-04T14:28:34.601746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create dataloader, you can modify the batch size if needed","metadata":{}},{"cell_type":"code","source":"batch_size = 32\ntrain_loader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)\nvalid_loader = DataLoader(dataset=valid_data, batch_size=batch_size, shuffle=False)\ntest_loader = DataLoader(dataset=test_data, batch_size=batch_size, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:34.605463Z","iopub.execute_input":"2022-01-04T14:28:34.605654Z","iopub.status.idle":"2022-01-04T14:28:35.346100Z","shell.execute_reply.started":"2022-01-04T14:28:34.605630Z","shell.execute_reply":"2022-01-04T14:28:35.345370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# AlexNet (modfied)","metadata":{}},{"cell_type":"code","source":"if False: \n    def init_my_layer(m):\n        torch.nn.init.xavier_normal_(m.weight, nn.init.calculate_gain('tanh'))\n        torch.nn.init.constant_(m.bias, 0)\n        return m\n\n    class AlexNet(nn.Module):    \n        def __init__(self):\n            super(Net, self).__init__()\n            self.cnn_features = nn.Sequential(\n                nn.Conv2d(3, 96, kernel_size=11, stride=4),\n                nn.ReLU(inplace=True),\n                nn.MaxPool2d(kernel_size=3, stride=2),\n                nn.Conv2d(96, 256, kernel_size=5, padding=2),\n                nn.ReLU(inplace=True),\n                nn.MaxPool2d(kernel_size=3, stride=2),\n                nn.Conv2d(256, 384, kernel_size=3, padding=1),\n                nn.ReLU(inplace=True),\n                nn.Conv2d(384, 256, kernel_size=3, padding=1),\n                nn.ReLU(inplace=True),\n                nn.Conv2d(256, 256, kernel_size=3, padding=1),\n                nn.ReLU(inplace=True),\n                nn.MaxPool2d(kernel_size=3, stride=2),\n            )\n            self.linear_layers = nn.Sequential(\n                nn.Dropout(p=0.5),\n                init_my_layer(nn.Linear(1024, 4096)),\n                nn.ReLU(inplace=True),\n                nn.Dropout(p=0.5),\n                init_my_layer(nn.Linear(4096, 4096)),\n                nn.ReLU(inplace=True),\n                init_my_layer(nn.Linear(4096, 2)),\n            )\n            self.sigmoid = nn.Sigmoid()\n\n        def forward(self, x):\n            x = self.cnn_features(x)\n            x = torch.flatten(x, 1)\n            x = self.linear_layers(x)\n            x = self.sigmoid(x)\n            return x","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:35.347238Z","iopub.execute_input":"2022-01-04T14:28:35.347471Z","iopub.status.idle":"2022-01-04T14:28:36.082665Z","shell.execute_reply.started":"2022-01-04T14:28:35.347440Z","shell.execute_reply":"2022-01-04T14:28:36.081947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Small NN (3x convolution + 2 linear layers)","metadata":{}},{"cell_type":"code","source":"\nclass Net(nn.Module):\n    def __init__(self):\n        super(Net,self).__init__()\n\n        self.cnn_layer1 = nn.Sequential(\n            nn.Conv2d(3,16,kernel_size=3, padding=0,stride=2), # 2D convolution\n            nn.BatchNorm2d(16),# normalize the input by the mean and standard deviation of the batch\n            nn.ReLU(), # max(0,x)\n        )\n\n        self.cnn_layer2 = nn.Sequential(\n            nn.Conv2d(16,32, kernel_size=3, padding=0, stride=2), # 2D convolution\n            nn.BatchNorm2d(32), # normalize the input by the mean and standard deviation of the batch\n            nn.ReLU(), # max(0,x)\n            nn.MaxPool2d(2) # aggregate pixel values together, no learnable weights\n            )\n\n        self.cnn_layer3 = nn.Sequential(\n            nn.Conv2d(32,64, kernel_size=3, padding=0, stride=2), # 2D convolution\n            nn.BatchNorm2d(64), # normalize the input by the mean and standard deviation of the batch\n            nn.ReLU(), # max(0,x)\n            nn.MaxPool2d(2) # aggregate pixel values together, no learnable weights\n        )\n\n\n        self.linear_layer1 = nn.Linear(3*3*64,10) # linear layer\n        self.dropout = nn.Dropout(0.5) # inject random noise during training (deactivate neurons to prevent overfitting)\n        self.linear_layer2 = nn.Linear(10,1) # linear layer\n        self.relu = nn.ReLU() # max(0,x)\n        self.sigmoid = nn.Sigmoid() # map between 0 and 1\n\n    def forward(self,x):\n        out = self.cnn_layer1(x)\n        out = self.cnn_layer2(out)\n        out = self.cnn_layer3(out)\n        out = out.view(out.size(0),-1)\n        out = self.relu(self.linear_layer1(out))\n        out = self.linear_layer2(out)\n        out = self.sigmoid(out)\n        return out.flatten().float()","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:36.085783Z","iopub.execute_input":"2022-01-04T14:28:36.085995Z","iopub.status.idle":"2022-01-04T14:28:36.832394Z","shell.execute_reply.started":"2022-01-04T14:28:36.085970Z","shell.execute_reply":"2022-01-04T14:28:36.831265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ResNet","metadata":{}},{"cell_type":"code","source":"#ResNet\nclass Residual(nn.Module):\n    def __init__(self, input_channels, num_channels, use_1x1conv=False, strides=1):\n        super().__init__()\n        self.conv1 = nn.Conv2d(input_channels, num_channels, kernel_size=3,\n                               padding=1, stride=strides)\n        self.conv2 = nn.Conv2d(num_channels, num_channels, kernel_size=3,\n                               padding=1)\n        if use_1x1conv:\n            self.conv3 = nn.Conv2d(input_channels, num_channels,\n                                   kernel_size=1, stride=strides)\n        else:\n            self.conv3 = None\n        self.bn1 = nn.BatchNorm2d(num_channels)\n        self.bn2 = nn.BatchNorm2d(num_channels)\n\n    def forward(self, X):\n        Y = F.relu(self.bn1(self.conv1(X)))\n        Y = self.bn2(self.conv2(Y))\n        if self.conv3:\n            X = self.conv3(X)\n        Y += X\n        return F.relu(Y)\n\ndef resnet_block(input_channels, num_channels, num_residuals):\n    blk = []\n    for i in range(num_residuals):\n        if i == 0 and input_channels != num_channels: # 1x1 applied only once per block if needed\n            blk.append(\n                Residual(input_channels, num_channels, use_1x1conv=True,\n                         strides=2))\n        else:\n            blk.append(Residual(num_channels, num_channels))\n    return blk","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:36.839193Z","iopub.execute_input":"2022-01-04T14:28:36.839660Z","iopub.status.idle":"2022-01-04T14:28:37.926073Z","shell.execute_reply.started":"2022-01-04T14:28:36.839622Z","shell.execute_reply":"2022-01-04T14:28:37.925303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"b1 = nn.Sequential(nn.Conv2d(3, 64, kernel_size=3, stride=2, padding=3),\n                              nn.BatchNorm2d(64), nn.ReLU(),\n                              nn.MaxPool2d(kernel_size=3, stride=2, padding=1))\nb2 = nn.Sequential(*resnet_block(64, 64, 2))\nb3 = nn.Sequential(*resnet_block(64, 128, 2))\nb4 = nn.Sequential(*resnet_block(128, 256, 2))\nb5 = nn.Sequential(*resnet_block(256, 512, 2))","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:37.927516Z","iopub.execute_input":"2022-01-04T14:28:37.927764Z","iopub.status.idle":"2022-01-04T14:28:39.069400Z","shell.execute_reply.started":"2022-01-04T14:28:37.927730Z","shell.execute_reply":"2022-01-04T14:28:39.068682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Choose model","metadata":{}},{"cell_type":"markdown","source":"Check out shape of train_loader","metadata":{}},{"cell_type":"code","source":"X,y = next(iter(train_loader))\nprint(X.shape)\nprint(y.shape)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:39.070782Z","iopub.execute_input":"2022-01-04T14:28:39.071078Z","iopub.status.idle":"2022-01-04T14:28:40.007729Z","shell.execute_reply.started":"2022-01-04T14:28:39.071040Z","shell.execute_reply":"2022-01-04T14:28:40.006951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install torchinfo","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:40.011054Z","iopub.execute_input":"2022-01-04T14:28:40.011273Z","iopub.status.idle":"2022-01-04T14:28:50.243648Z","shell.execute_reply.started":"2022-01-04T14:28:40.011247Z","shell.execute_reply":"2022-01-04T14:28:50.242832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchinfo import summary\n\n# model = AlexNet()\n# model = Net()\nmodel = model = nn.Sequential(b1, b2, b3, b4, b5, nn.AdaptiveAvgPool2d((1, 1)),\n                    nn.Flatten(), nn.Linear(512, 1), nn.Sigmoid())\n\n\nsummary(model, input_size=(32, 3, 112, 112))","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:50.245192Z","iopub.execute_input":"2022-01-04T14:28:50.245456Z","iopub.status.idle":"2022-01-04T14:28:59.831009Z","shell.execute_reply.started":"2022-01-04T14:28:50.245417Z","shell.execute_reply":"2022-01-04T14:28:59.830121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check if a GPU with Cuda capacities is available\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\") #0, first GPU if multiple one\nmodel.to(device)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:28:59.834463Z","iopub.execute_input":"2022-01-04T14:28:59.834665Z","iopub.status.idle":"2022-01-04T14:29:00.605136Z","shell.execute_reply.started":"2022-01-04T14:28:59.834641Z","shell.execute_reply":"2022-01-04T14:29:00.604306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"learning_rate = 1e-3\n\ncriterion = torch.nn.BCELoss()#nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n\nwandb.watch(model, log=\"all\", criterion=criterion, log_freq=1,  log_graph=(True)) ","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:29:00.608416Z","iopub.execute_input":"2022-01-04T14:29:00.608648Z","iopub.status.idle":"2022-01-04T14:29:01.496589Z","shell.execute_reply.started":"2022-01-04T14:29:00.608621Z","shell.execute_reply":"2022-01-04T14:29:01.495867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_accuracy(y_true, y_prob):\n    assert y_true.ndim == 1 and y_true.size() == y_prob.size()\n    y_prob = y_prob > 0.5\n    return (y_true == y_prob).sum().item() / y_true.size(0)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:29:01.499680Z","iopub.execute_input":"2022-01-04T14:29:01.499974Z","iopub.status.idle":"2022-01-04T14:29:02.453577Z","shell.execute_reply.started":"2022-01-04T14:29:01.499944Z","shell.execute_reply":"2022-01-04T14:29:02.452860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN = True\n\nif TRAIN:\n    nb_epochs = 20\n    # Training\n    for t in range(nb_epochs):\n        \n        model.train() # put the network in training mode\n        epoch_loss = 0\n        epoch_accuracy = 0\n        \n        for X, y in train_loader:\n            # put on GPU if available\n            X, y = X.to(device), y.to(device)\n            # Feed forward to get the logits\n            y_pred = model(X)\n\n            # Compute the loss \n            loss = criterion(y_pred, y.float().view(y_pred.shape))\n\n            # zero the gradients before running\n            # the backward pass.\n            optimizer.zero_grad()\n\n            # Backward pass to compute the gradient\n            # of loss w.r.t our learnable params. \n            loss.backward()\n\n            # Update params\n            optimizer.step()\n            \n            \n            # get accuracy and loss per epoch\n            acc = get_accuracy(y.float(), y_pred.flatten())\n            epoch_accuracy += acc/len(train_loader)\n            epoch_loss += loss/len(train_loader)\n\n        wandb.log({'mlp/train_loss': epoch_loss.item(),'mlp/train_acc': epoch_accuracy})\n        print('Epoch : {}, train accuracy : {}, train loss : {}'.format(t+1, epoch_accuracy,epoch_loss))\n\n        with torch.no_grad(): # validation run\n            epoch_val_accuracy = 0\n            epoch_val_loss = 0\n            model.eval() # validation mode\n\n            for X, y in valid_loader:\n                # put on GPU if available\n                X, y = X.to(device), y.to(device)\n\n                y_pred = model(X)\n                #print(len(X))\n                #print(y_pred)\n                #print(y)\n                #print(y.float().view(32,1))\n                val_loss = criterion(y_pred, y.float().view(y_pred.shape))\n\n                # get validation accuracy and loss per epoch\n                acc = get_accuracy(y.float(), y_pred.flatten())\n                epoch_val_accuracy += acc/ len(valid_loader)\n                epoch_val_loss += val_loss/ len(valid_loader)\n\n            wandb.log({'mlp/val_loss': epoch_val_loss.item(),'mlp/val_acc': epoch_val_accuracy})\n            print('Epoch : {}, val_accuracy : {}, val_loss : {}'.format(t+1, epoch_val_accuracy,epoch_val_loss))\nelse:\n    model.load_state_dict(torch.load('/kaggle/input/model-resnet/model_resnet.pt'))","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:32:18.579271Z","iopub.execute_input":"2022-01-04T14:32:18.579560Z","iopub.status.idle":"2022-01-04T14:32:21.146069Z","shell.execute_reply.started":"2022-01-04T14:32:18.579528Z","shell.execute_reply":"2022-01-04T14:32:21.145268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if True:\n    torch.save(model.state_dict(), 'model.pt')","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:29:04.846144Z","iopub.status.idle":"2022-01-04T14:29:04.846710Z","shell.execute_reply.started":"2022-01-04T14:29:04.846484Z","shell.execute_reply":"2022-01-04T14:29:04.846508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Evaluation","metadata":{}},{"cell_type":"code","source":"prob = []\nmodel.eval()\nwith torch.no_grad():\n    for X, y in test_loader:\n        X = X.to(device)\n        y_pred = model(X).flatten().tolist()\n        #y_pred = F.softmax(model(X), dim=1)[:, 1].tolist()\n        prob = prob + y_pred \n\nidx = [i for i in range(1,len(prob)+1)]   \nsubmission = pd.DataFrame({'id':idx,'label':prob})\nsubmission.to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:42:01.882481Z","iopub.execute_input":"2022-01-04T14:42:01.882843Z","iopub.status.idle":"2022-01-04T14:44:46.053464Z","shell.execute_reply.started":"2022-01-04T14:42:01.882782Z","shell.execute_reply":"2022-01-04T14:44:46.052726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:46:07.489720Z","iopub.execute_input":"2022-01-04T14:46:07.490292Z","iopub.status.idle":"2022-01-04T14:46:08.940044Z","shell.execute_reply.started":"2022-01-04T14:46:07.490252Z","shell.execute_reply":"2022-01-04T14:46:08.939298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Show examplary classifications","metadata":{}},{"cell_type":"code","source":"import random\nimport matplotlib.pyplot as plt\n\nid_list = []\n\nfig, axes = plt.subplots(3, 6, figsize=(18, 10), facecolor='w')\n\nfor ax in axes.ravel():\n    \n    i = random.choice(submission['id'].values)\n    \n    label = submission.loc[submission['id'] == i, 'label'].values[0]\n    if label > 0.5:\n        label = 'dog'\n    else:\n        label = 'cat'\n        \n    img_path = os.path.join(test_dir, '{}.jpg'.format(i))\n    img = Image.open(img_path)\n    \n    ax.set_title(label)\n    ax.imshow(img)","metadata":{"execution":{"iopub.status.busy":"2022-01-04T14:46:25.899351Z","iopub.execute_input":"2022-01-04T14:46:25.899607Z","iopub.status.idle":"2022-01-04T14:46:28.866130Z","shell.execute_reply.started":"2022-01-04T14:46:25.899578Z","shell.execute_reply":"2022-01-04T14:46:28.865290Z"},"trusted":true},"execution_count":null,"outputs":[]}]}