{"cells":[{"metadata":{},"cell_type":"markdown","source":"### THIS NOTEBOOK CLASSIFIES THE DIFFERENT IMAGES OF DOGS AND CATS USING RESNET34 ARCHITECTURE."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import zipfile\n\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/train.zip\",\"r\") as zip_ref:\n    zip_ref.extractall(\"./\")\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/test1.zip\",\"r\") as zip_ref:\n    zip_ref.extractall(\"./\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport torch\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport pandas as pd\nimport numpy as np\nimport cv2\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import train_test_split\nfrom torchvision import models","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# CREATE DATAFRAME\ncategories = []\nfiles = []\nl = []\nfor image in os.listdir('./train'):\n    ct = image.split('.')[0]\n    categories.append(ct)\n    files.append(image)\n    if ct == 'dog':\n        l.append(0)\n    else:\n        l.append(1)\n    \ndataframe = pd.DataFrame({'filename':files, 'category':categories, 'encoded_category':l})\ndataframe","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.countplot(dataframe.category)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# VISUALIZE \nplt.figure(figsize=(10,10))\nfor i in range(6):\n    plt.subplot(2,3, i+1)\n    plt.imshow(read_image(dataframe.filename.values[i]))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# CREATE DATASETS AND DATALOADER\n\ndef read_image(filename):\n    return cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2RGB)\n\ndef scale_image(image):\n    return image/255.0\n\ndef resize_image(image):\n    return cv2.resize(image, (300, 300))\n    \ndef normalize_image(image):\n    means = [0.485, 0.456, 0.406]\n    stds = [0.229, 0.224, 0.225]\n    image = (image - means)/stds\n    return image\n\nclass dog_cat_dataset(torch.utils.data.Dataset):    \n    def __init__(self, filename, category, train=False):\n        if train == True:\n            filename = './train/'+ filename\n        else:\n            filename = './test1/'+ filename\n            \n        self.filename = filename\n        self.category = category\n        \n    def __len__(self):\n        return len(self.category)\n    \n    def __getitem__(self, index):\n        x = read_image(self.filename[index])\n        x = resize_image(x)\n        x = scale_image(x)\n        x = normalize_image(x)\n        x = np.rollaxis(x, 2)\n        return x, self.category[index]\n        \n\nx_train, x_val, y_train, y_val = train_test_split(dataframe.filename, dataframe.encoded_category, test_size=0.2, random_state=42)\n\ndevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\n\ntrain_ds = dog_cat_dataset(x_train.reset_index(drop=True), y_train.reset_index(drop=True), train=True)\nvalid_ds = dog_cat_dataset(x_val.reset_index(drop=True), y_val.reset_index(drop=True), train=True)\n\nBATCH = 64\ntrain_dl = torch.utils.data.DataLoader(train_ds, batch_size=BATCH, shuffle=True)\nvalid_dl =  torch.utils.data.DataLoader(valid_ds, batch_size=BATCH)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class ResNetModel(torch.nn.Module):\n    def __init__(self):\n        super(ResNetModel, self).__init__()\n        resnet = models.resnet34(pretrained=True)\n        inputs = resnet.fc.in_features\n        layers = list(resnet.children())[:8]\n        self.feature1 = torch.nn.Sequential(*layers[:6])\n        self.feature2 = torch.nn.Sequential(*layers[6:])\n        self.classifier = torch.nn.Sequential(torch.nn.BatchNorm1d(inputs), torch.nn.Linear(inputs, 2))\n    \n    # RESNET > RELU > POOLING > FLATTEN > BATCHNORM > LINEAR > SOFTMAX\n    def forward(self, x):\n        x = self.feature1(x)\n        x = self.feature2(x)\n        x = torch.nn.functional.relu(x)\n        x = torch.nn.AdaptiveAvgPool2d((1,1))(x)\n        x = x.view(x.shape[0], -1)\n        out_class = self.classifier(x)\n        return torch.nn.functional.softmax(out_class, dim=1)\n\ndef train_model(model, optimizer, train_dl, valid_dl, epochs):\n    model.train()\n    for i in range(epochs):\n        total = 0\n        sum_loss = 0\n        \n        for x, y in train_dl:\n            x = x.to(device).float()\n            y = y.to(device)\n            \n            # FORWARD PASS\n            out_class = model(x)\n            # CALCULATE LOSS\n            loss = torch.nn.functional.cross_entropy(out_class, y, reduction='sum')\n            # INITIALIZE THE GRADIENTS\n            optimizer.zero_grad()\n            # BACKPROPAGATE THE LOSS\n            loss.backward()\n            # UPDATE THE WEIGHTS\n            optimizer.step()\n            \n            total += y.shape[0]\n            sum_loss += loss.item()\n            \n        train_loss = sum_loss / total\n        val_loss, val_acc = validation_model(model, valid_dl)\n        print(' EPOCH {} train_loss {:.3f} val_loss {:.3f} val_acc {:.3f}'.format(i, train_loss, val_loss, val_acc))\n    return sum_loss/total\n        \ndef validation_model(model, valid_dl):\n    model.eval()\n    total = 0\n    sum_loss = 0\n    correct = 0\n    for x, y in valid_dl:\n        x = x.to(device).float()\n        y = y.to(device)\n        batch = y.shape[0]\n        out_class = model(x)\n        loss = torch.nn.functional.cross_entropy(out_class, y)\n        \n        _, index = torch.max(out_class, 1)\n        correct += index.eq(y).sum().item()\n        sum_loss += loss.item()\n        total += batch\n        \n    return sum_loss/total, correct/total","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = ResNetModel().to(device)\noptimizer = torch.optim.Adam(model.parameters(), lr=0.001)\ntrain_model(model, optimizer, train_dl, valid_dl, 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"t = []\nfor i in os.listdir('./test1'):\n    t.append(i)\n    \ntest_ds = pd.DataFrame({'filename':t, 'label':pd.Series(np.zeros(len(t)))})\ntest_ds.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data = dog_cat_dataset(test_ds.filename, test_ds.label)\nanimal = {0:'dog', 1:'cat'}\n\ndef inference_code(index):\n    image, *_ = test_data[index]\n    image = torch.FloatTensor(image[None, ])\n    out_class = model(image.to(device))\n    y_class = out_class.cpu().data.numpy().argmax()\n    confidence = out_class.cpu().data.numpy()[0][y_class]\n    return animal[y_class], confidence","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(test_data)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### FIRST 30 IMAGES"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(20, 20))\nplt.rc('font', size=14)\nfor i in range(30):\n    plt.subplot(6, 5, i+1)\n    y_class, conf = inference_code(i)\n    image = read_image('./test1/'+test_ds.filename.values[i])\n    plt.imshow(image)\n    plt.xlabel('predicted : {}'.format(y_class))\n    \nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### NEXT 30 IMAGES"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(20, 20))\nplt.rc('font', size=14)\nfor i in range(30, 60, 1):\n    j = i-30\n    plt.subplot(6, 5, j+1)\n    y_class, conf = inference_code(i)\n    image = read_image('./test1/'+test_ds.filename.values[i])\n    plt.imshow(image)\n    plt.xlabel('predicted : {}'.format(y_class))\n    \nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### NEXT 30 IMAGES"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(20, 20))\nplt.rc('font', size=14)\nfor i in range(60, 90, 1):\n    j = i-60\n    plt.subplot(6, 5, j+1)\n    y_class, conf = inference_code(i)\n    image = read_image('./test1/'+test_ds.filename.values[i])\n    plt.imshow(image)\n    plt.xlabel('predicted : {}'.format(y_class))\n    \nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"It gives pretty good results in just 1 epoch."}],"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":4,"nbformat_minor":4}