{"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":"markdown","source":"# **SEGMENTACIJA PLOVILA IZ SATELITSKIH SNIMAKA**\n\n## Autor: Luka Paladin, univ.bacc.ing.el","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", category=DeprecationWarning) \n\nfrom fastai.conv_learner import *\nfrom fastai.dataset import *\n\nimport pandas as pd\nimport numpy as np\nimport os\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nprint('done')","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:45:55.277779Z","iopub.execute_input":"2021-08-26T20:45:55.278167Z","iopub.status.idle":"2021-08-26T20:45:57.049916Z","shell.execute_reply.started":"2021-08-26T20:45:55.278087Z","shell.execute_reply":"2021-08-26T20:45:57.048998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> ## Data","metadata":{}},{"cell_type":"code","source":"PATH = './'\nTRAIN = '../input/airbus-ship-detection/train_v2/'\nTEST = '../input/airbus-ship-detection/test_v2/'\nSEGMENTATION = '../input/airbus-ship-detection/train_ship_segmentations_v2.csv'\nprint('done')","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:46:04.736426Z","iopub.execute_input":"2021-08-26T20:46:04.736732Z","iopub.status.idle":"2021-08-26T20:46:04.744325Z","shell.execute_reply.started":"2021-08-26T20:46:04.736674Z","shell.execute_reply":"2021-08-26T20:46:04.740728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"nw = 2           \narch = resnet34  \n\ntrain_names = [f for f in os.listdir(TRAIN)]\ntest_names = [f for f in os.listdir(TEST)]\ntr_n, val_n = train_test_split(train_names, test_size=0.05, random_state=42)\nsegmentation_df = pd.read_csv(os.path.join(PATH, SEGMENTATION)).set_index('ImageId')","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:46:06.479592Z","iopub.execute_input":"2021-08-26T20:46:06.479918Z","iopub.status.idle":"2021-08-26T20:46:18.067942Z","shell.execute_reply.started":"2021-08-26T20:46:06.479856Z","shell.execute_reply":"2021-08-26T20:46:18.066973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> ## Funkcije","metadata":{}},{"cell_type":"code","source":"def cut_empty(names):\n    return [name for name in names \n            if(type(segmentation_df.loc[name]['EncodedPixels']) != float)]\n\ntr_n = cut_empty(tr_n)\nval_n = cut_empty(val_n)\n\ndef get_mask(img_id, df):\n    shape = (768,768)\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    masks = df.loc[img_id]['EncodedPixels']\n    if(type(masks) == float): return img.reshape(shape)\n    if(type(masks) == str): masks = [masks]\n    for mask in masks:\n        s = mask.split()\n        for i in range(len(s)//2):\n            start = int(s[2*i]) - 1\n            length = int(s[2*i+1])\n            img[start:start+length] = 1\n    return img.reshape(shape).T\n\ndef get_data(sz,bs):\n    #data augmentation\n    aug_tfms = [RandomRotate(10, tfm_y=TfmType.CLASS),\n                RandomDihedral(tfm_y=TfmType.CLASS),\n                RandomLighting(0.05, 0.05, tfm_y=TfmType.CLASS)]\n    tfms = tfms_from_model(arch, sz, crop_type=CropType.NO, tfm_y=TfmType.CLASS, \n                aug_tfms=aug_tfms)\n    tr_names = tr_n if (len(tr_n)%bs == 0) else tr_n[:-(len(tr_n)%bs)] #cut incomplete batch\n    ds = ImageData.get_ds(pdFilesDataset, (tr_names,TRAIN), \n                (val_n,TRAIN), tfms, test=(test_names,TEST))\n    md = ImageData(PATH, ds, bs, num_workers=nw, classes=None)\n    return md","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:46:32.208256Z","iopub.execute_input":"2021-08-26T20:46:32.208557Z","iopub.status.idle":"2021-08-26T20:47:00.568503Z","shell.execute_reply.started":"2021-08-26T20:46:32.208504Z","shell.execute_reply":"2021-08-26T20:47:00.567756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class pdFilesDataset(FilesDataset):\n    def __init__(self, fnames, path, transform):\n        self.segmentation_df = pd.read_csv(SEGMENTATION).set_index('ImageId')\n        super().__init__(fnames, transform, path)\n    \n    def get_x(self, i):\n        img = open_image(os.path.join(self.path, self.fnames[i]))\n        if self.sz == 768: return img \n        else: return cv2.resize(img, (self.sz, self.sz),cv2.INTER_AREA)\n    \n    def get_y(self, i):\n        mask = np.zeros((768,768), dtype=np.uint8) if (self.path == TEST) \\\n            else get_mask(self.fnames[i], self.segmentation_df)\n        img = Image.fromarray(mask).resize((self.sz, self.sz),cv2.INTER_AREA).convert('RGB')\n        return np.array(img).astype(np.float32)\n    \n    def get_c(self): return 0","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:47:00.570043Z","iopub.execute_input":"2021-08-26T20:47:00.570329Z","iopub.status.idle":"2021-08-26T20:47:00.581119Z","shell.execute_reply.started":"2021-08-26T20:47:00.570282Z","shell.execute_reply":"2021-08-26T20:47:00.580140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> ## Model","metadata":{}},{"cell_type":"code","source":"cut,lr_cut = model_meta[arch]\ndef get_base(pre=True):                   #load ResNet34 model\n    layers = cut_model(arch(pre), cut)\n    return nn.Sequential(*layers)","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:47:07.089891Z","iopub.execute_input":"2021-08-26T20:47:07.090194Z","iopub.status.idle":"2021-08-26T20:47:07.094692Z","shell.execute_reply.started":"2021-08-26T20:47:07.090141Z","shell.execute_reply":"2021-08-26T20:47:07.093953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ResBlock(nn.Module):\n    def __init__(self, x_in, filters=64):\n        super().__init__()\n        self.conv1 = nn.Conv2d(x_in,filters,1)\n        self.bn1 = nn.BatchNorm2d(filters)\n        self.conv2 = nn.Conv2d(filters,filters,(3,3),padding=1)\n        self.bn2 = nn.BatchNorm2d(filters)\n        self.conv3 = nn.Conv2d(filters,x_in,1)\n        \n    def forward(self, x):\n        r = self.conv1(x)\n        r = F.relu(r)\n        r = self.bn1(r)\n        r = self.conv2(r)\n        r = F.relu(r)\n        r = self.bn2(r)\n        r = self.conv3(r)\n        return x + r\n    \nclass SEBlock(nn.Module):\n    def __init__(self, channel, reduction=16):\n        super(SEBlock, self).__init__()\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.fc = nn.Sequential(\n                nn.Linear(channel, channel // reduction),\n                nn.ReLU(inplace=True),\n                nn.Linear(channel // reduction, channel),\n                nn.Sigmoid())\n\n    def forward(self, x):\n        b, c, _, _ = x.size()\n        y = self.avg_pool(x).view(b, c)\n        y = self.fc(y).view(b, c, 1, 1)\n        return x * y\n\nclass UnetBlock(nn.Module):\n    def __init__(self, up_in, x_in, n_out, dropout=0.0):\n        super().__init__()\n        up_out = x_out = n_out//2\n        self.x_conv  = nn.Conv2d(x_in,  x_out,  1)\n        self.tr_conv = nn.ConvTranspose2d(up_in, up_out, 2, stride=2)\n        self.cat_conv = nn.Conv2d(n_out, n_out, (3,3), padding=(1,1))\n        self.bn = nn.BatchNorm2d(n_out)\n        self.se = SEBlock(n_out)\n        self.dropout = nn.Dropout2d(dropout)\n        self.r = ResBlock(n_out,n_out//2)\n        #self.conv1 = nn.Conv2d(2*n_out,n_out,1)\n        #self.conv2 = nn.Conv2d(n_out,n_out,1)\n        #self.bn_g = nn.BatchNorm2d(n_out)\n        #self.GLU = nn.GLU(dim=1)\n        #self.conv1 = nn.Conv2d(n_out,n_out,(3,3), padding=(1,1))\n        #self.conv2 = nn.Conv2d(n_out,n_out,(3,3), padding=(1,1))\n        #self.bn_in = nn.BatchNorm2d(n_out)\n        \n    def forward(self, up_p, x_p):\n        up_p = self.tr_conv(up_p)\n        x_p = self.x_conv(x_p)\n        cat_p = self.dropout(torch.cat([up_p,x_p], dim=1))\n        x = self.bn(F.relu(self.cat_conv(cat_p)))\n        x = self.r(x)\n        #g = self.bn_g(self.conv2(F.relu(self.conv1(cat_p))))\n        #x = self.GLU(torch.cat([x_p,g], dim=1))\n        x = self.se(x)\n        return x\n\nclass SaveFeatures():\n    features=None\n    def __init__(self, m): self.hook = m.register_forward_hook(self.hook_fn)\n    def hook_fn(self, module, input, output): self.features = output\n    def remove(self): self.hook.remove()\n    \nclass Unet34SE_hc(nn.Module):\n    def __init__(self, rn, dropout = 0.0):\n        super().__init__()\n        self.rn = rn\n        self.hc_sz = 16\n        self.filters = [64,64,128,256,512]\n        self.u_out = [self.hc_sz,128,128,256,256]\n        self.sfs = [SaveFeatures(rn[i]) for i in [2,4,5,6]]\n        self.up1 = UnetBlock(self.filters[4],self.filters[3],self.u_out[4],dropout)\n        self.up2 = UnetBlock(self.u_out[4],self.filters[2],self.u_out[3],dropout)\n        self.up3 = UnetBlock(self.u_out[3],self.filters[1],self.u_out[2],dropout/2)\n        self.up4 = UnetBlock(self.u_out[2],self.filters[0],self.u_out[1])\n        self.up5 = nn.ConvTranspose2d(self.u_out[1], self.u_out[0], 2, stride=2)\n        self.hc_neck1 = nn.Conv2d(self.u_out[4], self.hc_sz, 1)\n        self.hc_neck2 = nn.Conv2d(self.u_out[3], self.hc_sz, 1)\n        self.hc_neck3 = nn.Conv2d(self.u_out[2], self.hc_sz, 1)\n        self.hc_neck4 = nn.Conv2d(self.u_out[1], self.hc_sz, 1)\n        self.head = nn.Sequential(nn.Conv2d(5*self.hc_sz,2*self.hc_sz,3,padding=1),\n                                 nn.ReLU(inplace=True),\n                                 nn.Conv2d(2*self.hc_sz,1,1))\n        \n    def forward(self,x):\n        x = F.relu(self.rn(x))\n        x = self.up1(x, self.sfs[3].features)\n        hc1 = self.hc_neck1(x)\n        x = self.up2(x, self.sfs[2].features)\n        hc2 = self.hc_neck2(x)\n        x = self.up3(x, self.sfs[1].features)\n        hc3 = self.hc_neck3(x)\n        x = self.up4(x, self.sfs[0].features)\n        hc4 = self.hc_neck4(x)\n        x = self.up5(x)\n        x = torch.cat((x,\n            F.interpolate(hc4,scale_factor=2,mode='bilinear'),\n            F.interpolate(hc3,scale_factor=4,mode='bilinear'),\n            F.interpolate(hc2,scale_factor=8,mode='bilinear'),\n            F.interpolate(hc1,scale_factor=16,mode='bilinear'),\n            ),dim=1)\n        x = self.head(x)\n        return x[:,0]\n    \n    def close(self):\n        for sf in self.sfs: sf.remove()\n            \nclass UnetModel():\n    def __init__(self,model,name='Unet'):\n        self.model,self.name = model,name\n\n    def get_layer_groups(self, precompute):\n        lgs = list(split_by_idxs(children(self.model.rn), [lr_cut]))\n        return lgs + [children(self.model)[1:]]","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:47:09.729411Z","iopub.execute_input":"2021-08-26T20:47:09.729737Z","iopub.status.idle":"2021-08-26T20:47:09.803624Z","shell.execute_reply.started":"2021-08-26T20:47:09.729693Z","shell.execute_reply":"2021-08-26T20:47:09.802096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> ## Loss funkcije","metadata":{}},{"cell_type":"code","source":"def dice_loss(input, target):\n    input = torch.sigmoid(input)\n    smooth = 1.0\n\n    iflat = input.view(-1)\n    tflat = target.view(-1)\n    intersection = (iflat * tflat).sum()\n    \n    return ((2.0 * intersection + smooth) / (iflat.sum() + tflat.sum() + smooth))\n\nclass FocalLoss(nn.Module):\n    def __init__(self, gamma):\n        super().__init__()\n        self.gamma = gamma\n        \n    def forward(self, input, target):\n        if not (target.size() == input.size()):\n            raise ValueError(\"Target size ({}) must be the same as input size ({})\"\n                             .format(target.size(), input.size()))\n\n        max_val = (-input).clamp(min=0)\n        loss = input - input * target + max_val + \\\n            ((-max_val).exp() + (-input - max_val).exp()).log()\n\n        invprobs = F.logsigmoid(-input * (target * 2.0 - 1.0))\n        loss = (invprobs * self.gamma).exp() * loss\n        \n        return loss.mean()\n    \nclass MixedLoss(nn.Module):\n    def __init__(self, alpha, gamma):\n        super().__init__()\n        self.alpha = alpha\n        self.focal = FocalLoss(gamma)\n        \n    def forward(self, input, target):\n        loss = self.alpha*self.focal(input, target) - torch.log(dice_loss(input, target))\n        return loss.mean()\n    \ndef dice(pred, targs):\n    pred = (pred>0).float()\n    return 2.0 * (pred*targs).sum() / ((pred+targs).sum() + 1.0)\n\ndef IoU(pred, targs):\n    pred = (pred>0).float()\n    intersection = (pred*targs).sum()\n    return intersection / ((pred+targs).sum() - intersection + 1.0)","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:47:12.189313Z","iopub.execute_input":"2021-08-26T20:47:12.189635Z","iopub.status.idle":"2021-08-26T20:47:12.206419Z","shell.execute_reply.started":"2021-08-26T20:47:12.189583Z","shell.execute_reply":"2021-08-26T20:47:12.205648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> ## Treniranje (256x256)","metadata":{}},{"cell_type":"markdown","source":"#### Preuzimanje Unet modela","metadata":{}},{"cell_type":"code","source":"m = to_gpu(Unet34SE_hc(get_base(True),0.15))\nmodels = UnetModel(m)\nprint('done')","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:47:14.786447Z","iopub.execute_input":"2021-08-26T20:47:14.786789Z","iopub.status.idle":"2021-08-26T20:47:21.210892Z","shell.execute_reply.started":"2021-08-26T20:47:14.786709Z","shell.execute_reply":"2021-08-26T20:47:21.210050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Definiranje parametara","metadata":{}},{"cell_type":"code","source":"sz = 256 #image size\nbs = 64  #batch size\n\nmd = get_data(sz,bs)\n\nlearn = ConvLearner(md, models)\nlearn.opt_fn=optim.Adamax\nlearn.clip = 1.0\nlearn.crit = MixedLoss(10.0, 2.0)\nlearn.metrics=[accuracy_thresh(0.5),dice,IoU]\n\nwd=1e-7\nlr = 2.5e-3","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:47:38.051967Z","iopub.execute_input":"2021-08-26T20:47:38.052272Z","iopub.status.idle":"2021-08-26T20:47:41.669619Z","shell.execute_reply.started":"2021-08-26T20:47:38.052218Z","shell.execute_reply":"2021-08-26T20:47:41.668732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#learn.freeze_to(1)","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:47:41.671140Z","iopub.execute_input":"2021-08-26T20:47:41.671467Z","iopub.status.idle":"2021-08-26T20:47:41.676809Z","shell.execute_reply.started":"2021-08-26T20:47:41.671414Z","shell.execute_reply":"2021-08-26T20:47:41.675250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fit(lr,1,wds=wd,cycle_len=1,use_clr=(5,8))\nlearn.save('Unet34r_256_0')","metadata":{"execution":{"iopub.status.busy":"2021-08-26T20:47:44.587346Z","iopub.execute_input":"2021-08-26T20:47:44.587651Z","iopub.status.idle":"2021-08-26T21:09:24.914526Z","shell.execute_reply.started":"2021-08-26T20:47:44.587592Z","shell.execute_reply":"2021-08-26T21:09:24.913582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lrs = np.array([lr/100,lr/10,lr])\nlearn.unfreeze() #unfreeze the encoder\nlearn.bn_freeze(True)\n\nlearn.fit(lrs,2,wds=wd,cycle_len=1,use_clr=(20,8))\n\nlearn.fit(lrs/3,2,wds=wd,cycle_len=2,use_clr=(20,8))\n\nlearn.save('Unet34r_256_1')","metadata":{"execution":{"iopub.status.busy":"2021-08-26T21:09:34.805917Z","iopub.execute_input":"2021-08-26T21:09:34.806218Z","iopub.status.idle":"2021-08-26T23:09:56.163418Z","shell.execute_reply.started":"2021-08-26T21:09:34.806165Z","shell.execute_reply":"2021-08-26T23:09:56.161913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Vizualizacija","metadata":{}},{"cell_type":"code","source":"def Show_images(x,yp,yt):\n    columns = 3\n    rows = min(bs,8)\n    fig=plt.figure(figsize=(columns*4, rows*4))\n    for i in range(rows):\n        fig.add_subplot(rows, columns, 3*i+1)\n        plt.axis('off')\n        plt.imshow(x[i])\n        fig.add_subplot(rows, columns, 3*i+2)\n        plt.axis('off')\n        plt.imshow(yp[i])\n        fig.add_subplot(rows, columns, 3*i+3)\n        plt.axis('off')\n        plt.imshow(yt[i])\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-26T23:09:56.165388Z","iopub.execute_input":"2021-08-26T23:09:56.165669Z","iopub.status.idle":"2021-08-26T23:09:56.173699Z","shell.execute_reply.started":"2021-08-26T23:09:56.165620Z","shell.execute_reply":"2021-08-26T23:09:56.172696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.model.eval();\nx,y = next(iter(md.val_dl))\nyp = to_np(F.sigmoid(learn.model(V(x))))\n\nShow_images(np.asarray(md.val_ds.denorm(x)), yp, y)","metadata":{"execution":{"iopub.status.busy":"2021-08-26T23:09:56.175521Z","iopub.execute_input":"2021-08-26T23:09:56.175792Z","iopub.status.idle":"2021-08-26T23:10:03.326660Z","shell.execute_reply.started":"2021-08-26T23:09:56.175729Z","shell.execute_reply":"2021-08-26T23:10:03.325257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Nastavak treniranja (384x384)","metadata":{}},{"cell_type":"code","source":"sz = 384 #image size\nbs = 16  #batch size\n\nmd = get_data(sz,bs)\nlearn.set_data(md)\nlearn.unfreeze()\nlearn.bn_freeze(True)","metadata":{"execution":{"iopub.status.busy":"2021-08-26T23:10:03.328278Z","iopub.execute_input":"2021-08-26T23:10:03.328555Z","iopub.status.idle":"2021-08-26T23:10:07.317489Z","shell.execute_reply.started":"2021-08-26T23:10:03.328513Z","shell.execute_reply":"2021-08-26T23:10:07.316610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fit(lrs/5,3,wds=wd,cycle_len=2,use_clr=(10,8))\nlearn.save('Unet34r_384_1')","metadata":{"execution":{"iopub.status.busy":"2021-08-26T23:10:07.318439Z","iopub.execute_input":"2021-08-26T23:10:07.318670Z","iopub.status.idle":"2021-08-27T02:22:56.777513Z","shell.execute_reply.started":"2021-08-26T23:10:07.318628Z","shell.execute_reply":"2021-08-27T02:22:56.776671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Vizualizacija 2","metadata":{}},{"cell_type":"code","source":"learn.model.eval();\nx,y = next(iter(md.val_dl))\nyp = to_np(F.sigmoid(learn.model(V(x))))\n\nShow_images(np.asarray(md.val_ds.denorm(x)), yp, y)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T02:22:56.778599Z","iopub.execute_input":"2021-08-27T02:22:56.778855Z","iopub.status.idle":"2021-08-27T02:23:00.296559Z","shell.execute_reply.started":"2021-08-27T02:22:56.778810Z","shell.execute_reply":"2021-08-27T02:23:00.295878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Nastavak treniranja (768x768)","metadata":{}},{"cell_type":"code","source":"sz = 768 #image size\nbs = 6  #batch size\n\nmd = get_data(sz,bs)\nlearn.set_data(md)\nlearn.unfreeze()\nlearn.bn_freeze(True)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T02:23:00.297564Z","iopub.execute_input":"2021-08-27T02:23:00.297967Z","iopub.status.idle":"2021-08-27T02:23:03.975939Z","shell.execute_reply.started":"2021-08-27T02:23:00.297919Z","shell.execute_reply":"2021-08-27T02:23:03.974937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fit(lrs/10,1,wds=wd,cycle_len=1,use_clr=(10,8))\nlearn.save('Unet34_768_1')","metadata":{"execution":{"iopub.status.busy":"2021-08-27T02:23:03.976901Z","iopub.execute_input":"2021-08-27T02:23:03.977153Z","iopub.status.idle":"2021-08-27T04:13:28.644506Z","shell.execute_reply.started":"2021-08-27T02:23:03.977109Z","shell.execute_reply":"2021-08-27T04:13:28.643396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Vizualizacija 3","metadata":{}},{"cell_type":"code","source":"learn.model.eval();\nx,y = next(iter(md.val_dl))\nyp = to_np(F.sigmoid(learn.model(V(x))))\n\nShow_images(np.asarray(md.val_ds.denorm(x)), yp, y)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T04:13:28.645836Z","iopub.execute_input":"2021-08-27T04:13:28.646125Z","iopub.status.idle":"2021-08-27T04:13:30.842227Z","shell.execute_reply.started":"2021-08-27T04:13:28.646076Z","shell.execute_reply":"2021-08-27T04:13:30.841413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}