{"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":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom skimage.io import imread\nimport torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nfrom torch.utils.data import Dataset,DataLoader\nfrom torchvision.io import read_image\nimport os\nimport cv2\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.metrics import accuracy_score,roc_auc_score\nimport time\nimport copy\nfrom tqdm import tqdm_notebook as tqdm\n\nimport warnings\nwarnings.filterwarnings(\"ignore\", category=DeprecationWarning)\nwarnings.filterwarnings(\"ignore\", category=UserWarning)\nwarnings.filterwarnings(\"ignore\", category=FutureWarning)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-02-24T17:08:12.463745Z","iopub.execute_input":"2022-02-24T17:08:12.464891Z","iopub.status.idle":"2022-02-24T17:08:16.736564Z","shell.execute_reply.started":"2022-02-24T17:08:12.464728Z","shell.execute_reply":"2022-02-24T17:08:16.735432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Hyper Paramaters","metadata":{}},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nnum_epochs = 30\nbatch_size = 256\nnum_classes = 2\nlearning_rate = 0.01","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:16.739114Z","iopub.execute_input":"2022-02-24T17:08:16.739759Z","iopub.status.idle":"2022-02-24T17:08:16.802004Z","shell.execute_reply.started":"2022-02-24T17:08:16.739711Z","shell.execute_reply":"2022-02-24T17:08:16.800933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path='../input/histopathologic-cancer-detection/train/'\nannotation_file='../input/histopathologic-cancer-detection/train_labels.csv'\ntest_path='../input/histopathologic-cancer-detection/test/'","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:16.805281Z","iopub.execute_input":"2022-02-24T17:08:16.805739Z","iopub.status.idle":"2022-02-24T17:08:16.816079Z","shell.execute_reply.started":"2022-02-24T17:08:16.805679Z","shell.execute_reply":"2022-02-24T17:08:16.815062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data =pd.read_csv('../input/histopathologic-cancer-detection/train_labels.csv')\nsub = pd.read_csv('../input/histopathologic-cancer-detection/sample_submission.csv')\ntrain_data.head()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:16.820419Z","iopub.execute_input":"2022-02-24T17:08:16.821138Z","iopub.status.idle":"2022-02-24T17:08:17.474341Z","shell.execute_reply.started":"2022-02-24T17:08:16.821092Z","shell.execute_reply":"2022-02-24T17:08:17.473363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Check data balanced","metadata":{}},{"cell_type":"code","source":"plt.pie(train_data.label.value_counts(), labels=['No Cancer', 'Cancer'], colors=['#90EE91', '#F47174'], autopct='%1.1f')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:17.476341Z","iopub.execute_input":"2022-02-24T17:08:17.476768Z","iopub.status.idle":"2022-02-24T17:08:17.628575Z","shell.execute_reply.started":"2022-02-24T17:08:17.476692Z","shell.execute_reply":"2022-02-24T17:08:17.627612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cancer = np.random.choice(train_data[train_data.label==1].id, size=50, replace=False)\nno_cancer = np.random.choice(train_data[train_data.label==0].id, size=50, replace=False)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:17.630598Z","iopub.execute_input":"2022-02-24T17:08:17.631224Z","iopub.status.idle":"2022-02-24T17:08:17.676120Z","shell.execute_reply.started":"2022-02-24T17:08:17.631175Z","shell.execute_reply":"2022-02-24T17:08:17.674919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualize the cancer images","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(5, 10, figsize=(20,10))\n\nfor n in range(5):\n    for m in range(10):\n        img_id = cancer[m + n*10]\n        image = plt.imread(path + img_id + \".tif\")\n        ax[n,m].imshow(image)\n        ax[n,m].grid(False)\n        ax[n,m].tick_params(labelbottom=False, labelleft=False)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:17.678246Z","iopub.execute_input":"2022-02-24T17:08:17.678903Z","iopub.status.idle":"2022-02-24T17:08:23.986525Z","shell.execute_reply.started":"2022-02-24T17:08:17.678856Z","shell.execute_reply":"2022-02-24T17:08:23.985466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualize Not cancer images","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(5, 10, figsize=(20,10))\n\nfor n in range(5):\n    for m in range(10):\n        img_id = no_cancer[m + n*10]\n        image = plt.imread(path + img_id + \".tif\")\n        ax[n,m].imshow(image)\n        ax[n,m].grid(False)\n        ax[n,m].tick_params(labelbottom=False, labelleft=False)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:23.988520Z","iopub.execute_input":"2022-02-24T17:08:23.988893Z","iopub.status.idle":"2022-02-24T17:08:30.280240Z","shell.execute_reply.started":"2022-02-24T17:08:23.988831Z","shell.execute_reply":"2022-02-24T17:08:30.279436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## train validation split","metadata":{}},{"cell_type":"code","source":"train, val = train_test_split(train_data, stratify=train_data['label'], test_size=0.1)\nprint(len(train), len(val))","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:30.281989Z","iopub.execute_input":"2022-02-24T17:08:30.282702Z","iopub.status.idle":"2022-02-24T17:08:30.406211Z","shell.execute_reply.started":"2022-02-24T17:08:30.282650Z","shell.execute_reply":"2022-02-24T17:08:30.404915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1, 2, figsize=(10,4))\n\nsns.countplot(train.label, palette=\"Blues\", ax=ax[0])\nax[0].set_title(\"Train dataset\")\nfor i, rows in enumerate(train['label'].value_counts().values):\n    ax[0].annotate(int(rows), xy=(i, rows), ha='center')\nsns.countplot(val.label, palette=\"Greens\", ax=ax[1])\nax[1].set_title(\"Validation dataset\")\nfor i, rows in enumerate(val['label'].value_counts().values):\n    ax[1].annotate(int(rows), xy=(i, rows), ha='center')","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:30.410831Z","iopub.execute_input":"2022-02-24T17:08:30.411262Z","iopub.status.idle":"2022-02-24T17:08:30.794834Z","shell.execute_reply.started":"2022-02-24T17:08:30.411230Z","shell.execute_reply":"2022-02-24T17:08:30.793974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset Class","metadata":{}},{"cell_type":"code","source":"class Dataset(Dataset):\n    \n    def __init__(self, df_data, data_dir = './', transform=None):\n        super().__init__()\n        self.df = df_data.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        img_path = os.path.join(self.data_dir, img_name + '.tif')\n        image = cv2.imread(img_path)\n        if self.transform is not None:\n            image = self.transform(image)\n        return image, label","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:30.798577Z","iopub.execute_input":"2022-02-24T17:08:30.798801Z","iopub.status.idle":"2022-02-24T17:08:30.806704Z","shell.execute_reply.started":"2022-02-24T17:08:30.798771Z","shell.execute_reply":"2022-02-24T17:08:30.805398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform_train = transforms.Compose([transforms.ToPILImage(),\n                                  transforms.RandomHorizontalFlip(), \n                                  transforms.RandomVerticalFlip(),\n                                  transforms.RandomRotation(20), \n                                  transforms.ToTensor(),\n                                  transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])])\n\ntransform_val = transforms.Compose([transforms.ToPILImage(),\n                                  transforms.ToTensor(),\n                                  transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])])\n\ntransform_test = transforms.Compose([transforms.ToPILImage(), \n                                  transforms.ToTensor(),\n                                  transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])])","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:30.808769Z","iopub.execute_input":"2022-02-24T17:08:30.809142Z","iopub.status.idle":"2022-02-24T17:08:30.821497Z","shell.execute_reply.started":"2022-02-24T17:08:30.809073Z","shell.execute_reply":"2022-02-24T17:08:30.820451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = Dataset(df_data=train, data_dir=path, transform=transform_train)\nval_dataset = Dataset(df_data=val, data_dir=path, transform=transform_val)\ntest_dataset = Dataset(df_data=sub, data_dir=test_path, transform=transform_test)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:30.823358Z","iopub.execute_input":"2022-02-24T17:08:30.824077Z","iopub.status.idle":"2022-02-24T17:08:30.855328Z","shell.execute_reply.started":"2022-02-24T17:08:30.824034Z","shell.execute_reply":"2022-02-24T17:08:30.854459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True,num_workers=4)\nval_dataloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=4)\ntest_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:30.857138Z","iopub.execute_input":"2022-02-24T17:08:30.857719Z","iopub.status.idle":"2022-02-24T17:08:30.864595Z","shell.execute_reply.started":"2022-02-24T17:08:30.857679Z","shell.execute_reply":"2022-02-24T17:08:30.863447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CNN(nn.Module):\n    def __init__(self):\n        super(CNN,self).__init__()\n        \n        self.conv1 = nn.Sequential(\n                        nn.Conv2d(3, 32, 3, stride=1, padding=1),\n                        nn.BatchNorm2d(32),\n                        nn.ReLU(inplace=True),\n                        nn.MaxPool2d(2,2))\n        \n        self.conv2 = nn.Sequential(\n                        nn.Conv2d(32, 64, 3, stride=1, padding=1),\n                        nn.BatchNorm2d(64),\n                        nn.ReLU(inplace=True),\n                        nn.MaxPool2d(2,2))\n        \n        self.conv3 = nn.Sequential(\n                        nn.Conv2d(64, 128, 3, stride=1, padding=1),\n                        nn.BatchNorm2d(128),\n                        nn.ReLU(inplace=True),\n                        nn.MaxPool2d(2,2))\n        \n        self.conv4 = nn.Sequential(\n                        nn.Conv2d(128, 256, 3, stride=1, padding=1),\n                        nn.BatchNorm2d(256),\n                        nn.ReLU(inplace=True),\n                        nn.MaxPool2d(2,2))\n        \n        self.conv5 = nn.Sequential(\n                        nn.Conv2d(256, 512, 3, stride=1, padding=1),\n                        nn.BatchNorm2d(512),\n                        nn.ReLU(inplace=True),\n                        nn.MaxPool2d(2,2))\n        \n        \n        self.fc=nn.Sequential(\n                nn.Linear(512*3*3, 256),\n                nn.ReLU(inplace=True),\n                nn.BatchNorm1d(256),\n                nn.Dropout(0.4),\n                nn.Linear(256, num_classes))\n        \n    def forward(self,x):\n        x=self.conv1(x)\n        x=self.conv2(x)\n        x=self.conv3(x)\n        x=self.conv4(x)\n        x=self.conv5(x)\n#        print(x.shape)\n        x=x.view(x.shape[0],-1)\n        x=self.fc(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:30.866776Z","iopub.execute_input":"2022-02-24T17:08:30.867157Z","iopub.status.idle":"2022-02-24T17:08:30.885580Z","shell.execute_reply.started":"2022-02-24T17:08:30.867116Z","shell.execute_reply":"2022-02-24T17:08:30.884246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = CNN().to(device)\nprint(model)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:30.888193Z","iopub.execute_input":"2022-02-24T17:08:30.889302Z","iopub.status.idle":"2022-02-24T17:08:34.200182Z","shell.execute_reply.started":"2022-02-24T17:08:30.889256Z","shell.execute_reply":"2022-02-24T17:08:34.199126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:34.201526Z","iopub.execute_input":"2022-02-24T17:08:34.202636Z","iopub.status.idle":"2022-02-24T17:08:34.208147Z","shell.execute_reply.started":"2022-02-24T17:08:34.202590Z","shell.execute_reply":"2022-02-24T17:08:34.207155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_losses = []\nval_losses = []\ntrain_auc = []\nval_auc = []\ntrain_auc_epoch = []\nval_auc_epoch = []\nbest_acc = 0.0\nmin_loss = np.Inf\n\nsince = time.time()\n\nfor e in range(num_epochs):\n    \n    train_loss = 0.0\n    val_loss = 0.0\n    \n    # Train the model\n    model.train()\n    for i, (images, labels) in enumerate(tqdm(train_dataloader, total=int(len(train_dataloader)))):\n        images = images.to(device)\n        labels = labels.to(device)\n        \n        # Forward pass\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        \n        # Backward and optimize\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        # Loss and accuracy\n        train_loss += loss.item()\n        y_actual = labels.data.cpu().numpy()\n        y_pred = outputs[:,-1].detach().cpu().numpy()\n        train_auc.append(roc_auc_score(y_actual, y_pred))\n    \n    # Evaluate the model\n    model.eval()\n    for i, (images, labels) in enumerate(tqdm(val_dataloader, total=int(len(val_dataloader)))):\n        images = images.to(device)\n        labels = labels.to(device)\n        \n        # Forward pass\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        \n        # Loss and accuracy\n        val_loss += loss.item()\n        y_actual = labels.data.cpu().numpy()\n        y_pred = outputs[:,-1].detach().cpu().numpy()\n        val_auc.append(roc_auc_score(y_actual, y_pred))\n    \n    # Average losses and accuracies\n    train_loss = train_loss/len(train_dataloader)\n    val_loss = val_loss/len(val_dataloader)\n    train_losses.append(train_loss)\n    val_losses.append(val_loss)\n    training_auc = np.mean(train_auc)\n    validation_auc = np.mean(val_auc)\n    train_auc_epoch.append(training_auc)\n    val_auc_epoch.append(validation_auc)\n    \n    # Updating best validation accuracy\n    if best_acc < validation_auc:\n        best_acc = validation_auc\n        \n    # Saving best model\n    if min_loss >= val_loss:\n        torch.save(model.state_dict(), 'best_model.pt')\n        min_loss = val_loss\n    \n    print('EPOCH {}/{} Train loss: {:.6f},Validation loss: {:.6f}, Train AUC: {:.4f}  Validation AUC: {:.4f}\\n  '.format(e+1, num_epochs,train_loss,val_loss, training_auc,validation_auc))\n    print('-' * 10)\ntime_elapsed = time.time() - since\nprint('Training completed in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))\nprint('Best validation accuracy: {:4f}'.format(best_acc))","metadata":{"execution":{"iopub.status.busy":"2022-02-24T17:08:34.209754Z","iopub.execute_input":"2022-02-24T17:08:34.210600Z","iopub.status.idle":"2022-02-24T19:13:33.429815Z","shell.execute_reply.started":"2022-02-24T17:08:34.210557Z","shell.execute_reply":"2022-02-24T19:13:33.428861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20,5))\nplt.plot(train_losses, '-o', label=\"train\")\nplt.plot(val_losses, '-o', label=\"val\")\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"Loss\")\nplt.title(\"Loss change over epoch\")\nplt.legend()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T19:13:33.433684Z","iopub.execute_input":"2022-02-24T19:13:33.433954Z","iopub.status.idle":"2022-02-24T19:13:33.744484Z","shell.execute_reply.started":"2022-02-24T19:13:33.433919Z","shell.execute_reply":"2022-02-24T19:13:33.743357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20,5))\nplt.plot(train_auc_epoch, '-o', label=\"train\")\nplt.plot(val_auc_epoch, '-o', label=\"val\")\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"Accuracy\")\nplt.title(\"Accuracy over epoch\")\nplt.legend()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T19:13:33.747029Z","iopub.execute_input":"2022-02-24T19:13:33.747747Z","iopub.status.idle":"2022-02-24T19:13:34.049465Z","shell.execute_reply.started":"2022-02-24T19:13:33.747698Z","shell.execute_reply":"2022-02-24T19:13:34.048436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_state_dict(torch.load('best_model.pt'))\n","metadata":{"execution":{"iopub.status.busy":"2022-02-24T19:13:34.052668Z","iopub.execute_input":"2022-02-24T19:13:34.052914Z","iopub.status.idle":"2022-02-24T19:13:34.080830Z","shell.execute_reply.started":"2022-02-24T19:13:34.052884Z","shell.execute_reply":"2022-02-24T19:13:34.079675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\n\npredictions = []\n\nfor i, (images, labels) in enumerate(tqdm(test_dataloader, total=int(len(test_dataloader)))):\n    images = images.to(device)\n    labels = labels.to(device)\n    \n    outputs = model(images)\n    pred = outputs[:,1].detach().cpu().numpy()\n    \n    for j in pred:\n        predictions.append(j)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T19:13:34.082738Z","iopub.execute_input":"2022-02-24T19:13:34.083111Z","iopub.status.idle":"2022-02-24T19:23:54.418636Z","shell.execute_reply.started":"2022-02-24T19:13:34.083039Z","shell.execute_reply":"2022-02-24T19:23:54.417654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub['label'] = predictions\nsub.to_csv('submission.csv', index=False)\nsub.info()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T19:23:54.420564Z","iopub.execute_input":"2022-02-24T19:23:54.421137Z","iopub.status.idle":"2022-02-24T19:23:54.750762Z","shell.execute_reply.started":"2022-02-24T19:23:54.421092Z","shell.execute_reply":"2022-02-24T19:23:54.749070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_images = np.random.choice(sub.id, size=50, replace=False)     \n\nfig, ax = plt.subplots(5, 10, figsize=(20,10))\n\nfor n in range(5):\n    for m in range(10):\n        img_id = test_images[m + n*10]\n        image = plt.imread(test_path + img_id + \".tif\")\n        pred = sub.loc[sub['id'] == img_id, 'label'].values[0]\n        label = \"Cancer\" if(pred >= 0.5) else \"Healthy\"  \n        ax[n,m].imshow(image)\n        ax[n,m].grid(False)\n        ax[n,m].tick_params(labelbottom=False, labelleft=False)\n        ax[n,m].set_title(\"Label: \" + label)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T19:23:54.752731Z","iopub.execute_input":"2022-02-24T19:23:54.753285Z","iopub.status.idle":"2022-02-24T19:24:01.268954Z","shell.execute_reply.started":"2022-02-24T19:23:54.753237Z","shell.execute_reply":"2022-02-24T19:24:01.266531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}