{"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-02-04T21:58:02.665658Z","iopub.execute_input":"2022-02-04T21:58:02.665990Z","iopub.status.idle":"2022-02-04T21:58:02.674577Z","shell.execute_reply.started":"2022-02-04T21:58:02.665947Z","shell.execute_reply":"2022-02-04T21:58:02.673841Z"},"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\nfrom torch import flatten\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)\ntorch.cuda.manual_seed(0)","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:02.676295Z","iopub.execute_input":"2022-02-04T21:58:02.677017Z","iopub.status.idle":"2022-02-04T21:58:05.141955Z","shell.execute_reply.started":"2022-02-04T21:58:02.676979Z","shell.execute_reply":"2022-02-04T21:58:05.141207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib\nmatplotlib.use(\"Agg\")\n\nfrom sklearn.metrics import classification_report\nimport argparse\n","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:05.143460Z","iopub.execute_input":"2022-02-04T21:58:05.143716Z","iopub.status.idle":"2022-02-04T21:58:05.151099Z","shell.execute_reply.started":"2022-02-04T21:58:05.143678Z","shell.execute_reply":"2022-02-04T21:58:05.150354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\n\nfrom kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\nsecret_value_0 = user_secrets.get_secret(\"wand_key\")\n\nwandb.login(key=secret_value_0)\nwandb.init(project='dogs-vs-cats-redux-kernels-edition', save_code=True)","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:05.153291Z","iopub.execute_input":"2022-02-04T21:58:05.153651Z","iopub.status.idle":"2022-02-04T21:58:14.189098Z","shell.execute_reply.started":"2022-02-04T21:58:05.153614Z","shell.execute_reply":"2022-02-04T21:58:14.188358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Unzip datasets","metadata":{}},{"cell_type":"code","source":"train_dir = 'train'\ntest_dir = 'test'\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip') as train_zip:\n    train_zip.extractall('')\n    \nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip') as test_zip:\n    test_zip.extractall('')\ntrain_list = glob.glob(os.path.join(train_dir,'*.jpg'))\ntest_list = glob.glob(os.path.join(test_dir, '*.jpg'))\nprint(f\"Train Data: {len(train_list)}\")\nprint(f\"Test Data: {len(test_list)}\")","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:14.190609Z","iopub.execute_input":"2022-02-04T21:58:14.190879Z","iopub.status.idle":"2022-02-04T21:58:33.676723Z","shell.execute_reply.started":"2022-02-04T21:58:14.190839Z","shell.execute_reply":"2022-02-04T21:58:33.676003Z"},"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-02-04T21:58:33.679036Z","iopub.execute_input":"2022-02-04T21:58:33.679292Z","iopub.status.idle":"2022-02-04T21:58:34.237880Z","shell.execute_reply.started":"2022-02-04T21:58:33.679256Z","shell.execute_reply":"2022-02-04T21:58:34.236061Z"},"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-02-04T21:58:34.239209Z","iopub.execute_input":"2022-02-04T21:58:34.239481Z","iopub.status.idle":"2022-02-04T21:58:35.828719Z","shell.execute_reply.started":"2022-02-04T21:58:34.239445Z","shell.execute_reply":"2022-02-04T21:58:35.827331Z"},"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-02-04T21:58:35.830023Z","iopub.execute_input":"2022-02-04T21:58:35.830524Z","iopub.status.idle":"2022-02-04T21:58:36.389015Z","shell.execute_reply.started":"2022-02-04T21:58:35.830486Z","shell.execute_reply":"2022-02-04T21:58:36.388357Z"},"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\n\ntest_transforms = transforms.Compose([\n        transforms.Resize(128),\n        transforms.CenterCrop(112),\n        transforms.ToTensor()])","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:36.393351Z","iopub.execute_input":"2022-02-04T21:58:36.393599Z","iopub.status.idle":"2022-02-04T21:58:37.039097Z","shell.execute_reply.started":"2022-02-04T21:58:36.393565Z","shell.execute_reply":"2022-02-04T21:58:37.038366Z"},"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-02-04T21:58:37.042170Z","iopub.execute_input":"2022-02-04T21:58:37.042394Z","iopub.status.idle":"2022-02-04T21:58:37.756832Z","shell.execute_reply.started":"2022-02-04T21:58:37.042367Z","shell.execute_reply":"2022-02-04T21:58:37.756136Z"},"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-02-04T21:58:37.759915Z","iopub.execute_input":"2022-02-04T21:58:37.760114Z","iopub.status.idle":"2022-02-04T21:58:39.322718Z","shell.execute_reply.started":"2022-02-04T21:58:37.760090Z","shell.execute_reply":"2022-02-04T21:58:39.322020Z"},"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\nEPOCHS = 80\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)\n\n\ntrainSteps = len(train_loader.dataset) // BATCH_SIZE\nvalSteps = len(valid_loader.dataset) // BATCH_SIZE","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:39.324142Z","iopub.execute_input":"2022-02-04T21:58:39.324399Z","iopub.status.idle":"2022-02-04T21:58:39.898734Z","shell.execute_reply.started":"2022-02-04T21:58:39.324363Z","shell.execute_reply":"2022-02-04T21:58:39.897867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Covolution Model","metadata":{}},{"cell_type":"code","source":"numChannels = 3\nclasses = 1\n\nclass Net(nn.Module):\n    def __init__(self, numChannels, classes):\n        # call the parent constructor\n        super(Net, self).__init__()\n        # initialize first set of CONV => RELU => POOL layers\n        self.conv1 = nn.Conv2d(in_channels=numChannels, out_channels=20,\n            kernel_size=(5, 5))\n        self.relu1 = nn.ReLU()\n        self.maxpool1 = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2))\n        # initialize second set of CONV => RELU => POOL layers\n        self.conv2 = nn.Conv2d(in_channels=20, out_channels=50,\n            kernel_size=(5, 5))\n        self.relu2 = nn.ReLU()\n        self.maxpool2 = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2))\n        # initialize first (and only) set of FC => RELU layers\n        self.fc1 = nn.Linear(in_features=31250, out_features=500)\n        self.relu3 = nn.ReLU()\n        # initialize our softmax classifier\n        self.fc2 = nn.Linear(in_features=500, out_features=classes)\n        #self.logSoftmax = nn.LogSoftmax(dim=1)\n        \n    def forward(self, x):\n        # pass the input through our first set of CONV => RELU =>\n        # POOL layers\n        x = self.conv1(x)\n        x = self.relu1(x)\n        x = self.maxpool1(x)\n        # pass the output from the previous layer through the second\n        # set of CONV => RELU => POOL layers\n        x = self.conv2(x)\n        x = self.relu2(x)\n        x = self.maxpool2(x)\n        # flatten the output from the previous layer and pass it\n        # through our only set of FC => RELU layers\n        x = flatten(x, 1)\n        #print(x.shape)\n        x = self.fc1(x)\n        x = self.relu3(x)\n        # pass the output to our softmax classifier to get our output\n        # predictions\n        x = self.fc2(x)\n        output = x #self.logSoftmax(x)\n        # return the output predictions\n        return output\n    \nprint(\"[INFO] initializing the Net model...\")\nmodel = Net(3,1).cuda()    ","metadata":{"_kg_hide-output":false,"execution":{"iopub.status.busy":"2022-02-04T21:58:39.900364Z","iopub.execute_input":"2022-02-04T21:58:39.902152Z","iopub.status.idle":"2022-02-04T21:58:43.600703Z","shell.execute_reply.started":"2022-02-04T21:58:39.902112Z","shell.execute_reply":"2022-02-04T21:58:43.599991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lossFn = nn.BCEWithLogitsLoss() #nn.BCELoss()\nopt = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:43.601822Z","iopub.execute_input":"2022-02-04T21:58:43.602064Z","iopub.status.idle":"2022-02-04T21:58:44.262028Z","shell.execute_reply.started":"2022-02-04T21:58:43.602030Z","shell.execute_reply":"2022-02-04T21:58:44.261357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# initialize a dictionary to store training history\nH = {\n\t\"train_loss\": [],\n\t\"train_acc\": [],\n\t\"val_loss\": [],\n\t\"val_acc\": []\n}","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:44.263281Z","iopub.execute_input":"2022-02-04T21:58:44.263554Z","iopub.status.idle":"2022-02-04T21:58:44.841810Z","shell.execute_reply.started":"2022-02-04T21:58:44.263518Z","shell.execute_reply":"2022-02-04T21:58:44.841096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# set the device we will be using to train the model\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:44.844817Z","iopub.execute_input":"2022-02-04T21:58:44.845026Z","iopub.status.idle":"2022-02-04T21:58:45.386709Z","shell.execute_reply.started":"2022-02-04T21:58:44.845000Z","shell.execute_reply":"2022-02-04T21:58:45.385975Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loop over our epochs\nfor e in range(0, EPOCHS):\n    # set the model in training mode\n    model.train()\n    # initialize the total training and validation loss\n    totalTrainLoss = 0\n    totalValLoss = 0\n    # initialize the number of correct predictions in the training\n    # and validation step\n    trainCorrect = 0\n    valCorrect = 0\n    # loop over the training set\n    for (x, y) in train_loader:\n        # send the input to the device\n        (x, y) = (x.to(device), y.to(device))\n        # perform a forward pass and calculate the training loss\n        pred = model(x)\n        y = y.unsqueeze(1).float()\n        loss = lossFn(pred, y)\n        # zero out the gradients, perform the backpropagation step,\n        # and update the weights\n        opt.zero_grad()\n        loss.backward()\n        opt.step()\n        # add the loss to the total training loss so far and\n        # calculate the number of correct predictions\n        totalTrainLoss += loss\n        trainCorrect += (pred.argmax(1) == y).type(\n            torch.float).sum().item()\n        \n        # switch off autograd for evaluation\n    with torch.no_grad():\n        # set the model in evaluation mode\n        model.eval()\n        # loop over the validation set\n        for (x, y) in valid_loader:\n            # send the input to the device\n            (x, y) = (x.to(device), y.to(device))\n            # make the predictions and calculate the validation loss\n            pred = model(x)\n            y = y.unsqueeze(1).float()\n            totalValLoss += lossFn(pred, y)\n            # calculate the number of correct predictions\n            valCorrect += (pred.argmax(1) == y).type(\n                torch.float).sum().item()\n            \n            # calculate the average training and validation loss\n    avgTrainLoss = totalTrainLoss / trainSteps\n    avgValLoss = totalValLoss / valSteps\n    # calculate the training and validation accuracy\n    trainCorrect = trainCorrect / len(train_loader.dataset)\n    valCorrect = valCorrect / len(valid_loader.dataset)\n    # update our training history\n    H[\"train_loss\"].append(avgTrainLoss.cpu().detach().numpy())\n    H[\"train_acc\"].append(trainCorrect)\n    H[\"val_loss\"].append(avgValLoss.cpu().detach().numpy())\n    H[\"val_acc\"].append(valCorrect)\n    # print the model training and validation information\n    print(\"[INFO] EPOCH: {}/{}\".format(e + 1, EPOCHS))\n    print(\"Train loss: {:.6f}, Train accuracy: {:.4f}\".format(\n        avgTrainLoss, trainCorrect))\n    print(\"Val loss: {:.6f}, Val accuracy: {:.4f}\\n\".format(\n        avgValLoss, valCorrect))\n    wandb.log({'num_epochs': EPOCHS, 'training_loss': avgTrainLoss,'Train acccuracy': trainCorrect, 'validation_loss': avgValLoss, 'Validation acccuracy': valCorrect})\n    \n    # SAVE THE MODEL\n    torch.save(model.state_dict(), 'my_model.pt')","metadata":{"execution":{"iopub.status.busy":"2022-02-04T21:58:45.388734Z","iopub.execute_input":"2022-02-04T21:58:45.388938Z","iopub.status.idle":"2022-02-05T00:08:58.802093Z","shell.execute_reply.started":"2022-02-04T21:58:45.388912Z","shell.execute_reply":"2022-02-05T00:08:58.801378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# we can now evaluate the network on the test set\nprint(\"[INFO] evaluating network...\")\ntestCorrect = 0\n# turn off autograd for testing evaluation\nwith torch.no_grad():\n    # set the model in evaluation mode\n    model.eval()\n    \n    # initialize a list to store our predictions\n    preds = []\n    y_true = []\n    preds2 = []\n    # loop over the test set\n    for (x, y) in test_loader:\n        # send the input to the device\n        # send the input to the device\n            (x, y) = (x.to(device), y.to(device))\n            # make the predictions and calculate the validation loss\n            pred = model(x)\n            y = y.unsqueeze(1).float()\n            # calculate the number of correct predictions\n            testCorrect += (pred.argmax(1) == y).type(\n                torch.float).sum().item()\n# generate a classification report\n#print(classification_report(y_true,preds2))\ntestCorrect = testCorrect / len(test_loader.dataset)\nprint(\"Test accuracy: {:.4f}\\n\".format(testCorrect))","metadata":{"execution":{"iopub.status.busy":"2022-02-05T01:00:46.966990Z","iopub.execute_input":"2022-02-05T01:00:46.967236Z","iopub.status.idle":"2022-02-05T01:01:31.012346Z","shell.execute_reply.started":"2022-02-05T01:00:46.967208Z","shell.execute_reply":"2022-02-05T01:01:31.011645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot the training loss and accuracy\nplt.style.use(\"ggplot\")\nplt.figure()\nplt.plot(H[\"train_loss\"], label=\"train_loss\")\nplt.plot(H[\"val_loss\"], label=\"val_loss\")\nplt.plot(H[\"train_acc\"], label=\"train_acc\")\nplt.plot(H[\"val_acc\"], label=\"val_acc\")\nplt.title(\"Training Loss and Accuracy on Dataset\")\nplt.xlabel(\"Epoch #\")\nplt.ylabel(\"Loss/Accuracy\")\nplt.legend(loc=\"lower left\")\n#plt.savefig(args[\"plot\"])\n# serialize the model to disk\n#torch.save(model, args[\"model\"])\nplt.imshow()","metadata":{"execution":{"iopub.status.busy":"2022-02-05T00:37:47.776680Z","iopub.execute_input":"2022-02-05T00:37:47.776966Z","iopub.status.idle":"2022-02-05T00:37:48.468944Z","shell.execute_reply.started":"2022-02-05T00:37:47.776933Z","shell.execute_reply":"2022-02-05T00:37:48.466197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}