{"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":"#Imports\nimport os\nimport sys\nimport glob\nimport torch\nimport torchvision\n\nimport numpy    as np\nimport datetime as dt\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport matplotlib.pyplot   as plt\n\nfrom PIL               import Image\nfrom torch.utils.data  import Dataset\nfrom torch.autograd    import Variable\nfrom torch.optim       import lr_scheduler\n\nfrom torch.utils.data  import Dataset, DataLoader\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom torchvision       import transforms, datasets, models\nfrom os                import listdir, makedirs, getcwd, remove\nfrom os.path           import isfile, join, abspath, exists, isdir, expanduser\n\n\n%matplotlib inline","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_path = \"../input/ammi-2021-convnets/\"\ntrain_path = join(data_path, \"train/train\")\ntest_path = join(data_path,\"test/test\")\nextraimage_path = join(data_path, \"extraimages/extraimages\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Transformations for both the training and testing data\nmean=[0.485, 0.456, 0.406]\nstd=[0.229, 0.224, 0.225]\n\n# Do data transforms here, Try many others\ntrain_transforms = transforms.Compose([transforms.RandomRotation(30),\n                                       transforms.RandomResizedCrop(224),\n                                       transforms.RandomHorizontalFlip(),\n                                       transforms.ToTensor()])\n\ntest_transforms = transforms.Compose([ transforms.Resize(255),\n                                       transforms.CenterCrop(224),\n                                       transforms.ToTensor()])\n\nnormalize = transforms.Normalize(mean=mean, std=std)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CassavaDataset(Dataset):\n    def __init__(self, path, transform=None):\n        self.classes = os.listdir(path)\n        self.path = [f\"{path}/{className}\" for className in self.classes]\n        self.file_list = [glob.glob(f\"{x}/*\") for x in self.path]\n        self.transform = transform\n\n        files = []\n        for i, className in enumerate(self.classes):\n            for fileName in self.file_list[i]:\n                files.append([i, className, fileName])\n        self.file_list = files\n        files = None\n\n    def __len__(self):\n        return len(self.file_list)\n\n    def __getitem__(self, idx):\n        fileName = self.file_list[idx][2]\n        classCategory = self.file_list[idx][0]\n        im = Image.open(fileName)\n        if self.transform:\n            im = self.transform(im)\n            \n        return im.view(3, 224, 224), classCategory","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = CassavaDataset(train_path, transform=train_transforms)\ntest_data = CassavaDataset(test_path, transform=test_transforms)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_split = .2\nshuffle_dataset = True\nrandom_seed= 42\n\n# Creating data indices for training and validation splits:\ndataset_size = len(train_data)\nindices = list(range(dataset_size))\nsplit = int(np.floor(validation_split * dataset_size))\n\nif shuffle_dataset :\n    np.random.seed(random_seed)\n    np.random.shuffle(indices)\n\ntrain_indices, val_indices = indices[split:], indices[:split]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Creating PT data samplers and loaders:\ntrain_sampler = SubsetRandomSampler(train_indices)\nvalid_sampler = SubsetRandomSampler(val_indices)\n\n\ntrain_loader = torch.utils.data.DataLoader(train_data, batch_size=32,\n                                             sampler=train_sampler)\nvalid_loader = torch.utils.data.DataLoader(train_data, batch_size=32,\n                                             sampler=valid_sampler)\ntest_loader = torch.utils.data.DataLoader(test_data, batch_size=32)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Device configuration\ndevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define Models \n\nclass Classifier(nn.Module):\n    def __init__(self, num_classes):\n        super(Classifier, self).__init__()\n        # Block 1\n        self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 32, kernel_size = 5, stride = 2, padding = 1)\n        self.relu1 = nn.ReLU()\n        self.maxpool1 = nn.MaxPool2d(kernel_size = 2)\n\n        #Block 2\n        self.conv2 = nn.Conv2d(in_channels = 32, out_channels = 64, kernel_size = 5, stride = 2)\n        self.relu2 = nn.ReLU()\n        self.maxpool2 = nn.MaxPool2d(kernel_size=2)\n\n        #Block 3\n        self.conv3 = nn.Conv2d(in_channels = 64, out_channels = 32, kernel_size = 3, stride = 2)\n        self.relu3 = nn.ReLU()\n        self.maxpool3 = nn.MaxPool2d(kernel_size=2)\n\n        # last fully-connected layer\n        self.fc = nn.Linear(32*3*3, num_classes)\n\n\n    def forward(self, input):\n\n        x = self.maxpool1(self.relu1(self.conv1(input)))\n        x = self.maxpool2(self.relu2(self.conv2(x)))\n        x = self.maxpool3(self.relu3(self.conv3(x)))\n\n        x = x.view(x.size(0), -1)\n        x = self.fc(x)\n        return x\n\n\nmodel = Classifier(5)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = torch.nn.CrossEntropyLoss()\noptimizer = torch.optim.SGD(model.parameters(), lr=1e-2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(model, criterion, data_loader, optimizer, num_epochs):\n    \"\"\"Simple training loop for a PyTorch model.\"\"\" \n    \n    # Make sure model is in training mode.\n    model.train()\n    \n    # Move model to the device (CPU or GPU).\n    model.to(device)\n    \n    # Exponential moving average of the loss.\n    ema_loss = None\n\n    print('----- Training Loop -----')\n    # Loop over epochs.\n    for epoch in range(num_epochs):\n        \n      # Loop over data.\n      for batch_idx, (features, target) in enumerate(data_loader):\n            \n          # Forward pass.\n        output = model(features.to(device))\n        loss = criterion(output.to(device), target.to(device))\n\n          # Backward pass.\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n      # NOTE: It is important to call .item() on the loss before summing.\n        if ema_loss is None:\n            ema_loss = loss.item()\n        else:\n            ema_loss += (loss.item() - ema_loss) * 0.01 \n\n      # Print out progress the end of epoch.\n      print('Epoch: {} \\tLoss: {:.6f}'.format(epoch, ema_loss),)\n  ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test(model, data_loader):\n    \"\"\"Measures the accuracy of a model on a data set.\"\"\" \n    # Make sure the model is in evaluation mode.\n    model.eval()\n    correct = 0\n    print('----- Model Evaluation -----')\n    # We do not need to maintain intermediate activations while testing.\n    with torch.no_grad():\n        \n        # Loop over test data.\n        for features, target in data_loader:\n          \n            # Forward pass.\n            output = model(features.to(device))\n            \n            # Get the label corresponding to the highest predicted probability.\n            pred = output.argmax(dim=1, keepdim=True)\n            \n            # Count number of correct predictions.\n            correct += pred.cpu().eq(target.view_as(pred)).sum().item()\n\n    # Print test accuracy.\n    percent = 100. * correct / len(data_loader.dataset)\n    print(f'Test accuracy: {correct} / {len(data_loader.dataset)} ({percent:.0f}%)')\n    torch.save(model.state_dict(), 'model.ckpt')\n    return percent","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epochs = 5\ntrain(model, criterion, train_loader, optimizer, num_epochs=num_epochs)\ntest(model, valid_loader)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test(model, test_loader)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make submission here","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}