{"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 numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport torch\nimport torch.nn as nn\nimport matplotlib.pyplot as plt\nimport torchvision\nfrom torch.utils.data import Dataset, DataLoader, ConcatDataset\nfrom torchvision import transforms\nimport copy\nfrom tqdm import tqdm\nfrom PIL import Image\n\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\ntrain_dir = '/kaggle/input/dogs-vs-cats/train.zip'\ntest_dir  = '/kaggle/input/dogs-vs-cats/test1.zip'\nbatch_size = 100\n\ndata_transform = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Resize((500, 500))\n])\n\n#Class loading Dataset\nclass CatDogDataset(Dataset):\n    def __init__(self, train_dir, transform = None):\n        super(CatDogDataset, self).__init__()\n        self.train_dir = train_dir\n        self.transform = transform\n        self.images = os.listdir(train_dir)\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, index):\n        image_path = os.path.join(self.train_dir, self.images[index])\n\n        label = self.images[index].split(\".\")[0]\n        label = 0 if label == 'cat' else 1\n        image = np.array(Image.open(image_path))\n        \n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\ndef validate(model, test_data_loader, device=\"cpu\"):\n    total = 0\n    correct = 0\n\n    for (images, labels) in test_data_loader:\n        images  = images.to(device)\n        y       = model(images)\n        _, pred = torch.max(y, 1)\n\n        total   += y.size(0)\n        correct += torch.sum(pred == labels)\n\n    return correct*100/total\n\ndef train_model(model, train_data_loader, test_data_loader, epoches, lr, device=\"cpu\"):\n    accuracies  = []\n    model       = model.to(device)\n    criterion   = nn.CrossEntropyLoss()\n    optimizer   = torch.optim.Adam(model.parameters(), lr=lr, amsgrad=True)\n\n    max_accuracy = 0\n\n    #Below runs as epoch1->epoch2-> . . .\n    print(\"Using device: \", device)\n    for epoch in range(epoches):\n        print(\"\\rEpoch {}\".format(epoch), end=\"\")\n        #Below runs batch-wise: batch1->batch2-> . . .\n        with tqdm(train_data_loader, unit=\"batch\") as tepoch:\n            for i, (images, labels) in enumerate(tepoch):\n                images = images.to(device)\n                labels = labels.to(device)\n\n                optimizer.zero_grad()\n                pred = model(images)\n                loss = criterion(pred, labels)\n                loss.backward()\n                optimizer.step()\n        accuracy = float(validate(model, test_data_loader))\n        accuracies.append(accuracy)\n        \n        if accuracy > max_accuracy:\n            best_model = copy.deepcopy(model)\n            max_accuracy = accuracy\n            print(\"saving best model with accuracy: \", accuracy)\n        print(\"Epoch: \", epoch+1, \"Accuracy: \", accuracy, \"%\")\n    \n    return best_model\n\n\ndef classifier():\n    #Load data into torch DataLoader\n    train_data = CatDogDataset(train_dir, data_transform)\n    test_data  = CatDogDataset(test_dir, data_transform)\n\n    train_data_loader = DataLoader(train_data, batch_size=batch_size)\n    test_data_loader  = DataLoader(test_data, batch_size=batch_size)\n\n    #Visualization of some datapoints/images - to be used in jupyter notebook\n    # samples, labels = iter(train_data_loader).next()\n    # plt.figure(figsize=(16,24))\n    # grid_imgs = torchvision.utils.make_grid(samples[:24])\n    # np_grid_imgs = grid_imgs.numpy()\n    # # in tensor, image is (batch, width, height), so you have to transpose it to (width, height, batch) in numpy to show it.\n    # plt.imshow(np.transpose(np_grid_imgs, (1,2,0)))\n\n    #Transfer learning\n    model       = torchvision.models.resnet18(pretrained=True)\n    \n    for param in model.parameters():\n        param.requires_grad = False\n    \n    num_ftrs    = model.fc.in_features\n    model.fc    = nn.Sequential(\n                    nn.Linear(num_ftrs, 2),\n                    nn.Softmax(dim=1)\n                )\n\n    epoches = 2\n    lr = 1e-4\n\n    transfer_model = train_model(model, train_data_loader, test_data_loader, epoches, lr)\n    torch.save(transfer_model.state_dict(), \"ResNet18_CatDog.pth\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-12-01T05:00:53.239591Z","iopub.execute_input":"2022-12-01T05:00:53.240108Z","iopub.status.idle":"2022-12-01T05:00:53.266092Z","shell.execute_reply.started":"2022-12-01T05:00:53.240066Z","shell.execute_reply":"2022-12-01T05:00:53.264706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ls","metadata":{"execution":{"iopub.status.busy":"2022-12-01T04:59:50.537976Z","iopub.execute_input":"2022-12-01T04:59:50.538766Z","iopub.status.idle":"2022-12-01T04:59:51.584492Z","shell.execute_reply.started":"2022-12-01T04:59:50.538712Z","shell.execute_reply":"2022-12-01T04:59:51.583162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classifier()","metadata":{"execution":{"iopub.status.busy":"2022-12-01T05:00:59.168057Z","iopub.execute_input":"2022-12-01T05:00:59.168979Z","iopub.status.idle":"2022-12-01T05:00:59.219011Z","shell.execute_reply.started":"2022-12-01T05:00:59.168906Z","shell.execute_reply":"2022-12-01T05:00:59.216978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}