{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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 in \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 \"../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# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\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\nfrom PIL import Image\nfrom collections import OrderedDict\n\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Download the pretrained model"},{"metadata":{"trusted":true},"cell_type":"code","source":"import torchvision.models as models\nmodel = models.googlenet(pretrained = True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Switch device to gpu if available"},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nprint('Device:', torch.cuda.get_device_name(torch.cuda.current_device()))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Freeze model's parameters "},{"metadata":{"trusted":true},"cell_type":"code","source":"for param in model.parameters():\n    param.requires_grad = False ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Upgrading model."},{"metadata":{"trusted":true},"cell_type":"code","source":"model.fc = nn.Sequential(OrderedDict([\n    ('fc1', nn.Linear(1024,512)),\n    ('relu', nn.ReLU()),\n    ('fc2', nn.Linear(512,2)),\n    ('output', nn.LogSoftmax(dim = 1))\n    ]))\nmodel #model structure ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I'm using .ImageFolder() as dataloader for train."},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_data(data_folder, batch_size, num_workers):\n    transform = transforms.Compose([\n        transforms.Resize(256),\n        transforms.ColorJitter(),\n        transforms.RandomCrop(224),\n        transforms.RandomHorizontalFlip(),\n        transforms.Resize(128),\n        transforms.ToTensor()\n    ])\n    \n    data = torchvision.datasets.ImageFolder(root = data_folder, transform = transform)\n    data_loader = torch.utils.data.DataLoader(data, batch_size=batch_size, shuffle=True, num_workers = num_workers)\n    return data_loader ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The code i used to prepare data for .ImageFolder() on kaggle, started here..."},{"metadata":{"trusted":true},"cell_type":"code","source":"import zipfile\nos.chdir('/kaggle/working/')\nfile_list = ['/kaggle/input/dogs-vs-cats/train.zip','/kaggle/input/dogs-vs-cats/test1.zip']\n\nfor file in file_list:\n    zip_ref = zipfile.ZipFile(file, 'r')\n    zip_ref.extractall()\n    zip_ref.close()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.mkdir('/kaggle/working/train/dog')\nos.mkdir('/kaggle/working/train/cat')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import shutil\n\ncategory = []\nfilenames = os.listdir('/kaggle/working/train/')\nod = '/kaggle/working/train/'\nfor file in filenames:\n    if os.path.isdir(od + file) == False:\n        category = file.split('.')[0]\n        if category == 'dog':\n            shutil.move('/kaggle/working/train/' + file, '/kaggle/working/train/dog/' + file)\n        else:\n            shutil.move('/kaggle/working/train/' + file, '/kaggle/working/train/cat/' + file)\n    else: pass","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"... and it ended."},{"metadata":{},"cell_type":"markdown","source":"Loading train data to the model"},{"metadata":{"trusted":true},"cell_type":"code","source":"data_folder = '/kaggle/working/train/'\nbatch_size = 32\nnum_workers = 0\ndataloader = load_data(data_folder, batch_size, num_workers)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"samples, labels = iter(dataloader).next()\nplt.figure(figsize=(16,24))\ngrid_imgs = torchvision.utils.make_grid(samples[:24])\nnp_grid_imgs = grid_imgs.numpy()\n\nplt.imshow(np.transpose(np_grid_imgs, (1,2,0)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = model.to(device) #shifting model to gpu\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.fc.parameters(), lr=0.001, amsgrad=True)\nscheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[500,1000,1500], gamma=0.5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Training the model."},{"metadata":{"trusted":true},"cell_type":"code","source":"epochs = 3\nitr = 1\np_itr = 200\nmodel.train()\ntotal_loss = 0\nloss_list = []\nacc_list = []\nfor epoch in range(epochs):\n    for samples, labels in dataloader:\n        samples, labels = samples.to(device), labels.to(device)\n        optimizer.zero_grad()\n        output = model(samples)\n        \n        loss = criterion(output, labels)\n        loss.backward()\n        optimizer.step()\n        total_loss += loss.item()\n        scheduler.step() \n        \n        if itr%p_itr == 0:\n            pred = torch.argmax(output, dim=1)\n            correct = pred.eq(labels)\n            acc = torch.mean(correct.float())\n            print('[Epoch {}/{}] Iteration {} -> Train Loss: {:.4f}, Accuracy: {:.3f}'.format(epoch+1, epochs, itr, total_loss/p_itr, acc))\n            loss_list.append(total_loss/p_itr)\n            acc_list.append(acc)\n            total_loss = 0\n        \n            \n        itr += 1\n\nplt.plot(loss_list, label='loss')\nplt.plot(acc_list, label='accuracy')\nplt.legend()\nplt.title('training loss and accuracy')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Loading test data to the model"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_dir = '/kaggle/working/test1'\ntest_files = os.listdir(test_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class CatDogDataset(Dataset):\n    def __init__(self, file_list, dir, mode='train', transform = None):\n        self.file_list = file_list\n        self.dir = dir\n        self.mode= mode\n        self.transform = transform\n        if self.mode == 'train':\n            if 'dog' in self.file_list[0]:\n                self.label = 1\n            else:\n                self.label = 0\n            \n    def __len__(self):\n        return len(self.file_list)\n    \n    def __getitem__(self, idx):\n        img = Image.open(os.path.join(self.dir, self.file_list[idx]))\n        if self.transform:\n            img = self.transform(img)\n        if self.mode == 'train':\n            img = img.numpy()\n            return img.astype('float32'), self.label\n        else:\n            img = img.numpy()\n            return img.astype('float32'), self.file_list[idx]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_transform = transforms.Compose([\n    transforms.Resize((128,128)),\n    transforms.ToTensor()\n])\n\ntestset = CatDogDataset(test_files, test_dir, mode='test', transform = test_transform)\ntestloader = DataLoader(testset, batch_size = 32, shuffle = False, num_workers=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fn_list = []\npred_list = []\nfor x, fn in testloader:\n    with torch.no_grad():\n        x = x.to(device)\n        output = model(x)\n        pred = torch.argmax(output, dim=1)\n        fn_list += [n[:-4] for n in fn]\n        pred_list += [p.item() for p in pred]\n\nsubmission = pd.DataFrame({\"id\":fn_list, \"label\":pred_list})\nsubmission.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Finally testing the model."},{"metadata":{"trusted":true},"cell_type":"code","source":"samples, _ = iter(testloader).next()\nsamples = samples.to(device)\nfig = plt.figure(figsize=(24, 16))\nfig.tight_layout()\noutput = model(samples[:24])\npred = torch.argmax(output, dim=1)\npred = [p.item() for p in pred]\nad = {0:'cat', 1:'dog'}\nfor num, sample in enumerate(samples[:24]):\n    plt.subplot(4,6,num+1)\n    plt.title(ad[pred[num]])\n    plt.axis('off')\n    sample = sample.cpu().numpy()\n    plt.imshow(np.transpose(sample, (1,2,0)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"So, I training the model on my laptop at GeForce MX110 with 2 Gb VRAM (not allowed) and bath size 24.  \nI had this result:   \n> [Epoch 1/3] Iteration 200 -> Train Loss: 0.3037, Accuracy: 0.958  \n> [Epoch 1/3] Iteration 400 -> Train Loss: 0.2527, Accuracy: 0.958  \n> [Epoch 1/3] Iteration 600 -> Train Loss: 0.2506, Accuracy: 0.917  \n> [Epoch 1/3] Iteration 800 -> Train Loss: 0.2286, Accuracy: 0.917  \n> [Epoch 1/3] Iteration 1000 -> Train Loss: 0.2193, Accuracy: 0.917  \n> [Epoch 2/3] Iteration 1200 -> Train Loss: 0.2300, Accuracy: 0.792  \n> [Epoch 2/3] Iteration 1400 -> Train Loss: 0.2057, Accuracy: 0.875  \n> [Epoch 2/3] Iteration 1600 -> Train Loss: 0.2116, Accuracy: 1.000  \n> [Epoch 2/3] Iteration 1800 -> Train Loss: 0.2023, Accuracy: 0.833  \n> [Epoch 2/3] Iteration 2000 -> Train Loss: 0.2072, Accuracy: 0.875  \n> [Epoch 3/3] Iteration 2200 -> Train Loss: 0.2073, Accuracy: 0.958  \n> [Epoch 3/3] Iteration 2400 -> Train Loss: 0.2093, Accuracy: 0.917  \n> [Epoch 3/3] Iteration 2600 -> Train Loss: 0.1987, Accuracy: 0.958  \n> [Epoch 3/3] Iteration 2800 -> Train Loss: 0.2049, Accuracy: 0.958  \n> [Epoch 3/3] Iteration 3000 -> Train Loss: 0.2007, Accuracy: 0.917  "},{"metadata":{},"cell_type":"markdown","source":"Interestingly, resnet18 shows slightly better results when on the same hardware:\n> [Epoch 1/3] Iteration 200 -> Train Loss: 0.2600, Accuracy: 0.875  \n> [Epoch 1/3] Iteration 400 -> Train Loss: 0.2020, Accuracy: 0.958  \n> [Epoch 1/3] Iteration 600 -> Train Loss: 0.2050, Accuracy: 0.875  \n> [Epoch 1/3] Iteration 800 -> Train Loss: 0.1875, Accuracy: 0.875  \n> [Epoch 1/3] Iteration 1000 -> Train Loss: 0.1840, Accuracy: 0.833  \n> [Epoch 2/3] Iteration 1200 -> Train Loss: 0.1809, Accuracy: 1.000  \n> [Epoch 2/3] Iteration 1400 -> Train Loss: 0.1794, Accuracy: 0.958  \n> [Epoch 2/3] Iteration 1600 -> Train Loss: 0.1855, Accuracy: 0.958  \n> [Epoch 2/3] Iteration 1800 -> Train Loss: 0.1654, Accuracy: 0.833  \n> [Epoch 2/3] Iteration 2000 -> Train Loss: 0.1656, Accuracy: 0.833  \n> [Epoch 3/3] Iteration 2200 -> Train Loss: 0.1641, Accuracy: 0.958  \n> [Epoch 3/3] Iteration 2400 -> Train Loss: 0.1748, Accuracy: 0.917  \n> [Epoch 3/3] Iteration 2600 -> Train Loss: 0.1739, Accuracy: 0.958  \n> [Epoch 3/3] Iteration 2800 -> Train Loss: 0.1663, Accuracy: 0.958  \n> [Epoch 3/3] Iteration 3000 -> Train Loss: 0.1619, Accuracy: 0.958  "}],"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}