{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Importing Libraries"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import os\nimport sys\nsys.path.append(\"../input/efficientnetpytorch\") #for efficient model\n\n#Basic library read and split data-csv\nimport pandas as pd\nimport numpy as np\nfrom sklearn.model_selection import StratifiedKFold\n\n#for albumentations uses cv2 where as torchvision transforms uses PIL\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensor\n\n#PyTorch - deep learning framework\nimport torch \nfrom torch import nn\nfrom torch.utils.data import Dataset,DataLoader\nimport torch.nn.functional as F\n\n#pytorch-lightning on top of PyTorch framework\nimport pytorch_lightning as pl\nfrom pytorch_lightning.metrics.functional import accuracy\nfrom pytorch_lightning.callbacks import ModelCheckpoint \n\n#for efficient model transfer learning\nfrom efficientnet_pytorch import EfficientNet","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Constants"},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGES_DIRS = \"../input/cassava-leaf-disease-classification/train_images/\"\nTRAIN_FILE = \"../input/cassava-leaf-disease-classification/train.csv\"\nPRETRAINED_PATH = \"../input/resources-for-google-landmark-recognition-2020/efficientnet-b3-5fb5a3c3.pth\"\nBATCH_SIZE = 40\nIMG_SIZE = 512\nCLASSES = 5","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Lightning Computation Module (Research code)"},{"metadata":{"trusted":true},"cell_type":"code","source":"class CassavaEfficientNet(pl.LightningModule):\n  def __init__(self):\n    super().__init__()\n    self.efficient_net = EfficientNet.from_name('efficientnet-b3')\n    #if you have acces to internet use just \\\n    #use this- EfficientNet.from_pretrained('efficientnet-b3',num_classes=CLASSES)\n    self.efficient_net.load_state_dict(torch.load(PRETRAINED_PATH))\n    in_features = self.efficient_net._fc.in_features\n    self.efficient_net._fc = nn.Linear(in_features,CLASSES)\n    \n  def forward(self,x):\n    out = self.efficient_net(x)\n    return out\n  \n  def configure_optimizers(self):\n    optimizer = torch.optim.Adam(self.parameters(),lr = 1e-4)\n    return optimizer\n  \n  def training_step(self,batch,batch_idx):\n    x,y = batch[\"x\"],batch[\"y\"]\n    y_hat = self(x)\n    loss = F.cross_entropy(y_hat,y)\n    # logs metrics for each training_step - [default:True],\n    # the average across the epoch, to the progress bar and logger-[default:False]\n    acc = accuracy(y_hat,y)\n    self.log(\"train_acc\",acc,on_step=False,on_epoch=True,prog_bar=True,logger=True),\n    self.log(\"train_loss\",loss,on_step=False,on_epoch=True,prog_bar=True,logger=True)\n    return loss\n  \n  def validation_step(self,batch,batch_idx):\n    x,y = batch[\"x\"],batch[\"y\"]\n    y_hat = self(x)\n    loss = F.cross_entropy(y_hat,y)\n    acc = accuracy(y_hat,y)\n    # logs metrics for each validation_step - [default:False]\n    #the average across the epoch - [default:True]\n    self.log(\"val_acc\",acc,prog_bar=True,logger=True),\n    self.log(\"val_loss\",loss,prog_bar=True,logger=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Train Dataset Loader "},{"metadata":{"trusted":true},"cell_type":"code","source":"class CassavaDataset(Dataset):\n  def __init__(self,path,image_ids,labels,transform):\n    super().__init__()\n    self.image_ids = image_ids\n    self.labels = labels\n    self.path = path\n    self.transform = transform\n      \n  def __len__(self):\n    return len(self.image_ids)\n  \n  def __getitem__(self,item):\n    image_id = str(self.image_ids[item])\n    img = cv2.imread(self.path+image_id)\n    img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)\n    img = self.transform(image=img)\n    #albumentations transform return a dictionary with \"image\" as key\n    image = img[\"image\"]\n    label = self.labels[item]\n    return {\n        \"x\":image,\n        \"y\":label,\n    }    ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Lightning Data Module"},{"metadata":{"trusted":true},"cell_type":"code","source":"\nclass CassavaDataModule(pl.LightningDataModule):\n  def __init__(self):\n    super().__init__()\n    self.train_transform = A.Compose([A.Resize(IMG_SIZE,IMG_SIZE),\n                                      A.RandomCrop(318,318),\n                                      A.HorizontalFlip(),\n                                      A.VerticalFlip(),\n                                      A.ShiftScaleRotate(),\n                                      A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n                                      ToTensor()])\n    self.test_transform = A.Compose([A.Resize(IMG_SIZE,IMG_SIZE),\n                                     A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n                                     ToTensor()])\n  \n  def prepare_data(self):\n    # prepare_data is called only once on 1- GPU in a distributed computing\n    df = pd.read_csv(TRAIN_FILE)\n    df[\"kfold\"] =-1\n    df = df.sample(frac=1).reset_index(drop=True)\n    stratify = StratifiedKFold(n_splits=5)\n    for i,(t_idx,v_idx) in enumerate(stratify.split(X=df.image_id.values,y=df.label.values)):\n      df.loc[v_idx,\"kfold\"]=i\n    df.to_csv(\"train_folds.csv\",index=False)\n\n  def setup(self,stage=None):\n    dfx = pd.read_csv(\"train_folds.csv\")\n    train = dfx.loc[dfx[\"kfold\"]!=1]\n    val = dfx.loc[dfx[\"kfold\"]==1]\n    self.train_dataset = CassavaDataset(IMAGES_DIRS,\n                                        image_ids = train.image_id.values,\n                                        labels = train.label.values,\n                                        transform = self.train_transform)\n    self.valid_dataset = CassavaDataset(IMAGES_DIRS,\n                                        image_ids = val.image_id.values,\n                                        labels = val.label.values,\n                                        transform = self.test_transform)\n  \n  def train_dataloader(self):\n    return DataLoader(self.train_dataset,\n                      batch_size=BATCH_SIZE,\n                      num_workers=4,\n                      shuffle=True)\n  \n  def val_dataloader(self):\n    return DataLoader(self.valid_dataset,\n                      batch_size=BATCH_SIZE,\n                      num_workers=4)\n  \n  #def test_dataloader(self):\n   # pass","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Saving Models in each epoch as *.ckpt*"},{"metadata":{"trusted":true},"cell_type":"code","source":"model_checkpoint = ModelCheckpoint(monitor = \"val_loss\",\n                                   verbose=True,\n                                   filename=\"{epoch}_{val_loss:.4f}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Finally- Trainer"},{"metadata":{"trusted":true},"cell_type":"code","source":"dm = CassavaDataModule()\ncassava_model = CassavaEfficientNet()\n\n#CPU:default,GPU:gpus,TPU:tpu_cores\ntrainer = pl.Trainer(gpus=-1,\n                     max_epochs=6,\n                     callbacks=[model_checkpoint]) \ntrainer.fit(model=cassava_model,\n            datamodule=dm) \n\n#manually you can save best checkpoints - \ntrainer.save_checkpoint(\"cassava_efficient_net.ckpt\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# INFERENCE "},{"metadata":{},"cell_type":"markdown","source":"## Setting Inference Data Loader"},{"metadata":{"trusted":true},"cell_type":"code","source":"TEST_IMAGE_DIRS = \"../input/cassava-leaf-disease-classification/test_images/\"\ntest = pd.read_csv(\"../input/cassava-leaf-disease-classification/sample_submission.csv\")\n\n\n#this is inference dataset object, as it does not have labels\nclass CassavaTestData(Dataset):\n  def __init__(self,path,image_ids):\n    super().__init__()\n    self.image_ids = image_ids\n    self.path = path\n    self.transform = A.Compose([A.Resize(IMG_SIZE,IMG_SIZE),\n                             A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n                             ToTensor()])\n      \n  def __len__(self):\n    return len(self.image_ids)\n  \n  def __getitem__(self,item):\n    image_id = str(self.image_ids[item])\n    image = cv2.imread(self.path+image_id)\n    image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)\n    image = self.transform(image=image)\n    return {\n        \"x\":image[\"image\"],\n    }\ntest_dataset = CassavaTestData(path = TEST_IMAGE_DIRS,\n                              image_ids = test.image_id.values)\ntest_loader = DataLoader(test_dataset,\n                        batch_size=32)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Freeze trained model and predict"},{"metadata":{"trusted":true},"cell_type":"code","source":"#loading the best checkpoints to model\nbest_checkpoints = trainer.checkpoint_callback.best_model_path\npretrained_model = CassavaEfficientNet.load_from_checkpoint(checkpoint_path = best_checkpoints)\npretrained_model = pretrained_model.to(\"cuda\")\npretrained_model.eval()\npretrained_model.freeze()\n\nfin_out = []\nfor data in test_loader:\n    y_hat = pretrained_model(data[\"x\"].to(\"cuda\"))\n    y_hat = torch.argmax(y_hat,dim=1)\n    fin_out.extend(y_hat.cpu().detach().numpy().tolist())\ntest[\"label\"] = fin_out\ntest[[\"image_id\",\"label\"]].to_csv(\"submission.csv\",index=False)\ntest.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#uncomment below lines to view the tensorboard\n#%load_ext tensorboard\n#%tensorboard --logdir ./lightning_logs","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}