{"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-03-14T22:31:51.284878Z","iopub.execute_input":"2022-03-14T22:31:51.285533Z","iopub.status.idle":"2022-03-14T22:31:51.312401Z","shell.execute_reply.started":"2022-03-14T22:31:51.285425Z","shell.execute_reply":"2022-03-14T22:31:51.311771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Standard library\nimport copy\nimport glob\nimport multiprocessing\nimport os\nimport time\nimport zipfile\n\n# Pytorch\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import models, transforms\n\n# Related third party\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nfrom skimage import io, transform\nfrom sklearn.model_selection import train_test_split\nfrom tqdm.notebook import tqdm\n","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:41:46.334169Z","iopub.execute_input":"2022-03-03T05:41:46.334673Z","iopub.status.idle":"2022-03-03T05:41:46.342598Z","shell.execute_reply.started":"2022-03-03T05:41:46.334625Z","shell.execute_reply":"2022-03-03T05:41:46.341683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocess data","metadata":{}},{"cell_type":"code","source":"base_dir = '../input/dogs-vs-cats-redux-kernels-edition'\nwith zipfile.ZipFile(os.path.join(base_dir, 'train.zip')) as train_zip:\n    train_zip.extractall('../data')\nwith zipfile.ZipFile(os.path.join(base_dir, 'test.zip')) as test_zip:\n    test_zip.extractall('../data')\n\ntrain_dir = '../data/train'\ntest_dir = '../data/test'","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:26:37.835753Z","iopub.execute_input":"2022-03-03T05:26:37.83603Z","iopub.status.idle":"2022-03-03T05:27:00.518542Z","shell.execute_reply.started":"2022-03-03T05:26:37.836002Z","shell.execute_reply":"2022-03-03T05:27:00.51762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_size = 224\nmean = [0.485, 0.456, 0.406]\nstd = [0.229, 0.224, 0.225]\n\n# Number of classes in the dataset\nnum_classes = 2 # dog, cat\n\n# Batch size for training (change depending on how much memory you have)\nbatch_size = 32\n\n# Number of epochs to train for\nnum_epochs = 2\n\n# Flag for feature extracting. When False, we finetune the whole model,\n#   when True we only update the reshaped layer params\nfeature_extract = True\n\n# Switch to perform multi-process data loading\nnum_workers = multiprocessing.cpu_count()","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:23:52.211377Z","iopub.execute_input":"2022-03-03T05:23:52.21169Z","iopub.status.idle":"2022-03-03T05:23:52.217894Z","shell.execute_reply.started":"2022-03-03T05:23:52.211658Z","shell.execute_reply":"2022-03-03T05:23:52.21712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, dataloaders, criterion, optimizer, num_epochs=25):\n    since = time.time()\n\n    history = {'accuracy': [],\n               'val_accuracy': [],\n               'loss': [],\n               'val_loss': []}\n\n    best_model_wts = copy.deepcopy(model.state_dict())\n    best_acc = 0.0\n\n    for epoch in range(num_epochs):\n        print('Epoch {}/{}'.format(epoch, num_epochs - 1))\n        print('-' * 10)\n\n        # Each epoch has a training and validation phase\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()  # Set model to training mode\n            else:\n                model.eval()   # Set model to evaluate mode\n\n            running_loss = 0.0\n            running_corrects = 0\n\n            # Iterate over data.\n            for inputs, labels in tqdm(dataloaders[phase]):\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n\n                # zero the parameter gradients\n                optimizer.zero_grad()\n\n                # forward\n                # track history if only in train\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = model(inputs)\n                    loss = criterion(outputs, labels)\n\n                    _, preds = torch.max(outputs, 1)\n\n                    # backward + optimize only if in training phase\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n\n                # statistics\n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += torch.sum(preds == labels.data)\n\n            epoch_loss = running_loss / len(dataloaders[phase].dataset)\n            epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset)\n\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))\n\n            # deep copy the model\n            if phase == 'val' and epoch_acc > best_acc:\n                best_acc = epoch_acc\n                best_model_wts = copy.deepcopy(model.state_dict())\n\n            if phase == 'train':\n                history['accuracy'].append(epoch_acc.item())\n                history['loss'].append(epoch_loss)\n            else:\n                history['val_accuracy'].append(epoch_acc.item())\n                history['val_loss'].append(epoch_loss) \n\n        print()\n\n    time_elapsed = time.time() - since\n    print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))\n    print('Best val Acc: {:4f}'.format(best_acc))\n\n    # load best model weights\n    model.load_state_dict(best_model_wts)\n    return model, history","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train data file looks './train/dog.10435.jpg'\n# test data file looks './test/10435.jpg'\ndef extract_class_from(path):\n    file = path.split('/')[-1]\n    return file.split('.')[0]","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:23:34.71523Z","iopub.execute_input":"2022-03-03T05:23:34.715864Z","iopub.status.idle":"2022-03-03T05:23:34.746008Z","shell.execute_reply.started":"2022-03-03T05:23:34.715729Z","shell.execute_reply":"2022-03-03T05:23:34.745058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_train_files = glob.glob(os.path.join(train_dir, '*.jpg'))\ntrain_list, val_list = train_test_split(all_train_files, random_state=42)\nfig, axes = plt.subplots(nrows=2,\n                         ncols=3,\n                         figsize=(18, 12))\nfor img_path, ax in zip(train_list, axes.ravel()):\n    ax.set_title(img_path)\n    ax.imshow(Image.open(img_path))","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:27:10.316366Z","iopub.execute_input":"2022-03-03T05:27:10.317644Z","iopub.status.idle":"2022-03-03T05:27:11.88835Z","shell.execute_reply.started":"2022-03-03T05:27:10.317573Z","shell.execute_reply":"2022-03-03T05:27:11.887411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset Class","metadata":{}},{"cell_type":"code","source":"class DogVsCatDataset(Dataset):\n  \n    def __init__(self, file_list, transform=None):\n        self.file_list = file_list\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.file_list)\n  \n    def __getitem__(self, idx):\n        if torch.is_tensor(idx):\n            idx = idx.tolist()\n       \n        img_name = self.file_list[idx]\n        image = Image.open(img_name)\n        if self.transform:\n            image = self.transform(image)\n    \n        label_category = extract_class_from(img_name)\n        label = 1 if label_category == 'dog' else 0\n    \n        return image, label","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:27:34.726065Z","iopub.execute_input":"2022-03-03T05:27:34.726361Z","iopub.status.idle":"2022-03-03T05:27:34.735673Z","shell.execute_reply.started":"2022-03-03T05:27:34.726333Z","shell.execute_reply":"2022-03-03T05:27:34.734573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transform = transforms.Compose([\n        transforms.RandomResizedCrop(input_size, scale=(0.5, 1.0)),\n        transforms.RandomHorizontalFlip(),\n        transforms.ToTensor(),\n        transforms.Normalize(mean, std)\n    ])\nval_transform = transforms.Compose([\n        transforms.Resize(input_size),\n        transforms.CenterCrop(input_size),\n        transforms.ToTensor(),\n        transforms.Normalize(mean, std)\n    ])","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:41:34.59393Z","iopub.execute_input":"2022-03-03T05:41:34.594569Z","iopub.status.idle":"2022-03-03T05:41:34.60223Z","shell.execute_reply.started":"2022-03-03T05:41:34.594507Z","shell.execute_reply":"2022-03-03T05:41:34.60095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create training and validation datasets\nimage_datasets = {\n    'train': DogVsCatDataset(train_list,\n                             transform=train_transform),\n    'val': DogVsCatDataset(val_list,\n                           transform=val_transform)\n}\n\n#train_datasets = DogVsCatDataset(train_list, transform=train_transform)\n#val_datasets = DogVsCatDataset(val_list, transform=val_transform)\n\n# Create training and validation dataloaders\ndataloaders_dict = {x: DataLoader(image_datasets[x],\n                                  batch_size=batch_size,\n                                  shuffle=True,\n                                  num_workers=num_workers) for x in ['train', 'val']}\n\n\n#train_loader = DataLoader()\n# Detect if we have a GPU available\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:43:02.855064Z","iopub.execute_input":"2022-03-03T05:43:02.855777Z","iopub.status.idle":"2022-03-03T05:43:02.864587Z","shell.execute_reply.started":"2022-03-03T05:43:02.855727Z","shell.execute_reply":"2022-03-03T05:43:02.863599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_ft = models.vgg19(pretrained=True)\nmodel_ft.classifier[1] = nn.Linear(1280, num_classes)","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:47:31.192106Z","iopub.execute_input":"2022-03-03T05:47:31.192381Z","iopub.status.idle":"2022-03-03T05:47:33.049542Z","shell.execute_reply.started":"2022-03-03T05:47:31.192352Z","shell.execute_reply":"2022-03-03T05:47:33.048576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_ft = model_ft.to(device)\nparams_to_update = model_ft.parameters()\noptimizer_ft = optim.SGD(params_to_update, lr=0.001, momentum=0.9)","metadata":{"execution":{"iopub.status.busy":"2022-03-03T05:48:12.934282Z","iopub.execute_input":"2022-03-03T05:48:12.934932Z","iopub.status.idle":"2022-03-03T05:48:12.949446Z","shell.execute_reply.started":"2022-03-03T05:48:12.934883Z","shell.execute_reply":"2022-03-03T05:48:12.948647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Setup the loss fxn\ncriterion = nn.CrossEntropyLoss()\n\n# Train and evaluate\nmodel_ft, hist = train_model(model_ft, dataloaders_dict, criterion, optimizer_ft, num_epochs=num_epochs)","metadata":{},"execution_count":null,"outputs":[]}]}