{"cells":[{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"scrolled":true},"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\nfrom os.path import isfile\nimport torch.nn.init as init\nimport torch\nimport torch.nn as nn\nimport numpy as np\nimport pandas as pd \nimport os\nfrom PIL import Image\n#from keras.preprocessing.image import img_to_array, array_to_img\nprint(os.listdir(\"../input\"))\nfrom sklearn.model_selection import train_test_split\nfrom torch.utils.data import Dataset\nfrom torchvision import transforms\nfrom torch.optim import Adam, SGD\nimport time\nfrom torch.autograd import Variable\nimport torch.functional as F\nfrom tqdm import tqdm\nfrom sklearn import metrics\nimport urllib\nimport pickle\nimport cv2\nimport torch.nn.functional as F\nfrom torchvision import models\nimport seaborn as sns","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"766f44c87272f67d632e519dce11cf54a3382696"},"cell_type":"code","source":"train = '../input/train/'\ntest = '../input/test/'\ntrain_labels = pd.read_csv('../input/train_labels.csv')\ncancer = train_labels[train_labels.label == 1].id.values\nno_cancer = train_labels[train_labels.label == 0].id.values\nprint(len(cancer))\nprint(len(no_cancer))\nlr = 0.01\nn_epochs = 10\n\ntrain_df, val_df = train_test_split(train_labels, test_size=0.2, random_state=2018)\ntrain_df.to_csv('../working/train.csv', index=False)\nval_df.to_csv('../working/val.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"64d7e44b053ac654c681e77b04de74ba32020fbd"},"cell_type":"code","source":"def expand_path(p):\n    if isfile(train + p + \".tif\"):\n        return train + (p + \".tif\")\n    if isfile(test + p + \".tif\"):\n        return test + (p + \".tif\")\n    return p\n\ndef p_show(imgs, label_name, per_row=3):\n    n = len(imgs)\n    rows = (n + per_row - 1)//per_row\n    cols = min(per_row, n)\n    fig, axes = plt.subplots(rows,cols, figsize=(15,15))\n    for ax in axes.flatten(): ax.axis('off')\n    for i,(img,ax) in enumerate(zip(imgs, axes.flatten())): \n       #img = array_to_img(img)\n        ax.imshow(img) \n    fig.suptitle(label_name)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b4739904397dd22d058c36769034b91964dcb9fe"},"cell_type":"code","source":"cancer_imgs = []\nno_cancer_imgs = []\nfor p in cancer:\n    img = Image.open(expand_path(p))\n    cancer_imgs.append(img)\n    if len(cancer_imgs) == 12: break\n        \nfor p in no_cancer:\n    img = Image.open(expand_path(p))\n    no_cancer_imgs.append(img)\n    if len(no_cancer_imgs) == 12: break\n        \np_show(cancer_imgs, 'cancer')\np_show(no_cancer_imgs, 'no_cancer')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"21908baa8df4e398b0d49a5146ce544504637c5a"},"cell_type":"code","source":"#torch.utils.data.Dataset\n#All other datasets should subclass it. All subclasses should override __len__, that provides the size of the dataset, \n#and __getitem__, supporting integer indexing in range from 0 to len(self) exclusive.\n\nclass MyDataset(Dataset):\n    \n    def __init__(self, file_path, root_path, transform=None):\n        self.csv = pd.read_csv(file_path)\n        self.root_path = root_path\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.csv)\n    \n    def __getitem__(self, idx):\n        \n        label = self.csv.label.values[idx]\n        label = np.expand_dims(label,-1)\n        p = self.csv.id.values[idx]\n        p_path = os.path.join(self.root_path, p +'.tif')\n        #print(p_path)\n        img = Image.open(p_path)\n        #img = img_to_array(img)\n        \n        if self.transform:\n            img = self.transform(img)\n        \n        return img, label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f590638fd07b9aefe2210a39612ac77e0689c0c1"},"cell_type":"code","source":"#ToTensorはnumpy形式のデータをpytorchでの計算に用いるtensor型へ変換する役割があります．\n#自分定義したTransform, callメソッドの中にデータに加えたい処理を書きます．\n#標準で用意されているTransformを用いる際はデータ形式をPIL Imageにする必要があります\n    \ntrain_transform = transforms.Compose([\n    transforms.RandomHorizontalFlip(),\n    #transforms.RandomCrop((96, 96), padding=4),\n    transforms.ToTensor()])\ntest_transform = transforms.Compose([transforms.ToTensor()])\n\ntrainset = MyDataset('../working/train.csv', root_path=\"../input/train\", transform=train_transform)\ntrain_loader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)\nvalset = MyDataset('../working/val.csv', root_path=\"../input/train\", transform=test_transform)\nval_loader = torch.utils.data.DataLoader(valset, batch_size=32, shuffle=False)\n\ntestset = MyDataset('../input/sample_submission.csv', root_path=\"../input/test\", transform=test_transform)\ntest_loader = torch.utils.data.DataLoader(testset, batch_size=32, shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"46ede4c1cf8e90bf831d2125e7359a8c643f2a68"},"cell_type":"code","source":"class ResUnit(nn.Module):\n\n    def __init__(self, inplanes, outplanes, stride=1):\n\n        \"\"\"\n        Residual Unit\n        \"\"\"\n        super(ResUnit, self).__init__()\n        self.conv1 = nn.Conv2d(inplanes, int(outplanes/4), kernel_size=1, bias=True)\n        self.bn1 = nn.BatchNorm2d(inplanes)\n        self.conv2 = nn.Conv2d(int(outplanes/4), int(outplanes/4), kernel_size=3, stride=stride, padding=1, bias=False)\n        self.bn2 = nn.BatchNorm2d(int(outplanes/4))\n        self.conv3 = nn.Conv2d(int(outplanes/4), outplanes, kernel_size=1, bias=True)\n        self.bn3 = nn.BatchNorm2d(int(outplanes/4))\n        self.relu = nn.ReLU(inplace=True)\n        self.inplanes = inplanes\n        self.outplanes = outplanes\n        self.stride = stride\n        self.make_downsample = nn.Conv2d(self.inplanes, self.outplanes, kernel_size=1,stride=stride, bias=False)\n\n    def forward(self, x):\n\n        residual = x\n\n        out = self.bn1(x)\n        out = self.relu(out)\n        out = self.conv1(out)\n\n        out = self.bn2(out)\n        out = self.relu(out)\n        out = self.conv2(out)\n\n        out = self.bn3(out)\n        out = self.relu(out)\n        out = self.conv3(out)\n\n        if (self.inplanes != self.outplanes) or (self.stride !=1 ):\n            residual = self.make_downsample(residual)\n\n        out += residual\n\n        return out","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0af1a12bbc88151f9e90817511347171d4d86711"},"cell_type":"code","source":"class AttentionModule_stage1(nn.Module):\n\n    def __init__(self, inplanes, outplanes, size1, size2, size3):\n        \"\"\"\n        max_pooling layers are used in mask branch size with input\n        \"\"\"\n        super(AttentionModule_stage1, self).__init__()\n        self.size1 = size1\n        self.size2 = size2\n        self.size3 = size3\n        self.Resblock1 = ResUnit(inplanes, outplanes) #first residual block\n\n        self.trunkbranch = nn.Sequential(ResUnit(inplanes, outplanes),\n                                         ResUnit(inplanes, outplanes))\n\n        self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.Resblock2 = ResUnit(inplanes, outplanes)\n        self.skip1 = ResUnit(inplanes, outplanes)\n\n        self.maxpool2 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.Resblock3 = ResUnit(inplanes, outplanes)\n        self.skip2 = ResUnit(inplanes, outplanes)\n\n        self.maxpool3 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.Resblock4 = nn.Sequential(ResUnit(inplanes, outplanes),\n                                       ResUnit(inplanes, outplanes))\n\n\n        #self.upsample3 = nn.UpsamplingBilinear2d(size=size3)\n        self.Resblock5 = ResUnit(inplanes, outplanes)\n\n        #self.upsample2 = nn.UpsamplingBilinear2d(size=size2)\n        self.Resblock6 = ResUnit(inplanes, outplanes)\n\n        #self.upsample1 = nn.UpsamplingBilinear2d(size=size1)\n\n        self.output_block = nn.Sequential(nn.BatchNorm2d(outplanes),\n                                    nn.ReLU(inplace=True),\n                                    nn.Conv2d(outplanes, outplanes, kernel_size=1, stride=1, bias=False),\n                                    nn.BatchNorm2d(outplanes),\n                                    nn.ReLU(inplace=True),\n                                    nn.Conv2d(outplanes, outplanes, kernel_size=1, stride=1, bias=False),\n                                    nn.Sigmoid())\n\n        self.last_block =  ResUnit(inplanes, outplanes)\n\n    def forward(self, x):\n        # The Number of pre-processing Residual Units Before\n        # Splitting into trunk branch and mask branch is 1.\n        # 48*48\n        x = self.Resblock1(x)\n\n        # The output of trunk branch\n        out_trunk = self.trunkbranch(x)\n\n        #soft Mask Branch\n        #The Number of Residual Units between adjacent pooling layer is 1.\n        pool1 = self.maxpool1(x) # (48,48) -> (24,24)\n        out_softmask1 = self.Resblock2(pool1)\n        skip_connection1 = self.skip1(pool1) #\"skip_connection\"\n\n        pool2 = self.maxpool2(out_softmask1) #(24,24) -> (12,12)\n        out_softmask2 = self.Resblock3(pool2)\n        skip_connection2 = self.skip2(pool2)\n\n        pool3 = self.maxpool3(out_softmask2) #(12,12) -> (6,6)\n        out_softmask3 = self.Resblock4(pool3)\n\n        out_interp3 = nn.functional.interpolate(out_softmask3, size=self.size3, mode= 'bilinear', align_corners=True) #(6,6)->(12,12)\n        out = out_interp3 + skip_connection2\n        out_softmask4 = self.Resblock5(out)\n\n        out_interp2 = nn.functional.interpolate(out_softmask4, size=self.size2, mode= 'bilinear', align_corners=True) #(12,12)->(24,24)\n        out = out_interp2 + skip_connection1\n        out_softmask5 = self.Resblock6(out)\n\n        out_interp1 = nn.functional.interpolate(out_softmask5, size=self.size1, mode= 'bilinear', align_corners=True) #(24,24)->(48,48)\n        out_softmask6 = self.output_block(out_interp1)\n\n        out = (1 + out_softmask6) * out_trunk\n        last_out = self.last_block(out)\n\n        return last_out\n\nclass AttentionModule_stage2(nn.Module):\n\n    def __init__(self, inplanes, outplanes, size1, size2):\n        \"\"\"\n        max_pooling layers are used in mask branch size with input\n        \"\"\"\n        super(AttentionModule_stage2, self).__init__()\n        self.size1 = size1\n        self.size2 = size2\n        self.Resblock1 = ResUnit(inplanes, outplanes) #first residual block\n\n        self.trunkbranch = nn.Sequential(ResUnit(inplanes, outplanes),\n                                         ResUnit(inplanes, outplanes))\n\n        self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) # (24,24) -> (12,12)\n        self.Resblock2 = ResUnit(inplanes, outplanes)\n        self.skip1 = ResUnit(inplanes, outplanes)\n        self.maxpool2 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) # (12,12) -> (6,6)\n        self.Resblock3 = nn.Sequential(ResUnit(inplanes, outplanes),\n                                       ResUnit(inplanes, outplanes))\n        #self.upsample2 = nn.UpsamplingBilinear2d(size2)\n        self.Resblock4 = ResUnit(inplanes, outplanes)\n        #self.upsample1 = nn.UpsamplingBilinear2d(size1)\n\n        self.output_block = nn.Sequential(nn.BatchNorm2d(outplanes),\n                                    nn.ReLU(inplace=True),\n                                    nn.Conv2d(outplanes, outplanes, kernel_size=1, stride=1, bias=False),\n                                    nn.BatchNorm2d(outplanes),\n                                    nn.ReLU(inplace=True),\n                                    nn.Conv2d(outplanes, outplanes, kernel_size=1, stride=1, bias=False),\n                                    nn.Sigmoid())\n\n        self.last_block =  ResUnit(inplanes, outplanes)\n\n    def forward(self, x):\n        # The Number of pre-processing Residual Units Before\n        # Splitting into trunk branch and mask branch is 1.\n        # 48*48\n        x = self.Resblock1(x)\n\n        # The output of trunk branch\n        out_trunk = self.trunkbranch(x)\n\n        #soft Mask Branch\n        #The Number of Residual Units between adjacent pooling layer is 1.\n        pool1 = self.maxpool1(x) # (24,24) -> (12,12)\n        out_softmask1 = self.Resblock2(pool1)\n        skip_connection1 = self.skip1(pool1) #\"skip_connection\"\n\n        pool2 = self.maxpool2(out_softmask1) #(12,12) -> (6,6)\n        out_softmask2 = self.Resblock3(pool2)\n\n        out_interp2 = nn.functional.interpolate(out_softmask2, size=self.size2, mode= 'bilinear', align_corners=True) #(6,6) ->(12,12)\n        out = out_interp2 + skip_connection1\n        out_softmask3 = self.Resblock4(out)\n        out_interp1 = nn.functional.interpolate(out_softmask3, size=self.size1, mode= 'bilinear', align_corners=True) #(24,24)\n        out_softmask4 = self.output_block(out_interp1)\n\n        out = (1 + out_softmask4) * out_trunk\n        last_out = self.last_block(out)\n\n        return last_out\n\nclass AttentionModule_stage3(nn.Module):\n\n    def __init__(self, inplanes, outplanes, size1):\n        \"\"\"\n        max_pooling layers are used in mask branch size with input\n        \"\"\"\n        super(AttentionModule_stage3, self).__init__()\n        self.size1 = size1\n        self.Resblock1 = ResUnit(inplanes, outplanes) #first residual block\n\n        self.trunkbranch = nn.Sequential(ResUnit(inplanes, outplanes),\n                                         ResUnit(inplanes, outplanes))\n\n        self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) # (12,12) -> (6,6)\n        self.Resblock2 = nn.Sequential(ResUnit(inplanes, outplanes),\n                                       ResUnit(inplanes, outplanes))\n        #self.upsample1 = nn.UpsamplingBilinear2d(size1)\n\n        self.output_block = nn.Sequential(nn.BatchNorm2d(outplanes),\n                                    nn.ReLU(inplace=True),\n                                    nn.Conv2d(outplanes, outplanes, kernel_size=1, stride=1, bias=False),\n                                    nn.BatchNorm2d(outplanes),\n                                    nn.ReLU(inplace=True),\n                                    nn.Conv2d(outplanes, outplanes, kernel_size=1, stride=1, bias=False),\n                                    nn.Sigmoid())\n\n        self.last_block =  ResUnit(inplanes, outplanes)\n\n    def forward(self, x):\n        # The Number of pre-processing Residual Units Before\n        # Splitting into trunk branch and mask branch is 1.\n        x = self.Resblock1(x)\n\n        # The output of trunk branch\n        out_trunk = self.trunkbranch(x)\n\n        #soft Mask Branch\n        #The Number of Residual Units between adjacent pooling layer is 1.\n        pool1 = self.maxpool1(x) # (12,12) -> (6,6)\n        out_softmask1 = self.Resblock2(pool1)\n        out_interp1 = nn.functional.interpolate(out_softmask1, size=self.size1, mode= 'bilinear', align_corners=True) #(6,6) ->(12,12)\n        out_softmask2 = self.output_block(out_interp1)\n        out = (1 + out_softmask2) * out_trunk\n        last_out = self.last_block(out)\n\n        return last_out\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f58c6869ddd690acb616c8b9a4e4b47e74e6bbf0"},"cell_type":"code","source":"class ResidualAttentionNetwork(nn.Module):\n\n    def __init__(self):\n        super(ResidualAttentionNetwork, self).__init__()\n        self.conv1 = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=16,\n                                             kernel_size=3, stride=1, padding=1, bias=False),\n                                   nn.BatchNorm2d(16),\n                                   nn.ReLU(inplace=True))\n        self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.Resblock1 = ResUnit(16, 64)\n        self.attention_module1 = AttentionModule_stage1(64, 64, size1=(48,48), size2=(24,24), size3=(12,12)) #(48,48)\n        self.attention_module2 = AttentionModule_stage1(64, 64, size1=(48,48), size2=(24,24), size3=(12,12)) \n        self.Resblock2 = ResUnit(64, 128, 2) #(24, 24)\n        self.attention_module3 = AttentionModule_stage2(128, 128, size1=(24,24), size2=(12,12))\n        self.attention_module4 = AttentionModule_stage2(128, 128, size1=(24,24), size2=(12,12))\n        self.Resblock3 = ResUnit(128, 256, 2)\n        self.attention_module5 = AttentionModule_stage3(256, 256, size1=(12,12))\n        self.attention_module6 = AttentionModule_stage3(256, 256, size1=(12,12))\n        self.Resblock4 = nn.Sequential(ResUnit(256, 512, 2),\n                                       ResUnit(512, 512),\n                                       ResUnit(512, 512))\n        self.Avergepool = nn.Sequential(\n                nn.BatchNorm2d(512),\n                nn.ReLU(inplace=True),\n                nn.AvgPool2d(kernel_size=6, stride=1)\n            )\n\n        self.fc1 = nn.Linear(512, 1)\n        #self.pred = nn.Sigmoid()\n\n    def forward(self, x):\n\n        x = self.conv1(x) # (96,96)\n        #print(x.shape)\n        x = self.maxpool1(x) #\n        x = self.Resblock1(x)\n        x = self.attention_module1(x)\n        x = self.attention_module2(x)\n        x = self.Resblock2(x)\n        x = self.attention_module3(x)\n        x = self.attention_module4(x)\n        x = self.Resblock3(x)\n        x = self.attention_module5(x)\n        x = self.attention_module6(x)\n        x = self.Resblock4(x)\n        x = self.Avergepool(x)\n        #print(x.shape)\n        x = x.view(x.size(0), -1)\n        x = self.fc1(x)\n        #print(x.shape)\n        #x = self.pred(x)\n        #x = x.squeeze()\n\n        return x\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5600b405f51d623922c315eef30612e91205bfff"},"cell_type":"code","source":"model = ResidualAttentionNetwork()\nmodel.cuda()\noptimizer = Adam(model.parameters(), lr=0.001)\ncriterion = nn.BCEWithLogitsLoss(reduction='sum').cuda()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d5eb83fbe407c87f8ba6ec3e86cabfb48c9fea16"},"cell_type":"code","source":"def weight_init(m):\n    if isinstance(m, nn.Conv2d):\n        init.xavier_normal_(m.weight.data)\n        if m.bias is not None:\n            init.normal_(m.bias.data)\n    if isinstance(m, nn.BatchNorm2d):\n        init.normal_(m.weight.data, mean=1, std=0.02)\n        init.constant_(m.bias.data, 0)\n    if isinstance(m, nn.Linear):\n        init.xavier_normal_(m.weight.data)\n        init.normal_(m.bias.data)\n\nmodel.apply(weight_init)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c338feda0eee741964b4c3d736c30b1e0a7e3ace"},"cell_type":"code","source":"#def sigmoid(x):\n    #return 1 / (1 + np.exp(-x))\n\ndef train(epoch):\n    model.train() #訓練モード\n    avg_loss = 0.\n    for idx, (imgs, labels) in enumerate(train_loader):\n        imgs_train, labels_train = imgs.cuda(), labels.cuda()\n        #print(labels_train)\n        optimizer.zero_grad()  # 勾配の初期化\n        output_train = model(imgs_train)\n        #print(output_train)#labels_train)\n        loss = criterion(output_train,labels_train.float())\n        loss.backward() # 勾配の計算\n        optimizer.step() # パラメータの更新\n        #print(loss.item())\n        avg_loss += loss.item() / len(train_loader)\n        #y_pred = output_train.cpu().detach().numpy()[:, 0]\n       # print(y_pred)\n        #if (idx+1) % 100 == 0:\n            #print('{}/{} \\t loss={:.4f}'.format(idx+1, len(train_loader), loss.item()))\n        \n    return avg_loss\n\ndef test():\n    avg_val_loss = 0.\n    model.eval() #実行モード\n    with torch.no_grad():\n        for idx, (imgs, labels) in enumerate(val_loader):\n            imgs_vaild, labels_vaild = imgs.cuda(), labels.cuda()\n            output_test = model(imgs_vaild)\n            avg_val_loss += criterion(output_test, labels_vaild.float()).item() / len(val_loader)\n        \n    return avg_val_loss\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3562bd2ec1b0650519ca196bfc0e60eb139ca180"},"cell_type":"code","source":"best_avg_loss = 100.0\ncount = 0\n\nfor i in range(n_epochs):\n    start_time = time.time()\n    avg_loss = train(i)\n    avg_val_loss = test()\n    elapsed_time = time.time() - start_time \n    print('Epoch {}/{} \\t loss={:.4f} \\t val_loss={:.4f} \\t time={:.2f}s'.format(\n        i + 1, n_epochs, avg_loss, avg_val_loss, elapsed_time))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"eb1b45c8955ee853c460b800e3e8883379574b63"},"cell_type":"code","source":"def sigmoid(x):\n    return 1 / (1 + np.exp(-x))\ntr_pred = []\ntr_true = []\n\nmodel.eval()\nwith torch.no_grad():\n    for data in val_loader:\n        images, groud_truth = data\n        images = images.cuda()\n        y_pred = model(images)\n        y_pred = sigmoid(y_pred.cpu().numpy())[:, 0]\n        tr_pred.extend(y_pred)\n        tr_true.extend(groud_truth)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"29e5455f3890e61a8a0d0278f7831772d913a416"},"cell_type":"code","source":"best_score = 0.\nbest_thresh = 0.\n\nfor thresh in [i * 0.01 for i in range(101)]:\n    thresh = np.round(thresh, 2)\n    score = metrics.f1_score(tr_true, (tr_pred > thresh).astype(int))\n    if score > best_score:\n        best_score = score\n        best_thresh = thresh\n    print(\"F1 score at threshold {0} is {1}\".format(thresh, score))\nprint(best_thresh)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6ee07ec6893d8c884f9763abcce9e38b8a94e938"},"cell_type":"code","source":"print(metrics.confusion_matrix(tr_true, (tr_pred > best_thresh).astype(int)))\nprint(metrics.accuracy_score(tr_true, (tr_pred > best_thresh).astype(int)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1afb101ec2c2f96b66bb1697eb3f9b2a6e59f402"},"cell_type":"code","source":"test_pred = []\n\nmodel.eval()\nwith torch.no_grad():\n    for data in test_loader:\n        images, _ = data\n        images = images.cuda()\n        pred = model(images)\n        pred = sigmoid(pred.cpu().numpy())[:, 0]\n        test_pred.extend(pred)\n        \noutput = test_pred\n#output = output.flatten()\n\nsubmission = pd.DataFrame({'id':pd.read_csv('../input/sample_submission.csv').id.values,\n                          'label':test_pred})\n\nprint(submission.head())\nsubmission.to_csv('submission.csv', index=False)\nprint(os.listdir('./'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c63bf161f48fb8aa087bfa30b152c30abc102f46"},"cell_type":"code","source":"class GradCam:\n    def __init__(self, model):\n        self.model = model.eval()\n        self.feature = None\n        self.gradient = None\n\n    def save_gradient(self, grad):\n        self.gradient = grad\n\n    def __call__(self, x):\n        image_size = (x.size(-1), x.size(-2))\n        feature_maps = []\n        \n        for i in range(x.size(0)):\n            img = x[i].data.cpu().numpy()\n            img = img - np.min(img)\n            if np.max(img) != 0:\n                img = img / np.max(img)\n\n            feature = x[i].unsqueeze(0)\n            \n            for name, module in self.model.named_children():\n                if name == 'fc1':\n                    feature = feature.view(feature.size(0), -1)\n                feature = module(feature)\n                if name == 'attention_module6':\n                    feature.register_hook(self.save_gradient)\n                    self.feature = feature\n                    \n            classes = F.sigmoid(feature)\n            one_hot, _ = classes.max(dim=-1)\n            self.model.zero_grad()\n            classes.backward()\n\n            weight = self.gradient.mean(dim=-1, keepdim=True).mean(dim=-2, keepdim=True)\n            \n            mask = F.relu((weight * self.feature).sum(dim=1)).squeeze(0)\n            mask = cv2.resize(mask.data.cpu().numpy(), image_size)\n            mask = mask - np.min(mask)\n            \n            if np.max(mask) != 0:\n                mask = mask / np.max(mask)\n                \n            feature_map = np.float32(cv2.applyColorMap(np.uint8(255 * mask), cv2.COLORMAP_JET))\n            cam = feature_map + np.float32((np.uint8(img.transpose((1, 2, 0)) * 255)))\n            cam = cam - np.min(cam)\n            \n            if np.max(cam) != 0:\n                cam = cam / np.max(cam)\n                \n            feature_maps.append(transforms.ToTensor()(cv2.cvtColor(np.uint8(255 * cam), cv2.COLOR_BGR2RGB)))\n            \n        feature_maps = torch.stack(feature_maps)\n        \n        return feature_maps","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"355225ce1d59318bc672d12886877b050da51053"},"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore')\ngrad_cam = GradCam(model)\n\ndef draw_features(p):\n    \n    img = Image.open('../input/train/{}.tif'.format(p))\n    img_tensor = (test_transform((img))).unsqueeze(dim=0).cuda()\n    #cancer_imgs.append(img)\n    feature_img = grad_cam(img_tensor).squeeze(dim=0)\n    feature_img = transforms.ToPILImage()(feature_img)\n    \n    return img, feature_img\n\ntest_imgs = []\ntest_feature_imgs = []\n\nfor p in cancer:\n    img, feature_img = draw_features(p)\n    test_imgs.append(img)\n    test_feature_imgs.append(feature_img)\n    \n    if len(test_imgs) == 18: break\n\np_show(test_imgs, 'Original Images')\np_show(test_feature_imgs, 'Feature Maps(Attention Stage 6)')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9aee194eb0935659ce2bd819941c4bfdcb847656"},"cell_type":"code","source":"test_imgs = []\ntest_feature_imgs = []\n\nfor p in no_cancer:\n    img, feature_img = draw_features(p)\n    test_imgs.append(img)\n    test_feature_imgs.append(feature_img)\n    \n    if len(test_imgs) == 18: break\n\np_show(test_imgs, 'Original Images')\np_show(test_feature_imgs, 'Feature Maps(Attention Stage 1)')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}