Switch to unified view

a b/Notebooks/old/memory_analysis.ipynb
1
{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"processing.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyPXHq1yCkcojNfTEGhu6F+n"},"kernelspec":{"display_name":"Python 3","name":"python3"},"accelerator":"GPU"},"cells":[{"cell_type":"markdown","metadata":{"id":"LZHTjYUqdlTw"},"source":["## Main code"]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"2-HpUGcR4JHS","executionInfo":{"status":"ok","timestamp":1607767565625,"user_tz":300,"elapsed":1383,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}},"outputId":"0c36dede-07e3-45c6-a848-95ef4e2e46e9"},"source":["# Things for Google Drive\n","from google.colab import drive\n","drive.mount('/content/drive', force_remount=True)"],"execution_count":1,"outputs":[{"output_type":"stream","text":["Mounted at /content/drive\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"v7aAjv76WxtQ","executionInfo":{"status":"ok","timestamp":1607767565626,"user_tz":300,"elapsed":1376,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}},"outputId":"a3ac12d4-5283-41e7-c832-bcd359c594da"},"source":["cd drive/MyDrive/MacAI"],"execution_count":2,"outputs":[{"output_type":"stream","text":["/content/drive/MyDrive/MacAI\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"LnWPBIgMyjDf","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1607767567871,"user_tz":300,"elapsed":3615,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}},"outputId":"b97b6963-f6a3-4797-a91d-14111b657305"},"source":["# Install a dependency\r\n","!pip install torchsummaryX"],"execution_count":3,"outputs":[{"output_type":"stream","text":["Requirement already satisfied: torchsummaryX in /usr/local/lib/python3.6/dist-packages (1.3.0)\n","Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (from torchsummaryX) (1.18.5)\n","Requirement already satisfied: torch in /usr/local/lib/python3.6/dist-packages (from torchsummaryX) (1.7.0+cu101)\n","Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (from torchsummaryX) (1.1.5)\n","Requirement already satisfied: future in /usr/local/lib/python3.6/dist-packages (from torch->torchsummaryX) (0.16.0)\n","Requirement already satisfied: typing-extensions in /usr/local/lib/python3.6/dist-packages (from torch->torchsummaryX) (3.7.4.3)\n","Requirement already satisfied: dataclasses in /usr/local/lib/python3.6/dist-packages (from torch->torchsummaryX) (0.8)\n","Requirement already satisfied: python-dateutil>=2.7.3 in /usr/local/lib/python3.6/dist-packages (from pandas->torchsummaryX) (2.8.1)\n","Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.6/dist-packages (from pandas->torchsummaryX) (2018.9)\n","Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (from python-dateutil>=2.7.3->pandas->torchsummaryX) (1.15.0)\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"Sna_syKU6nnp","executionInfo":{"status":"ok","timestamp":1607767568681,"user_tz":300,"elapsed":4420,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["from lib import medzoo\n","import numpy as np\n","import torch\n","import matplotlib.pyplot as plt\n","from lib import losses3D\n","from torch.utils.checkpoint import checkpoint_sequential\n","from skimage import transform\n","import nibabel as nb\n","\n","using_TPU = False\n","if using_TPU:\n","  import torch_xla\n","  import torch_xla.core.xla_model as xm"],"execution_count":4,"outputs":[]},{"cell_type":"code","metadata":{"id":"ugRZjfUJBcNU","executionInfo":{"status":"ok","timestamp":1607767568684,"user_tz":300,"elapsed":4420,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["# Get bounding box of a 3D image, shamelessly stolen from the following link.\n","# There's probably actually a way to rotate an image to fit into the smallest\n","# bounding box possible based on scipy.optimize, but whatever\n","# https://stackoverflow.com/questions/31400769/bounding-box-of-numpy-array\n","def bbox2_3D(img):\n","\n","    r = np.any(img, axis=(1, 2))\n","    c = np.any(img, axis=(0, 2))\n","    z = np.any(img, axis=(0, 1))\n","\n","    rmin, rmax = np.where(r)[0][[0, -1]]\n","    cmin, cmax = np.where(c)[0][[0, -1]]\n","    zmin, zmax = np.where(z)[0][[0, -1]]\n","\n","    return rmin, rmax, cmin, cmax, zmin, zmax"],"execution_count":5,"outputs":[]},{"cell_type":"code","metadata":{"id":"cTwSbkYSH837","colab":{"base_uri":"https://localhost:8080/","height":286},"executionInfo":{"status":"ok","timestamp":1607767573017,"user_tz":300,"elapsed":8749,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}},"outputId":"c3552952-8c48-45d6-d30a-853ffea9fc3e"},"source":["# Load a file and apply brain mask (obtained using FSMRIB library)\n","# then crop image\n","\n","seg = nb.load('files/segmentation.nii.gz').get_fdata()\n","t1 = nb.load('files/T1.nii').get_fdata()/1000\n","brain_mask = nb.load('files/T1_mask.nii.gz').get_fdata()\n","t1[brain_mask==0] = 0\n","xmin, xmax, ymin, ymax, zmin, zmax = bbox2_3D(t1)\n","t1 = t1[xmin:xmax, ymin:ymax]#, zmin:zmax]\n","seg = seg[xmin:xmax, ymin:ymax]#, zmin:zmax]\n","plt.imshow(t1[220])\n","\n","print('Space conserving factor of ' + str(round((512*512*320)/np.prod(t1.shape), 4)) + ' by brain masking and cropping')"],"execution_count":6,"outputs":[{"output_type":"stream","text":["Space conserving factor of 2.083 by brain masking and cropping\n"],"name":"stdout"},{"output_type":"display_data","data":{"image/png":"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\n","text/plain":["<Figure size 432x288 with 1 Axes>"]},"metadata":{"tags":[],"needs_background":"light"}}]},{"cell_type":"code","metadata":{"id":"kAB5BCBxOqIL","executionInfo":{"status":"ok","timestamp":1607767579912,"user_tz":300,"elapsed":15636,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["# This shouldn't be a thing in the final model, but U-net complains\n","# if each dimension isn't divisible by something like 16 or 32\n","# This should be easily fixable by changing the padding in the UNet3D\n","t1 = transform.resize(t1, [320, 400, 320])\n","seg = transform.resize(seg, [320, 400, 320])"],"execution_count":7,"outputs":[]},{"cell_type":"code","metadata":{"id":"nKI-uixLLG9S","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1607767579913,"user_tz":300,"elapsed":15634,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}},"outputId":"524fa9c1-00a4-47ec-bda0-6ed4f5c8e04c"},"source":["# More code shamelessly stolen from stack overflow, makes pytorch use GPU\n","\n","if using_TPU:\n","  device = xm.xla_device()\n","else:\n","  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n","  if device.type != 'cpu':\n","      print(torch.cuda.get_device_name(0))\n","  print('Allocated:', round(torch.cuda.memory_allocated()/1024**3,1), 'GB')\n","  print('Reserved:', round(torch.cuda.memory_reserved()/1024**3,1), 'GB')\n","  \n","print('Using device:', device)\n","print()\n"],"execution_count":8,"outputs":[{"output_type":"stream","text":["Tesla T4\n","Allocated: 0.0 GB\n","Reserved: 0.0 GB\n","Using device: cuda\n","\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"DyZS8-XZIfaT","executionInfo":{"status":"ok","timestamp":1607767584213,"user_tz":300,"elapsed":19929,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["# So (a single) raw image series are about 8-16x too big to fit using batch size 1\n","# The optimizations that I've identified here that we need are:\n","# 16-bit precision (or less, but Pytorch doesn't support it): Reduction by factor 2\n","# Brain masking and cropping the brain - in this case, reduction by a factor of 2\n","# Making the network have 2x less filters works, I guess the true amount of reduction was less than 16x\n","# Gradient checkpointing gives marginal improvements, but not the massive ones we were looking for\n","# This is probably because most of the memory is in the first (largest) layer\n","\n","# Next steps\n","# checkpoint_sequential is weird\n","# Also, you'd still have to reduce the high number of image channels to one or two channels\n","\n","t1_tensor = torch.Tensor(np.expand_dims(np.expand_dims(t1, axis=0), axis=0)).half().cuda()#to(device)\n","seg_tensor = torch.Tensor(np.expand_dims(np.expand_dims(seg, axis=0), axis=0)).half().cuda()#to(device)\n"],"execution_count":9,"outputs":[]},{"cell_type":"code","metadata":{"id":"IhNPY8UhZZZq","executionInfo":{"status":"ok","timestamp":1607767584215,"user_tz":300,"elapsed":19927,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["t1_tensor.requires_grad = True\r\n","seg_tensor.requires_grad = True"],"execution_count":10,"outputs":[]},{"cell_type":"code","metadata":{"id":"bIOm2vGXXCN1","executionInfo":{"status":"ok","timestamp":1607767584620,"user_tz":300,"elapsed":20328,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["import torch.nn as nn\r\n","import torch\r\n","from torchsummary import summary\r\n","import torchsummaryX\r\n","from lib.medzoo.BaseModelClass import BaseModel\r\n","from torch.utils.checkpoint import checkpoint, checkpoint_sequential\r\n","\r\n","class UNet3D(BaseModel):\r\n","    \"\"\"\r\n","    Implementations based on the Unet3D paper: https://arxiv.org/abs/1606.06650\r\n","    \"\"\"\r\n","\r\n","    def __init__(self, in_channels, n_classes, base_n_filter=8):\r\n","        super(UNet3D, self).__init__()\r\n","        self.in_channels = in_channels\r\n","        self.n_classes = n_classes\r\n","        self.base_n_filter = base_n_filter\r\n","\r\n","        self.lrelu = nn.LeakyReLU()\r\n","        self.dropout3d = nn.Dropout3d(p=0.6)\r\n","        self.upsacle = nn.Upsample(scale_factor=2, mode='nearest')\r\n","        self.softmax = nn.Softmax(dim=1)\r\n","\r\n","        self.conv3d_c1_1 = nn.Conv3d(self.in_channels, self.base_n_filter, kernel_size=3, stride=1, padding=1,\r\n","                                     bias=False)\r\n","        self.conv3d_c1_2 = nn.Conv3d(self.base_n_filter, self.base_n_filter, kernel_size=3, stride=1, padding=1,\r\n","                                     bias=False)\r\n","        self.lrelu_conv_c1 = self.lrelu_conv(self.base_n_filter, self.base_n_filter)\r\n","        self.inorm3d_c1 = nn.InstanceNorm3d(self.base_n_filter)\r\n","\r\n","        self.conv3d_c2 = nn.Conv3d(self.base_n_filter, self.base_n_filter * 2, kernel_size=3, stride=2, padding=1,\r\n","                                   bias=False)\r\n","        self.norm_lrelu_conv_c2 = self.norm_lrelu_conv(self.base_n_filter * 2, self.base_n_filter * 2)\r\n","        self.inorm3d_c2 = nn.InstanceNorm3d(self.base_n_filter * 2)\r\n","\r\n","        self.conv3d_c3 = nn.Conv3d(self.base_n_filter * 2, self.base_n_filter * 4, kernel_size=3, stride=2, padding=1,\r\n","                                   bias=False)\r\n","        self.norm_lrelu_conv_c3 = self.norm_lrelu_conv(self.base_n_filter * 4, self.base_n_filter * 4)\r\n","        self.inorm3d_c3 = nn.InstanceNorm3d(self.base_n_filter * 4)\r\n","\r\n","        self.conv3d_c4 = nn.Conv3d(self.base_n_filter * 4, self.base_n_filter * 8, kernel_size=3, stride=2, padding=1,\r\n","                                   bias=False)\r\n","        self.norm_lrelu_conv_c4 = self.norm_lrelu_conv(self.base_n_filter * 8, self.base_n_filter * 8)\r\n","        self.inorm3d_c4 = nn.InstanceNorm3d(self.base_n_filter * 8)\r\n","\r\n","        self.conv3d_c5 = nn.Conv3d(self.base_n_filter * 8, self.base_n_filter * 16, kernel_size=3, stride=2, padding=1,\r\n","                                   bias=False)\r\n","        self.norm_lrelu_conv_c5 = self.norm_lrelu_conv(self.base_n_filter * 16, self.base_n_filter * 16)\r\n","        self.norm_lrelu_upscale_conv_norm_lrelu_l0 = self.norm_lrelu_upscale_conv_norm_lrelu(self.base_n_filter * 16,\r\n","                                                                                             self.base_n_filter * 8)\r\n","\r\n","        self.conv3d_l0 = nn.Conv3d(self.base_n_filter * 8, self.base_n_filter * 8, kernel_size=1, stride=1, padding=0,\r\n","                                   bias=False)\r\n","        self.inorm3d_l0 = nn.InstanceNorm3d(self.base_n_filter * 8)\r\n","\r\n","        self.conv_norm_lrelu_l1 = self.conv_norm_lrelu(self.base_n_filter * 16, self.base_n_filter * 16)\r\n","        self.conv3d_l1 = nn.Conv3d(self.base_n_filter * 16, self.base_n_filter * 8, kernel_size=1, stride=1, padding=0,\r\n","                                   bias=False)\r\n","        self.norm_lrelu_upscale_conv_norm_lrelu_l1 = self.norm_lrelu_upscale_conv_norm_lrelu(self.base_n_filter * 8,\r\n","                                                                                             self.base_n_filter * 4)\r\n","\r\n","        self.conv_norm_lrelu_l2 = self.conv_norm_lrelu(self.base_n_filter * 8, self.base_n_filter * 8)\r\n","        self.conv3d_l2 = nn.Conv3d(self.base_n_filter * 8, self.base_n_filter * 4, kernel_size=1, stride=1, padding=0,\r\n","                                   bias=False)\r\n","        self.norm_lrelu_upscale_conv_norm_lrelu_l2 = self.norm_lrelu_upscale_conv_norm_lrelu(self.base_n_filter * 4,\r\n","                                                                                             self.base_n_filter * 2)\r\n","\r\n","        self.conv_norm_lrelu_l3 = self.conv_norm_lrelu(self.base_n_filter * 4, self.base_n_filter * 4)\r\n","        self.conv3d_l3 = nn.Conv3d(self.base_n_filter * 4, self.base_n_filter * 2, kernel_size=1, stride=1, padding=0,\r\n","                                   bias=False)\r\n","        self.norm_lrelu_upscale_conv_norm_lrelu_l3 = self.norm_lrelu_upscale_conv_norm_lrelu(self.base_n_filter * 2,\r\n","                                                                                             self.base_n_filter)\r\n","\r\n","        self.conv_norm_lrelu_l4 = self.conv_norm_lrelu(self.base_n_filter * 2, self.base_n_filter * 2)\r\n","        self.conv3d_l4 = nn.Conv3d(self.base_n_filter * 2, self.n_classes, kernel_size=1, stride=1, padding=0,\r\n","                                   bias=False)\r\n","\r\n","        self.ds2_1x1_conv3d = nn.Conv3d(self.base_n_filter * 8, self.n_classes, kernel_size=1, stride=1, padding=0,\r\n","                                        bias=False)\r\n","        self.ds3_1x1_conv3d = nn.Conv3d(self.base_n_filter * 4, self.n_classes, kernel_size=1, stride=1, padding=0,\r\n","                                        bias=False)\r\n","        self.sigmoid = nn.Sigmoid()\r\n","\r\n","    def conv_norm_lrelu(self, feat_in, feat_out):\r\n","        return  nn.Sequential(\r\n","            nn.Conv3d(feat_in, feat_out, kernel_size=3, stride=1, padding=1, bias=False),\r\n","            nn.InstanceNorm3d(feat_out),\r\n","            nn.LeakyReLU())\r\n","        \r\n","\r\n","    def norm_lrelu_conv(self, feat_in, feat_out):\r\n","        return nn.Sequential(\r\n","            nn.InstanceNorm3d(feat_in),\r\n","            nn.LeakyReLU(),\r\n","            nn.Conv3d(feat_in, feat_out, kernel_size=3, stride=1, padding=1, bias=False))\r\n","\r\n","    def lrelu_conv(self, feat_in, feat_out):\r\n","        return nn.Sequential(\r\n","            nn.LeakyReLU(),\r\n","            nn.Conv3d(feat_in, feat_out, kernel_size=3, stride=1, padding=1, bias=False))\r\n","\r\n","    def norm_lrelu_upscale_conv_norm_lrelu(self, feat_in, feat_out):\r\n","        return nn.Sequential(\r\n","            nn.InstanceNorm3d(feat_in),\r\n","            nn.LeakyReLU(),\r\n","            nn.Upsample(scale_factor=2, mode='nearest'),\r\n","            # should be feat_in*2 or feat_in\r\n","            nn.Conv3d(feat_in, feat_out, kernel_size=3, stride=1, padding=1, bias=False),\r\n","            nn.InstanceNorm3d(feat_out),\r\n","            nn.LeakyReLU())\r\n","\r\n","    def forward(self, x):\r\n","        #  Level 1 context pathway\r\n","        out = checkpoint(self.conv3d_c1_1, x)\r\n","        residual_1 = out\r\n","        out = self.lrelu(out)\r\n","        out = checkpoint(self.conv3d_c1_2, out)\r\n","        out = self.dropout3d(out)\r\n","        out = checkpoint(self.lrelu_conv_c1, out)\r\n","        # Element Wise Summation\r\n","        out += residual_1\r\n","        context_1 = self.lrelu(out)\r\n","        out = self.inorm3d_c1(out)\r\n","        out = self.lrelu(out)\r\n","\r\n","        # Level 2 context pathway\r\n","        out = checkpoint(self.conv3d_c2, out)\r\n","        residual_2 = out\r\n","        out = checkpoint(self.norm_lrelu_conv_c2, out)\r\n","        out = self.dropout3d(out)\r\n","        out = checkpoint(self.norm_lrelu_conv_c2, out)\r\n","        out += residual_2\r\n","        out = self.inorm3d_c2(out)\r\n","        out = self.lrelu(out)\r\n","        context_2 = out\r\n","\r\n","        # Level 3 context pathway\r\n","        out = checkpoint(self.conv3d_c3, out)\r\n","        residual_3 = out\r\n","        out = checkpoint(self.norm_lrelu_conv_c3,out)\r\n","        out = self.dropout3d(out)\r\n","        out = checkpoint(self.norm_lrelu_conv_c3,out)\r\n","        out += residual_3\r\n","        out = self.inorm3d_c3(out)\r\n","        out = self.lrelu(out)\r\n","        context_3 = out\r\n","\r\n","        # Level 4 context pathway\r\n","        out = checkpoint(self.conv3d_c4, out)\r\n","        residual_4 = out\r\n","        out = checkpoint(self.norm_lrelu_conv_c4,out)\r\n","        out = self.dropout3d(out)\r\n","        out = checkpoint(self.norm_lrelu_conv_c4,out)\r\n","        out += residual_4\r\n","        out = self.inorm3d_c4(out)\r\n","        out = self.lrelu(out)\r\n","        context_4 = out\r\n","\r\n","        # Level 5\r\n","        out = checkpoint(self.conv3d_c5, out)\r\n","        residual_5 = out\r\n","        out = checkpoint(self.norm_lrelu_conv_c5,out)\r\n","        out = self.dropout3d(out)\r\n","        out = checkpoint(self.norm_lrelu_conv_c5,out)\r\n","        out += residual_5\r\n","        out = checkpoint(self.norm_lrelu_upscale_conv_norm_lrelu_l0,out)\r\n","\r\n","        out = checkpoint(self.conv3d_l0, out)\r\n","        out = self.inorm3d_l0(out)\r\n","        out = self.lrelu(out)\r\n","\r\n","        # Level 1 localization pathway\r\n","        out = torch.cat([out, context_4], dim=1)\r\n","        out = checkpoint(self.conv_norm_lrelu_l1, out)\r\n","        out = checkpoint(self.conv3d_l1,out)\r\n","        out = checkpoint(self.norm_lrelu_upscale_conv_norm_lrelu_l1,out)\r\n","\r\n","        # Level 2 localization pathway\r\n","        # print(out.shape)\r\n","        # print(context_3.shape)\r\n","        out = torch.cat([out, context_3], dim=1)\r\n","        out = checkpoint(self.conv_norm_lrelu_l2, out)\r\n","        ds2 = out\r\n","        out = checkpoint(self.conv3d_l2,out)\r\n","        out = checkpoint(self.norm_lrelu_upscale_conv_norm_lrelu_l2,out)\r\n","\r\n","        # Level 3 localization pathway\r\n","        out = torch.cat([out, context_2], dim=1)\r\n","        out = checkpoint(self.conv_norm_lrelu_l3,out)\r\n","        ds3 = out\r\n","        out = checkpoint(self.conv3d_l3,out)\r\n","        out = checkpoint(self.norm_lrelu_upscale_conv_norm_lrelu_l3,out)\r\n","\r\n","        # Level 4 localization pathway\r\n","        out = torch.cat([out, context_1], dim=1)\r\n","        out = checkpoint(self.conv_norm_lrelu_l4,out)\r\n","        out_pred = checkpoint(self.conv3d_l4,out)\r\n","\r\n","        ds2_1x1_conv = checkpoint(self.ds2_1x1_conv3d, ds2)\r\n","        ds1_ds2_sum_upscale = self.upsacle(ds2_1x1_conv)\r\n","        ds3_1x1_conv = checkpoint(self.ds3_1x1_conv3d,ds3)\r\n","        ds1_ds2_sum_upscale_ds3_sum = ds1_ds2_sum_upscale + ds3_1x1_conv\r\n","        ds1_ds2_sum_upscale_ds3_sum_upscale = self.upsacle(ds1_ds2_sum_upscale_ds3_sum)\r\n","\r\n","        out = out_pred + ds1_ds2_sum_upscale_ds3_sum_upscale\r\n","        seg_layer = out\r\n","        return seg_layer\r\n","\r\n","    def test(self,device='cpu'):\r\n","\r\n","        input_tensor = torch.rand(1, 2, 32, 32, 32)\r\n","        ideal_out = torch.rand(1, self.n_classes, 32, 32, 32)\r\n","        out = self.forward(input_tensor)\r\n","        assert ideal_out.shape == out.shape\r\n","        summary(self.to(torch.device(device)), (2, 32, 32, 32),device='cpu')\r\n","        # import torchsummaryX\r\n","        # torchsummaryX.summary(self, input_tensor.to(device))\r\n","        print(\"Unet3D test is complete\")\r\n"],"execution_count":11,"outputs":[]},{"cell_type":"code","metadata":{"id":"7zxltE4UrY48","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1607767610232,"user_tz":300,"elapsed":45936,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}},"outputId":"730f9343-fe4b-4a20-dd37-460637f67bd9"},"source":["print(t1_tensor.shape)\n","\n","# If base_n_filter=6 using default medzoo.UNet3D, goes OOM\n","# but if base_n_filter=6 using checkpointed medzoo.UNet3D, works\n","# Definitely room for improvement, it is quite slow as implemented here\n","unet = UNet3D(1,1, base_n_filter=6).cuda() \n","unet.half()\n","\n","print('Allocated:', round(torch.cuda.memory_allocated(0)/1024**3,1), 'GB')\n","\n","optimizer = torch.optim.Adam(unet.parameters()) \n","# Pixel-wise CE gives some weird shape error with \"weights\"\n","\n","loss_function = losses3D.WeightedSmoothL1Loss()\n","for i in range(1):\n","  outputs = unet(t1_tensor)\n","  loss = loss_function(outputs, seg_tensor)\n","\n","  optimizer.zero_grad()\n","  loss.backward()\n","  optimizer.step()\n","  print(loss)"],"execution_count":12,"outputs":[{"output_type":"stream","text":["torch.Size([1, 1, 320, 400, 320])\n","Allocated: 0.2 GB\n","tensor(0.1796, device='cuda:0', dtype=torch.float16, grad_fn=<MeanBackward0>)\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"VpmAXrs_dIeO","executionInfo":{"status":"ok","timestamp":1607767610233,"user_tz":300,"elapsed":45932,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["#from lib.medzoo.HighResNet3D import HighResNet3D\r\n","#unet = HighResNet3D(1,1).cuda()#to(device) \r\n","#unet.half()\r\n","\r\n","#print('Allocated:', round(torch.cuda.memory_allocated(0)/1024**3,1), 'GB')\r\n","\r\n","#optimizer = torch.optim.Adam(unet.parameters()) \r\n","# Pixel-wise CE gives some weird shape error with \"weights\"\r\n","\r\n","#modules = [module for k, module in unet._modules.items()]\r\n","\r\n","\r\n","#loss_function = losses3D.WeightedSmoothL1Loss()\r\n","#for i in range(1):\r\n","# outputs = checkpoint_sequential(modules, 4, t1_tensor)\r\n","  #outputs = unet(t1_tensor)\r\n","#  loss = loss_function(outputs, seg_tensor)\r\n","#  print(loss)\r\n","#  optimizer.zero_grad()\r\n","#  loss.backward()\r\n","#  optimizer.step()"],"execution_count":13,"outputs":[]},{"cell_type":"code","metadata":{"id":"gJXMtMJs8dW6","executionInfo":{"status":"ok","timestamp":1607767610233,"user_tz":300,"elapsed":45929,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["# Wait this experiment makes no sense\n","#import sys\n","#import os\n","#models = [\n","#medzoo.Unet3D.UNet3D(1, 1),\n","#medzoo.HighResNet3D(1, 1),\n","#medzoo.DenseVoxelNet(1,1 ),\n","#medzoo.ResNet3D_VAE.ResNet3dVAE(1,1 ),\n","#medzoo.Vnet.VNetLight(1,1),\n","#medzoo.SkipDenseNet3D.SkipDenseNet3D(1,1)\n","#]\n","\n","#if not os.path.exists('model_sizes'):\n","#  os.mkdir('model_sizes')\n","#types = ['Unet', 'ResNet', 'VoxelNet', 'ResNetVAE','VNet']\n","#for i, model in enumerate(models):\n"," # model.eval()\n","#  torch.save(model.state_dict(), 'model_sizes/'+types[i]+'.pt')\n","\n"],"execution_count":14,"outputs":[]},{"cell_type":"code","metadata":{"id":"eAGjCU3fPjHw","executionInfo":{"status":"ok","timestamp":1607767610236,"user_tz":300,"elapsed":45927,"user":{"displayName":"Matt S.","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GhmRxRxaRotY25GfYgUeKEyA_6-qp74-hgHOeKY-g=s64","userId":"02813631548679962447"}}},"source":["# Every single network crashes even using 1 series\n","# Also some might have problems with image sizes that aren't multiples of 2, idk\n","\n","\n","# Crashes list\n","# Unet3D.UNet3D(1, 1)\n","# medzoo.HighResNet3D(1, 1)\n","# medzoo.DenseVoxelNet(1,1 )\n","# medzoo.ResNet3D_VAE.ResNet3dVAE(1,1 )\n","# VNetLight\n","# SkipDenseNet3D\n","# doesn't work for 1 channel\n","# medzoo.HyperDenseNet_2Mod(1, 1)\n","# medzoo.ResNet3DMedNet.ResNetMed3D(1,1)\n","# still crashes with TPU which has 64 GB HBM\n","\n","# Just stuff for TPUs, but didn't seem to work\n","#!curl https://raw.githubusercontent.com/pytorch/xla/master/contrib/scripts/env-setup.py -o pytorch-xla-env-setup.py\n","#!python pytorch-xla-env-setup.py \n"],"execution_count":15,"outputs":[]}]}