{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Important: This notebook will only work with fastai-0.7.x. Do not try to run any fastai-1.x code from this path in the repository because it will load fastai-0.7.x**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "%reload_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fastai.conv_learner import *\n",
    "from fastai.dataset import *\n",
    "from fastai.models.resnet import vgg_resnet50\n",
    "\n",
    "import json"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "torch.cuda.set_device(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "torch.backends.cudnn.benchmark=True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "PATH = Path('data/carvana')\n",
    "MASKS_FN = 'train_masks.csv'\n",
    "META_FN = 'metadata.csv'\n",
    "masks_csv = pd.read_csv(PATH/MASKS_FN)\n",
    "meta_csv = pd.read_csv(PATH/META_FN)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def show_img(im, figsize=None, ax=None, alpha=None):\n",
    "    if not ax: fig,ax = plt.subplots(figsize=figsize)\n",
    "    ax.imshow(im, alpha=alpha)\n",
    "    ax.set_axis_off()\n",
    "    return ax"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TRAIN_DN = 'train-128'\n",
    "MASKS_DN = 'train_masks-128'\n",
    "sz = 128\n",
    "bs = 64\n",
    "nw = 16"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TRAIN_DN = 'train'\n",
    "MASKS_DN = 'train_masks_png'\n",
    "sz = 128\n",
    "bs = 64\n",
    "nw = 16"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MatchedFilesDataset(FilesDataset):\n",
    "    def __init__(self, fnames, y, transform, path):\n",
    "        self.y=y\n",
    "        assert(len(fnames)==len(y))\n",
    "        super().__init__(fnames, transform, path)\n",
    "    def get_y(self, i): return open_image(os.path.join(self.path, self.y[i]))\n",
    "    def get_c(self): return 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_names = np.array([Path(TRAIN_DN)/o for o in masks_csv['img']])\n",
    "y_names = np.array([Path(MASKS_DN)/f'{o[:-4]}_mask.png' for o in masks_csv['img']])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "val_idxs = list(range(1008))\n",
    "((val_x,trn_x),(val_y,trn_y)) = split_by_idx(val_idxs, x_names, y_names)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aug_tfms = [RandomRotate(4, tfm_y=TfmType.CLASS),\n",
    "            RandomFlip(tfm_y=TfmType.CLASS),\n",
    "            RandomLighting(0.05, 0.05, tfm_y=TfmType.CLASS)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tfms = tfms_from_model(resnet34, sz, crop_type=CropType.NO, tfm_y=TfmType.CLASS, aug_tfms=aug_tfms)\n",
    "datasets = ImageData.get_ds(MatchedFilesDataset, (trn_x,trn_y), (val_x,val_y), tfms, path=PATH)\n",
    "md = ImageData(PATH, datasets, bs, num_workers=16, classes=None)\n",
    "denorm = md.trn_ds.denorm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x,y = next(iter(md.trn_dl))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(torch.Size([64, 3, 128, 128]), torch.Size([64, 128, 128]))"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.shape,y.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simple upsample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f = resnet34\n",
    "cut,lr_cut = model_meta[f]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_base():\n",
    "    layers = cut_model(f(True), cut)\n",
    "    return nn.Sequential(*layers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def dice(pred, targs):\n",
    "    pred = (pred>0).float()\n",
    "    return 2. * (pred*targs).sum() / (pred+targs).sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class StdUpsample(nn.Module):\n",
    "    def __init__(self, nin, nout):\n",
    "        super().__init__()\n",
    "        self.conv = nn.ConvTranspose2d(nin, nout, 2, stride=2)\n",
    "        self.bn = nn.BatchNorm2d(nout)\n",
    "        \n",
    "    def forward(self, x): return self.bn(F.relu(self.conv(x)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Upsample34(nn.Module):\n",
    "    def __init__(self, rn):\n",
    "        super().__init__()\n",
    "        self.rn = rn\n",
    "        self.features = nn.Sequential(\n",
    "            rn, nn.ReLU(),\n",
    "            StdUpsample(512,256),\n",
    "            StdUpsample(256,256),\n",
    "            StdUpsample(256,256),\n",
    "            StdUpsample(256,256),\n",
    "            nn.ConvTranspose2d(256, 1, 2, stride=2))\n",
    "        \n",
    "    def forward(self,x): return self.features(x)[:,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class UpsampleModel():\n",
    "    def __init__(self,model,name='upsample'):\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.features)[1:]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m_base = get_base()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m = to_gpu(Upsample34(m_base))\n",
    "models = UpsampleModel(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn = ConvLearner(md, models)\n",
    "learn.opt_fn=optim.Adam\n",
    "learn.crit=nn.BCEWithLogitsLoss()\n",
    "learn.metrics=[accuracy_thresh(0.5),dice]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.freeze_to(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "e4667e9fa899453da7cbf0a0524fb426",
       "version_major": 2,
       "version_minor": 0
      },
      "text/html": [
       "<p>Failed to display Jupyter Widget of type <code>HBox</code>.</p>\n",
       "<p>\n",
       "  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n",
       "  that the widgets JavaScript is still loading. If this message persists, it\n",
       "  likely means that the widgets JavaScript library is either not installed or\n",
       "  not enabled. See the <a href=\"https://ipywidgets.readthedocs.io/en/stable/user_install.html\">Jupyter\n",
       "  Widgets Documentation</a> for setup instructions.\n",
       "</p>\n",
       "<p>\n",
       "  If you're reading this message in another frontend (for example, a static\n",
       "  rendering on GitHub or <a href=\"https://nbviewer.jupyter.org/\">NBViewer</a>),\n",
       "  it may mean that your frontend doesn't currently support widgets.\n",
       "</p>\n"
      ],
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=1), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 86%|█████████████████████████████████████████████████████████████          | 55/64 [00:22<00:03,  2.46it/s, loss=3.21]"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "learn.lr_find()\n",
    "learn.sched.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lr=4e-2\n",
    "wd=1e-7\n",
    "lrs = np.array([lr/100,lr/10,lr])/2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "0dfb71a3eb494433bd0f58647124a177",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=4), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  0%|          | 0/64 [00:00<?, ?it/s]\n",
      "epoch      trn_loss   val_loss   <lambda>   dice           \n",
      "    0      0.216882   0.133512   0.938017   0.855221  \n",
      "    1      0.169544   0.115158   0.946518   0.878381       \n",
      "    2      0.153114   0.099104   0.957748   0.903353       \n",
      "    3      0.144105   0.093337   0.964404   0.915084       \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.09333742126112893, 0.9644036065964472, 0.9150839788573129]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lr,1, wds=wd, cycle_len=4,use_clr=(20,8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.save('tmp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('tmp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.unfreeze()\n",
    "learn.bn_freeze(True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f8176783850a4cf48c3ba20494fac24e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=4), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch      trn_loss   val_loss   <lambda>   dice           \n",
      "    0      0.174897   0.061603   0.976321   0.94382   \n",
      "    1      0.122911   0.053625   0.982206   0.957624       \n",
      "    2      0.106837   0.046653   0.985577   0.965792       \n",
      "    3      0.099075   0.042291   0.986519   0.968925        \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.042291240323157536, 0.986519161670927, 0.9689251193924556]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lrs,1,cycle_len=4,use_clr=(20,8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.save('128')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x,y = next(iter(md.val_dl))\n",
    "py = to_np(learn.model(V(x)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQUAAAD8CAYAAAB+fLH0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAABA5JREFUeJzt3dtt02AAhuG06hSZIkugTMCUTFCxRKfoGISrSH0L6dGJf9vPc4ki4V709edD4O50Ou0Azu7nPgBgLKIAhCgAIQpAiAIQogCEKAAhCkCIAhAPcx/Abrfb/bj/6bVKuLLff37dfeRzlgIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhAPcx8Ay/b4/LQ77g///Nklrz/LeCwFICwFLnrrjP+Vz136rPUwFksBCEthgz5zZr8F62EsorAho8XgLS+PVSBuy+UDEKKwEUtaCcxLFIBwT2Hl1rAQzj+Dewu3YSkAYSms1BoWwmsWw21YCivz+Py0yiC8tPafb26iAIQosEhbWERzEQUgRIFFsximJwor4peDKYgCEKKwAia0lTQlUQBCFIDwmvOCmczlNehpWApAiMJCWQlciygAIQqsjke03yMKQIgCEB5JLoxZzLVZCkCIwsIc9wcv53BVogCEewoL454C12YpsFreV/gaUQDC5cNCOONxK5YCEKLA6llZnyMKQIgCEKKwAOYvtyQKQIgCEKIAhJeXBuZewnT88+8fZykAIQpAiAKb4puT7xMFIEQBCE8fBmTeMidLAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIDw3YeB+M4DI7AUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFNgkL4pdJgpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCiwScf9Ye5DGJYoACEKQIgCEKIAhCgAIQpAiAIQojCQ4/7g+TmzEwUgRAEIUQDiYe4DgFtyz+Z9osAmiMHHuXwAQhSAEAUgRAEIUQDC04cBne+U++/Sv8cTh68RBVZDBKbh8gEIS2Fg/zvzvXVJ8d6Zci2XIxbBdVkKQFgKC/Odm5BTnmGnXB3O/GMRhYWa+xdp7r+f63H5AIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAcXc6neY+BmAglgIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgA8RefEJKlJ3LAMQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img(py[0]>0);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQUAAAD8CAYAAAB+fLH0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAABA5JREFUeJzt3dFN22AARtFQMQVTsETFBJ2yE6AuwRSM0fQJNbdqCAE79m+f81hVyCDl+rOdwN3xeDwAvPm29AEA6yIKQIgCEKIAhCgAIQpAiAIQogCEKABxv/QBHA6Hw/dvP7ytEmb26/fPu4/8P0sBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAGI+6UPgHV5fn2Z9es/PTzO+vX5OksBCEthR+ZeAVMeg0WxHEsBCFFglZ5fX1axbPZIFHZi1BfYqMc9MlEAQhSAEAUgPJLcuC1ck799Dx5T3oalAIQoMAyPKW/D5cNGefHwWZYCEKIAhCgAIQobs4ebcVv//pYmCkCIAhCiwJD2cJm0FFEAQhQ2xJmTKYgCEKIAhM8+DMBlwXX+/Xn5yPV1LAUgLAWGdvoLWM4tqtN/txousxSAsBRW7NK9hLeznnsOTEkUBiYGf/lZTMflAxCWwoqd3hRzJuRWLAUgLIVB/O9RmvVQHjdOw1IYlCAwF1EAQhTYDL94ZRqiAIQbjYNxJrzMH6T9GksBCEthEBbC9SyGz7EU2DxBvY4oACEKA3Cm45ZEAQhRAMLThxVz2TAdTyI+zlIAQhSAEAUgRIFd8UnKy0QBCFEAQhSAEAUgvHlphdwIY0mWAhCiAIQosEsu0c4TBSBEAQhRAEIUgPA+hRVx84s1sBSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFFbk6eHx8PTwuPRhsHOiAIQoACEKQIgCu+TezXmiAIQoACEKK+TRJEsSBSBEAQhRAEIUgLhf+gA47/Rm4/Pry4JHsh1u4F5mKQBhKQzivTOcFfE+6+A6lgIQlsIGzH0mXOMScfafjyhwkRfgvrh8AEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAuDsej0sfA7AilgIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgA8QfWQY8SR/FLYgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img(y[0]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## U-net (ish)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class 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()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class UnetBlock(nn.Module):\n",
    "    def __init__(self, up_in, x_in, n_out):\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.bn = 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 = torch.cat([up_p,x_p], dim=1)\n",
    "        return self.bn(F.relu(cat_p))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Unet34(nn.Module):\n",
    "    def __init__(self, rn):\n",
    "        super().__init__()\n",
    "        self.rn = rn\n",
    "        self.sfs = [SaveFeatures(rn[i]) for i in [2,4,5,6]]\n",
    "        self.up1 = UnetBlock(512,256,256)\n",
    "        self.up2 = UnetBlock(256,128,256)\n",
    "        self.up3 = UnetBlock(256,64,256)\n",
    "        self.up4 = UnetBlock(256,64,256)\n",
    "        self.up5 = nn.ConvTranspose2d(256, 1, 2, stride=2)\n",
    "        \n",
    "    def forward(self,x):\n",
    "        x = F.relu(self.rn(x))\n",
    "        x = self.up1(x, self.sfs[3].features)\n",
    "        x = self.up2(x, self.sfs[2].features)\n",
    "        x = self.up3(x, self.sfs[1].features)\n",
    "        x = self.up4(x, self.sfs[0].features)\n",
    "        x = self.up5(x)\n",
    "        return x[:,0]\n",
    "    \n",
    "    def close(self):\n",
    "        for sf in self.sfs: sf.remove()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class 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:]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m_base = get_base()\n",
    "m = to_gpu(Unet34(m_base))\n",
    "models = UnetModel(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn = ConvLearner(md, models)\n",
    "learn.opt_fn=optim.Adam\n",
    "learn.crit=nn.BCEWithLogitsLoss()\n",
    "learn.metrics=[accuracy_thresh(0.5),dice]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('Conv2d-1',\n",
       "              OrderedDict([('input_shape', [-1, 3, 128, 128]),\n",
       "                           ('output_shape', [-1, 64, 64, 64]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 9408)])),\n",
       "             ('BatchNorm2d-2',\n",
       "              OrderedDict([('input_shape', [-1, 64, 64, 64]),\n",
       "                           ('output_shape', [-1, 64, 64, 64]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 128)])),\n",
       "             ('ReLU-3',\n",
       "              OrderedDict([('input_shape', [-1, 64, 64, 64]),\n",
       "                           ('output_shape', [-1, 64, 64, 64]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('MaxPool2d-4',\n",
       "              OrderedDict([('input_shape', [-1, 64, 64, 64]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-5',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 36864)])),\n",
       "             ('BatchNorm2d-6',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 128)])),\n",
       "             ('ReLU-7',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-8',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 36864)])),\n",
       "             ('BatchNorm2d-9',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 128)])),\n",
       "             ('ReLU-10',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-11',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-12',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 36864)])),\n",
       "             ('BatchNorm2d-13',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 128)])),\n",
       "             ('ReLU-14',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-15',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 36864)])),\n",
       "             ('BatchNorm2d-16',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 128)])),\n",
       "             ('ReLU-17',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-18',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-19',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 36864)])),\n",
       "             ('BatchNorm2d-20',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 128)])),\n",
       "             ('ReLU-21',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-22',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 36864)])),\n",
       "             ('BatchNorm2d-23',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 128)])),\n",
       "             ('ReLU-24',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-25',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 64, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-26',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 73728)])),\n",
       "             ('BatchNorm2d-27',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('ReLU-28',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-29',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 147456)])),\n",
       "             ('BatchNorm2d-30',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('Conv2d-31',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 8192)])),\n",
       "             ('BatchNorm2d-32',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('ReLU-33',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-34',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-35',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 147456)])),\n",
       "             ('BatchNorm2d-36',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('ReLU-37',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-38',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 147456)])),\n",
       "             ('BatchNorm2d-39',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('ReLU-40',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-41',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-42',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 147456)])),\n",
       "             ('BatchNorm2d-43',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('ReLU-44',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-45',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 147456)])),\n",
       "             ('BatchNorm2d-46',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('ReLU-47',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-48',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-49',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 147456)])),\n",
       "             ('BatchNorm2d-50',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('ReLU-51',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-52',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 147456)])),\n",
       "             ('BatchNorm2d-53',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 256)])),\n",
       "             ('ReLU-54',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-55',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-56',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 294912)])),\n",
       "             ('BatchNorm2d-57',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-58',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-59',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-60',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('Conv2d-61',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 32768)])),\n",
       "             ('BatchNorm2d-62',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-63',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-64',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-65',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-66',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-67',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-68',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-69',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-70',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-71',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-72',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-73',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-74',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-75',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-76',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-77',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-78',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-79',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-80',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-81',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-82',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-83',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-84',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-85',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-86',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-87',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-88',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-89',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-90',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-91',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-92',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-93',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-94',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-95',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-96',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 589824)])),\n",
       "             ('BatchNorm2d-97',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('ReLU-98',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-99',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-100',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 1179648)])),\n",
       "             ('BatchNorm2d-101',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 1024)])),\n",
       "             ('ReLU-102',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-103',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 2359296)])),\n",
       "             ('BatchNorm2d-104',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 1024)])),\n",
       "             ('Conv2d-105',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 131072)])),\n",
       "             ('BatchNorm2d-106',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 1024)])),\n",
       "             ('ReLU-107',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-108',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-109',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 2359296)])),\n",
       "             ('BatchNorm2d-110',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 1024)])),\n",
       "             ('ReLU-111',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-112',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 2359296)])),\n",
       "             ('BatchNorm2d-113',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 1024)])),\n",
       "             ('ReLU-114',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-115',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-116',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 2359296)])),\n",
       "             ('BatchNorm2d-117',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 1024)])),\n",
       "             ('ReLU-118',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('Conv2d-119',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 2359296)])),\n",
       "             ('BatchNorm2d-120',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('trainable', False),\n",
       "                           ('nb_params', 1024)])),\n",
       "             ('ReLU-121',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('BasicBlock-122',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 512, 4, 4]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('ConvTranspose2d-123',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 128, 8, 8]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 262272)])),\n",
       "             ('Conv2d-124',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 128, 8, 8]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 32896)])),\n",
       "             ('BatchNorm2d-125',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('UnetBlock-126',\n",
       "              OrderedDict([('input_shape', [-1, 512, 4, 4]),\n",
       "                           ('output_shape', [-1, 256, 8, 8]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('ConvTranspose2d-127',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 131200)])),\n",
       "             ('Conv2d-128',\n",
       "              OrderedDict([('input_shape', [-1, 128, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 16, 16]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 16512)])),\n",
       "             ('BatchNorm2d-129',\n",
       "              OrderedDict([('input_shape', [-1, 256, 16, 16]),\n",
       "                           ('output_shape', [-1, 256, 16, 16]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('UnetBlock-130',\n",
       "              OrderedDict([('input_shape', [-1, 256, 8, 8]),\n",
       "                           ('output_shape', [-1, 256, 16, 16]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('ConvTranspose2d-131',\n",
       "              OrderedDict([('input_shape', [-1, 256, 16, 16]),\n",
       "                           ('output_shape', [-1, 128, 32, 32]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 131200)])),\n",
       "             ('Conv2d-132',\n",
       "              OrderedDict([('input_shape', [-1, 64, 32, 32]),\n",
       "                           ('output_shape', [-1, 128, 32, 32]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 8320)])),\n",
       "             ('BatchNorm2d-133',\n",
       "              OrderedDict([('input_shape', [-1, 256, 32, 32]),\n",
       "                           ('output_shape', [-1, 256, 32, 32]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('UnetBlock-134',\n",
       "              OrderedDict([('input_shape', [-1, 256, 16, 16]),\n",
       "                           ('output_shape', [-1, 256, 32, 32]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('ConvTranspose2d-135',\n",
       "              OrderedDict([('input_shape', [-1, 256, 32, 32]),\n",
       "                           ('output_shape', [-1, 128, 64, 64]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 131200)])),\n",
       "             ('Conv2d-136',\n",
       "              OrderedDict([('input_shape', [-1, 64, 64, 64]),\n",
       "                           ('output_shape', [-1, 128, 64, 64]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 8320)])),\n",
       "             ('BatchNorm2d-137',\n",
       "              OrderedDict([('input_shape', [-1, 256, 64, 64]),\n",
       "                           ('output_shape', [-1, 256, 64, 64]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 512)])),\n",
       "             ('UnetBlock-138',\n",
       "              OrderedDict([('input_shape', [-1, 256, 32, 32]),\n",
       "                           ('output_shape', [-1, 256, 64, 64]),\n",
       "                           ('nb_params', 0)])),\n",
       "             ('ConvTranspose2d-139',\n",
       "              OrderedDict([('input_shape', [-1, 256, 64, 64]),\n",
       "                           ('output_shape', [-1, 1, 128, 128]),\n",
       "                           ('trainable', True),\n",
       "                           ('nb_params', 1025)]))])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[torch.Size([3, 64, 64, 64]),\n",
       " torch.Size([3, 64, 32, 32]),\n",
       " torch.Size([3, 128, 16, 16]),\n",
       " torch.Size([3, 256, 8, 8])]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[o.features.size() for o in m.sfs]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.freeze_to(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a2661ed6f2c049098c0b37f13ac2e03e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/html": [
       "<p>Failed to display Jupyter Widget of type <code>HBox</code>.</p>\n",
       "<p>\n",
       "  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n",
       "  that the widgets JavaScript is still loading. If this message persists, it\n",
       "  likely means that the widgets JavaScript library is either not installed or\n",
       "  not enabled. See the <a href=\"https://ipywidgets.readthedocs.io/en/stable/user_install.html\">Jupyter\n",
       "  Widgets Documentation</a> for setup instructions.\n",
       "</p>\n",
       "<p>\n",
       "  If you're reading this message in another frontend (for example, a static\n",
       "  rendering on GitHub or <a href=\"https://nbviewer.jupyter.org/\">NBViewer</a>),\n",
       "  it may mean that your frontend doesn't currently support widgets.\n",
       "</p>\n"
      ],
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=1), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  0%|                                                                                           | 0/64 [00:00<?, ?it/s]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Exception in thread Thread-14:\n",
      "Traceback (most recent call last):\n",
      "  File \"C:\\Users\\j\\Anaconda3\\envs\\fastai\\lib\\threading.py\", line 916, in _bootstrap_inner\n",
      "    self.run()\n",
      "  File \"C:\\Users\\j\\Anaconda3\\envs\\fastai\\lib\\site-packages\\tqdm\\_tqdm.py\", line 144, in run\n",
      "    for instance in self.tqdm_cls._instances:\n",
      "  File \"C:\\Users\\j\\Anaconda3\\envs\\fastai\\lib\\_weakrefset.py\", line 60, in __iter__\n",
      "    for itemref in self.data:\n",
      "RuntimeError: Set changed size during iteration\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 92%|█████████████████████████████████████████████████████████████████▍     | 59/64 [00:22<00:01,  2.68it/s, loss=2.45]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "learn.lr_find()\n",
    "learn.sched.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lr=4e-2\n",
    "wd=1e-7\n",
    "\n",
    "lrs = np.array([lr/100,lr/10,lr])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "dce9710ec3314546b8d1dfc8e1d250f6",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=8), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch      trn_loss   val_loss   <lambda>   dice           \n",
      "    0      0.12936    0.03934    0.988571   0.971385  \n",
      "    1      0.098401   0.039252   0.990438   0.974921        \n",
      "    2      0.087789   0.02539    0.990961   0.978927        \n",
      "    3      0.082625   0.027984   0.988483   0.975948        \n",
      "    4      0.079509   0.025003   0.99171    0.981221        \n",
      "    5      0.076984   0.022514   0.992462   0.981881        \n",
      "    6      0.076822   0.023203   0.992484   0.982321        \n",
      "    7      0.075488   0.021956   0.992327   0.982704        \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.021955982234979434, 0.9923273126284281, 0.9827044502137199]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lr,1,wds=wd,cycle_len=8,use_clr=(5,8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.save('128urn-tmp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('128urn-tmp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.unfreeze()\n",
    "learn.bn_freeze(True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "86aa94831fa840b7ae471989af971594",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=20), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  0%|          | 0/64 [00:00<?, ?it/s]\n",
      "epoch      trn_loss   val_loss   <lambda>   dice            \n",
      "    0      0.073786   0.023418   0.99297    0.98283   \n",
      "    1      0.073561   0.020853   0.992142   0.982725        \n",
      "    2      0.075227   0.023357   0.991076   0.980879        \n",
      "    3      0.074245   0.02352    0.993108   0.983659        \n",
      "    4      0.073434   0.021508   0.993024   0.983609        \n",
      "    5      0.073092   0.020956   0.993188   0.983333        \n",
      "    6      0.073617   0.019666   0.993035   0.984102        \n",
      "    7      0.072786   0.019844   0.993196   0.98435         \n",
      "    8      0.072256   0.018479   0.993282   0.984277        \n",
      "    9      0.072052   0.019479   0.993164   0.984147        \n",
      "    10     0.071361   0.019402   0.993344   0.984541        \n",
      "    11     0.070969   0.018904   0.993139   0.984499        \n",
      "    12     0.071588   0.018027   0.9935     0.984543        \n",
      "    13     0.070709   0.018345   0.993491   0.98489         \n",
      "    14     0.072238   0.019096   0.993594   0.984825        \n",
      "    15     0.071407   0.018967   0.993446   0.984919        \n",
      "    16     0.071047   0.01966    0.993366   0.984952        \n",
      "    17     0.072024   0.018133   0.993505   0.98497         \n",
      "    18     0.071517   0.018464   0.993602   0.985192        \n",
      "    19     0.070109   0.018337   0.993614   0.9852          \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.018336569653853538, 0.9936137114252362, 0.9852004420189631]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lrs/4, 1, wds=wd, cycle_len=20,use_clr=(20,10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.save('128urn-0')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('128urn-0')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x,y = next(iter(md.val_dl))\n",
    "py = to_np(learn.model(V(x)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQUAAAD8CAYAAAB+fLH0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAABA5JREFUeJzt3dFN21AAhtFQMQVTsETFBJ2yE6AuwRSM0fQpEl9VwNBg32uf8wZCwqDw+Xewkpvz+XwCuPi29QEAYxEFIEQBCFEAQhSAEAUgRAEIUQBCFIC43foATqfT6fu3H26rhC/26/fPmyVfZykAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKABxu/UBMJbH56fVvtfD3f1q34vlLAUgLIUDWnMNvOWt47AitmMpAGEpHMgoC2GJl8dqNazLUjiImYLAtkQBCJcPO7eHhXD5GVxGrMNSAEIUmMbj89Muls/oRAEIUQBCFHZqz1N7rz/XKEQBCFFgSnteQlsTBSDcvLQzzp78L0sBCFEAQhSYmiccr08UgBAFdsFauB5R2JGj/2G4lLgOUQDCfQoTeO3sd3nREWfH+tfvwwu0LGcpAGEpTMxC4CtYCkBYCgOzBNiCpTCwh7t7T5CxOlEAQhQmYC2wJlEAQhQm43mGj/P7+hj/fZiEBzZrsRSAsBTYLevqcywFICyFybjLcTlvYf85lgIQlsIkLATWYimwe4L6MaIAhCgAIQpAiMIEXBOzJlHgELwnxHKiAIT7FAbmzHZ97nJ8n6UAhCgAIQpAiAIQogCEKAAhCkCIAhCiwCG5Mex17mgckAcsW7IUgBAFIEQBCFEAQhSAEAUgRAEIUQDCzUsDcdMSI7AUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQhYE83N1741M2JwpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiwCF52bvXicKAvFYjWxIFIEQBCFEAQhSAEAUgbrc+AFiT/+q8TxQG9vIB/Pj8lM9dPmYZMVjO5QMQlsIk/j7TvXbmO/KCsAauw1IAwlLYmbfOlrOuCAtgXaJwIP64WMLlAxCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAxM35fN76GICBWApAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAxB8Zg4ZPO/0D6QAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img(py[0]>0);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQUAAAD8CAYAAAB+fLH0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAABA5JREFUeJzt3dFN22AARtFQMQVTsETFBJ2yE6AuwRSM0fQJNbdqCAE79m+f81hVyCDl+rOdwN3xeDwAvPm29AEA6yIKQIgCEKIAhCgAIQpAiAIQogCEKABxv/QBHA6Hw/dvP7ytEmb26/fPu4/8P0sBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAGI+6UPgHV5fn2Z9es/PTzO+vX5OksBCEthR+ZeAVMeg0WxHEsBCFFglZ5fX1axbPZIFHZi1BfYqMc9MlEAQhSAEAUgPJLcuC1ck799Dx5T3oalAIQoMAyPKW/D5cNGefHwWZYCEKIAhCgAIQobs4ebcVv//pYmCkCIAhCiwJD2cJm0FFEAQhQ2xJmTKYgCEKIAhM8+DMBlwXX+/Xn5yPV1LAUgLAWGdvoLWM4tqtN/txousxSAsBRW7NK9hLeznnsOTEkUBiYGf/lZTMflAxCWwoqd3hRzJuRWLAUgLIVB/O9RmvVQHjdOw1IYlCAwF1EAQhTYDL94ZRqiAIQbjYNxJrzMH6T9GksBCEthEBbC9SyGz7EU2DxBvY4oACEKA3Cm45ZEAQhRAMLThxVz2TAdTyI+zlIAQhSAEAUgRIFd8UnKy0QBCFEAQhSAEAUgvHlphdwIY0mWAhCiAIQosEsu0c4TBSBEAQhRAEIUgPA+hRVx84s1sBSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFFbk6eHx8PTwuPRhsHOiAIQoACEKQIgCu+TezXmiAIQoACEKK+TRJEsSBSBEAQhRAEIUgLhf+gA47/Rm4/Pry4JHsh1u4F5mKQBhKQzivTOcFfE+6+A6lgIQlsIGzH0mXOMScfafjyhwkRfgvrh8AEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAEAUgRAEIUQBCFIAQBSBEAQhRAEIUgBAFIEQBCFEAQhSAuDsej0sfA7AilgIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgAIQpAiAIQogCEKAAhCkCIAhCiAIQoACEKQIgCEKIAhCgA8QfWQY8SR/FLYgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img(y[0]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 512x512"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sz=512\n",
    "bs=16"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tfms = tfms_from_model(resnet34, sz, crop_type=CropType.NO, tfm_y=TfmType.CLASS, aug_tfms=aug_tfms)\n",
    "datasets = ImageData.get_ds(MatchedFilesDataset, (trn_x,trn_y), (val_x,val_y), tfms, path=PATH)\n",
    "md = ImageData(PATH, datasets, bs, num_workers=4, classes=None)\n",
    "denorm = md.trn_ds.denorm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m_base = get_base()\n",
    "m = to_gpu(Unet34(m_base))\n",
    "models = UnetModel(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn = ConvLearner(md, models)\n",
    "learn.opt_fn=optim.Adam\n",
    "learn.crit=nn.BCEWithLogitsLoss()\n",
    "learn.metrics=[accuracy_thresh(0.5),dice]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.freeze_to(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('128urn-0')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "2cd9f452b7dc40b58895f0ca5b876936",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=5), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch      trn_loss   val_loss   <lambda>   dice              \n",
      "    0      0.071421   0.02362    0.996459   0.991772  \n",
      "    1      0.070373   0.014013   0.996558   0.992602          \n",
      "    2      0.067895   0.011482   0.996705   0.992883          \n",
      "    3      0.070653   0.014256   0.996695   0.992771          \n",
      "    4      0.068621   0.013195   0.996993   0.993359          \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.013194938530288046, 0.996993034604996, 0.993358936574724]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lr,1,wds=wd, cycle_len=5,use_clr=(5,5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.save('512urn-tmp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.unfreeze()\n",
    "learn.bn_freeze(True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('512urn-tmp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "8768382fe1fe4b8e94e6647899e20575",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=8), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch      trn_loss   val_loss   <lambda>   dice              \n",
      "    0      0.06605    0.013602   0.997      0.993014  \n",
      "    1      0.066885   0.011252   0.997248   0.993563          \n",
      "    2      0.065796   0.009802   0.997223   0.993817          \n",
      "    3      0.065089   0.009668   0.997296   0.993744          \n",
      "    4      0.064552   0.011683   0.997269   0.993835          \n",
      "    5      0.065089   0.010553   0.997415   0.993827          \n",
      "    6      0.064303   0.009472   0.997431   0.994046          \n",
      "    7      0.062506   0.009623   0.997441   0.994118          \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.009623114736602894, 0.9974409020136273, 0.9941179137381296]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lrs/4,1,wds=wd, cycle_len=8,use_clr=(20,8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.save('512urn')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('512urn')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x,y = next(iter(md.val_dl))\n",
    "py = to_np(learn.model(V(x)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQYAAAD8CAYAAACVSwr3AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAABIxJREFUeJzt3NFt40YUQFF64SpUhZsIXEGqTAVCmnAVLiPKR7CA4LsbS7IsDofn/BkwoCFB3nmmJT2dTqcF4NyPtRcAjEcYgBAGIIQBCGEAQhiAEAYghAEIYQDiee0FLMuy/PHjT2+/hG/29z9/PV36uyYGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYgntdeAOs5vr8tr4eX5fj+9rDXfD28POy1uJ0w7NB5CB4Zhc9eTzTGIQw78ugIXOvn+gRifZ4x7MToUTi3pbXOShgYkjisSxh2YKs32VbXPQNhmJybi1sIAxDCMLEZpoUZjmGLhIHhicPjCQMQwjCp2XbZ2Y5ndMIAhDBMyO7KVwkDmyF4jyMMQAjDZGbfVWc/vlEIAxDCMJG97KZ7Oc41CQMQwjAJuyj3JAxACMME9jgt7PGYH8mXwW7Ax5vAl6Xy3UwMg/vVznh8f7NjLr+fGpyfrzMxDMzFfZ2P5+v8Z1PWdUwMQAgDu2D6uo4wbJi/pd3w38UzBjZPHO7PxDAwD8xYi4lhcOdxsDPeTmSvIwwbIhKXez28LMf3N0G4kTAwjY8REIXbecawQaYFvpswbIwo/J5zcz/CwFTE4T6EYUNc9DyKMDAdAf06YdgIFzuPJAwbIArX8zmSrxEGpiYOtxGGwbmwWYMwDEwUWIswMD2BvZ4wACEMQAjDoIy/9+V8XkcYgBAGIIQBCGFgNzxnuJwwACEMA7KzsTZhYFdE9zLCAIQwDMaOxgiEAQhhAEIYgBAGdsdznM8JAxDCAIQwACEMQAgDEMIAhDAAIQxACAMQwgCEMAAhDAPxHn5GIQxACAMQwjCQ18PL2kuAZVmEAfgFYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYRiIL2phFMIwEB+7ZhTCMBATA6MQhoGYGBiFMAAhDEAIA7vjT7bPCQMQwjAYuxkjEAYghIFdMZFdRhiAEIYB2dVYmzAAIQyDMjWwJmEYmDjcl/N5uee1F8D/O7+YffrydqJwHWHYkEsubvH4jxB8jTBM5rMbYqZwuPm/jzDszKg3089gvR5eluP727Dr3AthYAjnIRCF9fmvBBDCAIQwACEMQAgDEMIAhDAAIQxACAMQwgCEMAAhDEAIAxDCAIQwACEMQAgDEMIAhDAAIQxACAMQwgCEMAAhDEAIAxDCAIQwACEMQAgDEMIAxNPpdFp7DcBgTAxACAMQwgCEMAAhDEAIAxDCAIQwACEMQAgDEMIAhDAAIQxACAMQwgCEMAAhDEAIAxDCAIQwACEMQAgDEMIAxL+fjtP4pEiy4gAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img(py[0]>0);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQYAAAD8CAYAAACVSwr3AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAABF9JREFUeJzt3NFtG0cUQFHJUBWuwk0EriBVpgIhTagKlRHmIwgi+MYSSe16Z2bP+TNgyMPBzp1HyuDj5XJ5AHjry9ELAMYjDEAIAxDCAIQwACEMQAgDEMIAhDAA8XT0Ah4eHh5++/K7/34JO/vzrz8er/27JgYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCejl4A43h+fdntZ3//+m23n832hOFk9jz8W/y7AjIGbyVO5Kgo3OL59WWKda5OGE7CYeMWwsCQhOxYwnACsx6yWde9AmEAQhgWN/utO/v6ZyUMC3OouJcwMDyB+/WEAQhhWNRqt+xqr2d0wgCEMCxo1dt11dc1ImEAQhgWs/qtuvrrG4UwACEMTMfUsD9hWIgDw1aEAQhhWIRpgS0JA1MSwn0JwwIcErbmW6IH97ND79uU/9kb+7APE8PA3psETAn/799vmbY/n2NiYBk/xuDHP5surmdimNzZb8azv/69CAMQwsD0TA3bE4aJORD/sRfbEoaB+bCMo/itxODexsGteD+RvY0wTEQkbiMG9xMGliEE2/EZw4RMC+xNGIAQhsmYFn7O3mxHGFiKOGxDGCbiob+Offo8YZiEh/029utzhGECHvL72Lf7CQNLE4f7CMPgPNgcQRiAEIaBmRa2YR9vJwxACAOnYGq4jTAMyoPMkYQBCGHgNExh1xMGIIRhQG42jiYMQAgDp2Iau44wACEMg3GjMQJh4HTE92PCAIQwACEMQAgDEMIAhDAAIQwD8Ws0RiEMQAgDp2Q6e58wACEMQAgDEMIAhDAAIQxACAMQwgCEMAAhDEAIAxDCAIQwACEMQAgDEMIAhDAAIQxACAMQwgCEMAAhDEAIA6f0/eu3o5cwNGEAQhiAEAYghGEg3vcyCmEAQhiAEAYghAEIYRiMDyD3Z48/JgxACAMQwgCEMAzIe+D92NvrCAMQwjAoNxtHEoaBicO27Of1no5eAO97+zA/v74cuJK5icJthGEi7z3colFicD9hWMQth2DViAjBdoThhBwgPuLDRyCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEA4vFyuRy9BmAwJgYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEAQhiAEAYghAEIYQBCGIAQBiCEAQhhAEIYgBAGIIQBCGEA4m/jpL5hSyL6CwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img(y[0]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1024x1024"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sz=1024\n",
    "bs=4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tfms = tfms_from_model(resnet34, sz, crop_type=CropType.NO, tfm_y=TfmType.CLASS)\n",
    "datasets = ImageData.get_ds(MatchedFilesDataset, (trn_x,trn_y), (val_x,val_y), tfms, path=PATH)\n",
    "md = ImageData(PATH, datasets, bs, num_workers=16, classes=None)\n",
    "denorm = md.trn_ds.denorm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m_base = get_base()\n",
    "m = to_gpu(Unet34(m_base))\n",
    "models = UnetModel(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn = ConvLearner(md, models)\n",
    "learn.opt_fn=optim.Adam\n",
    "learn.crit=nn.BCEWithLogitsLoss()\n",
    "learn.metrics=[accuracy_thresh(0.5),dice]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('512urn')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.freeze_to(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a864769b63b7438fa112cf68e2835a0e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=2), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch      trn_loss   val_loss   <lambda>   dice                 \n",
      "    0      0.007656   0.008155   0.997247   0.99353   \n",
      "    1      0.004706   0.00509    0.998039   0.995437             \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.005090427414942828, 0.9980387706605215, 0.995437301104031]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lr,1, wds=wd, cycle_len=2,use_clr=(5,4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.save('1024urn-tmp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('1024urn-tmp')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.unfreeze()\n",
    "learn.bn_freeze(True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lrs = np.array([lr/200,lr/30,lr])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=4), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch      trn_loss   val_loss   <lambda>   dice                 \n",
      "    0      0.005688   0.006135   0.997616   0.994616  \n",
      "    1      0.004412   0.005223   0.997983   0.995349             \n",
      "    2      0.004186   0.004975   0.99806    0.99554              \n",
      "    3      0.004016   0.004899   0.99812    0.995627             \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.004898778487196458, 0.9981196409180051, 0.9956271404784823]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lrs/10,1, wds=wd,cycle_len=4,use_clr=(20,8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6ba1a0b69230449da669623edfd3f6c1",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(IntProgress(value=0, description='Epoch', max=4), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch      trn_loss   val_loss   <lambda>   dice                 \n",
      "    0      0.004169   0.004962   0.998049   0.995517  \n",
      "    1      0.004022   0.004595   0.99823    0.995818             \n",
      "    2      0.003772   0.004497   0.998215   0.995916             \n",
      "    3      0.003618   0.004435   0.998291   0.995991             \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.004434524739663753, 0.9982911745707194, 0.9959913929776539]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "learn.fit(lrs/10,1, wds=wd,cycle_len=4,use_clr=(20,8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAD8CAYAAABpcuN4AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJztnXl8FOX9xz/fPbJJOCUEBAKE+74UEbwFDxAq1nqg1Z9WW63V2tZahXrUixa1VVurba1irTfVahEUL0TBg0vlBgmXcoebBHLs7vP7Y+aZfWZ2ZnZ2s5tNst/364XOzjwz8+wkeb7zvUkIAYZhGIZxwpftCTAMwzANGxYUDMMwjCssKBiGYRhXWFAwDMMwrrCgYBiGYVxhQcEwDMO4woKCYRiGcYUFBcMwDOMKCwqGYRjGlUC2J5AO2rZtK0pLS7M9DYZhmEbF0qVL9wghihONaxKCorS0FEuWLMn2NBiGYRoVRLTFyzg2PTEMwzCusKBgGIZhXGFBwTAMw7jCgoJhGIZxhQUFwzAM4woLCoZhGMYVFhQMwzCMKywoPPDxN+VYvvVAtqfBMAyTFZpEwl2muWr6IgDA5mnjszwThmGY+oc1ikbEjoNH8X/TF+FQVW22p8IwTA7BgiIJIlGR1fv/5cP1+OSbcsz8entW58EwTG7BgiIJaiPRrN5/057KrN6fYZjcJKcFRdnuCqzdecjz+GxrFF9s3JfV+zMMk5vktKCYOns1bnttuefx4Uh2BYUknGXNhmGY3CKnBYWPCFHhffGvjTaMBXrq22uyPQWGYXKInBYUREAya//zn3sq3Z5xahuIZsMwTG6Q44KCkMyS++cP12Phxr0Zm08ihnZuDQC46cyeWZsDwzC5R04LCh8BIgnTEwDsPFSVodkkpm3zEAAg4KeszYFhmNwjxwVFcj4KANhbUZOh2STGp8uHbIfpMgyTW7CgSNLcf9+s1ZmZTBI4RV+t3HYQG8or6nk2DMM0dXK61hMRktYosomcaY2DRjHh8QUAuCYVwzDpJec1imTlxKXDO2dmMknApieGYeqTnBYUXjWKoOI89mXxicmpNpTEP4ZhcoOcFhReNQq/LyYosl3GA3A2PTEMw2QC9lF4kBTqkIawRv/3y20gEG4f2wftWuZnezoMwzRxWKPwoCCoQ8JZLeMRm8nrX27FKQ9+lMW5MAyTK+S4oPCqUcTG1IQbgEqhwyYohmHqgxwXFN4S7tQh2RQU1qm2axHKzkQYhskpclpQkMeEO3VIQ3qLL6+oxo+fW4yt+48g2gCc7AzDNE1y3pntpdaTOqY6zRrFoapaDL7nPdw/cQCuHFWa1LlCAB+s2Y38oB+DOrVK67wYhmEkOa1RaEUBE48zaRRpFhS79SKDz3koYe401XBE4OvvDqRxVgzDMDFyWqNIxUeR/qzouleCDUejWL3de0tXhmGYZPCkURDRWCJaR0RlRDTZ5niIiF7Vjy8kolLl2BR9/zoiOtdynp+IviKiWTbXfJyIMlrhLpWigJlyZidrAlOpjQhsP1iVcBzDMEwqJBQUROQH8ASAcQD6A7iMiPpbhl0LYL8QoieARwE8qJ/bH8AkAAMAjAXwpH49yS8AxPX1JKLhAFon/W2SxEvCnXXRXb+7AkIIPDhnLe6ZucrTfbbsrUTp5NlYumW/3R2U/6ZGOBrF4JKYj6KqtuE43BmGafx40ShGACgTQmwUQtQAeAXARMuYiQCe07dfAzCGiEjf/4oQoloIsQlAmX49EFEJgPEAnlYvpAuShwHcltpX8o6XhDt5/Jdn9TL2fbfvKP42bwP+9dlmT/eZu3Y3AOClhd/GHQtLlaYOkqI2IpDnj/0oD1fVpn4xhmEYC14ERScA3ymft+r7bMcIIcIADgIoSnDuY9CEgfX19yYAM4UQOzzMrU54SbiTR0nxJdQmmZ1dURUGoGVTW0mmwJ86slPrAmN7z+Fq1Co2tD1ZbK7EMEzTw4ugsPO2Wlc3pzG2+4loAoDdQoilposQdQRwMYDHE06K6DoiWkJES8rLyxMNd7qGZ9MTEYy39l/PWJbUff70/jeOx6RGsXFPJQ4c8b7Aq/Pu17ElwoqT/UhNOKn5MQzDuOFFUGwFoDZhKAGw3WkMEQUAtAKwz+XckwGcT0SboZmyRhPRCwCGAegJoEw/VkhEZXaTEkI8JYQYLoQYXlxc7OFrxEMewmNjGgUwtIvmNvl235GU7meHusD//u04dw2+2XXYGKPO1UcxGTx7+Q5sO3A0dk1OvmMYJo14ERSLAfQiom5ElAfNOT3TMmYmgKv07YsAzBXaq/hMAJP0qKhuAHoBWCSEmCKEKBFClOrXmyuEuEIIMVsIcawQolQ/dkR3kGeEZHwUPh8hFNAe177K5Ew7EwZ3cDymOp7X7zYHeT05rwznPPoJpr2zNuE9DhyJ+SW4XwXDMOkkoaDQfQ43AXgXWoTSDCHEKiK6j4jO14c9A6BIf/u/BcBk/dxVAGYAWA1gDoAbhRCR9H+N1PDio1CPS0GRLGq0k9UstGr7QWP7q2/NSXMPzVkHAHh6waa4a5JL+sUhdmYzDJNGPK18Qoi3hRC9hRA9hBBT9X13CyFm6ttVQoiLhRA9hRAjhBAblXOn6uf1EUK8Y3PteUKICQ73bZ7a1/KGW8LdH95Zg9LJs43PREBeAkHx7KebsHTLPhw8al6odyg5Dos3m0Nk/+BBW5B41RN+9uKXnq/JMAyTiJzOzHYrCviPjzVZJ+UIgUwhqFZqwlHc+9ZqAJrT+5up4/Dlt/sxtMScDuJWvK9zmwLT52FdWsdpGRKfjUqhaUiOl2cYhkmJnK/1BLhnMstQWCJg4jBrVHBs4a8OxyxqNZEopi/YhAuf/AzTPzWbjVoVBh3v1TwUO1YdjhhhtZcO7xw3T7sigPlBf9w+hmGYupLTgkLmRri9hdfqJTsIwMhuRXHHZdnx5VsPmvbfN0vTLsp2e69CogqbPnfOMZzbqnlsWJfWWPfAWPQ5tkXc+UdqGoz7h2GYJkROCwpPGkUklkcR9Mebe2TZ8R8+vdD2/I17KtGlTSHat9SaDNVaakV1LSqMXcuh9Ia1EGEo4IffV/diggzDMF7IbUHhs9coHlES5OQiTSDbxTlRkUAfAZGoQIFuFrI2Pup8jCIoFI1CFUq1EYGt+49g/vo9cceLmuWZrlfcIoSz+rV3nRPDMEwy5LSgkP5ga+TTXz5cb2wbgoI057fVoZ2o413rgjyEo1EU5AVM15NELKU31u86jEhUGJqMvMcNL2iRTBvLKwHEnNnFSjvUnu2aI+AjfLBmF1eQZRgmbeS2oNB9FG5raq0lec1qfkqkUQwvPUbXKHy246NCYGCnlsbnsx/9BF9s3GuZQ9TIv5AC4I2vtgEA1u48bIzzUSwU98l5G1znxTAM45WcFhT/WarVK1y946DjGLmwk/4GH7BqFAkExQOz1yAcFSjIk6Yns+ARAmgRMkdCrdlhbkJUE47GSok4zAMAjtbGTFdS82AYhqkrOS0o5GKqvpVbkYuv1COsyXQ14Siqat2jjSIRgYJgwBhvOiYEfJafwgOzzTWfaiNRI9tOmsvsssTVoraJ5sQwDOOVnBYUkpXbnNuIVuomH6eSGTWRCKb8d4Xr9VWNQvVRrNh6EEu37EdFdcQ163vx5v3YuEcTanIadoJC9UtsP3jU9nj6W7kyDNPUYUEB4OVF8Q2FJLLeklVO9Oug+RWqw1F8tmEP3IhEBQr1qCe1oOBjH2jRVcu+O4B8j3WkpCgIBWLJdY9dOhQA8PsLBxn77DK6//zhevS6452MtXNlGKZpwoIiAdJf4LOExm7Xy3rXhKPYdaja9Rpa1JO2sD/87jpjv3pNO5+DHRHdxyGvBwAXDOuEzdPG44w+7bDy3lhb8rBFe3hO78h34Cg3NmIYxjssKDxi1Sikr8LL23lUmBd2SUARFF4T6CK6eemu8f1sjzcPxcp3Ldt6EPPXx5o6yZBaayQXwzCMGzldFDApHJwUifIoJAU2dZhU4eB3qxuuIJsSFbcIYcLgDph0QhfHsT/422cAgM3TxgOIfQU2PTEMkww5rVH89ry+AMxv9k44jfC66AYV09JrS7Xe2f4UNAo1XPevlx+HU3q1TXjOUaMGlNQoWFAwDOOdnBYUl5/YFQDwizG9Eo51jHryKChUF8St/1mm74td1BoiCwDXntINU8b19XR9N2SoLGsUDMOkQk4LCqlJ+C3Z1mpZjNF92wGIZXE/c9VwAMB9Ewdo/9erxCbi1cXfOd4fsM8OP6NPsW2V2GSRhQvl7byayxiGYYAcFxTSuWttJlTcPISz+rVDp9YFcW/jY/q1x6I7xuACvTeF19LeG2wypfdWxKKP+toIhOFd25hMVl75zbl9TJ9lsUEp7FijYBgmGXJaUEjTj/UFW0DzAYSCPuNtXNU52rXINxUHPHdA4mqt5/SPjZHJdf07xmo8PTZpGO44LxbJdOXIrijI87v2xnZiiKWrnlWjYB8FwzDJkNOCQi6cEWGtvyTgIyDo82G/niBnXbBVQRGJ2msEKucP7Whsd2iVD8Ds4G4eCmB0v3bGZ+NYCpGsVr+47HMh60SxRsEwTDLktKAgIq3PtMX0FBUCPiKs23VYKZ1hXn3VZLlV2w8aYasqPziuxNge2DHWuvSYQq2HhJRPp/UuBmBuZSpLn1sv27Nd84Tfa2+lOaGuKmw2n23XK8wyDMN4IacFBaCZn6waRVTE/BcSNxPQjoNVppant57TG69eNxJDu2gmoMtGdEFp22ZYfs85aJEfQKsCrVrsrsPagv3UlccDgG0ZD2FRKdoU5sWNsdKlTaHp8+/+t8r0He56c2XCazAMw0hyXlD4iGw1CmvihJc8BzmmV/sWOLF7kVGkb+1OrQxIy/wg+h7bwjD9vLRQqzElNQk7jSKV/kNDOpt9FKtlGRJF2lnLezAMwziR84LC7yNTlzkAgI1GYScoJgzuYPo8Rg+llYv7l1v2AzAX6Av6fY7OZLUirCyzYe2+VxekJgMAR9JQhnz3YTZhMUwuwIKC7ExPmjP7J6d2M/ZZBQcA3HhmT2P7shFdEDDyMbTr2ZUOzwv4HPMY1MKAMqS1W9tmAIDxUiilEAUFAIs378PyrbEGTQeP1LqMTsxnG/ZgxNQP8d6qnXW6DsMwDZ+cFxQ+n53pSRMMw7ocY+yz0yh6FMccy0TAPecPwBUju2B0Xy0Utm3zUNw5Qb/PNero4YsGa9fTJULXomZY9rtz8MeLhuC4Lq1x94T+SXy7GJ9vMLdXnbEkPgEwGdbs0Jo9Xff80rhjX2zcy42TGKYJkfOCQjqz1+w4hHnrdgPQNAoiYPX2Q6ZxVoJ+MhzEBC2/4oELBhmaxJm6Keqvlw8zznHTKADg7P7t0a9DS/zszB7GvlYFQRTk+fHfn52MgZ1aOZ6rMqp7kenz/iPmSKjH55Z5uo4TwsEkdu9bqzDpqS9wxxvsMGeYpkLOCwofESJRYNyf5+PqZxfjaE0EW/drvSbUSCa76q5EZPgV7ExTJ5S2wZd3nY0Jg2M5FKEEGkXrwjy884tTTdpKKrx83Ug8eukQ4/Ozn26u0/W8Iu/z5bf76+V+DMNknpwXFH5fLCoIAB77UOs6986KnRjRrY0yzt45IDvNOYXPtmlmDmdVndmtCoK4dHjnlOeeiO8PK0k8KEUS+dgrq8MZuzfDMPULCwoiLPsuFpUks5iP1kZwjlKaw9rhTuKmUdiRF4hpFNGoQGEovk9FQ2bV9oPYfuBowmgsrzWwGIZp+OS8oLAKALUTXckxscQ1p8ZCuw+7t0G1Eo4K7D9Si70V1aiJRE2lQOoDtS6V2v3OK+P/sgAnTZtrm4muahGVNaxRMExTwdMqRURjiWgdEZUR0WSb4yEielU/vpCISpVjU/T964joXMt5fiL6iohmKfte1MeuJKLpRBREBrGalJyqtdr1izAd96hRvLxIS7K7+3+rUBuJplQdti4M7RyL5LrymUV412N464qtBxOO/eN7sX7gaUz/YBgmyyRcpYjID+AJAOMA9AdwGRFZYzSvBbBfCNETwKMAHtTP7Q9gEoABAMYCeFK/nuQXANZYrvUigL4ABgEoAPDjJL9TUlg1BadonkACSZFslddP1pcjKpwFU6b4sZIbApiTAZ2orA7je39dgOuVUNhiJfRXhhcnq10xDNM48LJKjQBQJoTYKISoAfAKgImWMRMBPKdvvwZgDGmlSicCeEUIUS2E2ASgTL8eiKgEwHgAT6sXEkK8LXQALAKQOY8s4k1PTmGjiQSBx06m+GzyaADA+UO0SKhgIMUMOo9Mv3q46bNVMHnJ/LYmJAIwmZ5qo5rPZV9FTdw4hmEaP14ERScAanbWVn2f7RghRBjAQQBFCc59DMBtAGxjRXWT05UA5niYY8o4+R6sFATtnc7/N0prp0oer9OxdYEpYzuYyKZVR2TynxPhSGJBYU1IBIBwNPZjm/z6CqzfdRjH6uXTGYZpWnhZpexWQOvK4TTGdj8RTQCwWwgRn9Yb40kAnwgh5ttOiug6IlpCREvKy5N3ykq8FPsDgAFKkyGV3Yc0c0tcvSgX8vw+Iyoo6M+sRpEITxqFnaBQBMwbX23D9S8sxcjubeLGMQzT+PEiKLYCUIP9SwBsdxpDRAEArQDsczn3ZADnE9FmaKas0UT0ghxERL8DUAzgFqdJCSGeEkIMF0IMLy4u9vA17PFadM9JY5ijO3gXrN/j+Z55AR8q9AihQD36KO75Xnz5Dy8Czmp6yg/6bM87XMWRTgzTFPGySi0G0IuIuhFRHjTn9EzLmJkArtK3LwIwV/cxzAQwSY+K6gagF4BFQogpQogSIUSpfr25QogrAICIfgzgXACXCSEyXgt77c7DtvsvHGa1rrlj7RvhRtBP2KQ3RGqRH0jqPnXh6pM1R/Z9EwcY+1RfQ004ih89uwgrtx00nRe1/BT8RIZfQuWB2da4hIbFym0H8cXGvYkHMgxjIqGg0H0ONwF4F1qE0gwhxCoiuo+IzteHPQOgiIjKoGkBk/VzVwGYAWA1NF/DjUKIRJlYfwfQHsDnRPQ1Ed2dwveqM3eM75d4UIrsOlRtlAcpzKs/QSE5s0+s5eqq7TGhsG7nYXy0rhy3v77cNN6qUVTWRIzERImdvlXXCrXpZsLjCzDpqS/w5lfbsj0VhmlUeFqlhBBvA3jbsu9uZbsKwMUO504FMNXl2vMAzFM+1//KaUOicFgr1lapXgnZlCLPNKozXS09Hgpq+6sttagiNg5va4kOOwve7sNVaFWY0TSYlPjlq1+jsiaMH57YNdtTYZhGQYNYlBsiyQYj2fWe8IKaCZ4pZt50sqn3tlM2uBR1ZbsrUDp5NgDgnV+cauq8J6mwCAq7suKLN+9Hr/YtUprzk/PKULa7Ao9cMjSl8xOxRqnvlQ4iUYHKmjBa5jc8wcgwdSXnS3g44TXT+vlrRwAArhyV2tvpsS0zH1I6uKQ1hirtUaXmIJGO6VobzWH28h22jutXFpv7WWw/GN/trmVB6u8hD81Zh/9+uQ37KjOTm3FSj7Zpvd6fP1yPwfe8h0NVDcvcxjDpgAWFA17DZk/tVYxFd4zBxcenlhfYuU1h4kFpxqpRXPfvJQDMuRGSmkjUFBlm7cftRjIhw07sOtQ42q2+tUwLBNzD2elME4QFhQPS3DL75lPwkN51zol2LfI9J9w1BKwhuR+u1Ro2zbcJ8Y1EhbHg//2K43Dz6J5xY6w89APtebn13XBDdYJnqgqtU9/yVJHC160pFcM0VlhQJGBAx1a4JIM9IxoK1eEIHn53Xdx+VVD4iOL8Fa0KzDb5oJ9wRt9i/ZqpLZrPfb7ZdP90UVoU096sUVt1RfqoUhWODNOQYUHBAHBOlnt31U4jwsnvixcUVgvdLWf3MZo5SUFxpCZsWwbEiXzFh2JnDksV1cxXneY3f5lhz4KCaYqwoMgCRXrXu77HphYRlAmcOtLtOFiF+2atBqAVULSWHLGa3GYt326E/FaHI6ioDqP/3e/ij++tc6zMa0Wtq+WlFpVX1NtX20Rp1QVDo2DTE9ME4fBYGzpkuLjdnF+ehhXbDmBEt6KM3icZ3HwBsoe4nyjOtm/VKE7rXWzY66tro4YAenLeBjw5bwOW3HkW2iolyu0IKYIinaanRZv2GdvpXtBlVV7WKJimCGsUNjz4A3fndV0pbhHC6L7t0TzUcOR0TTiKCYM72B6TwiHgI/Q9NlYccdW95+L2sX1NY289pw98PkKe34eaSBQBiySRGeluqOat/UfSEx47d+0uk3BI94IeYh8F04RhQWFDNrKls011OOpYrUpqGz4foVkogM3TxmPztPFoFgrgYoujX4YV10SimPn19rgwYy8aQp5i3rplxrIkvoUzXysNmoJ+StnR7oQ0PdnlojBMYyf3VkQPWJsZNUVm/fwU9O8Q0w5qwtH44vEWnHJLxg081nb/tgNH4/bZ9dpOZUxdyPP70v7mL81t0z/dhD+8vQZnP/KxqY4WwzRmWFAoSL9sDsgJDOzUCpeeENMG9lZWY/aKHa7nOGWrt9Gd8yrd2zZD5zYFcTWgIh6imBYrvoR00VIJ480LpF9QSHPZ0i378Y9PNmL97gpc/PfP03oPhskWLCgUehQ3B+C9W11jR3VgT3tnbcLxThqFnaA4rusxtsUEE0UxRaMCz32+JeFckqW3UnMqFPCjOpzeqCe7eliZShZkmPom5wXFTWfGMo1lW1SvdZ4aO2oPjT0ViUtPWB3Tkp+e3iNuX37QZ+v3SGRW8tpIKlmkb+TRS4dkVKNgmKZIzguKX5/TGwDQpU1hTpmeAHNegeqE/evlw2zHOwnQZjbRW3l+P2rC0bjcicSCwvUwAOD5zzejdPLspBb7F77QtJROrQsRCvjSHh6biwEQTO6Q87/dRITnrhmB1346yjCtpNpboqkwYXBH2/3JvO0HA2Sb/ZwoQ/vLb/cnvPajH6wHgKQqtcp6VgeO1CAv4Et7CY9c0UKZ3CTnBQUAnN67GO1a5huCIlPmj4ZGsmtbMm1bQ34faiPxpqf3Vu90Pe+ON1YY26VFhbb+DxlhlEphP7+PNNNTmjWKZFrhMkxjgwWFgnRiW1t/NlXs3oJnXD/KcXzXomaerx30+yBEvPP67RXugmJDeaWxfXzXNkY5j6raiKGNBAOp11Xy+QihDGgUDNOUYUGhIPO8kilg15j5wXElGNCxJU7tFWviM7iklbE9sFNL3HGe1jtcHWPHDWf0wI9OLjU+W6up/ubcPo7nCiFQOnk2/vSeuXptXoBQE9H8HH3vmoPJ/9V6eQf9qSe3DezYCnkBf9qLAjJMU6bh1JBoAMg37ByREyhuEcLsm0/F819sMXpRyEV47f1j4fcRFpRp+xOFDFtLeRi1jyJaiKjMYxjTt13cuUf1An2Pzy0z7ZeJcd/t0xL3ZizZiocuGpKS6emsfu2xeW8liluEMpJwpyqhLfMDOORQjZdhGiOsUSjEBEWOSAqdQiW0U/pp8oN+BP0+VOm5AIVJhn+W6+G2+yo1hzMB6FHczDaMVAoCK0HdzyH9Ca0LNWET0FW/ZARFJBpFod6fPBT0pT2PQuWyE7sAMJdLZ5jGDGsUCj797zpXTE+SgrzEQsCX5Jp3WI9I2lAeKwKYH/Sjyqa8t8xxaNMsDweO1Bgancx3UBsnAarpybugCEeFkQeyevshbNpTiUNVtWiZH0xwZvL8+uw+2FReiS17j6T92gyTDfiVR0F2a8uFWk8qmah4On6QFmIr3+KJdEFh8yYvF3wfEcYN1CrYfnDLaQj6fQhHhXFcanqxkt7eBXptJGq0gN20R3OYP/r+N5iz0t257hU5ExlV1SwUwJFaNj8xTQMWFArTLhyM28b2wYnd2mR7KvVK0O/8ayBdE8mWNZFaylHddEUg5Ad9qLKJNlq8WavtVFFdi4Cf0LWoED3btTAc4tKHITWLVHwUtRFhnCd59tPN+OkLS+PGfrfvCN74aqvna6t8edfZADSN6rt9R7GvMj1l0t2Y8Ph8PPFRWeKBDJMiLCgUjmmWh5+d0TNnaj1J8lyyikf3bY/LT+yC332vf1LXlGGtar2j/IC96emB2WsAAFW1UQgRMzHJbGfZ/Ei6jlJpOxqORA3fRiIu/Ntn+NWryzx35FMnJ7XSD9ZoCX7H3f++Y/fAdLFy2yHbfucMky5YUDBx7U1V8gI+/P77g9CuRXJd/6QjV2oDhukpQQvSqBCGFiO1kgpDUGiLccCIqEpOowh4dLSUH9Yc8cl213N6v3jqk41JXYdhGhosKBijam46URPlJCEH05OKEDAKqMhrVOihpjIRMi+FtqO1kairQLTjf19vT2q8E68u/i4t12GYbMGCgkHnNoVpv2Z+ntn0RNAW/kQahYAwTE8ylFZqFFGr6SnJqCfpiymyKQtix6//4727nlX3mDIullcy1qGxUzr4bl/2Iqs+/qYc222aUzFNDxYUTEaQ2kDSpqdozIQjzVfvrd6lH7NGPSWnUUgfxcMXe++JnoyfQtVXxiv9x9NdV0rl1Ic+yti13ThUVYurpi/CSdPmZuX+TP3CgoLJCEG/D34fGVFPgLbwVyVY3MNRAb/uS8gPaMJmkaXjXTCQoulJv+7ovu1NyXBuwuC8vyzA6u2HEl7feolQIJabUpuB8ONsM33BpmxPgalHWFAwAID7Jg7AAxcMTOs1C4J+HKnRzEYEQn7Aj4iSFyG5YGisrHl1OGKYlkKWzOZwVGDhxr2Gj2L++vKEGgoA7DxYhV2Hqk1RT6qv5PONex3PXbPjEM77y/yE9wDMIcSqIEqlym1DJ8dyUnMeT4KCiMYS0ToiKiOiyTbHQ0T0qn58IRGVKsem6PvXEdG5lvP8RPQVEc1S9nXTr7Fev6Y3gzJTJ/5vVCmuGNk1rddsFvKjslrVKOw1BLW235GaiJFBrb6VSy596gtj+6N15bh/1uqE87jimYUAnEuzHDxi7mthzbdIBbVUSSrFCxs6PdulPwCCabgk/IsgIj+AJwCMA9AfwGVEZA2qvxbAfiFETwCPAnhQP7c/gEkABgAYC+BJ/XqSXwBYY7nWgwAeFUL0ArBfvzbTCGkeChilPEDApxu0AoM2QHt+AAAgAElEQVQ/fHqhaZxaMqWyOmyEsTrldyzfesDY/mbX4YTz2HmwCoBzuKt1b0mbgrgxiVrFWvtRqG1jm2KvCvn1uhalPxCCaXh4eXUaAaBMCLFRCFED4BUAEy1jJgJ4Tt9+DcAY0vTwiQBeEUJUCyE2ASjTrwciKgEwHsDT8iL6OaP1a0C/5gWpfDEm+zTPD+JwtTQ9AfPWlduOUxfwIzWRhIlxX34bExS7D7sv4M9+usmImpqxxD7b2m8p2WKneAx/4APX+wBmZ7Zqhoo2PcuTgRfTH9P48SIoOgFQA8G36vtsxwghwgAOAihKcO5jAG4DoP4ZFQE4oF/D6V5MI6FFKIDDVbGs6qnfj/lAhBB4ZsEmHDxaa2oUdaQmbCTUdWtr3yhJDW9NVHjv3rcSm6aspiZHzcPF6W136LIRnQEAlTWZycxONiEwncjvmygvhmkaeBEUdq931t9QpzG2+4loAoDdQghroR0v99IGEl1HREuIaEl5uf2bKpNd8oN+I8t5+qeb0LZ5yDj2adle3D9rNe59a5XJ9FRRHUbQZ64Sa0UVIKf2aoups1djWx3i+astUUlOC3Cihdmamf3ABYMAAPPX78mIQzsTxRyThTWK3MCLoNgKoLPyuQSANWXVGENEAQCtAOxzOfdkAOcT0WZopqzRRPQCgD0AWuvXcLoXAEAI8ZQQYrgQYnhxcbGHr8HUN2rU0rb9R012e/mWvaG80qRRVNUmrsmk+gvmr9+Df87fhJPrEM9v7U3h5PRO1imtmrSOelhQr/3XYpROnu1ZU2gIfVOsQpZpmngRFIsB9NKjkfKgOadnWsbMBHCVvn0RgLlC09NnApikR0V1A9ALwCIhxBQhRIkQolS/3lwhxBX6OR/p14B+zf/V4fsxWSSkOKOJgFN7aQK9U+sCQ3Vc9t2BuIXRrZotAGx2MDf9+/PNrudJUxAAPHLJEGPb+mbutFC7Jc4lWrK9vHl/uFYrJNjjt28nHAtkt7d79kUUU58kFBS6v+AmAO9Ci1CaIYRYRUT3EdH5+rBnABQRURmAWwBM1s9dBWAGgNUA5gC4UQiR6C/mdgC36Ncq0q/NNELU8FYirU/Dqb3aorhFyDAV9WzXPO7NWBUUr/10lOf73f2/VabP1gVf/XzhcSXGtvWt2FmjcH97JhvL6R8v1gRSVY39ubsPV+FITRhvLUu+rpTgl3mmnvDU4U4I8TaAty377la2qwBc7HDuVABTXa49D8A85fNG6JFRTONG1ShuObs3AE0IRKLCcDLn6Z8HdmqJldu0DOjZy3fg0UuHAgCGl6beG+S9VeamREM6t7Yd59VH4eYTcHq5t5YykVTVRlBZHcaIqR9iQMeWWOUh+9tKNk1PSZVgZxo9nJnNZAxVUJygL/gBH5nezH0+LXy0eSj2zpKu2kg3vPil6fPlI7rYjrP6KCJRgeO7HhM37kii6CUb10pBnvYMZHMmyYVPfobj9ZDbVIQEkF3TE5NbsKBgMoYqKGTSmWxvKlm57RC+2X04LpchVeat2+14zKkhVXWt1fQEDClpjStGmgXLoarkw1xlhvadb6407V+9w104eOnb3hCc2UDTLFHCmGFBwWSMkFLGok/7FgCAzzbsQdnuCtO4A0dqjdLidrx10yk4o4+3yLarn11su/+kHkVx+17+yUgA9qYnvw8YXGI2Vb351TbH+zplXxcozyCZvAe73uJx92wYcsKUKc80TVhQMBlDahSXDC8xkuj2W+oqSdw0ikElrXDx8Z3j9g918DnY2c+HdYkfO6pHEVrkB0ympxVbD+JobQQ+IhzXxWx++vfnWxznCNgnAamOeXkfLz0k1Kq7Tlg1Ci/nZIIf/O3zrNzXiaraCPtQ0gwLCiZjSEHhJf9AzbG4ZHhJ3HE7hWNEN3tH9w69tpNKuUOpj1DAb9IoLn9aKzpYWRNGz3bN8YcLB7nOOxGqFiEX8sfnrk94XqJy7Oq1j9OF4L4jNalMMSUa6jpcUR1G37vm4NH3v8n2VJoULCiYjFGYpzmo1S5oM663D3f1EWHWz08BAPx8dK+4492L48t5tCoI2l7LrpmOU52nUMBn8lFIDUCa3QvzYqajcQ6d6o7WRPDOip22x9TugTLyKeChOq2XvAu5WMvn3BAytbNNpV7X6y9zy7I8k6aFp/BYhkkFWYxvoVJWfNeh+Ld9QDM9DezUCpunjbc93vfYlnH7WhfaCwo7fnZGD9v9oaDP5A/YV6m9lYd1SaHmghzj0EL11v8sw7cO5qQ2yjly8fdSxtyLoJCmJ9n7IluC4uSe8f6fbBFIU1AEY4Y1CiZjnN5bc0B3Vsp22zmVAcDn4Q980R1jcOnwmK9CdRQnYpTDfUMBP6ptFmUZmSWFHQBs3lNpe43ZK3a43lsKi32Vmn/Gy2LmVGzv0n98jttfWw4gZnqSQQOZFBQ3v/wVSifPNj5L531hnh+7DrlX8GUaPywomIwhW5aGFR+FNJMAwJCSVsa23yXqSdKuRT4evGgw5t92JpbceZaroDjvz+audE5v8aGAz7ZekczlUB3Pn21w7oTnxlS9c+Al/9Ccvm6Oe2neshNegKadvbpEK8g8Vy/5sa+ixjTnTDBTzxxfue2gaf+RmkhcFFs24dySzMCCgskYsqWpGmevFvwb1uUYdGyVD8B98bTSuU0h2jYP2Tq4JdY8BSeNxUlQSNNTUfO6N1gMW8Ji3ZYyWVokUXisEAIPzNZ6fq3TmzfVh+lJFmS0rscNJcqogUyjycGCgskYLfM1H8IPlLpKqtklEhWG1uGWR+HEwaP2obbJkB/02woKGak16QT7bO5kCFk69bktqtLfcM2/luABlzavG8pjZjCpLWVSo5A88ZG9kzibvTFUGkoSYlODBQWTMfKDfqy5byxuH9vX2KdmRwsIQ3Ck0qa6TbNYf4u/Xj4spTlqUU/xb+9SC3JqxyrxIqzU8iSAuz9Gzbt4esEml6vGFkQ5x0xoFN2nzDb5JhZv3m87zi4kORs0EHnV5GBBwWSUgjy/48IohJaVDSRnepKM7tsOJ3Zrgw9uOR3n9LcPXZU4lS4PBf3GAqtGGqnmslk/P8Wo/fTiQi3pbsH6PdhQXoHyw4kXyJHdzY707pbOfV2LCvHT07WorHYtQqZjh6rsBZEqcG8a3RMAMGelfYhuXXBaeK0v7s+4CLXtB46idPJszF+f+QZjt85YlvF75CIsKJisERUCe/Vw1FQsBn4f4dXrR6Fnu+aOguamM3virgn9TY5zFdVHcUDJGlcd8AM7tcLSLdqb9B1vaDWbrnhmIcb86WPY52Ob8fkIZ/YpNsqYyO/63DUj0LZ5Hl776Um4fWwfbPj9eaZwWsA50kqdX2mRJnhe/9I+VyQV7pm5yqRJSM7q1852/L8+2+xoUpMlPp5PkNmeDj7fmFrAAeMOCwomawzsFFu8K+tYfsJJISlqnodrT+nmWBBQExQ2picXG4aqeZz1yMee5tcsFDC0FHnpvse2wJI7z0ZxixCICH4fGUUEJU4CVM00zw+m/8/4X59ttt0v/U5201q787DtOTIXhbvhNV5YUDBZQy37nUrjHhUiwvqp47Dx9+eZ9icyaWl5FNoCFo7GFrLH9H4YdjySQnmIUMBvCBjpcLWTXXGOb4fr/exFrd384JJW6NAqlqeS6R7Wal4JANw1ob+x7eTQlqbH+nY0h7mqbdpgQcFkDae3/FQJ+n1x/pBE0VShYMz0JM05j1wyBN0sfoT5t51pbDvVjXKjXcsQyiuqUVUbMRZMu7lZn4mTOUeWPJ88ri+KFb/GsPvejxsbjQq8uvhb3PzyV5iz0j05EHAXNpWWnhxn92tvbE94fAFufvmruOKEMkemviOj6iMKLFdgQcFkFSffQbpIrFH4UBOJIhoVxiJot4B3blOIy0/UNKD2LfOTnkeP4uaojQjsOlRl9JrwkmSYaGm1JhL27xhf6uT1L7fi9tdXYOay7fjpC1/GHbfiVt22QhdQwkErmrlsO+7+n7n3hk+fYr0LCjZ1pQ0WFExWKbZE+aSbRHWVpP28JhLFI+9pJqV3HN66ZSZ4KuYd6UeoDkcNH4WX3JFE1hprNFdXpQihJNl8k8ufXuh4bNnWg47HJNa6V74saRROZVCY5GFBwdQ7o/u2w0XHa0l4V44qBRBrIpRu5n3jHpIpfQLVtVEj69hpgXn2Uy0EdIZeQsOKNV9CJV8XSK8v3YqNe7SSF+Thry/R4mrN87AbnWzocSLT2oEjNa6ajnVOUoNassU+ByOdqD1Kpr2zJuP3yxVYUDD1zvSrT8AfLx4CQCscuHnaeMeifXWlU+sC1+Mh/U2/KhwxSm04Fe27W3fcDrYxl917/gDMvfX0hPf5xycb8cIX3wLwplHsTpCnITUKqTm9YdOFL90VVXcqFYDtvsKEwR1Mn99dlf78DifUYIA3v65bgAQTgwUF0+RQ3+zPHdDeZWSsX/aJv//QECqn9mprO/YEvVFSXiC+GGHv9i3QroWz7yJkc46X9fuml75yPS4XRrWGlrXfdiiJKrtu9GzXHICu5bioFKoPefHmfXhOz5+ojwrgnJidGVhQME2Ot/QGSEBis8veypiZ5b3VuwAA5wywz/KWPopKS4goANtcDBW7XIeAr+5/flKjULUTa7SPNeQ2VdrqBRIrq2Pf1S5yTfpwln13ABf/PdYmlctrNF5YUDBNjm5tm6GX/vabSFCoZc8l6tu5ikyGs3MOFzVzd8rbaRRBh/skomV+bM7SH6Cu12W7K/DPTzYaCX5O5UuSRWpqVqF44bBOps8y3HjiE5+m5b7JIlvD9j22Bbbstc9sZ5KDBQXTJJELZyJBcekJneP2OUVKSY3C2n9h1s9PwaAEYb52b/Ve80hk1z3J1Sd3M7aNEFvlbX3C4wsw9e01eOqTjQDiy5zXOuQX1EaiGHbfe47zkIKyujZqNC4CgEcuHYpFd4wxPifSrjKK0IRn9+JmWLvzME5/eF725tKEYEHBNEnIQw0mACiyaW/q9AZekGdv61dLkTgRrIP5Jy53QTnWskB7y79jfL+48x5+dx3mrt2FSNQsGOT1rBw4Uov9Sr0r+WYukf3DVdOWnEtx8xB+fIomwNxKddRH3woCmYQ9Z2jXHRYUTJPEeNFOsC4REcYPMkfpWOstSepi629d4L2/t5VyS7MgVRGRWsmkEfZ9M6751xJTAUHAuSKtsJQuv+aUbqbj0kxXHY7EPVciwp0T+qNFKGAECKh9SCSZzpaW30Et8PjFxn1OwxmPsKBgmjReXmC/N6Sj6bOTucrOVPTSj0/0NI9mLjkWifhYzwWRX4VA+HTyaHxwi3M4rsr2A+YQ29Mfnocrn1kY93av5mz4CBg/qAOe/dEJxj4pQA8djWkk1keilURxNj3VR7Y0kTmEl6k7LCiYJolc1IWHgEknm30iFv12DE7qaR9KWxeseQ+lRVq2tVo2o1PrAiNcNRGPfhBfxHD++j1xPSRUzcNHBCLCmX3aGQ5z6aP53cxVjvfaU1GDFxd+i6M1EVPZcxl67GSWqo1EMWv59joLErsXgzSXFMso0xdswpT/rsj2NOJgQcE0SaSJ2otG0a9DfH2kRDx00WC0S6Hmk2TcQOdGS3N+eSqmfn+g8VmG48Y0ivQge25LVLOQGm4rHeaFio/GqaS45P01u0yfR/fV+lg4CYpRf/gQN730FV5aWPeeFVbB0IjkBO6btRovL/oWOxtIx0AJCwqmSfLE5cfh6pNK0d+DEFDfzGUnOydkVraXgn5uXK93tLOfTwv88MSueO9XpwEA3lqu1Z6y81GkE/VtXr2HVHAKQzFBIftVOAUNHLVUmZXnOmkMeyq0yK41O9wFUCKkMFVriDXG/I1fvfp1tqdgwpOgIKKxRLSOiMqIaLLN8RARvaofX0hEpcqxKfr+dUR0rr4vn4gWEdEyIlpFRPcq48cQ0ZdE9DURLSCinnX/mkyu0bWoGe45f4Brf2o7EsXdL9eL4qXS1vO5a0bggQsG4t1fnmaqSeSEzAVZtElzxkozmlNYbdvmdSuwqNZiUu8gn2GiAosq1pDcwqB9DoaVqjSE1hLIVK+qJpLFcN0kUDPqj2a4r0iyJPzJE5EfwBMAxgHoD+AyIupvGXYtgP1CiJ4AHgXwoH5ufwCTAAwAMBbAk/r1qgGMFkIMATAUwFgiklXh/gbgh0KIoQBeAnBn3b4iwyTmRd0p/YcLB7uOk3LnutOcNQInTu9djCtGdkWfY1t4Gh/fm8J9/BdTRhvZ06nw17nrje1DSgitdO4nU1wwvoyIttRUVIWx35IXolLXxkt24bfVSVaRPXikNiumn5+/HCvXYs2dyTZeXhFGACgTQmwUQtQAeAXARMuYiQCe07dfAzCGtN/yiQBeEUJUCyE2ASgDMEJoyKyloP5P/oQFAGkvaAWAK3sxGefknm2x6Q/n4ez+7rWhWhdqC3H7lpktjy65cmRXo4+2XAOdigkG/D7H0N66IM1sdoIiHLVfhK0ahQwtnvTUFxh2f3xzJcm7q3Y5HvMKETBlXF/jc7IhuWMe+Rgj//BhneeRLLNXxMrbH9syH6WTZ+O3bzQMx7YXQdEJgFpXeau+z3aMECIM4CCAIrdzichPRF8D2A3gfSGELIL/YwBvE9FWAFcCmJbMF2KYVPGSKf2ni4dgUKdWhsDINKGAz3jLjpmenMc3sylJIvn7Fce53uvKkV1t9+/V325rwlGcN8jshK+N2Ks5X317wPT5sK6hSAFiffNPVz0qyflDYyHPyfbqluXm6xs1n2eTbgJ9aeG3WZmLFS8/HbtfS+tvh9MYx3OFEBHdvFQCYAQRyTCPXwE4TwhRAuBZAI/YToroOiJaQkRLysuTtxczTCqc2bcd3vr5KUn3eEgVtVWr4cx2Gb/JxccydqA5sbBPe7MJLFEU1yfr9+DtFeaS4U5ZzzOVHujrHhhrqk8FxC/eyS7mTsiFqUOrAqOsSLqunWnKFQElKwackoHw61TwIii2AlAL4pQg3hxkjCGiADST0T4v5wohDgCYB81PUQxgiKJdvArgJLtJCSGeEkIMF0IMLy4u9vA1GKbxkR/wIxIVqI1EY+GxLpJixvWjPF973a7D+N/Xsf4VVr+ClZoUHc2hgB8TLEmN6uL9zS5zpFOieXi+r1/Wpkpt3uqzqQ9O7x1bxxqacPMiKBYD6EVE3YgoD5pzeqZlzEwAV+nbFwGYKzTdciaASXpUVDcAvQAsIqJiImoNAERUAOAsAGsB7AfQioh669c6GwC3qWJylpDSQjVW68lZUgzt3BrzbzsTn08Z7en6v3glFoaZaH22q7RrTfpziowKWkqqq2Gy5zz6ielYXRZJ1aIln12qZUN+85/ljsdqwlHszZCJqlmeP87cmG0S1hUQQoSJ6CYA7wLwA5guhFhFRPcBWCKEmAngGQDPE1EZNE1ikn7uKiKaAWA1gDCAG4UQESLqAOA5PQLKB2CGEGIWABDRTwC8TkRRaILjmjR/Z4ZpNEjn9O5DVWir5wYkcqV0tumb7UZNOIq8gA8RZZW1Swj89Tm90at9czw0Zx0AYPzgDnF+nZN7FuGjdTFT8HWndQcANLeYntyy4atqI7YFGJdvPYDlWw/iCgdfikTOSQqtVLO9VQEz+k/zcMHQTrh5TC8AQO873wEA3HBGD3xvcEc0DwXQrmWoTsEEsoRKfjAmKBxiBeodTx4kIcTbQojeQogeQoip+r67dSEBIUSVEOJiIURPIcQIIcRG5dyp+nl9hBDv6PuWCyGGCSEGCyEGCiHuU8a/IYQYJIQYIoQ4Q70Ww+Qachke88jH2H7gaFLn/t+o+AX1g1tOi9u3WfdrSJPPT07thid/GO/4blkQNFXbtRZTBICp3x9kvvYe7dpWn45b+KdTLsX5f/0Ud765Et/tO+J4rvr+7fNpVWTroqF8+a2WW7KxvBKPvB9fCuVv8zbgvL/Mx2kPf4QbXlia8n2AmKNfC2DQ5vzVd5nvM+4FzsxmmAbMQplsJ4Cxj80H4N00c9/EWBmQ6/U3+57tWmDztPFGSXAAqNBLhER1jeJnZ/S0jQDL8/tMDZjOsxEUrQvNVXKdDCcTHl/gOO+qBHkP//hkg+txdeahgC/pPAqVb/cewcbyisQDAZMmlQpf6gmPAX+ssGKiZ1FfsKBgmAZM9+L4wn+phEzePrav6XOeEo4qF1Jp+nDKZg/4yDivuUM13MK8QJ0jwhIl3e2tcElGs4TdHq4OY/qnmxwG26MmLQb9Ptz55sqkzk+VBWV7AACHq2obXNkRFhQM04D5pW4TV9mWpAkKiF/81eQuaYt/URdA1oV+xvWj8MMTu8DvI3yqL2YVNn3DJWq58kQiY+7aWILdWf20woGJBMWxrdzDeO18OF4rBL+1bLtRdwrQ2tV+tmGvp3PThdo8CgBWbz9Ur/e3gwUFwzRgkq1VZeXV60bGaRNWZPjoJt2fYL3liG5tMPX7g0BEON8S5pqIkItz99OyPbjmX0uMz9d46JAHmAv+ecVraZB/zje7RLfujxfKbl36Ig1NFUgTLCgYpoEjk65Gdm8DALj/goFuw02c2L0IN5wRX5dqyrhY69SDR81vsE4lQgB4ykhXS6TLXhp2yAKL2nz6GhFDdov60ZrYPhl1ZYfTMu01esga3nvfrNVxY47UOAud+23G15UnPipL+zWThQUFwzRwZK5CcYt8dG/bzLHURjKo4ae/eW256S3ZTVC4mZwkPzyxKzZPG49/XzPCCCe148E5a43t/KAf+QEpKOJX9ZcWeffL2M3+j+85CxcV+RQKHfqjA/GCVUWWX08nQX/2O2qwoGCYBo5cfJZ9dyBtvSisb84vL4qVZHNzRh/XJXF5dMlpvYsRVO6z8LdjMO/WM2zH5gd9hvCy6+mdqPy7xGoVkt0Cn/9iiyc/hQxRbWXT4zxfT+BzExRWjtSEsWD9Hs/jrd0NAaBXe2/VhjMJCwqGaeDInt7f7jticrTWhTxLET61SqmboJBhswUpJJa1b5mP0rbNbI/lB/1GtJFdjsWZeoc8L6ihvaqZLuxQwFBF5pLYfb8W+UFc/s8vMO7P8x3PP00vw7FlbyVmLPkOU/67Alc8szChoDuiN3r60cmlccf2V9ZgV5Z7gLOgYJgGjrp4JPM260ZdqrW+eePJmHvr6Smff2K3NrbzkSVCpr2zFldNX2Q6bjWHSVPZC19sweg/zcPRmgiu+/cSrNh20DSud/tYeLGXUh6yt/ewLvGdDqtqI44RUAM7aZ0RRpRq553+8Dzc9tpyrNNbxlojmaz85jWtXMg/58eH8j69YBNO/H39lz1XYUHBMA2c/ED6e0wEHWoyXTq8s+1+laGdW6NDq4KU723XbjYU9Js0mY+/Kce9b60yPlsLBT6zQFtQ73xzJTaWV+KKZxbivdVaqK0qUvL8sWfnxb8yXF/of3p697hjbqYro1yIRWuR5UMSmb027E6c1Oc1xDcTsKBgmAaOtI2nE6eupv06ZN4e3swmWc/ONv/sp5uN7ajF+fDAbHOt0B0OuSVqLcLfv524vqi8TXubXA2n3huAFhab5/fFLeYygitRvSkZRqxWkLXixXSWKVhQMEwDx+pPSAct8+OdtQDgT6IvdqrYRRS5pR+s2HoQ8xKUx9iutC5VrVR9j21pbNvlRMTPQ5uInwjNLPO05kiowq06HEXQT6i1CISjHgVFRI/fDfoJb954MgBgSEkr05jaLFYIZEHBMA2cjoqZZ+mdZ6Xlmu1a5uO5a0bg+tO7m0xB/nSFVblg14XPKYmtOhzB9/66AM9/sQWA2efgJYlONWdZF3GVSFTg/lmrsUMXOESwrWCroprvaiNRBAPxGoWMolq9wz27+sRuRQCAcwYci6GdW2PztPH4302nmK/FGgXDME7I7GwioKh5+np1n967GFPG9cPJShc1OxNQuilqHp+0ZxeOCgB97pxj+vzYpcOM7b53zbEOBxAfIvv6DVrvs1N7OXeLW7x5H55ZsMkIRfYRmSLM1CKKAHDL2b1N+Q01kSiCfp/ho5DHZAvYh991z+Poc6xm8jupR5HjGKdugvUBCwqGaQQ8fNFgvPfL+BLh6UCNgKqPFq9n9IkPdbWLMrKjf8eWCcdYo5uO73oM8vw+157obkmGLfMDcdrFzWN6IU8JMqgJR00+imQDEKRZK+BzXpJrs1gehAUFwzQCLh7eOWOJV+qbcX0ICr+PcFa/9rbHrH4BO6xv91bs/AGFIb+RqwBoZiv1c8CS/azKjUNVYcxdu9v4fPPongDMArY2IhD0k/HWXxhKTlCEjcq95v1/njQ0NoY1CoZhsoWapV0fggLQ3tLtcHvrlyRy7tu5Ow4cqcW/P99iCIdTH/oI/e9+N3ZNixPfR4SLjy8xPkvTEAC00utdqfOoDWumJxkZ1dbGRLj9wFEcdMiniDpoFBOHdordg30UDMNki7Bi0qgvQSHf4L83pCP+ceXxccftFlqJUw6IxBpKq/LYB+sBAOWHzf2urecQzMJB7b+Rp8/dzkchGw7tsemnfdK0uTj1obm285I/A7vnL4tChjnqiWGYbPGQ4mitL0Fx9Und0CIUwB3n9cO5A2L9ueXdf31Ob8dzExXJi7gICllK3Yq1ORERoYWu9Qzt3BrjBsa6+UlNQtUoaiJRtC4MGhnYuw7FCwpAM2NV1Ubw2tKtpkgvGR5r9/xlS1uOemIYJmv86qzYolwf4bGA5pRece+58U2I9Nu3aRYfGSULCiYqY2Ln8+3SRit3frQmgifnxcp2y/LlaslzQOvJMaCjlsfwo5NLMapHkSGg5Nv/ym2xkFchtHpV1Q79vlUe/eAb3PqfZfhgTczvId0PdlFnUoMKszObYZhs0b5lzMzjbwAlrYF4QfH13WcbBQUTNTayy8mQNZzW7jxk6mehOqlViAgDO7XCV3edbfgJxvTVHPAy5NWKlnAXu3evdvFtbAHgc6gR1GcAAA1GSURBVL1elCrwDusVc+00CmmmY2c2wzBZI6A6s+tJo3BC3t0qKNQ8C/XN+o7z+sGKVTsAYsLQ+lK+dMt+AEAHh/aqxyjz6KuXNzniUDNq055KrNt1GGV63SankNv1u7TjqkB7ct4GAPbPXwoPdmYzDJM1RirVXMs8FKfLJDLqSRUM15/W3RQNpWZkO5Utt3LL2X0AAMMtBQmnf6oVF5wwuEPcOVZkhrxdraqR3dvgG10AvLpYa7K0btdh2+tIx7mdK8Wu9W3M9MQaBcMwWaJdy9jbtJdS3Jmkq946VY1suvXcPqYxauE8rwUTZV6DrDBr7NfzNrz0Jr/o+BI89IPBRm9v2T+8Z7vmmH71Cca4vXo/Dacsd5mUVxuNYvnWA/hsg3tjI3md1dvdy4BkEvtgZoZhcpKz+9snwtUX068+AYs27UOrgiB+c24fDOvcOi4c9vwhHVG2uwLvrNyJk3uYy3KM7N4Gl9iUSi+ycY4DwE9P1/qJuwRKGfh8hEtOiF173MBjMXPZdvQobobCvACahwKoqA4bxQfbNg9hp03DIWn+emjOOk/9RQ7oY/7wzlq0yA/i4uElCUOE0w1rFAzDGLRvaW+rry/aNg/hvEGaGejGM3vipJ7x9ZmICL8+pw8+uOV0+HyEcxTh9sp1o3DhcSW259gh/R1ORQndCOnajHSu/+HCQQCARZv2AQCaJcjOtgqJ1oX29a7Uoo2/fWMFet3xjhGtVV+woGAYxqA+igKmm8cvH5Z4kIVJJ3RGXkBLkNtbUY1/f74l6WuE9HpO1bWaoLAKhkKbKrluONV5sisJ75QPkilYUDAMY9AYBUUohQ6Ak8f1hY+AvRU1OP6BDxKG3NrfV2oU2tu9tXz6r87uhUcuGYI5vzzV0/WuO829hpXKgjL3/hzphgUFwzAG9ZWZnQ0uG9HF2C7I86OqNorXlm5N+Xoyie8cPbPcGg01um97XHhcial5kht+l8qxVh6c4162PN2wM5thGAMvRfkaK785tw9eXqSFrlqLAKZCu5b5WHnvuUbFW7vOfcmQTE9sa7e9TMOCgmEY3D9xAF5c+G22p5FR2jTLw9r7x0KI9AlEtVhgc5v8Cis+cm77mqhdajbxJFaJaCwRrSOiMiKabHM8RESv6scXElGpcmyKvn8dEZ2r78snokVEtIyIVhHRvcp4IqKpRPQNEa0hopvr/jUZhnHjylGlmJOhxkgNifyg37XF6ayfn4L7LxiY0rULFUHx8k9G2o5xUwSSMfvJsN76IqGgICI/gCcAjAPQH8BlRNTfMuxaAPuFED0BPArgQf3c/gAmARgAYCyAJ/XrVQMYLYQYAmAogLFEJJ/s1QA6A+grhOgH4JU6fUOGYZo83xvSEROHdkzqnEGdWsXtG9ipFa4c2TWlORQEYwJolEtLUyfUKrpWiluYy66/v3pnvdZ+8mJ6GgGgTAixEQCI6BUAEwGsVsZMBHCPvv0agL+SpttNBPCKEKIawCYiKgMwQgjxOQBZKyCo/5Oy9gYAlwshogAghLCv2sUwDKPz+GXJh8iu2BZfE6ou+H2EW87ujTP6FCcerDC86zEY1aMIPR2KCAJA1zaFph4aG8or8bd5G/DzMb1Snm8yeDE9dQLwnfJ5q77PdowQIgzgIIAit3OJyE9EXwPYDeB9IcRCfUwPAJcS0RIieoeI6udJMAyT07ybBtPbzWN6YXBJ67j9y353Dpbfcw7G2mgNr91wEn59Tp+4/Sq3j+sLwFwS/k/vf4P73lrtdEpa8SIo7AxnVkub0xjHc4UQESHEUAAlAEYQkTQMhgBUCSGGA/gngOm2kyK6ThcmS8rL6zemmGGYxs/rN4wytkd1LzJ1tEs3rQqCaJkfxOcb96Z0/gmlbbB52nj84izze7MsaphpvAiKrdB8BpISANudxhBRAEArAPu8nCuEOABgHjQfhrzW6/r2GwAG201KCPGUEGK4EGJ4cXFyqh7DMEyn1oXG9r+uOcFlZPo4rku8ttEY8CIoFgPoRUTdiCgPmnN6pmXMTABX6dsXAZgrtOIpMwFM0qOiugHoBWARERUTUWsAIKICAGcBWKuf/yaA0fr26QC+Se2rMQzDOCNbmeYHfSlld6dCwJK/8f6v6m7u2nbgaJ2vkYiEzmwhRJiIbgLwLgA/gOlCiFVEdB+AJUKImQCeAfC87qzeB02YQB83A5rjOwzgRiFEhIg6AHhOj4DyAZghhJil33IagBeJ6FfQHN4/TucXZhiGAWJ5D7cm8A+kE1kiZfygDvjxqd3Qq33dzV0VDh330omnhDshxNsA3rbsu1vZrgJwscO5UwFMtexbDsA2TEE3RY33Mi+GYZhUyQv4sHla/S41UjiNH9wBw7ock2B0w4EzsxmGYeqJO8b3Q/P8AEb3bZe2a2bSCS9hQcEwDFNPtC7Mw+++NyDb00garh7LMAzDuMKCgmEYphEhO+kBwGeTR7uMTB8sKBiGYRoRal+Njq0L6uWe7KNgGIZpZDx3zQgcsvTcziQsKBiGYRoZp/eu32oUbHpiGIZhXGFBwTAMw7jCgoJhGIZxhQUFwzAM4woLCoZhGMYVFhQMwzCMKywoGIZhGFdYUDAMwzCukNaIrnFDROUAtqRwalsAe9I8nXTQEOfVEOcENMx58Zy80xDn1RDnBGRmXl2FEAmz95qEoEgVIloihBie7XlYaYjzaohzAhrmvHhO3mmI82qIcwKyOy82PTEMwzCusKBgGIZhXMl1QfFUtifgQEOcV0OcE9Aw58Vz8k5DnFdDnBOQxXnltI+CYRiGSUyuaxQMwzBMAnJWUBDRWCJaR0RlRDS5nu+9mYhWENHXRLRE39eGiN4novX6/4/R9xMR/UWf53IiOi6N85hORLuJaKWyL+l5ENFV+vj1RHRVBuZ0DxFt05/X10R0nnJsij6ndUR0rrI/bT9fIupMRB8R0RoiWkVEv9D3Z/tZOc0ra8+LiPKJaBERLdPndK++vxsRLdS/96tElKfvD+mfy/TjpYnmmuZ5/YuINinPaqi+v15+hvr1/ET0FRHN0j9n9VnZIoTIuX8A/AA2AOgOIA/AMgD96/H+mwG0tex7CMBkfXsygAf17fMAvAOAAIwEsDCN8zgNwHEAVqY6DwBtAGzU/3+Mvn1Mmud0D4Bbbcb21392IQDd9J+pP90/XwAdABynb7cA8I1+72w/K6d5Ze156d+5ub4dBLBQfwYzAEzS9/8dwA369s8A/F3fngTgVbe51uFZOc3rXwAushlfLz9D/Zq3AHgJwCz9c1afld2/XNUoRgAoE0JsFELUAHgFwMQsz2kigOf07ecAXKDs/7fQ+AJAayLqkI4bCiE+AbCvjvM4F8D7Qoh9Qoj9AN4HMDbNc3JiIoBXhBDVQohNAMqg/WzT+vMVQuwQQnypbx8GsAZAJ2T/WTnNy4mMPy/9O1foH4P6PwFgNIDX9P3WZyWf4WsAxhARucw1JVzm5US9/AyJqATAeABP658JWX5WduSqoOgE4Dvl81a4/4GlGwHgPSJaSkTX6fvaCyF2ANoCAKCdvr++55rsPOprfjfpJoDp0sSTjTnp6v4waG+kDeZZWeYFZPF56aaUrwHshraQbgBwQAgRtrm+cW/9+EEARemek928hBDyWU3Vn9WjRBSyzsty/3TP6zEAtwGI6p+L0ACelZVcFRRks68+w79OFkIcB2AcgBuJ6DSXsdmeq8RpHvUxv78B6AFgKIAdAP6UjTkRUXMArwP4pRDikNvQLM8rq89LCBERQgwFUALtzbafy/Xr7VlZ50VEAwFMAdAXwAnQzEm319e8iGgCgN1CiKXqbpfrZ+1vMFcFxVYAnZXPJQC219fNhRDb9f/vBvAGtD+mXdKkpP9/d5bmmuw8Mj4/IcQu/Y88CuCfiKnV9TYnIgpCW4xfFEL8V9+d9WdlN6+G8Lz0eRwAMA+ajb81EQVsrm/cWz/eCprpMWO/V8q8xurmOyGEqAbwLOr3WZ0M4Hwi2gzN3DcamobRYJ6VQTodHo3lH4AANCdUN8ScdwPq6d7NALRQtj+DZuN8GGbH6EP69niYnWqL0jyfUpgdx0nNA9pb2CZojr1j9O02aZ5TB2X7V9DssQAwAGYn3kZojtm0/nz17/xvAI9Z9mf1WbnMK2vPC0AxgNb6dgGA+QAmAPgPzA7an+nbN8LsoJ3hNtc6PCuneXVQnuVjAKbV9++7ft0zEHNmZ/VZ2c4vnRdrTP+gRTV8A81+ekc93re7/kNdBmCVvDc0W+OHANbr/2+j7ycAT+jzXAFgeBrn8jI000QttLeSa1OZB4BroDnQygD8KANzel6/53IAM2FeCO/Q57QOwLhM/HwBnAJNlV8O4Gv933kN4Fk5zStrzwvAYABf6fdeCeBu5fd+kf69/wMgpO/P1z+X6ce7J5prmuc1V39WKwG8gFhkVL38DJVrnoGYoMjqs7L7x5nZDMMwjCu56qNgGIZhPMKCgmEYhnGFBQXDMAzjCgsKhmEYxhUWFAzDMIwrLCgYhmEYV1hQMAzDMK6woGAYhmFc+X99JBjOVeFOIwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "learn.sched.plot_loss()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.save('1024urn')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn.load('1024urn')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x,y = next(iter(md.val_dl))\n",
    "py = to_np(learn.model(V(x)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQ8AAAD8CAYAAABpXiE9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAABIlJREFUeJzt3dFN21AYgNGAmIIpWKJigk7ZCVCXYArGaPpQkBBQCF/s2Nc+5z3K1VX+z9chJFfH4/EA8F3XSy8AGJN4AIl4AIl4AIl4AIl4AIl4AIl4AIl4AMnN0gv4zI/rnz7+CjP7/efXVXmckweQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQiAeQ3Cy9ANbl4elxkee9v71b5HnpxIPD4bBcNE59fnFZH7ctLB6OU4ywxr0Rj50baShHWuseiMeOjTiMI655q8SD4QjIOojHThlAziUeDEn8liceO2TwmIJ4MCwRXJZ47IyBYyriwdDEcDniASTisSOu0kxJPBieKC5DPHbCgDE18QAS8WATnKwuTzx2wGAxB/FgM0TyssRj4wwUcxEPIBEPNsVJ63J8e/rAPhqU198ybpCYk3gM6LMoPDw97v5nCt7uwVeRpXHbwi49PD06mZ1JPDbKYPxjH+YjHhtkYE5nrzrxYJNeouC9jfl4w5TNcqqYl5PHgFxNp2MvO/EY1P3tnRc+i3LbMri3AXFU/5zgTkc82DzBmIfbFiARjw1xy8IlicdGCMf/2Zt5iMcGGI6v2aPpicfgDMXp7NW0xGNghoEliQe74l/xpyMegzIA57F/5xMPIBEPIBGPATlyT8M+nkc8gEQ8gEQ8BuOoPS372YkHkIgHu+f00YjHQLzIWRPxABLxABLxABLxGIT3O+Zlf79PPIBEPIBEPIBEPIBEPIBEPIBEPAbgz4iskXjAM5H+HvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEYwP3t3dJLgHfEA0jEA0jEA0jEA0jEYwB+BpE1Eg8gEQ8gEY8B+JwHayQeQCIeQCIe8Mzt4feIB5CIxyBcFVkb8QAS8QAS8YCD28JCPIBEPAbi6siaiMdgBIS1EI8B3d/eiciE7GVzs/QC6F6/6H3nRyMcnXhsxEdDICjvicV0xGPDTh2U15F5eczI4RGIyxAPPhw2A8hXvGEKJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJFfH43HpNQADcvIAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAEvEAkr87r79YklPCmgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img(py[0]>0);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQ8AAAD8CAYAAABpXiE9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAABIRJREFUeJzt3NFRE0EAgOHgUAVV0IRDBVZpBYxNUAVlGB/QGRVR8+eOu937vkdmCJud23/3kpCb8/l8ArjUh60HAIxJPIBEPIBEPIBEPIBEPIBEPIBEPIBEPIDkdusB/M3HD598/BVW9uXr55vye04eQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQCIeQHK79QDYv8fnp9Ue++HufrXHZl3iwel0WjcQS/xdkdkfty1sFo5LjDDGoxGPgxtpUY401iMQD4YiIPshHgc26kIcddyzEY+DsgC5lngwJPHbnngckIXHEsSDYYngtsQDSMTjYGbbrWd7PiMRDyARjwOZdZee9XntnXgAiXgchN2ZpYkHUxDH9yceQCIeB3CUXfkoz3MvxANIxGNydmPWIh5MRSzfj3hMzEJiTb49fVB/CoNvGOc9iceA3jpR/Pj50SPy+Pz0yxwI7TrctnBIj89PbuuuJB6TsjBe/GsezFMnHkxJFNYnHkAiHhOy674wD+sSjwF5p2A55rITj0E93N278NmUz3kM7veAOKr/neAuRzyYmlisx23LRJw6XjMn6xEPIBGPSdhh32Zu1iEeE7A4/s0cLU88BmdRsBXxGJhwXMZ/0i5LPDgcAVmGeAzKAriO+bueeACJeACJeAzIkXsZ5vE64gEk4gEk4jEYR+1lmc9OPIBEPIBEPAbiiL0O89qIB5CIB5CIB5zcuhTiMQgXN3sjHkAiHkAiHkAiHkAiHvCdF6UvIx5AIh5AIh4DcJxmj8QDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMRjAA9391sPAV4RD/hOpC8jHkAiHkAiHkAiHoNwP87eiAeQiAecnOwK8QAS8RiI3ZE9EY/BCMjyzGkjHgN6uLt3wS/EPHa3Ww+A7ucL//H5acORjEk4riMek3hrIYjKrwRjOeIxubJYZgqOWKxHPHjFguN/eMEUSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSMQDSG7O5/PWYwAG5OQBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJOIBJN8ANEq7NH8OpbAAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img(y[0]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}