{"cells":[{"metadata":{},"cell_type":"markdown","source":"This ia beginner Kernel based on https://www.kaggle.com/abhishek/very-simple-pytorch-training-0-59\n\nAny feedback is welcome.\n\n**Note:** The model is not accurate. "},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import pandas as pd\n\nimport time\nimport torchvision\nimport torch.nn as nn\nfrom tqdm import tqdm_notebook as tqdm\n\nfrom PIL import Image, ImageFile\nimport matplotlib.pyplot as plt\n%matplotlib inline\nfrom torch.utils.data import Dataset\nimport torch\nimport torch.optim as optim\nfrom torchvision import transforms\nfrom torch.optim import lr_scheduler\nimport os\nimport numpy as np\ndevice = torch.device(\"cuda:0\")\nImageFile.LOAD_TRUNCATED_IMAGES = True\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom collections import OrderedDict\n\nprint(os.listdir('../input'))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Display the 4 differnet classes for illustration"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"\npath_0 =\"../input/aptos2019-blindness-detection/train_images/002c21358ce6.png\"\nimg_0 = Image.open(path_0)\n#plt.figure(figsize = (10,10))\n\npath_1=\"../input/aptos2019-blindness-detection/train_images/0024cdab0c1e.png\"\nimg_1 = Image.open(path_1)\nprint(type(img_1))\nimg_1 = transforms.functional.adjust_contrast(img_1, contrast_factor=3)\nprint(type(img_1))\nimg_1 = transforms.functional.adjust_gamma(img_1, gamma=3)\nprint(type(img_1))\n#plt.figure(figsize = (10,10))\n\npath_2=\"../input/aptos2019-blindness-detection/train_images/000c1434d8d7.png\"\nimg_2 = Image.open(path_2)\n#plt.figure(figsize = (10,10))\n\npath_3=\"../input/aptos2019-blindness-detection/train_images/03c85870824c.png\"\nimg_3 = Image.open(path_3)\n\npath_4=\"../input/aptos2019-blindness-detection/train_images/02685f13cefd.png\"\nimg_4 = Image.open(path_4)\n\n#plt.figure(figsize = (10,10))\n# Four polar axes\nf, axarr = plt.subplots(1, 5, figsize=(20, 10) )\naxarr[0].imshow(img_0)\naxarr[0].set_title('0 - No DR')\naxarr[1].imshow(img_1)\naxarr[1].set_title('1 - Mild')\naxarr[2].imshow(img_2)\naxarr[2].set_title('2 - Moderate')\naxarr[3].imshow(img_3)\naxarr[3].set_title('3 - Severe')\naxarr[4].imshow(img_4)\naxarr[4].set_title('4 - Proliferative DR')\n\n#Apply transformations\n\n#f.subplots_adjust(hspace=10)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Define a Loader for Training Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"class RetinopathyDatasetTrain(Dataset):\n\n    def __init__(self, csv_file, transform):\n\n        self.data = pd.read_csv(csv_file)\n        self.transform = transform\n        self.labels = torch.eye(5)[self.data['diagnosis']]\n        \n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        img_name = os.path.join('../input/aptos2019-blindness-detection/train_images', self.data.loc[idx, 'id_code'] + '.png')\n        image = Image.open(img_name)\n        image = transforms.functional.adjust_saturation(image, saturation_factor=0)\n        image = transforms.functional.adjust_contrast(img=image, contrast_factor=2)\n        image = transforms.functional.adjust_gamma(img=image, gamma=2)\n        image = self.transform(image)\n        label = torch.tensor(self.data.loc[idx, 'diagnosis'])\n        #label = self.labels[idx]\n        return {'image': image,\n                'labels': label\n                }\n    \ntransformer = transforms.Compose([\n    transforms.Resize((128, 128)),\n    transforms.CenterCrop((64, 64)),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])    \n\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Import the model. For now use the pretrained VGG models.\n\nFreeze the model parameter gradients.\n\nDefine the custom Classifer. This classifier has 5 output classes. "},{"metadata":{"trusted":true},"cell_type":"code","source":"loadSavedModel = False\n#model = torchvision.models.resnet101(pretrained=True)\nmodel = []\nif (not loadSavedModel):\n    model = torchvision.models.vgg16_bn(pretrained=True)\n    model = model.to(device)\n    #Disable grad for the hidden layers\n    for params in model.parameters():\n        params.requires_grad = False\n    #Add custom layer - after setting other layers no grad.\n    custom_classifier = nn.Sequential(OrderedDict([\n                          ('fc1',nn.Linear(25088, 4096)),\n                          ('r1',nn.ReLU()),\n                          ('fc2',nn.Linear(4096, 512)),\n                          ('r2',nn.ReLU()),\n                          ('fc3',nn.Linear(512, 5)),\n                          ('s3',nn.LogSoftmax(dim=1)) ]               \n                          ))\n    model.classifier = custom_classifier\n    \nelse:    \n    model = torchvision.models.vgg16_bn(pretrained=False)\n    saved_checkpoint = torch.load('saved_model.pth')\n    #Create empty model\n    #Add custom layer\n    temp_model.classifier = nn.Sequential(OrderedDict([\n                          ('fc1',nn.Linear(25088, 4096)),\n                          ('r1',nn.ReLU()),\n                          ('d1',nn.Dropout(p=0.3)),  \n                          ('fc2',nn.Linear(4096, 512)),\n                          ('r2',nn.ReLU()),\n                          ('d2',nn.Dropout(p=0.3)),\n                          ('fc3',nn.Linear(512, 5)),\n                          ('s3',nn.LogSoftmax(dim=1)) ]               \n                          ))\n    model.classifier = custom_classifier\n    #Load model\n    temp_model.load_state_dict(saved_checkpoint['state_dict'])\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#print(model)\nparams = list(model.parameters())\nprint(len(params))\nprint(params[0].size())  # conv1's .weight\nprint(params[1].size())  # conv1's .weight\nprint(params[2].size())  # conv1's .weight\nprint(params[4].size())  # conv1's .weight","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_dataset = RetinopathyDatasetTrain(csv_file='../input/aptos2019-blindness-detection/train.csv',transform=transformer)\n#data_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, shuffle=True, num_workers=4)\n\nbatch_size = 16\nvalidation_split = .1\nshuffle_dataset = True\nrandom_seed= 42\n\n# Creating data indices for training and validation splits:\ndataset_size = len(train_dataset)\nindices = list(range(dataset_size))\nsplit = int(np.floor(validation_split * dataset_size))\nnp.random.seed(random_seed)\nnp.random.shuffle(indices)\ntrain_indices, val_indices = indices[split:], indices[:split]\n\n# Creating PT data samplers and loaders:\ntrain_sampler = SubsetRandomSampler(train_indices)\nvalid_sampler = SubsetRandomSampler(val_indices)\n\ntrain_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, \n                                           sampler=train_sampler, num_workers=4)\nvalidation_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size,\n                                                sampler=valid_sampler, num_workers=4)\n\n#TODO Split the data set into train and validate sets.\n#https://stackoverflow.com/questions/50544730/how-do-i-split-a-custom-dataset-into-training-and-test-datasets\n\nim = next(iter(train_loader))\nimage = im[\"image\"]\nlabels = im[\"labels\"]\nprint(f\"image shape {image.shape}\")\nprint(f\"labels shape {labels.shape}\")\nprint(f\"labels {labels}\")\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"criterion = nn.NLLLoss()\n\noptimizer = optim.Adam(model.classifier.parameters(), lr = 0.001)\n\ndebugTrain = False\ndebugVal = False\ndevice = torch.device(device)\nmodel = model.to(device)\n#Train - number of epochs\nepochs = 10\nacc_loss = 0\nfor epoch in range(epochs):\n    batch_count = 0\n    tk0 = tqdm(train_loader, total=int(len(train_loader)))\n    counter = 0\n    for bi, d in enumerate(tk0):\n        batch_count += 1\n        #print(f\"batch {batch_count}\")\n        #print(images.shape)\n        inputs = d[\"image\"]\n        #labels = d[\"labels\"].view(-1, 1)\n        labels = d[\"labels\"]\n        inputs = inputs.to(device, dtype=torch.float)\n        labels = labels.to(device, dtype=torch.float)\n        labels_val = labels.long()\n        optimizer.zero_grad()\n             \n        logps = model.forward(inputs)\n        loss = criterion(logps, labels_val)\n        if(debugTrain):\n            #print(f\"train - logps {logps.shape}\")\n            print(f\"logps[0][0] {logps[0][0]} logps[0][1] {logps[0][1]}\")\n            #print(logps.type())\n            #print(labels_val.type())    \n            print(f\" loss {loss}\")\n            \n        loss.backward()\n        optimizer.step()\n        acc_loss += loss.item()\n        \n    #End of epoch - print loss and accuracy\n    val_loss = 0\n    accuracy = 0\n    model.eval()\n    with torch.no_grad():\n        tk1 = tqdm(validation_loader, total=int(len(validation_loader)))\n        for bi, d in enumerate(tk1):\n            inputs = d[\"image\"]\n            #labels = d[\"labels\"].view(-1, 1)\n            labels = d[\"labels\"]\n            inputs = inputs.to(device, dtype=torch.float)\n            labels = labels.to(device, dtype=torch.float)\n            labels_val = labels.long()\n            logps = model.forward(inputs)\n            \n\n            batch_loss = criterion(logps, labels_val)\n            val_loss+= batch_loss.item()\n            \n            ps = torch.exp(logps)\n            top_p, top_class = ps.topk(1, dim =1)\n            if(debugVal):\n                #print(logps.type())\n                #print(labels_val.type())\n                #print(f\" val - labelabels_valls shape {labels_val.shape}\")\n                #print(f\" val - logps shape {logps.shape}\")\n                print(f\" top_class {top_class} labels {labels}\")\n                #print(top_class.type())\n                #print(labels.type())\n                #print(labels_val.type())\n                #top_class = top_class.type(torch.DoubleTensor)\n                \n            equals = top_class == labels_val.view(-1, 1)\n            #print(f\"equals {equals}\")\n            accuracy += torch.mean(equals.type(torch.FloatTensor)).item()\n            \n    #Set model to train again\n    model.train()    \n    #End of epoch - print loss and accuracy\n    print(f\"training loss {acc_loss/len(train_loader):.3f}\")\n    print(f\"val loss {val_loss/len(validation_loader):.3f}\")\n    print(f\"val accuracy {accuracy/len(validation_loader):.3f}\")\n\n    acc_loss =0\n    \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Save model for loading without internet\ncheckpoint ={\"state_dict\":model.state_dict()}\ntorch.save(checkpoint, 'saved_model_vgg16_bn_aptos_competition.pth')\n\n\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Predict the class for the Test data"},{"metadata":{"trusted":true},"cell_type":"code","source":"class RetinopathyDatasetTest(Dataset):\n\n    def __init__(self, csv_file, transform):\n        self.data = pd.read_csv(csv_file)\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        img_name = os.path.join('../input/aptos2019-blindness-detection/test_images', self.data.loc[idx, 'id_code'] + '.png')\n        image = Image.open(img_name)\n        image = self.transform(image)\n        return {'image': image}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_dataset = RetinopathyDatasetTest(csv_file='../input/aptos2019-blindness-detection/test.csv', transform = transformer)\ntest_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16, shuffle=False)\ntest_preds = np.zeros((len(test_dataset), 1))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.eval()\nwith torch.no_grad():\n    tk2 = tqdm(test_loader, total=int(len(test_loader)))\n    for i, d in enumerate(tk2):\n         #print(bi)\n         inputs = d[\"image\"]\n         inputs = inputs.to(device, dtype=torch.float)\n         #print(f\" Test inputs shape {inputs.shape}\")\n         #print(f\" Test labels shape {labels.shape}\")\n         logps = model.forward(inputs)\n         print(f\"logps {logps}\")\n         ps = torch.exp(logps)\n         top_p, top_class = ps.topk(1, dim =1)\n         #print(logps.shape)   \n         print(f\" top_class {top_class} top_p {top_p}\")\n         #print(top_class.type())\n         top_class = top_class.type(torch.DoubleTensor)\n         #print(f\"top class {top_class}\")\n         print(top_class.type())\n         #print(type(top_class.numpy().ravel()))\n         print(top_class.detach().cpu().squeeze().numpy().ravel().reshape(-1, 1))\n         test_preds[i * 16:(i + 1) * 16] = top_class.detach().cpu().squeeze().numpy().ravel().reshape(-1, 1)\n         \n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample = pd.read_csv(\"../input/aptos2019-blindness-detection/sample_submission.csv\")\nsample.diagnosis = test_preds.astype(int)\nsample.to_csv(\"submission.csv\", index=False)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Check if the file present\nos.listdir('.')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}