{"cells":[{"metadata":{},"cell_type":"markdown","source":"Introduction\n* Predicting protein organelle localization labels for each cell in the image.\n* Dataset:  \n    - There are four filter images of each cell. In this implementation we are using only 3 as per the host suggestion.\n    - Concatenation of Red, Yellow and Blue to form 3-channel. Resize, cropping and normalization of image to pipline to model.\n    - Final image size will be 224 for the model.\n* Model - [EfficientNet](https://github.com/lukemelas/EfficientNet-PyTorch) :\n    - Pretrained `efficientnet-b0` is used for casual results, it can be further improved with higher models and optimization.\n* Loss: `BCEWithLogitsLoss` from pytorch\n* Optimizer: 'AdamW' optimizer , adam with weight decay generalizes well compare with adam."},{"metadata":{"trusted":true,"_kg_hide-output":true,"collapsed":true},"cell_type":"code","source":"!pip install efficientnet_pytorch","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Importing Libraries"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"from efficientnet_pytorch import EfficientNet\n\nimport os \nimport sys \nfrom glob import glob\nfrom tqdm import tqdm\n\nimport numpy as np \nimport pandas as pd \npd.options.display.max_columns = 100\n\n%matplotlib inline\nimport matplotlib.pyplot as plt\n\nimport torch \ntorch.manual_seed(12)\nfrom torch import nn \nimport torch.nn.functional  as F \nfrom torch.utils.data import Dataset,DataLoader\nimport torchvision \nfrom torchvision import transforms, utils \nfrom PIL import Image\n\nfrom sklearn.metrics import f1_score\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import MultiLabelBinarizer","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Read csv file"},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAIN_IMAGES = \"../input/hpa-single-cell-image-classification/train/\"\nTEST_IMAGES = \"../input/hpa-single-cell-image-classification/test/\"\ntrain = pd.read_csv(\"../input/hpa-single-cell-image-classification/train.csv\")\nsample = pd.read_csv(\"../input/hpa-single-cell-image-classification/sample_submission.csv\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Prelimanary Study"},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"train columns\",train.columns)\nprint(\"test columns\",sample.columns)\nprint(\"train shape\",train.shape,\"test shape\",sample.shape)\nmlb = MultiLabelBinarizer()\ntrain.Label = train.Label.apply(lambda x: list(map(int,x.split(\"|\"))))\ntrain[list(range(19))] = mlb.fit_transform(train.Label)\nprint(\"different classes created\",mlb.classes_)\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Creating Dataset Generator"},{"metadata":{"trusted":true},"cell_type":"code","source":"class ProteinOrganelleDataset(Dataset):\n    def __init__(self,images_path,image_ids,labels,transform=None):\n        super().__init__()\n        self.transform = transform\n        self.images_path = images_path\n        self.image_ids = image_ids\n        self.labels = labels\n        self.filters = [\"yellow\", \"blue\", \"red\"]\n    def __len__(self):\n        return len(self.image_ids)\n    \n    def __getitem__(self,idx):\n        image_ids = self.image_ids[idx]\n        images_path = [os.path.join(self.images_path,str(image_ids)+\"_\"+i+\".png\") for i in self.filters]\n        images = [np.asarray(Image.open(img)) for img in images_path]\n        images = np.concatenate([np.expand_dims(img,-1) for img in images],axis=-1)\n        images = Image.fromarray(images)\n        if self.transform:\n             images = self.transform(images) \n        labels = self.labels[idx,:]\n        return {\n            \"images\": images,\n            \"labels\": torch.tensor(labels,dtype=torch.float)\n        }","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Image Transformations"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_transform = transforms.Compose([\n                transforms.Resize(250),\n                transforms.CenterCrop(224),\n                transforms.ToTensor(),\n                transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                 std=[0.229, 0.224, 0.225]),])\nvalidation_transform = transforms.Compose([\n                transforms.Resize(250),\n                transforms.CenterCrop(224),\n                transforms.ToTensor(),\n                transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                 std=[0.229, 0.224, 0.225]),])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Prepare DataLoader"},{"metadata":{"trusted":true},"cell_type":"code","source":"def dataloader(batchsize):\n    dfx = pd.read_csv(\"../input/hpa-single-cell-image-classification/train.csv\")\n    mlb = MultiLabelBinarizer()\n    dfx.Label = dfx.Label.apply(lambda x: list(map(int,x.split(\"|\"))))\n    dfx[list(range(19))] = mlb.fit_transform(dfx.Label)\n    train,val = train_test_split(dfx,test_size=0.25)\n    train_dataset = ProteinOrganelleDataset(images_path=TRAIN_IMAGES,\n                                   image_ids=train.ID.values,\n                                   labels=train.iloc[:,-19:].values,\n                                    transform = train_transform)\n    validation_dataset = ProteinOrganelleDataset(images_path=TRAIN_IMAGES,\n                                   image_ids=val.ID.values,\n                                   labels=val.iloc[:,-19:].values,\n                                    transform = train_transform)\n    train_dataloader = DataLoader(train_dataset,batch_size=batchsize,shuffle=True,num_workers=4)\n    validation_dataloader = DataLoader(validation_dataset,batch_size=batchsize,shuffle=False,num_workers=4)\n    return train_dataloader, validation_dataloader\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Visualization"},{"metadata":{"trusted":true},"cell_type":"code","source":"data_loader,_ = dataloader(5)\ndata = next(iter(data_loader))\n\ndef show(img):\n    npimg = img.numpy()\n    plt.figure(figsize=(20, 50))\n    plt.imshow(np.transpose(npimg, (1,2,0)))\n    \nshow(utils.make_grid(data[\"images\"],padding=10,normalize=True))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Creating the Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"class EfficientNetProtein(nn.Module):\n    def __init__(self,n_classes=19):\n        super().__init__()\n        self.efficientnet = EfficientNet.from_pretrained('efficientnet-b0',num_classes=n_classes)\n    \n    def forward(self,img):\n        out = self.efficientnet(img)\n        return out             ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Training and Validation Functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_fn(dataloader,model,optimizer,device):\n    model.train()\n    f_output=[]\n    f_target=[]\n    losses = []\n    for d in tqdm(dataloader,total=len(dataloader)):\n        images = d[\"images\"].to(device)\n        targets = d[\"labels\"].to(device)\n        optimizer.zero_grad()\n        out = model(images)\n        loss = loss_fn(out,targets)\n        loss.backward()\n        optimizer.step()\n        losses.append(loss.cpu().detach().numpy())\n        outs = torch.sigmoid(out.cpu().detach())\n        outs = np.round(outs.numpy())\n        f_output.extend(outs)\n        f_target.extend(targets.cpu().detach().numpy())\n    f1 = f1_score(f_target,f_output,average=\"macro\")\n    return sum(losses)/len(dataloader),f1\n\ndef validation_fn(dataloader,model,device):\n    model.eval()\n    f_output=[]\n    f_target=[]\n    losses = []\n    with torch.no_grad():\n        for d in tqdm(dataloader,total=len(dataloader)):\n            images = d[\"images\"].to(device)\n            targets = d[\"labels\"].to(device)\n            out = model(images)\n            loss = loss_fn(out,targets)\n            losses.append(loss.cpu().detach().numpy())\n            outs = torch.sigmoid(out.cpu().detach())\n            outs = np.round(outs.numpy())\n            f_output.extend(outs)\n            f_target.extend(targets.cpu().detach().numpy())\n    f1 = f1_score(f_target,f_output,average=\"macro\")\n    return sum(losses)/len(dataloader),f1\n\ndef loss_fn(output,target):\n    return nn.BCEWithLogitsLoss()(output,target)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Training the Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"EPOCHS=5\nTRAINED_MODEL = \"protein_efficientnet.pth\"\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\ndef run():\n    train_dataloader,validation_dataloader = dataloader(batchsize=64) \n    model = EfficientNetProtein()\n    model.to(DEVICE)\n    optimizer = torch.optim.AdamW(model.parameters()) \n    print(f\"TRAINING on {str(DEVICE).upper()}...\")\n    best_loss = np.inf\n    save_table = np.zeros(shape=(EPOCHS,4))\n    for e in range(EPOCHS):\n        train_loss,train_f1 = train_fn(train_dataloader,model,optimizer,DEVICE)\n        validation_loss,val_f1 = validation_fn(validation_dataloader,model,DEVICE) \n        if validation_loss<best_loss:\n            best_loss = validation_loss\n            print(f\"model saved at {best_loss:.4f} loss\")\n            torch.save(model.state_dict(),TRAINED_MODEL)\n        print(f\"Epoch:{e+1} | train: loss {train_loss:.5f} f1 {train_f1:.5f} | val: loss {validation_loss:.5f} f1 {val_f1:.5f}\")\n        save_table[e,:] = train_loss,train_f1,validation_loss,val_f1\n    np.savetxt(f\"{model.__class__.__name__}_{EPOCHS}.txt\",save_table,delimiter=\",\")        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"run() ","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}