{"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\n# import numpy as np # linear algebra\n# import 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\n# import os\n# for 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","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nimport torch\nimport cv2\nimport torchvision\nfrom torchvision.transforms import transforms\nfrom torch.utils.data import Dataset, DataLoader, ConcatDataset\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom PIL import ImageFile\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport cv2\nimport os\nimport torch.nn as nn\nimport torch.nn.functional as f\nfrom skimage import io\nfrom torch.utils.data import (\n    Dataset,\n    DataLoader,\n) \nimport warnings\nwarnings.filterwarnings('ignore')\ntorch.manual_seed(0)\nimport sys\n\ndevice=torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(device)","metadata":{"execution":{"iopub.status.busy":"2021-11-18T11:57:15.445567Z","iopub.execute_input":"2021-11-18T11:57:15.445868Z","iopub.status.idle":"2021-11-18T11:57:15.463813Z","shell.execute_reply.started":"2021-11-18T11:57:15.445787Z","shell.execute_reply":"2021-11-18T11:57:15.463146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_lebel=pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\n","metadata":{"execution":{"iopub.status.busy":"2021-11-18T11:57:38.069779Z","iopub.execute_input":"2021-11-18T11:57:38.070031Z","iopub.status.idle":"2021-11-18T11:57:38.092019Z","shell.execute_reply.started":"2021-11-18T11:57:38.07Z","shell.execute_reply":"2021-11-18T11:57:38.091256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_lebel","metadata":{"execution":{"iopub.status.busy":"2021-11-18T11:57:45.532842Z","iopub.execute_input":"2021-11-18T11:57:45.533392Z","iopub.status.idle":"2021-11-18T11:57:45.554155Z","shell.execute_reply.started":"2021-11-18T11:57:45.533355Z","shell.execute_reply":"2021-11-18T11:57:45.553475Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_lebel['diagnosis'].unique()","metadata":{"execution":{"iopub.status.busy":"2021-11-18T11:58:04.494232Z","iopub.execute_input":"2021-11-18T11:58:04.494511Z","iopub.status.idle":"2021-11-18T11:58:04.504192Z","shell.execute_reply.started":"2021-11-18T11:58:04.494481Z","shell.execute_reply":"2021-11-18T11:58:04.503556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_lebel['diagnosis'].value_counts()\n","metadata":{"execution":{"iopub.status.busy":"2021-11-18T11:59:16.582093Z","iopub.execute_input":"2021-11-18T11:59:16.582533Z","iopub.status.idle":"2021-11-18T11:59:16.592596Z","shell.execute_reply.started":"2021-11-18T11:59:16.582489Z","shell.execute_reply":"2021-11-18T11:59:16.591652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# #Histogram of label counts.\n# data_lebel.diagnosis.hist()\n# plt.xticks([0,1,2,3,4])\n# plt.grid(False)\n# plt.show() ","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:12:21.62386Z","iopub.execute_input":"2021-11-18T12:12:21.624373Z","iopub.status.idle":"2021-11-18T12:12:21.847855Z","shell.execute_reply.started":"2021-11-18T12:12:21.62433Z","shell.execute_reply":"2021-11-18T12:12:21.84721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:14:21.18023Z","iopub.execute_input":"2021-11-18T12:14:21.180506Z","iopub.status.idle":"2021-11-18T12:14:21.239843Z","shell.execute_reply.started":"2021-11-18T12:14:21.180478Z","shell.execute_reply":"2021-11-18T12:14:21.239104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import PIL.Image as Image ","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:46:38.185031Z","iopub.execute_input":"2021-11-18T12:46:38.185294Z","iopub.status.idle":"2021-11-18T12:46:38.189329Z","shell.execute_reply.started":"2021-11-18T12:46:38.185265Z","shell.execute_reply":"2021-11-18T12:46:38.188548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.utils import class_weight #For calculating weights for each class.\nclass_weights = class_weight.compute_class_weight(class_weight='balanced',classes=np.array([0,1,2,3,4]),y=data_lebel['diagnosis'].values)\nclass_weights = torch.tensor(class_weights,dtype=torch.float).to(device)\n \nprint(class_weights) #Prints the calculated weights for the classes.\n","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:31:57.173281Z","iopub.execute_input":"2021-11-18T12:31:57.173694Z","iopub.status.idle":"2021-11-18T12:31:57.18575Z","shell.execute_reply.started":"2021-11-18T12:31:57.173651Z","shell.execute_reply":"2021-11-18T12:31:57.184711Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMAGE_SIZE = 28 \ntransform_image = transforms.Compose([\n                                transforms.ToPILImage(),\n                                transforms.RandomRotation(20,expand=True), \n                                transforms.Resize(IMAGE_SIZE),  ## image resize\n                                transforms.CenterCrop(IMAGE_SIZE),\n                                transforms.ToTensor(), ## array converted into torch tensor and then divided by 255 (1.0/255)\n                               ])","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:31:57.18806Z","iopub.execute_input":"2021-11-18T12:31:57.188623Z","iopub.status.idle":"2021-11-18T12:31:57.194553Z","shell.execute_reply.started":"2021-11-18T12:31:57.188581Z","shell.execute_reply":"2021-11-18T12:31:57.19378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class dataset(Dataset): # Inherits from the Dataset class.\n    \n    def __init__(self,df,data_path,image_transform=None,train=True): # Constructor.\n        super(Dataset,self).__init__() #Calls the constructor of the Dataset class.\n        self.df = df\n        self.data_path = data_path\n        self.image_transform = image_transform\n        self.train = train\n        \n    def __len__(self):\n        return len(self.df) #Returns the number of samples in the dataset.\n    \n    def __getitem__(self,index):\n        image_id = self.df['id_code'][index]\n        image = Image.open(f'{self.data_path}/{image_id}.png') #Image.\n        if self.image_transform :\n            image = self.image_transform(image) #Applies transformation to the image.\n        \n        if self.train :\n            label = self.df['diagnosis'][index] #Label.\n            return image,label #If train == True, return image & label.\n        \n        else:\n            return image #If train != True, return image.","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:40:54.358189Z","iopub.execute_input":"2021-11-18T12:40:54.35856Z","iopub.status.idle":"2021-11-18T12:40:54.365293Z","shell.execute_reply.started":"2021-11-18T12:40:54.358519Z","shell.execute_reply":"2021-11-18T12:40:54.364549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = \"/kaggle/input/aptos2019-blindness-detection/\"","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:41:56.50127Z","iopub.execute_input":"2021-11-18T12:41:56.50181Z","iopub.status.idle":"2021-11-18T12:41:56.505509Z","shell.execute_reply.started":"2021-11-18T12:41:56.501774Z","shell.execute_reply":"2021-11-18T12:41:56.504541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_transform = transforms.Compose([transforms.Resize([299,299]),\n                                      transforms.ToTensor(),\n                                      transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))]) #Transformations to apply to the image.\ndata_set = dataset(data_lebel,f'{path}train_images',image_transform=image_transform)\n\n#Split the data_set so that valid_set contains 0.1 samples of the data_set. \ntrain_set,valid_set = torch.utils.data.random_split(data_set,[3302,360])","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:42:47.232656Z","iopub.execute_input":"2021-11-18T12:42:47.232919Z","iopub.status.idle":"2021-11-18T12:42:47.239832Z","shell.execute_reply.started":"2021-11-18T12:42:47.232892Z","shell.execute_reply":"2021-11-18T12:42:47.239049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataloader = DataLoader(train_set,batch_size=32,shuffle=True) #DataLoader for train_set.\nvalid_dataloader = DataLoader(valid_set,batch_size=32,shuffle=False) #DataLoader for validation_set.","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:42:49.972534Z","iopub.execute_input":"2021-11-18T12:42:49.973273Z","iopub.status.idle":"2021-11-18T12:42:49.978671Z","shell.execute_reply.started":"2021-11-18T12:42:49.973224Z","shell.execute_reply":"2021-11-18T12:42:49.977581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchvision.models as models\ninception_v3= models.inception_v3(pretrained=True,aux_logits=False) \n\n# image size must be >= 299 x 299 during training if aux_logits is set to be True.\n\ninception_v3.cuda()\nnum_classes = 5\nbatch_size = 32\n\nlearning_rate=0.0001\n\noptimizer = torch.optim.Adam(inception_v3.parameters(),lr=learning_rate)\n\n \ncriterion = torch.nn.CrossEntropyLoss(weight=class_weights)\n\ninception_v3.fc = nn.Linear(2048, 5)\ninception_v3.cuda()\nprint(\"Model Is Ready To Run \")","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:44:08.847077Z","iopub.execute_input":"2021-11-18T12:44:08.847349Z","iopub.status.idle":"2021-11-18T12:44:09.235072Z","shell.execute_reply.started":"2021-11-18T12:44:08.847321Z","shell.execute_reply":"2021-11-18T12:44:09.233485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(dataloader,model,loss_fn,optimizer):\n\n    model.train() #Sets the model for training.\n    \n    total = 0\n    correct = 0\n    running_loss = 0\n    \n    for batch,(x,y) in enumerate(dataloader): #Iterates through the batches.\n        \n        output = model(x.to(device)) #model's predictions.\n        loss   = loss_fn(output,y.to(device)) #loss calculation.\n       \n        running_loss += loss.item()\n        \n        total        += y.size(0)\n        predictions   = output.argmax(dim=1).cpu().detach() #Index for the highest score for all the samples in the batch.\n        correct      += (predictions == y.cpu().detach()).sum().item() #No.of.cases where model's predictions are equal to the label.\n        \n        optimizer.zero_grad() #Gradient values are set to zero.\n        loss.backward() #Calculates the gradients.\n        optimizer.step() #Updates the model weights.\n             \n    \n    avg_loss = running_loss/len(dataloader) # Average loss for a single batch\n    \n    print(f'\\nTraining Loss = {avg_loss:.6f}',end='\\t')\n    print(f'Accuracy on Training set = {100*(correct/total):.6f}% [{correct}/{total}]') #Prints the Accuracy.\n    \n    return avg_loss","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:43:20.966488Z","iopub.execute_input":"2021-11-18T12:43:20.967012Z","iopub.status.idle":"2021-11-18T12:43:20.97472Z","shell.execute_reply.started":"2021-11-18T12:43:20.966976Z","shell.execute_reply":"2021-11-18T12:43:20.973679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def validate(dataloader,model,loss_fn):\n    \n    model.eval() #Sets the model for evaluation.\n    \n    total = 0\n    correct = 0\n    running_loss = 0\n    \n    with torch.no_grad(): #No need to calculate the gradients.\n        \n        for x,y in dataloader:\n            \n            output        = model(x.to(device)) #model's output.\n            loss          = loss_fn(output,y.to(device)).item() #loss calculation.\n            running_loss += loss\n            \n            total        += y.size(0)\n            predictions   = output.argmax(dim=1).cpu().detach()\n            correct      += (predictions == y.cpu().detach()).sum().item()\n            \n    avg_loss = running_loss/len(dataloader) #Average loss per batch.      \n    \n    print(f'\\nValidation Loss = {avg_loss:.6f}',end='\\t')\n    print(f'Accuracy on Validation set = {100*(correct/total):.6f}% [{correct}/{total}]') #Prints the Accuracy.\n    \n    return avg_loss","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:43:48.903046Z","iopub.execute_input":"2021-11-18T12:43:48.903331Z","iopub.status.idle":"2021-11-18T12:43:48.913862Z","shell.execute_reply.started":"2021-11-18T12:43:48.903284Z","shell.execute_reply":"2021-11-18T12:43:48.912999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def optimize(train_dataloader,valid_dataloader,model,loss_fn,optimizer,nb_epochs):\n    #Lists to store losses for all the epochs.\n    train_losses = []\n    valid_losses = []\n\n    for epoch in range(nb_epochs):\n        print(f'\\nEpoch {epoch+1}/{nb_epochs}')\n        print('-------------------------------')\n        train_loss = train(train_dataloader,model,loss_fn,optimizer) #Calls the train function.\n        train_losses.append(train_loss)\n        valid_loss = validate(valid_dataloader,model,loss_fn) #Calls the validate function.\n        valid_losses.append(valid_loss)\n    \n    print('\\nTraining has completed!')\n    \n    return train_losses,valid_losses","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:44:36.41448Z","iopub.execute_input":"2021-11-18T12:44:36.414741Z","iopub.status.idle":"2021-11-18T12:44:36.42105Z","shell.execute_reply.started":"2021-11-18T12:44:36.414712Z","shell.execute_reply":"2021-11-18T12:44:36.420296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test(dataloader,model):\n    \n    y_true_tensor = torch.tensor([]).cuda()\n    y_pred_tensor = torch.tensor([]).cuda()\n    \n    model.eval() #Sets the model for evaluation.\n    \n    total = 0\n    correct = 0\n    \n    with torch.no_grad(): #No need to calculate the gradients.\n        \n        for x,y in dataloader:\n            \n            output        = model(x.to(device)) #model's output.\n            \n            total        += y.size(0)\n            predictions   = output.argmax(dim=1).cpu().detach()\n            correct      += (predictions == y.cpu().detach()).sum().item()\n            \n            y_true_tensor = torch.cat((y_true_tensor,y.to(device)))\n            y_pred_tensor = torch.cat((y_pred_tensor,predictions.to(device)))\n            \n      \n    print(f'Accuracy on Test set = {100*(correct/total):.6f}% [{correct}/{total}]') #Prints the Accuracy.\n    \n    from sklearn.metrics import confusion_matrix\n    from sklearn.metrics import classification_report\n    y_true = y_true_tensor.tolist()\n    y_pred = y_pred_tensor.tolist()\n    matrix = confusion_matrix(y_true,y_pred)\n    print(matrix)\n    \n    classify_report = classification_report(y_true, y_pred)\n    print(classify_report)","metadata":{"execution":{"iopub.status.busy":"2021-11-18T12:46:44.227129Z","iopub.execute_input":"2021-11-18T12:46:44.227378Z","iopub.status.idle":"2021-11-18T13:04:11.838264Z","shell.execute_reply.started":"2021-11-18T12:46:44.22735Z","shell.execute_reply":"2021-11-18T13:04:11.837083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchvision.models as models\ndensenet121= models.densenet121(pretrained=True)\n\nfor param in densenet121.parameters():\n    param.requires_grad = False\n\ndensenet121.classifier = nn.Sequential(\n    nn.Linear(1024, 256),\n    nn.ReLU(),\n    nn.Dropout(0.4),\n    nn.Linear(256, 5), \n)\ndensenet121.cuda()\nnum_classes = 5\nbatch_size = 32\nlearning_rate = 0.0001\n \ncriterion = torch.nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(densenet121.parameters(),lr=learning_rate)\n\n\nnb_epochs = 30\n\n\ntrain_losses, valid_losses = optimize(train_dataloader,valid_dataloader,densenet121,criterion,optimizer,nb_epochs)\n\ntorch.save(densenet121,'densenet121.pth')\n\n# inception_v3 = torch.load(PATH)\n\ntest(valid_dataloader,densenet121)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}