{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os, sys\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\nimport PIL\nfrom PIL import Image, ImageOps\nimport cv2\nfrom tqdm import tqdm_notebook\nimport time\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, Dataset, SubsetRandomSampler\nimport torch.utils.data as utils\nimport torchvision.models as models\n\nimport torchvision\nfrom torchvision import transforms\n\nfrom sklearn.metrics import cohen_kappa_score\nfrom sklearn.model_selection import StratifiedKFold\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\nIMG_SIZE = 224","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pretrained_model = torchvision.models.densenet161(pretrained=False, num_classes=5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_dir = '../input/aptos2019-blindness-detection/'\ntrain_dir = data_dir + '/train_images/'\ntest_dir = data_dir + '/test_images/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv(data_dir+\"train.csv\")\ndf_test = pd.read_csv(data_dir+\"test.csv\")\ndf_test['diagnosis'] = -1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_test.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def crop_image_from_gray(img,tol=7):\n    if img.ndim ==2:\n        mask = img>tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img>tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): # image is too dark so that we crop out everything,\n            return img # return original image\n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n            img = np.stack([img1,img2,img3],axis=-1)\n        return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_ben_color(path, sigmaX=10):\n    image = cv2.imread(path)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n    image=cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , sigmaX) ,-4 ,128)\n        \n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class ImageData(Dataset):\n    def __init__(self, df, data_dir, transform):\n        super().__init__()\n        self.df = df.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        \n        img_path = os.path.join(self.data_dir, img_name+'.png')\n        image = load_ben_color(img_path,sigmaX=10)\n        if self.transform:\n            image = self.transform(image)\n        return image, label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_transf = torchvision.transforms.Compose([\n    torchvision.transforms.ToPILImage(),\n    torchvision.transforms.RandomRotation((-180, 180)),\n    torchvision.transforms.RandomHorizontalFlip(p=0.4),\n    torchvision.transforms.RandomVerticalFlip(p=0.5),\n    torchvision.transforms.ToTensor(),\n    torchvision.transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))\n])\n\ntransforms_valid = torchvision.transforms.Compose([\n    torchvision.transforms.ToPILImage(),\n    torchvision.transforms.ToTensor(),\n    torchvision.transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))\n])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_one_fold(i_fold, model, loss_func, optimizer, train_loader, valid_loader, n_epochs):\n    best_loss = float('+inf')\n    train_fold_results = []\n\n    for epoch in range(n_epochs):\n        train_start = time.time()\n\n        print('  Epoch {}/{}'.format(epoch + 1, n_epochs))\n        print('  ' + ('-' * 20))\n\n        model.train()\n        tr_loss = 0\n        train_kappa = []\n        optimizer.zero_grad()\n        for ii, (data, target) in tqdm_notebook(enumerate(train_loader), total=len(train_loader)):\n\n            images = data.to('cuda', dtype = torch.float)  \n#             target = target.unsqueeze(1)\n            labels = target.to('cuda', dtype = torch.float)  \n            \n            labels = labels.view(-1,1)\n            optimizer.zero_grad()\n            \n            \n            with torch.set_grad_enabled(True):\n                output = model(images)   \n                \n                loss = loss_func(output, labels)\n                loss.backward()\n\n                optimizer.step()\n            \n            tr_loss += loss.item()\n            \n            y_actual = labels.data.cpu().numpy()\n            y_pred = output[:,-1].detach().cpu().numpy()\n            kappa = cohen_kappa_score(y_actual, y_pred.round(), weights='quadratic')\n            train_kappa.append(kappa)\n        \n        train_kappa_epoch = np.mean(train_kappa)\n\n        train_end = time.time()\n            \n        val_start = time.time()\n        # Validate\n        model.eval()\n        \n        val_loss = 0\n        val_preds = None\n        val_labels = None\n        val_kappa = []\n        \n        for ii, (data, target) in tqdm_notebook(enumerate(valid_loader), total=len(valid_loader)):\n\n\n            images = data.to('cuda', dtype = torch.float)\n            labels = target.to('cuda', dtype = torch.float)\n            labels = labels.view(-1,1)\n\n            with torch.no_grad():\n                outputs = model(images)\n                \n                loss = loss_func(outputs, labels)\n                val_loss += loss.item()\n\n            y_actual = labels.data.cpu().numpy()\n            y_pred = outputs[:,-1].detach().cpu().numpy()\n            kappa = cohen_kappa_score(y_actual, y_pred.round(), weights='quadratic')\n            val_kappa.append(kappa)\n\n           \n        val_kappa_epoch = np.mean(val_kappa)\n        val_end = time.time()\n        train_loss = tr_loss/len(train_loader)\n        valid_loss = val_loss/len(valid_loader)\n        \n        print('Fold: {}, Epoch: {}, Train duration: {:.6f}, Valid duration: {:.6f}, Train Loss: {:.6f}, Valid Loss: {:.6f}, Train Kappa: {:.4f}, Valid Kappa: {:.4f}'.format(i_fold+1, epoch+1, train_end - train_start, val_end - val_start, train_loss, valid_loss, train_kappa_epoch, val_kappa_epoch))\n        if best_loss > valid_loss:\n            best_loss = valid_loss\n            torch.save(model.state_dict(), '../input/aptos-checkpoints/aptos_3_pretrained_model_161_{}_fold_{}_epoch.pth'.format(i_fold, epoch))\n    return train_loss, valid_loss, train_kappa_epoch, val_kappa_epoch","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"N_FOLDS = 2\nBATCH_SIZE = 32\nN_EPOCHS = 15\n\nfolds = StratifiedKFold(n_splits=N_FOLDS, shuffle=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"state_dict = torch.load('../input/aptos-checkpoints/aptos_3_pretrained_model_161_1_fold_0_epoch.pth', map_location=lambda storage, loc: storage)\npretrained_model.load_state_dict(state_dict)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data = ImageData(df = df_test, data_dir = test_dir, transform = transforms_valid)\ntest_loader = DataLoader(test_data, batch_size=4, num_workers=4, shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":" def round_off_preds(preds, coef=[0.5, 1.5, 2.5, 3.5]):\n    for i, pred in enumerate(preds):\n            if pred < coef[0]:\n                preds[i] = 0\n            elif pred >= coef[0] and pred < coef[1]:\n                preds[i] = 1\n            elif pred >= coef[1] and pred < coef[2]:\n                preds[i] = 2\n            elif pred >= coef[2] and pred < coef[3]:\n                preds[i] = 3\n            else:\n                preds[i] = 4\n    return preds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def predict(model, testloader):\n    '''Function used to make predictions on the test set'''\n    model.eval()\n    preds = []\n    for batch_i, (data, target) in tqdm_notebook(enumerate(testloader), total=len(testloader)):\n        data, target = data, target\n        output = model(data)\n        pr = output.detach().cpu().numpy()\n        for item in pr:\n            preds.append(item.mean())\n            \n    return preds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_pred = round_off_preds(predict(pretrained_model, test_loader))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_test['diagnosis'] = test_pred\ndf_test.to_csv('submission.csv',index=False)\ndf_test","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}