{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nfrom skimage import io, transform\nfrom torch.utils.data import Dataset\nfrom torch.utils.data import DataLoader\nimport numpy as np\nimport pandas as pd\nimport torch\nimport time\nimport openslide\n\n\nn_tiles = 16\ntile_size = 256\nimage_size = 256\n\ndef get_tiles(img, mode=0):\n    \n    result = []\n    h, w, c = img.shape\n    \n    # number of \"pixels\" we need to pad both ways\n    pad_h = (tile_size - h % tile_size) % tile_size + ((tile_size * mode) // 2)\n    pad_w = (tile_size - w % tile_size) % tile_size + ((tile_size * mode) // 2)\n\n    # padded images, which can be divided each dimension by tile_size\n    img2 = np.pad(img, [[pad_h // 2, pad_h - pad_h // 2], [pad_w // 2, pad_w - pad_w // 2], [0, 0]], constant_values=255)\n    #print(f'img2.shape: {img2.shape}')\n\n    # getting the number of tiles in the padded image (getting the shape)\n    img3 = img2.reshape(img2.shape[0] // tile_size, tile_size, img2.shape[1] // tile_size, tile_size, 3)\n    #print(f'img3.shape: {img3.shape}')\n\n    # reshaping image\n    img3 = img3.transpose(0, 2, 1, 3, 4).reshape(-1, tile_size, tile_size, 3)\n    #print(f'img3.shape: {img3.shape}')\n\n    # if number of tiles we prepared is lower than n_tiles defined, pad more\n    #print(f'len(img3):{len(img3)} n_tiles: {n_tiles}')\n    if len(img3) < n_tiles:\n        img3 = np.pad(img3, [[0, n_tiles - len(img3)], [0, 0], [0, 0], [0, 0]], constant_values=255)\n\n    # getting the indexes of the tiles\n    idxs = np.argsort(img3.reshape(img3.shape[0],-1).sum(-1))[:n_tiles]\n\n\n    img3 = img3[idxs]\n\n    for i in range(len(img3)):\n        result.append({'img': img3[i], 'idx': i})\n    return result\n\ndef tiles_to_img(tiles, mode):\n    n_row_tiles = int(np.sqrt(n_tiles))\n    idxes = list(range(n_tiles))\n    images = np.zeros((image_size * n_row_tiles, image_size * n_row_tiles, 3))\n    for h in range(n_row_tiles):\n        for w in range(n_row_tiles):\n            i = h * n_row_tiles + w\n\n            if len(tiles) > idxes[i]:\n                this_img = tiles[idxes[i]]['img']\n            else:\n                this_img = np.ones((image_size, image_size, 3)).astype(np.uint8) * 255\n            if(mode):\n                this_img = 255 - this_img\n            h1 = h * image_size\n            w1 = w * image_size\n            images[h1:h1 + image_size, w1:w1 + image_size] = this_img\n    return images\n\nclass Dataset(Dataset):\n    def __init__(self, images_dir, masks_dir, device, transform=None):\n        self.image_dir = images_dir\n        self.mask_dir = masks_dir\n        self.transform = transform\n        ### inserting testing code ###\n        import time\n        df = pd.read_csv(\"/kaggle/input/prostate-cancer-grade-assessment/train.csv\")\n        df = df.loc[df['data_provider'] == 'radboud']\n        image_list = []\n        mask_list = []\n        for i in df.index:\n            if(os.path.isfile('/kaggle/input/prostate-cancer-grade-assessment/train_label_masks/'+df.at[i, \"image_id\"] + '_mask.tiff')):\n                image_list.append(df.at[i, \"image_id\"] + '.tiff')\n                mask_list.append(df.at[i, \"image_id\"] + '_mask.tiff')\n        image_list = [\"/kaggle/input/prostate-cancer-grade-assessment/train_images/000920ad0b612851f8e01bcc880d9b3d.tiff\"]\n        mask_list = [\"/kaggle/input/prostate-cancer-grade-assessment/train_label_masks/000920ad0b612851f8e01bcc880d9b3d_mask.tiff\"]\n        self.images = image_list\n        self.masks = mask_list\n        ### end of testing code, below correct version\n        #self.images = os.listdir(images_dir)\n        #self.masks = os.listdir(masks_dir)\n        self.device = device\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, index):\n        img_path = os.path.join(self.image_dir, self.images[index])\n        mask_path = os.path.join(self.mask_dir, self.masks[index])\n\n        image = openslide.OpenSlide(img_path)\n        image = image.read_region((0,0), 2, image.level_dimensions[2])\n        image = np.asarray(image)[:,:,0:3]\n        mask = openslide.OpenSlide(mask_path)\n        mask = mask.read_region((0,0), 2, mask.level_dimensions[2])\n        mask = np.asarray(mask)[:,:,0:3]\n\n        image_tiles = get_tiles(image)\n        mask_tiles = get_tiles(mask)\n\n\n        images = tiles_to_img(image_tiles, 1)\n        masks = tiles_to_img(mask_tiles, 0)\n        masks = masks[:,:,0]\n\n        images = images.astype(np.float32)\n        images /= 255\n        images = images.transpose(2, 0, 1)\n\n        masks = masks.astype(np.float32)\n        masks = np.where(masks==255, 6, masks) \n        #masks /= 255\n        #masks = masks.transpose(2, 0, 1)\n\n        images = torch.tensor(images).to(self.device)\n        masks = torch.tensor(masks).to(torch.long).to(self.device)\n        #print(\"Masks: \", masks)\n        return images, masks\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-09-20T18:44:56.69724Z","iopub.execute_input":"2021-09-20T18:44:56.697592Z","iopub.status.idle":"2021-09-20T18:44:56.726383Z","shell.execute_reply.started":"2021-09-20T18:44:56.697562Z","shell.execute_reply":"2021-09-20T18:44:56.724543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\nimport torch\nimport torch.nn as nn\nimport numpy as np\nfrom PIL import Image\nimport torch.nn.functional as F\n#from torchsummary import summary\nimport time\n\ndef load_image(infilename):\n    img = Image.open(infilename, 'r')\n    img.load()\n    data = np.asarray(img, dtype=\"float32\")\n    return data\n\n\ndef double_conv(in_c, out_c):\n    conv = nn.Sequential(\n        nn.Conv2d(in_c, out_c, kernel_size=3, padding=1),\n        nn.ReLU(inplace=True),\n        nn.Conv2d(out_c, out_c, kernel_size=3, padding=1),\n        nn.ReLU(inplace=True)\n    )\n    return conv\n\ndef crop_img(tensor, target_tensor):\n    # square images\n    target_size = target_tensor.size()[2]\n    if tensor.size()[2] % 2 == 1:\n        tensor_size = tensor.size()[2]-1\n    else:\n        tensor_size = tensor.size()[2]\n    delta = tensor_size - target_size\n    delta = delta // 2\n    return tensor[:, :, delta:tensor_size-delta, delta:tensor_size-delta]\n\nclass UNet(nn.Module):\n    def __init__(self, nb_classes):\n        super(UNet, self).__init__()\n        self.max_pool_2x2 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.down_conv_1 = double_conv(3, 64)\n        self.down_conv_2 = double_conv(64, 128)\n        self.down_conv_3 = double_conv(128, 256)\n        self.down_conv_4 = double_conv(256, 512)\n        self.down_conv_5 = double_conv(512, 1024)\n\n        ## transposed convolutions\n        self.up_trans_1 = nn.ConvTranspose2d(1024, 512, 2, 2)\n        self.up_conv_1 = double_conv(1024, 512)\n\n        self.up_trans_2 = nn.ConvTranspose2d(512, 256, 2, 2)\n        self.up_conv_2 = double_conv(512, 256)\n\n        self.up_trans_3 = nn.ConvTranspose2d(256, 128, 2, 2)\n        self.up_conv_3 = double_conv(256, 128)\n\n        self.up_trans_4 = nn.ConvTranspose2d(128, 64, 2, 2)\n        self.up_conv_4 = double_conv(128, 64)\n\n        self.out = nn.Conv2d(64, nb_classes, 1)\n\n\n    def forward(self, image):\n        # encoder part\n        # input image\n        x1 = self.down_conv_1(image) # this is passed to decoder\n        # max pooling\n        x2 = self.max_pool_2x2(x1)\n\n        x3 = self.down_conv_2(x2) # this is passed to decoder\n        x4 = self.max_pool_2x2(x3)\n\n        x5 = self.down_conv_3(x4) # this is passed to decoder\n        x6 = self.max_pool_2x2(x5)\n\n        x7 = self.down_conv_4(x6) # this is passed to decoder\n        x8 = self.max_pool_2x2(x7)\n\n        x9 = self.down_conv_5(x8)\n\n        # decoder part\n        x = self.up_trans_1(x9)\n        y = crop_img(x7, x)\n        x = self.up_conv_1(torch.cat([x, y], 1))\n\n        x = self.up_trans_2(x)\n        y = crop_img(x5, x)\n        x = self.up_conv_2(torch.cat([x, y], 1))\n\n        x = self.up_trans_3(x)\n        y = crop_img(x3, x)\n        x = self.up_conv_3(torch.cat([x, y], 1))\n\n        x = self.up_trans_4(x)\n        y = crop_img(x1, x)\n        x = self.up_conv_4(torch.cat([x, y], 1))\n\n        x = self.out(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2021-09-20T18:44:57.109366Z","iopub.execute_input":"2021-09-20T18:44:57.109775Z","iopub.status.idle":"2021-09-20T18:44:57.130983Z","shell.execute_reply.started":"2021-09-20T18:44:57.109746Z","shell.execute_reply":"2021-09-20T18:44:57.129476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 1\nnum_epochs = 100\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n#device = torch.device(\"cpu\")\nprint(f'DEVICE: {device}')\n\n\ndataset = Dataset('/kaggle/input/prostate-cancer-grade-assessment/train_images','/kaggle/input/prostate-cancer-grade-assessment/train_label_masks', device)\ndataset_size = len(dataset)\ntrain_loader = DataLoader(dataset, batch_size=batch_size)\n\nmodel = UNet(nb_classes=7)\nmodel = model.to(device)\n#sparcecategoricalentropy for number in targets\ncriterion = torch.nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-4)\n#summary(model, input_size=(3, 128, 128))\n\nPREDS = []\nTARGETS = []\n\nfor epoch in range(num_epochs):\n    for i, (inputs, labels) in enumerate(train_loader):\n        y_pred = model(inputs)\n        #print(y_pred.detach().cpu().numpy())\n        #print(np.unique(labels.detach().cpu().numpy()))\n        #time.sleep(10)\n        loss = criterion(y_pred, labels)\n\n        ### additional evaluation ?\n        #print(\"Unique: \", np.unique(labels.detach().cpu().numpy()))\n        #preds = y_pred.sigmoid().sum(1).detach().round()\n        #print(preds)\n        #print(preds.cpu().numpy().size)\n        #print(np.unique(labels.detach().cpu().numpy()))\n        #print(y_pred.sigmoid().detach().cpu().numpy()[0])\n        ### \n        \n        # Zero gradients, perform a backward pass, and update the weights.\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        print(f'epoch: {epoch}, i: {i}, loss: {loss.item()}')\n        print(torch.sigmoid(y_pred).data.cpu().numpy().shape)\nprint('done')","metadata":{"execution":{"iopub.status.busy":"2021-09-20T18:58:03.471831Z","iopub.execute_input":"2021-09-20T18:58:03.472246Z","iopub.status.idle":"2021-09-20T18:58:03.971667Z","shell.execute_reply.started":"2021-09-20T18:58:03.472216Z","shell.execute_reply":"2021-09-20T18:58:03.968424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install torchsummary","metadata":{"execution":{"iopub.status.busy":"2021-09-19T21:09:15.434165Z","iopub.execute_input":"2021-09-19T21:09:15.434492Z","iopub.status.idle":"2021-09-19T21:09:22.682761Z","shell.execute_reply.started":"2021-09-19T21:09:15.434461Z","shell.execute_reply":"2021-09-19T21:09:22.681764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\n\ndf = pd.read_csv('/kaggle/input/prostate-cancer-grade-assessment/train.csv')\ndf","metadata":{"execution":{"iopub.status.busy":"2021-09-19T21:05:31.276177Z","iopub.execute_input":"2021-09-19T21:05:31.276518Z","iopub.status.idle":"2021-09-19T21:05:31.313069Z","shell.execute_reply.started":"2021-09-19T21:05:31.276487Z","shell.execute_reply":"2021-09-19T21:05:31.312135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.path.isfile(\"/kaggle/input/prostate-cancer-grade-assessment/train_images/0005f7aaab2800f6170c399693a96917.tiff\")","metadata":{"execution":{"iopub.status.busy":"2021-09-20T16:45:24.374077Z","iopub.execute_input":"2021-09-20T16:45:24.374425Z","iopub.status.idle":"2021-09-20T16:45:24.391882Z","shell.execute_reply.started":"2021-09-20T16:45:24.374374Z","shell.execute_reply":"2021-09-20T16:45:24.391066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}