{"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":"# 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-09-12T18:01:13.430054Z","iopub.execute_input":"2022-09-12T18:01:13.430482Z","iopub.status.idle":"2022-09-12T18:01:13.443364Z","shell.execute_reply.started":"2022-09-12T18:01:13.430447Z","shell.execute_reply":"2022-09-12T18:01:13.441605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Step 1: Extract Files\nimport zipfile\ntest_path = '/kaggle/input/dogs-vs-cats/test1.zip'\ntrain_path = '/kaggle/input/dogs-vs-cats/train.zip'\nextract_path = '/kaggle/working/extracted'\nwith zipfile.ZipFile(test_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_path)\n    \nwith zipfile.ZipFile(train_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_path)\n    \n# Check whats inside the folder. Folder contains jpg files of cats and dogs.\n# for dirname, _, filenames in os.walk('/kaggle/working'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))","metadata":{"execution":{"iopub.status.busy":"2022-09-12T18:01:13.446211Z","iopub.execute_input":"2022-09-12T18:01:13.447622Z","iopub.status.idle":"2022-09-12T18:01:35.132469Z","shell.execute_reply.started":"2022-09-12T18:01:13.447582Z","shell.execute_reply":"2022-09-12T18:01:35.130970Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Step 2: Visualize some images from the train set.\nimport cv2\nimport matplotlib.pyplot as plt\n\nnum_images = 1\ncount = 0\nfor dirname, _, filenames in os.walk('/kaggle/working/extracted/train'):\n    for filename in filenames:\n        if count < num_images:\n            image_path = os.path.join(dirname, filename)\n            print(image_path)\n            image_read = cv2.imread(image_path)\n            plt.figure(figsize=(8,8))\n            plt.imshow(image_read)\n            count += 1\n","metadata":{"execution":{"iopub.status.busy":"2022-09-12T18:01:35.135514Z","iopub.execute_input":"2022-09-12T18:01:35.136372Z","iopub.status.idle":"2022-09-12T18:01:35.592453Z","shell.execute_reply.started":"2022-09-12T18:01:35.136316Z","shell.execute_reply":"2022-09-12T18:01:35.591205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Step 3: Create a dataloader for Pytorch\n\n# Label 0 = Cat, 1 = dog\n# train_dir = '/kaggle/working/extracted/train'\n# print(os.listdir(train_dir))\n\nfrom torch.utils.data import Dataset, DataLoader\n\nclass CatDogDataset(Dataset):\n\n    def __init__(self, train_dir, img_list, transform = None):\n        \n        self.train_dir = train_dir\n        self.transform = transform\n        self.images = img_list\n        \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        label = self.images[index].split(\".\")[0]\n\n        label = 0 if label == 'cat' else 1\n        img = cv2.imread(image_path)\n        if self.transform:\n            img = self.transform(img)\n        img = img.numpy()\n        return img.astype('float32'), label","metadata":{"execution":{"iopub.status.busy":"2022-09-12T18:01:35.594625Z","iopub.execute_input":"2022-09-12T18:01:35.595564Z","iopub.status.idle":"2022-09-12T18:01:35.608234Z","shell.execute_reply.started":"2022-09-12T18:01:35.595494Z","shell.execute_reply":"2022-09-12T18:01:35.606653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Step 4: Create training dataset\nfrom torchvision import transforms\nimport torchvision\n\ntrain_dir = '/kaggle/working/extracted/train'\ndata_transform = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Resize((256, 256)),\n    transforms.ColorJitter(),\n    transforms.RandomCrop(224),\n    transforms.RandomHorizontalFlip()\n])\nimg_list = os.listdir(train_dir)\ntrain_dataset = CatDogDataset(train_dir, img_list, transform = data_transform)\n\n# Visualize created dataset\ndataloader = DataLoader(train_dataset, batch_size = 32, shuffle=True, num_workers=2)\n\nsamples, labels = iter(dataloader).next()\nplt.figure(figsize=(16,32))\ngrid_imgs = torchvision.utils.make_grid(samples[:32])\nnp_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.\nplt.imshow(np.transpose(np_grid_imgs, (1,2,0)))","metadata":{"execution":{"iopub.status.busy":"2022-09-12T18:01:35.612541Z","iopub.execute_input":"2022-09-12T18:01:35.613389Z","iopub.status.idle":"2022-09-12T18:01:37.593516Z","shell.execute_reply.started":"2022-09-12T18:01:35.613321Z","shell.execute_reply":"2022-09-12T18:01:37.591991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Step 5: Define Deep Learning model\n# First model will be a model from scratch, 2nd model will use transfer learning to utilize pretrained Resnet model\n\nimport torch\nimport torch.nn as nn\n\n## First model\nclass scratch_nn(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.conv1 = nn.Conv2d(in_channels=3, out_channels=100, kernel_size=5, stride=1, padding=0)\n        self.conv2 = nn.Conv2d(100, 200, 3, stride=1, padding=0)\n        self.conv3 = nn.Conv2d(200, 400, 3, stride=1, padding=0)\n        self.mpool = nn.MaxPool2d(kernel_size=3)\n        self.relu = nn.ReLU()\n        self.linear1 = nn.Linear(19600,1024)\n        self.linear2 = nn.Linear(1024,512)\n        self.linear3 = nn.Linear(512,2)\n        self.classifier = nn.Softmax(dim=1)\n        \n    def forward(self,x):\n        x = self.mpool( self.relu(self.conv1(x)) )\n        x = self.mpool( self.relu(self.conv2(x)) )\n        x = self.mpool( self.relu(self.conv3(x)) )\n        x = torch.flatten(x, start_dim=1)\n        x = self.linear1(x)\n        x = self.linear2(x)\n        x = self.linear3(x)\n        x = self.classifier(x)\n        return x\n\n# Test code\n# net = scratch_nn()\n# print(net)\n# y_pred = net.forward(samples)\n# print(samples.shape)\n# print(y_pred)\n# print(y_pred.shape)","metadata":{"execution":{"iopub.status.busy":"2022-09-12T18:01:37.595723Z","iopub.execute_input":"2022-09-12T18:01:37.596644Z","iopub.status.idle":"2022-09-12T18:01:37.615396Z","shell.execute_reply.started":"2022-09-12T18:01:37.596571Z","shell.execute_reply":"2022-09-12T18:01:37.613573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Step 6: Define train_step and predict functions\n\nfrom tqdm import tqdm\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n# device = \"cpu\"\nprint(device)\n\ndef train_step(model, optimizer, criterion, train_loader):\n    model.train()\n    avg_loss = []\n    for x,y in tqdm(train_loader):\n        x = x.to(device)\n        y = y.to(device)\n        y_pred = model(x=x)\n        loss = criterion(y_pred, y)\n        loss.backward()\n        optimizer.step()\n        optimizer.zero_grad()\n        avg_loss.append(loss.item())\n    return sum(avg_loss)/len(avg_loss)\n\ndef predict(model, test_loader):\n    model.eval()\n    total_preds = torch.Tensor()\n    total_labels = torch.Tensor()\n    with torch.no_grad():\n        for x,y in tqdm(test_loader):\n            x = x.to(device)\n            y = y.to(device)\n            pred = model(x=x)\n            y_pred = torch.argmax(pred, dim=1)\n#             print(y)\n#             print(len(y))\n#             print(y_pred)\n#             print(len(y_pred))\n            total_preds = torch.cat((total_preds, y_pred.cpu()), 0)\n            total_labels = torch.cat((total_labels, y.cpu()), 0)\n    return total_labels.numpy().flatten(),total_preds.numpy().flatten()\n    ","metadata":{"execution":{"iopub.status.busy":"2022-09-12T18:01:37.617767Z","iopub.execute_input":"2022-09-12T18:01:37.618853Z","iopub.status.idle":"2022-09-12T18:01:37.640905Z","shell.execute_reply.started":"2022-09-12T18:01:37.618799Z","shell.execute_reply":"2022-09-12T18:01:37.639399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Step 7: Define main train function\n\nfrom sklearn.metrics import accuracy_score\nimport copy\n\ndef train(model, dataset, val_dataset):\n    num_epoch = 300\n    # lr and weight_decay are hyperparameters. For now setting their values manually\n    lr = 0.001\n    weight_dec = 0.001\n    optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=weight_dec)\n    criterion = nn.CrossEntropyLoss()\n    batch_size = 32\n    dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True, num_workers=2)\n    val_dataloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=True, num_workers=2)\n    max_accuracy = 0\n    model = model.to(device)\n    model_file_name = \"working\\scratch_best_model.model\"\n    for epoch in range(1, num_epoch + 1):\n        train_loss = train_step(model, optimizer, criterion, dataloader)\n        if epoch % 100 == 0:\n            print(f\"Loss at epoch {epoch} is {train_loss}\")\n        G,P = predict(model, val_dataloader)\n        accuracy = accuracy_score(G, P)\n        if accuracy > max_accuracy:\n            max_accuracy = accuracy\n            best_model = copy.deepcopy(model)\n            torch.save(best_model.state_dict(), model_file_name)\n            print(\"saving best model with accuracy: \", accuracy)\n    return best_model\n    \n    ","metadata":{"execution":{"iopub.status.busy":"2022-09-12T18:01:37.643156Z","iopub.execute_input":"2022-09-12T18:01:37.644154Z","iopub.status.idle":"2022-09-12T18:01:37.660930Z","shell.execute_reply.started":"2022-09-12T18:01:37.644089Z","shell.execute_reply":"2022-09-12T18:01:37.659391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Step 8: Create train and validation dataset and train model\n\nfrom sklearn.metrics import classification_report\n\ndata_transform = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Resize((256, 256)),\n    transforms.ColorJitter(),\n    transforms.RandomCrop(224),\n    transforms.RandomHorizontalFlip()\n])\ntrain_dir = '/kaggle/working/extracted/train'\ntrain_img_list = os.listdir(train_dir)[1:20000]\nval_img_list = os.listdir(train_dir)[20000:25000]\ntrain_dataset = CatDogDataset(train_dir, train_img_list, transform = data_transform)\nval_dataset = CatDogDataset(train_dir, val_img_list, transform = data_transform)\n\nmodel = scratch_nn()\n\nbest_model = train(model=model, dataset=train_dataset, val_dataset=val_dataset)\n\nval_dataloader = DataLoader(val_dataset, batch_size=32, shuffle=True, num_workers=2)\nG,P = predict(model, val_dataloader)\nprint(classification_report(G,P))\n","metadata":{"execution":{"iopub.status.busy":"2022-09-14T12:39:43.346892Z","iopub.execute_input":"2022-09-14T12:39:43.348014Z","iopub.status.idle":"2022-09-14T12:39:44.441380Z","shell.execute_reply.started":"2022-09-14T12:39:43.347873Z","shell.execute_reply":"2022-09-14T12:39:44.439988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}