{"cells":[{"metadata":{},"cell_type":"markdown","source":"transforms.RandomRotation(20) -> 30\nself.pool(F.leaky_relu(self.bn5(self.conv5(x)))) -> celu"},{"metadata":{"_uuid":"8b3d80ed7ad56834d70ed4d6e012f46257579e07","trusted":true},"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfrom sklearn.model_selection import train_test_split\n\nimport torch \nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import TensorDataset, DataLoader, Dataset","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b0b625dddcf44cd8db7690bf380c6cb25f555cbd","trusted":true},"cell_type":"code","source":"## Parameters for model\n\n# Hyper parameters\nnum_epochs = 8\nnum_classes = 2\nbatch_size = 128\nlearning_rate = 0.002\n\n# Device configuration\ndevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') # gpu or cpu","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Read data"},{"metadata":{"_uuid":"08fbba4de055ecb31736a3e5358252ca8180244b","trusted":true},"cell_type":"code","source":"labels = pd.read_csv('../input/train_labels.csv')\nsub = pd.read_csv('../input/sample_submission.csv')\ntrain_path = '../input/train/'\ntest_path = '../input/test/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels.sample(5)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"16937da840e0d80e2604e0d362171796516886d3","trusted":true},"cell_type":"code","source":"#Splitting data into train and val\ntrain, val = train_test_split(labels, stratify=labels.label, test_size=0.1) \n# 10% of train data are used for validation\nlen(train), len(val)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"64e44031b4f051993af3648cdb99877563f37d6f"},"cell_type":"markdown","source":"**Simple custom generator**"},{"metadata":{"_uuid":"a5f0097544dc230bb794e75a163196f08de0c13c","trusted":true},"cell_type":"code","source":"class MyDataset(Dataset):\n    def __init__(self, df_data, data_dir = './', transform=None):\n        super().__init__()\n        self.df = df_data.values\n        self.data_dir = data_dir\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, index):\n        img_name,label = self.df[index]\n        img_path = os.path.join(self.data_dir, img_name+'.tif')\n        image = cv2.imread(img_path)\n        if self.transform is not None:\n            image = self.transform(image)\n        return image, label","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cbacdb7bcd20d414d115cde200f564934b69f308","trusted":true},"cell_type":"code","source":"# torchvision.transforms provides common image transformations\n# transforms.Compose - composes several transforms together\ntrans_train = transforms.Compose([transforms.ToPILImage(), # Convert a tensor to PIL Image (Python Imaging Library)\n                                  transforms.Pad(64, padding_mode='reflect'),\n                                  transforms.RandomHorizontalFlip(), #randomly flips\n                                  transforms.RandomVerticalFlip(), #randomly flips\n                                  transforms.RandomRotation(30), #rotates the image by angle in [1,20]\n                                  transforms.ToTensor(),\n                                  transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])])\n\ntrans_valid = transforms.Compose([transforms.ToPILImage(),\n                                  transforms.Pad(64, padding_mode='reflect'),\n                                  transforms.ToTensor(),\n                                  transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])])\n\ndataset_train = MyDataset(df_data=train, data_dir=train_path, transform=trans_train)\ndataset_valid = MyDataset(df_data=val, data_dir=train_path, transform=trans_valid)\n\n\n# DataLoader - combines a dataset and a sampler, and provides an iterable over the given dataset\n# there are 128 samples per batch to load\n# DataLoader shuffles train data every epoch and doesnt shuffle valid data\nloader_train = DataLoader(dataset = dataset_train, batch_size=batch_size, shuffle=True, num_workers=0)\nloader_valid = DataLoader(dataset = dataset_valid, batch_size=batch_size//2, shuffle=False, num_workers=0)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ac596a6914e7455f1326c01eb532d7b36b972e7f"},"cell_type":"markdown","source":"### set up the model"},{"metadata":{"_uuid":"f32c84715ab1c585a56b41fc71c05c42d55bfd4b","trusted":true},"cell_type":"code","source":"class SimpleCNN(nn.Module):  # Base class for my neural network\n    def __init__(self):\n        # ancestor constructor call\n        super(SimpleCNN, self).__init__() \n        # nn.Conv2d - applies a 2D convolution\n        # out_channels of previous layer should be equal to in_channels of current layer\n        # \n        self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=2)\n        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=2)\n        self.conv3 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=2)\n        self.conv4 = nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, padding=2)\n        self.conv5 = nn.Conv2d(in_channels=256, out_channels=512, kernel_size=3, padding=2)\n        # BatchNorm2d normalizes outputs of each layer\n        self.bn1 = nn.BatchNorm2d(32)\n        self.bn2 = nn.BatchNorm2d(64)\n        self.bn3 = nn.BatchNorm2d(128)\n        self.bn4 = nn.BatchNorm2d(256)\n        self.bn5 = nn.BatchNorm2d(512)\n        # pooling function is 2D max\n        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n        \n        self.avg = nn.AvgPool2d(8) # 2D average pooling\n        self.fc = nn.Linear(512 * 1 * 1, 2) #linear transformation to the incoming data\n\n    def forward(self, x):\n        # first convolutional layer then batchnorm, then activation then pooling layer\n        # LeakyReLU as activation function\n        x = self.pool(F.celu(self.bn1(self.conv1(x)))) \n        x = self.pool(F.celu(self.bn2(self.conv2(x))))\n        x = self.pool(F.celu(self.bn3(self.conv3(x))))\n        x = self.pool(F.celu(self.bn4(self.conv4(x))))\n        x = self.pool(F.celu(self.bn5(self.conv5(x))))\n        x = self.avg(x)\n        x = x.view(-1, 512 * 1 * 1)\n        x = self.fc(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"67522fc88f034ddb684f9fba0e154c341760d1d1","trusted":true},"cell_type":"code","source":"model = SimpleCNN().to(device)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a56a159ba70e958c82e518d718be99bd41c17299","trusted":true},"cell_type":"code","source":"# Cross-entropy as loss function\ncriterion = nn.CrossEntropyLoss()\n# AdaMax is used as gradient descent optimization algorithm\noptimizer = torch.optim.Adamax(model.parameters(), lr=learning_rate)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Train the model"},{"metadata":{"_uuid":"dca29061dd5d6a60ba95f16dbaea70e6dc822150","trusted":true},"cell_type":"code","source":"total_step = len(loader_train)\nfor epoch in range(num_epochs):\n    for i, (images, labels) in enumerate(loader_train):\n        images = images.to(device)\n        labels = labels.to(device)\n        \n        # Forward pass\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        #backpropagation method for grad calculating\n        # Backward and optimize\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        if (i+1) % 100 == 0:\n            # value of Loss function after each epochs\n            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' \n                   .format(epoch+1, num_epochs, i+1, total_step, loss.item()))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9de7463bf94c03149a7121ce2bb96dc05ecf2d7b"},"cell_type":"markdown","source":"**Accuracy Check**"},{"metadata":{"_uuid":"998c3c05a3c3fb6fc7f2523dddff50496490d051","trusted":true},"cell_type":"code","source":"# Test the model\nmodel.eval()  # eval mode (batchnorm uses moving mean/variance instead of mini-batch mean/variance)\nwith torch.no_grad():\n    correct = 0\n    total = 0\n    for images, labels in loader_valid:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = model(images)\n        _, predicted = torch.max(outputs.data, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n          \n    print('Test Accuracy of the model on the 22003 test images: {} %'.format(100 * correct / total))\n\n# Save the model checkpoint\ntorch.save(model.state_dict(), 'model.ckpt')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c1c0709b4a1e7edea538eda5168819a7b949eedf"},"cell_type":"markdown","source":"**CSV submission**"},{"metadata":{"_uuid":"4d03acf3711d8036703041276749bbaf2ef64e71","trusted":true},"cell_type":"code","source":"dataset_valid = MyDataset(df_data=sub, data_dir=test_path, transform=trans_valid)\nloader_test = DataLoader(dataset = dataset_valid, batch_size=32, shuffle=False, num_workers=0)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b85e1661e660b45486ab1b46a4d925e18f541b75","trusted":true},"cell_type":"code","source":"\nmodel.eval()\n\npreds = []\nfor batch_i, (data, target) in enumerate(loader_test):\n    data, target = data.cuda(), target.cuda()\n    output = model(data)\n\n    pr = output[:,1].detach().cpu().numpy()\n    for i in pr:\n        preds.append(i)\nsub.shape, len(preds)\nsub['label'] = preds\nsub.to_csv('s.csv', index=False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.6"}},"nbformat":4,"nbformat_minor":1}