{"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":"import random\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nfrom torchvision import datasets, models, transforms, io\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data import Dataset, DataLoader","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-23T07:46:58.748512Z","iopub.execute_input":"2023-06-23T07:46:58.749111Z","iopub.status.idle":"2023-06-23T07:46:58.757322Z","shell.execute_reply.started":"2023-06-23T07:46:58.749069Z","shell.execute_reply":"2023-06-23T07:46:58.756178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!unzip -q -o /kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip -d data/\n!unzip -q -o /kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip -d data/","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:46:58.759406Z","iopub.execute_input":"2023-06-23T07:46:58.759885Z","iopub.status.idle":"2023-06-23T07:47:10.646516Z","shell.execute_reply.started":"2023-06-23T07:46:58.759851Z","shell.execute_reply":"2023-06-23T07:47:10.645204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom PIL import Image\n\nclass CatDogDataset(Dataset):\n    def __init__(self, path:str, transform=None, train = True, train_split = 0.8):\n        self.path = path\n        self.file_list = os.listdir(self.path)\n        self.transform = transform\n        self.class_names = ['cat','dog']\n        \n        split_idx = int(len(self.file_list)*train_split)\n        random.shuffle(self.file_list)\n        self.file_list = self.file_list[:split_idx] if train == True else self.file_list[split_idx:]\n        \n    def __len__(self):\n        return len(self.file_list)\n    def __getitem__(self, idx:int):\n        img_name = self.file_list[idx]\n        img_path = os.path.join(self.path, img_name)\n        img = Image.open(img_path).convert('RGB')\n        if self.transform is not None:\n            img = self.transform(img)\n        label = self.get_label(img_name)\n        return img, label\n    def get_label(self, img_name: str):\n        classes_map = {'cat': 0, 'dog': 1}\n        return classes_map[img_name.split('.')[0]]","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:47:10.648566Z","iopub.execute_input":"2023-06-23T07:47:10.649267Z","iopub.status.idle":"2023-06-23T07:47:10.660246Z","shell.execute_reply.started":"2023-06-23T07:47:10.649214Z","shell.execute_reply":"2023-06-23T07:47:10.659274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datasets = { x : CatDogDataset(\n    '/kaggle/working/data/train',\n    transforms.Compose([\n        transforms.Resize((224,224)),\n        transforms.RandomHorizontalFlip(),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ]),\n    train= x == 'train',\n) for x in ('train', 'val')}\n\nclass_names = datasets['train'].class_names\n\ndataloaders = { x : DataLoader(\n    datasets[x],\n    batch_size = 64,\n    shuffle = True\n) for x in ('train','val')}","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:47:10.662918Z","iopub.execute_input":"2023-06-23T07:47:10.663194Z","iopub.status.idle":"2023-06-23T07:47:10.745512Z","shell.execute_reply.started":"2023-06-23T07:47:10.663171Z","shell.execute_reply":"2023-06-23T07:47:10.741650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import clear_output as cls\n\ndef plot_images(data, class_names):\n    \n    r, c = 3, 4\n    imgLen = r*c\n    \n    plt.figure(figsize=(20, 15))\n    i = 1\n    \n    for images, labels in iter(data):\n        \n        id = np.random.randint(len(images))\n        img = torch.unsqueeze(images[id].permute(1,2,0), dim = 0)\n        img = img.numpy()\n        lab = class_names[labels[id]]\n        \n        plt.subplot(r, c, i)\n        plt.imshow(img[0])\n        plt.title(lab)\n        plt.axis('off')\n        cls()\n        \n        i+=1\n        if i > imgLen:\n            break\n    plt.show()\n    \nplot_images(dataloaders['train'], class_names)","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:47:10.748165Z","iopub.execute_input":"2023-06-23T07:47:10.749099Z","iopub.status.idle":"2023-06-23T07:47:15.509891Z","shell.execute_reply.started":"2023-06-23T07:47:10.749062Z","shell.execute_reply":"2023-06-23T07:47:15.508697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS = 10\nPATIENCE = 3\nLR = 1e-4\nMOMENTUM = 0.9\n\ndevice = 'cuda' if torch.cuda.is_available() is True else 'cpu'\nmodel = models.resnet50(weights=models.ResNet50_Weights.DEFAULT)\n\nfor param in model.parameters():\n    param.requires_grad = False   \n    \nmodel.fc = nn.Sequential(\n               nn.Linear(2048, 128),\n               nn.ReLU(inplace=True),\n               nn.Linear(128, 2))\n\nmodel = model.to(device)","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:47:15.510933Z","iopub.execute_input":"2023-06-23T07:47:15.511264Z","iopub.status.idle":"2023-06-23T07:47:20.312957Z","shell.execute_reply.started":"2023-06-23T07:47:15.511217Z","shell.execute_reply":"2023-06-23T07:47:20.311952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, criterion, optimizer, device, num_epochs=3, patience=5):\n    history = {\n        'train_loss': [],\n        'train_acc': [],\n        'val_loss': [],\n        'val_acc': []\n    }\n    \n    trigger_time = 0\n    \n    for epoch in range(num_epochs):\n        print('Epoch {}/{}'.format(epoch+1, num_epochs))\n        print('-' * 10)\n\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()\n            else:\n                model.eval()\n\n            running_loss = 0.0\n            running_corrects = 0\n\n            for inputs, labels in dataloaders[phase]:\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n\n                outputs = model(inputs)\n                loss = criterion(outputs, labels)\n\n                if phase == 'train':\n                    optimizer.zero_grad()\n                    loss.backward()\n                    optimizer.step()\n\n                _, preds = torch.max(outputs, 1)\n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += torch.sum(preds == labels.data)\n\n            epoch_loss = running_loss / len(datasets[phase])\n            epoch_acc = running_corrects.double() / len(datasets[phase])\n\n            print('{} loss: {:.4f}, acc: {:.4f}'.format(phase,\n                                                        epoch_loss,\n                                                        epoch_acc))\n            if phase == 'train':\n                history['train_loss'] += [epoch_loss]\n                history['train_acc'] += [epoch_acc]\n            else:\n                history['val_loss'] += [epoch_loss]\n                history['val_acc'] += [epoch_acc]\n        \n        # Early Stopping\n        if epoch >= 2 and epoch + 1 < num_epochs and history['val_acc'][-1] - history['val_acc'][-2] < 1e-3:\n            trigger_time += 1\n            if trigger_time >= patience:\n                print('Early Stopping at epoch {}'.format(epoch+1))\n                return model, history\n        \n    return model, history\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=LR, momentum=MOMENTUM)\n\nmodel, history = train_model(model, criterion, optimizer, device, num_epochs=EPOCHS, patience=PATIENCE)","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:47:20.314458Z","iopub.execute_input":"2023-06-23T07:47:20.314792Z","iopub.status.idle":"2023-06-23T07:49:02.384364Z","shell.execute_reply.started":"2023-06-23T07:47:20.314761Z","shell.execute_reply":"2023-06-23T07:49:02.382496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = history\nacc = list(map(lambda x: float(x), history['train_acc']))\nloss = list(map(lambda x: float(x), history['train_loss']))\nval_acc = list(map(lambda x: float(x), history['val_acc']))\nval_loss = list(map(lambda x: float(x), history['val_loss']))\n\nepochs_range = range(1, len(acc) + 1)\n\nplt.figure(figsize=(12, 4))\nplt.subplot(1, 2, 1)\nplt.plot(epochs_range, acc, label='Training Accuracy')\nplt.plot(epochs_range, val_acc, label='Validation Accuracy')\nplt.legend(loc='lower right')\nplt.title('Training and Validation Accuracy')\n\nplt.subplot(1, 2, 2)\nplt.plot(epochs_range, loss, label='Training Loss')\nplt.plot(epochs_range, val_loss, label='Validation Loss')\nplt.legend(loc='upper right')\nplt.title('Training and Validation Loss')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:49:02.385559Z","iopub.status.idle":"2023-06-23T07:49:02.386059Z","shell.execute_reply.started":"2023-06-23T07:49:02.385784Z","shell.execute_reply":"2023-06-23T07:49:02.385806Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = []\nillu_imgs = []\nfile_list = os.listdir('/kaggle/working/data/test')\n\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\nfor i in range(25):\n    img = Image.open(os.path.join('/kaggle/working/data/test',file_list[i*2])).convert('RGB')\n    illu_img = img\n    pred_img = torch.unsqueeze(transform(img), 0)\n    test_data += [pred_img]\n    illu_imgs += [illu_img]\n\nmodel.eval()\n\n# label = []\npreds = []\n\nwith torch.no_grad():\n    for img in test_data:\n        pred = model(img.to(device)).cpu()\n        preds += [pred]","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:49:02.388340Z","iopub.status.idle":"2023-06-23T07:49:02.388804Z","shell.execute_reply.started":"2023-06-23T07:49:02.388567Z","shell.execute_reply":"2023-06-23T07:49:02.388589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"r, c = 5, 5\nimgLen = r*c\n\nplt.figure(figsize=(20, 15))\n\nfor i in range(25):\n    img = illu_imgs[i]\n    lab = class_names[np.argmax(preds[i])]\n    \n    plt.subplot(r, c, i+1)\n    plt.imshow(img)\n    plt.title(lab)\n    plt.axis('off')\n    cls()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:49:02.390023Z","iopub.status.idle":"2023-06-23T07:49:02.390898Z","shell.execute_reply.started":"2023-06-23T07:49:02.390652Z","shell.execute_reply":"2023-06-23T07:49:02.390679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# torch.save(model.state_dict(), 'catdogweights.pth')","metadata":{"execution":{"iopub.status.busy":"2023-06-23T07:49:02.392151Z","iopub.status.idle":"2023-06-23T07:49:02.392634Z","shell.execute_reply.started":"2023-06-23T07:49:02.392398Z","shell.execute_reply":"2023-06-23T07:49:02.392424Z"},"trusted":true},"execution_count":null,"outputs":[]}]}