{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install pretrainedmodels\n!pip install segmentation_models_pytorch","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-14T13:02:29.774330Z","start_time":"2020-12-14T13:02:28.267654Z"},"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","code_folding":[27],"execution":{"iopub.execute_input":"2020-11-29T18:06:22.415213Z","iopub.status.busy":"2020-11-29T18:06:22.414459Z","iopub.status.idle":"2020-11-29T18:06:24.833392Z","shell.execute_reply":"2020-11-29T18:06:24.833987Z"},"papermill":{"duration":2.443781,"end_time":"2020-11-29T18:06:24.834187","exception":false,"start_time":"2020-11-29T18:06:22.390406","status":"completed"},"tags":[],"trusted":true},"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore')\n\nimport numpy as np\nimport pandas as pd\nimport pathlib, sys, os, random, time\nimport numba, cv2, gc\nimport glob\n\nfrom sklearn.model_selection import KFold\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfrom tqdm.notebook import tqdm\nimport albumentations as A\nimport rasterio\nfrom rasterio.windows import Window\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.utils.data as D\n\nimport torchvision\nfrom torchvision import transforms as T\n\ndef set_seeds(seed=42):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n    \nset_seeds();","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-14T09:39:33.147970Z","start_time":"2020-12-14T09:39:33.092978Z"},"execution":{"iopub.execute_input":"2020-11-29T18:06:27.154021Z","iopub.status.busy":"2020-11-29T18:06:27.153309Z","iopub.status.idle":"2020-11-29T18:06:27.158143Z","shell.execute_reply":"2020-11-29T18:06:27.157280Z"},"papermill":{"duration":0.369641,"end_time":"2020-11-29T18:06:27.158268","exception":false,"start_time":"2020-11-29T18:06:26.788627","status":"completed"},"tags":[],"trusted":true},"cell_type":"code","source":"DATA_PATH = '../input/hubmap-kidney-segmentation/'\nDEVICE = 'cuda' if torch.cuda.is_available() else 'cpu' \nprint(DEVICE)\n\nimport logging\n\nlogging.basicConfig(filename='log.log',\n                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',\n                    datefmt='%Y-%m-%d %H:%M:%S ',\n                    level=logging.INFO)","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-14T09:39:33.207714Z","start_time":"2020-12-14T09:39:33.150013Z"},"code_folding":[1,12,29,45,50],"execution":{"iopub.execute_input":"2020-11-29T18:06:27.214344Z","iopub.status.busy":"2020-11-29T18:06:27.201055Z","iopub.status.idle":"2020-11-29T18:06:27.217004Z","shell.execute_reply":"2020-11-29T18:06:27.216522Z"},"papermill":{"duration":0.04383,"end_time":"2020-11-29T18:06:27.217106","exception":false,"start_time":"2020-11-29T18:06:27.173276","status":"completed"},"tags":[],"trusted":true},"cell_type":"code","source":"# used for converting the decoded image to rle mask\ndef rle_encode(im):\n    '''\n    im: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = im.flatten(order = 'F')\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef rle_decode(mask_rle, shape=(256, 256)):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape, order='F')\n\n@numba.njit()\ndef rle_numba(pixels):\n    size = len(pixels)\n    points = []\n    if pixels[0] == 1: points.append(0)\n    flag = True\n    for i in range(1, size):\n        if pixels[i] != pixels[i-1]:\n            if flag:\n                points.append(i+1)\n                flag = False\n            else:\n                points.append(i+1 - points[-1])\n                flag = True\n    if pixels[-1] == 1: points.append(size-points[-1]+1)    \n    return points\n\ndef rle_numba_encode(image):\n    pixels = image.flatten(order = 'F')\n    points = rle_numba(pixels)\n    return ' '.join(str(x) for x in points)\n\ndef make_grid(shape, window=256, min_overlap=32):\n    \"\"\"\n        Return Array of size (N,4), where N - number of tiles,\n        2nd axis represente slices: x1,x2,y1,y2 \n    \"\"\"\n    x, y = shape\n    nx = x // (window - min_overlap) + 1\n    x1 = np.linspace(0, x, num=nx, endpoint=False, dtype=np.int64)\n    x1[-1] = x - window\n    x2 = (x1 + window).clip(0, x)\n    ny = y // (window - min_overlap) + 1\n    y1 = np.linspace(0, y, num=ny, endpoint=False, dtype=np.int64)\n    y1[-1] = y - window\n    y2 = (y1 + window).clip(0, y)\n    slices = np.zeros((nx,ny, 4), dtype=np.int64)\n    \n    for i in range(nx):\n        for j in range(ny):\n            slices[i,j] = x1[i], x2[i], y1[j], y2[j]    \n    return slices.reshape(nx*ny,4)","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-14T09:39:33.283627Z","start_time":"2020-12-14T09:39:33.209121Z"},"execution":{"iopub.execute_input":"2020-11-29T18:06:27.269448Z","iopub.status.busy":"2020-11-29T18:06:27.265161Z","iopub.status.idle":"2020-11-29T18:06:27.272198Z","shell.execute_reply":"2020-11-29T18:06:27.271658Z"},"papermill":{"duration":0.039912,"end_time":"2020-11-29T18:06:27.272302","exception":false,"start_time":"2020-11-29T18:06:27.232390","status":"completed"},"tags":[],"trusted":true},"cell_type":"code","source":"identity = rasterio.Affine(1, 0, 0, 0, 1, 0)\n\nclass HubDataset(D.Dataset):\n\n    def __init__(self, path, tiff_ids, transform,\n                 window=256, overlap=32, threshold = 100, isvalid=False):\n        self.path = pathlib.Path(path)\n        self.tiff_ids = tiff_ids\n        self.overlap = overlap\n        self.window = window\n        self.transform = transform\n        self.csv = pd.read_csv((self.path / 'train.csv').as_posix(),\n                               index_col=[0])\n        self.threshold = threshold\n        self.isvalid = isvalid\n        \n        self.x, self.y, self.id = [], [], []\n        self.build_slices()\n        self.len = len(self.x)\n        self.as_tensor = T.Compose([\n            T.ToTensor(),\n            T.Normalize([0.625, 0.448, 0.688],\n                        [0.131, 0.177, 0.101]),\n        ])\n        \n    \n    def build_slices(self):\n        self.masks = []\n        self.files = []\n        self.slices = []\n        for i, filename in enumerate(self.csv.index.values):\n            if not filename in self.tiff_ids:\n                continue\n            \n            filepath = (self.path /'train'/(filename+'.tiff')).as_posix()\n            self.files.append(filepath)\n            \n            # print('Transform', filename)\n            with rasterio.open(filepath, transform = identity) as dataset:\n                self.masks.append(rle_decode(self.csv.loc[filename, 'encoding'], dataset.shape))\n                slices = make_grid(dataset.shape, window=self.window, min_overlap=self.overlap)\n                \n                for slc in slices:\n                    x1,x2,y1,y2 = slc\n                    # print(slc)\n                    image = dataset.read([1,2,3],\n                            window=Window.from_slices((x1,x2),(y1,y2)))\n                    image = np.moveaxis(image, 0, -1)\n                    \n                    image = cv2.resize(image, (256, 256))\n                    masks = cv2.resize(self.masks[-1][x1:x2,y1:y2], (256, 256))\n                    \n                    if self.isvalid:\n                        self.slices.append([i,x1,x2,y1,y2])\n                        self.x.append(image)\n                        self.y.append(masks)\n                        self.id.append(filename)\n                    else:\n                        if self.masks[-1][x1:x2,y1:y2].sum() >= self.threshold or (image>32).mean() > 0.99:\n                            self.slices.append([i,x1,x2,y1,y2])\n                            \n                            self.x.append(image)\n                            self.y.append(masks)\n                            self.id.append(filename)\n    \n    # get data operation\n    def __getitem__(self, index):\n        image, mask = self.x[index], self.y[index]\n        augments = self.transform(image=image, mask=mask)\n        return self.as_tensor(augments['image']), augments['mask'][None]\n    \n    def __len__(self):\n        \"\"\"\n        Total number of samples in the dataset\n        \"\"\"\n        return self.len\n","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-14T09:39:34.017436Z","start_time":"2020-12-14T09:39:33.286616Z"},"code_folding":[0,24,44,58,79,123,140,146,203,301],"trusted":true},"cell_type":"code","source":"def get_model():\n    model = torchvision.models.segmentation.fcn_resnet50(False)\n    \n    pth = torch.load('../fcn_resnet50_coco-1167a1af.pth')\n    for key in [\"aux_classifier.0.weight\", \"aux_classifier.1.weight\", \"aux_classifier.1.bias\", \"aux_classifier.1.running_mean\", \"aux_classifier.1.running_var\", \"aux_classifier.1.num_batches_tracked\", \"aux_classifier.4.weight\", \"aux_classifier.4.bias\"]:\n        del pth[key]\n    \n    model.load_state_dict(pth)\n    model.classifier[4] = nn.Conv2d(512, 1, kernel_size=(1, 1), stride=(1, 1))\n    return model\n\n\nimport functools\nimport torch.utils.model_zoo as model_zoo\nfrom torchvision.models.resnet import ResNet\nfrom torchvision.models.resnet import BasicBlock\nfrom torchvision.models.resnet import Bottleneck\nfrom pretrainedmodels.models.torchvision_models import pretrained_settings\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport numpy as np\n\n\ndef preprocess_input(x, mean=None, std=None, input_space='RGB', input_range=None, **kwargs):\n\n    if input_space == 'BGR':\n        x = x[..., ::-1].copy()\n\n    if input_range is not None:\n        if x.max() > 1 and input_range[1] == 1:\n            x = x / 255.\n\n    if mean is not None:\n        mean = np.array(mean)\n        x = x - mean\n\n    if std is not None:\n        std = np.array(std)\n        x = x / std\n\n    return x\n\n\nclass Model(nn.Module):\n\n    def __init__(self):\n        super().__init__()\n\n    def initialize(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n            elif isinstance(m, nn.BatchNorm2d):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n\nclass Conv2dReLU(nn.Module):\n    def __init__(self, in_channels, out_channels, kernel_size, padding=0,\n                 stride=1, use_batchnorm=True, **batchnorm_params):\n\n        super().__init__()\n\n        layers = [\n            nn.Conv2d(in_channels, out_channels, kernel_size,\n                              stride=stride, padding=padding, bias=not (use_batchnorm)),\n            nn.ReLU(inplace=True),\n        ]\n\n        if use_batchnorm:\n            layers.insert(1, nn.BatchNorm2d(out_channels, **batchnorm_params))\n\n        self.block = nn.Sequential(*layers)\n\n    def forward(self, x):\n        return self.block(x)\n\n\nclass EncoderDecoder(Model):\n\n    def __init__(self, encoder, decoder, activation):\n        super().__init__()\n        self.encoder = encoder\n        self.decoder = decoder\n\n        if callable(activation) or activation is None:\n            self.activation = activation\n        elif activation == 'softmax':\n            self.activation = nn.Softmax(dim=1)\n        elif activation == 'sigmoid':\n            self.activation = nn.Sigmoid()\n        else:\n            raise ValueError('Activation should be \"sigmoid\"/\"softmax\"/callable/None')\n\n    def forward(self, x):\n        \"\"\"Sequentially pass `x` trough model`s `encoder` and `decoder` (return logits!)\"\"\"\n        x = self.encoder(x)\n        x = self.decoder(x)\n        return x\n\n    def predict(self, x):\n        \"\"\"Inference method. Switch model to `eval` mode, call `.forward(x)`\n        and apply activation function (if activation is not `None`) with `torch.no_grad()`\n\n        Args:\n            x: 4D torch tensor with shape (batch_size, channels, height, width)\n\n        Return:\n            prediction: 4D torch tensor with shape (batch_size, classes, height, width)\n\n        \"\"\"\n        if self.training:\n            self.eval()\n\n        with torch.no_grad():\n            x = self.forward(x)\n            if self.activation:\n                x = self.activation(x)\n\n        return x\n\n\nclass DecoderBlock(nn.Module):\n    def __init__(self, in_channels, out_channels, use_batchnorm=True):\n        super().__init__()\n        self.block = nn.Sequential(\n            Conv2dReLU(in_channels, out_channels, kernel_size=3, padding=1, use_batchnorm=use_batchnorm),\n            Conv2dReLU(out_channels, out_channels, kernel_size=3, padding=1, use_batchnorm=use_batchnorm),\n        )\n\n    def forward(self, x):\n        x, skip = x\n        x = F.interpolate(x, scale_factor=2, mode='nearest')\n        if skip is not None:\n            x = torch.cat([x, skip], dim=1)\n        x = self.block(x)\n        return x\n\n\nclass CenterBlock(DecoderBlock):\n\n    def forward(self, x):\n        return self.block(x)\n\n\nclass UnetDecoder(Model):\n\n    def __init__(\n            self,\n            encoder_channels,\n            decoder_channels=(256, 128, 64, 32, 16),\n            final_channels=1,\n            use_batchnorm=True,\n            center=False,\n    ):\n        super().__init__()\n\n        if center:\n            channels = encoder_channels[0]\n            self.center = CenterBlock(channels, channels, use_batchnorm=use_batchnorm)\n        else:\n            self.center = None\n\n        in_channels = self.compute_channels(encoder_channels, decoder_channels)\n        out_channels = decoder_channels\n\n        self.layer1 = DecoderBlock(in_channels[0], out_channels[0], use_batchnorm=use_batchnorm)\n        self.layer2 = DecoderBlock(in_channels[1], out_channels[1], use_batchnorm=use_batchnorm)\n        self.layer3 = DecoderBlock(in_channels[2], out_channels[2], use_batchnorm=use_batchnorm)\n        self.layer4 = DecoderBlock(in_channels[3], out_channels[3], use_batchnorm=use_batchnorm)\n        self.layer5 = DecoderBlock(in_channels[4], out_channels[4], use_batchnorm=use_batchnorm)\n        self.final_conv = nn.Conv2d(out_channels[4], final_channels, kernel_size=(1, 1))\n\n        self.initialize()\n\n    def compute_channels(self, encoder_channels, decoder_channels):\n        channels = [\n            encoder_channels[0] + encoder_channels[1],\n            encoder_channels[2] + decoder_channels[0],\n            encoder_channels[3] + decoder_channels[1],\n            encoder_channels[4] + decoder_channels[2],\n            0 + decoder_channels[3],\n        ]\n        return channels\n\n    def forward(self, x):\n        encoder_head = x[0]\n        skips = x[1:]\n\n        if self.center:\n            encoder_head = self.center(encoder_head)\n\n        x = self.layer1([encoder_head, skips[0]])\n        x = self.layer2([x, skips[1]])\n        x = self.layer3([x, skips[2]])\n        x = self.layer4([x, skips[3]])\n        x = self.layer5([x, None])\n        x = self.final_conv(x)\n\n        return x\n\n\nclass ResNetEncoder(ResNet):\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.pretrained = False\n        del self.fc\n\n    def forward(self, x):\n        x0 = self.conv1(x)\n        x0 = self.bn1(x0)\n        x0 = self.relu(x0)\n\n        x1 = self.maxpool(x0)\n        x1 = self.layer1(x1)\n\n        x2 = self.layer2(x1)\n        x3 = self.layer3(x2)\n        x4 = self.layer4(x3)\n\n        return [x4, x3, x2, x1, x0]\n\n    def load_state_dict(self, state_dict, **kwargs):\n        state_dict.pop('fc.bias')\n        state_dict.pop('fc.weight')\n        super().load_state_dict(state_dict, **kwargs)\n\n\nresnet_encoders = {\n    'resnet18': {\n        'encoder': ResNetEncoder,\n        'pretrained_settings': pretrained_settings['resnet18'],\n        'out_shapes': (512, 256, 128, 64, 64),\n        'params': {\n            'block': BasicBlock,\n            'layers': [2, 2, 2, 2],\n        },\n    },\n\n    'resnet34': {\n        'encoder': ResNetEncoder,\n        'pretrained_settings': pretrained_settings['resnet34'],\n        'out_shapes': (512, 256, 128, 64, 64),\n        'params': {\n            'block': BasicBlock,\n            'layers': [3, 4, 6, 3],\n        },\n    },\n\n    'resnet50': {\n        'encoder': ResNetEncoder,\n        'pretrained_settings': pretrained_settings['resnet50'],\n        'out_shapes': (2048, 1024, 512, 256, 64),\n        'params': {\n            'block': Bottleneck,\n            'layers': [3, 4, 6, 3],\n        },\n    },\n\n    'resnet101': {\n        'encoder': ResNetEncoder,\n        'pretrained_settings': pretrained_settings['resnet101'],\n        'out_shapes': (2048, 1024, 512, 256, 64),\n        'params': {\n            'block': Bottleneck,\n            'layers': [3, 4, 23, 3],\n        },\n    },\n\n    'resnet152': {\n        'encoder': ResNetEncoder,\n        'pretrained_settings': pretrained_settings['resnet152'],\n        'out_shapes': (2048, 1024, 512, 256, 64),\n        'params': {\n            'block': Bottleneck,\n            'layers': [3, 8, 36, 3],\n        },\n    },\n}\n\nencoders = {}\nencoders.update(resnet_encoders)\n\ndef get_encoder(name, encoder_weights=None):\n    Encoder = encoders[name]['encoder']\n    encoder = Encoder(**encoders[name]['params'])\n    encoder.out_shapes = encoders[name]['out_shapes']\n\n    if encoder_weights is not None:\n        settings = encoders[name]['pretrained_settings'][encoder_weights]\n        encoder.load_state_dict(model_zoo.load_url(settings['url']))\n\n    return encoder\n\n\ndef get_encoder_names():\n    return list(encoders.keys())\n\n\ndef get_preprocessing_fn(encoder_name, pretrained='imagenet'):\n    settings = encoders[encoder_name]['pretrained_settings']\n\n    if pretrained not in settings.keys():\n        raise ValueError('Avaliable pretrained options {}'.format(settings.keys()))\n\n    input_space = settings[pretrained].get('input_space')\n    input_range = settings[pretrained].get('input_range')\n    mean = settings[pretrained].get('mean')\n    std = settings[pretrained].get('std')\n    \n    return functools.partial(preprocess_input, mean=mean, std=std, input_space=input_space, input_range=input_range)\n\n\nclass Unet(EncoderDecoder):\n    \"\"\"Unet_ is a fully convolution neural network for image semantic segmentation\n\n    Args:\n        encoder_name: name of classification model (without last dense layers) used as feature\n            extractor to build segmentation model.\n        encoder_weights: one of ``None`` (random initialization), ``imagenet`` (pre-training on ImageNet).\n        decoder_channels: list of numbers of ``Conv2D`` layer filters in decoder blocks\n        decoder_use_batchnorm: if ``True``, ``BatchNormalisation`` layer between ``Conv2D`` and ``Activation`` layers\n            is used.\n        classes: a number of classes for output (output shape - ``(batch, classes, h, w)``).\n        activation: activation function used in ``.predict(x)`` method for inference.\n            One of [``sigmoid``, ``softmax``, callable, None]\n        center: if ``True`` add ``Conv2dReLU`` block on encoder head (useful for VGG models)\n\n    Returns:\n        ``torch.nn.Module``: **Unet**\n\n    .. _Unet:\n        https://arxiv.org/pdf/1505.04597\n\n    \"\"\"\n\n    def __init__(\n            self,\n            encoder_name='resnet34',\n            encoder_weights='imagenet',\n            decoder_use_batchnorm=True,\n            decoder_channels=(256, 128, 64, 32, 16),\n            classes=1,\n            activation='sigmoid',\n            center=False,  # usefull for VGG models\n    ):\n        encoder = get_encoder(\n            encoder_name,\n            encoder_weights=encoder_weights\n        )\n\n        decoder = UnetDecoder(\n            encoder_channels=encoder.out_shapes,\n            decoder_channels=decoder_channels,\n            final_channels=classes,\n            use_batchnorm=decoder_use_batchnorm,\n            center=center,\n        )\n\n        super().__init__(encoder, decoder, activation)\n\n        self.name = 'u-{}'.format(encoder_name)\n","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-14T09:39:34.025640Z","start_time":"2020-12-14T09:39:34.019778Z"},"trusted":true},"cell_type":"code","source":"def train(model, train_loader, criterion, optimizer):\n    losses = []\n    for i, (image, target) in enumerate(train_loader):\n        image, target = image.to(DEVICE), target.float().to(DEVICE)\n        optimizer.zero_grad()\n        \n        output = model(image)\n        loss = criterion(output, target, 1, False)\n        loss.backward()\n        optimizer.step()\n        losses.append(loss.item())\n        # print('train, ', loss.item())\n    return np.array(losses).mean()\n\ndef np_dice_score(probability, mask):\n    p = probability.reshape(-1)\n    t = mask.reshape(-1)\n\n    p = p>0.5\n    t = t>0.5\n    uion = p.sum() + t.sum()\n    \n    overlap = (p*t).sum()\n    dice = 2*overlap/(uion+0.001)\n    return dice\n\ndef validation(model, val_loader, criterion):\n    val_probability, val_mask = [], []\n    model.eval()\n    with torch.no_grad():\n        for image, target in val_loader:\n            image, target = image.to(DEVICE), target.float().to(DEVICE)\n            output = model(image)\n            \n            output_ny = output.sigmoid().data.cpu().numpy()\n            target_np = target.data.cpu().numpy()\n            \n            val_probability.append(output_ny)\n            val_mask.append(target_np)\n            \n    val_probability = np.concatenate(val_probability)\n    val_mask = np.concatenate(val_mask)\n    \n    return np_dice_score(val_probability, val_mask)\n    ","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-14T09:43:58.209019Z","start_time":"2020-12-14T09:43:58.197214Z"},"trusted":true},"cell_type":"code","source":"class SoftDiceLoss(nn.Module):\n    def __init__(self, smooth=1., dims=(-2,-1)):\n        super(SoftDiceLoss, self).__init__()\n        self.smooth = smooth\n        self.dims = dims\n    \n    def forward(self, x, y):\n        tp = (x * y).sum(self.dims)\n        fp = (x * (1 - y)).sum(self.dims)\n        fn = ((1 - x) * y).sum(self.dims)\n        dc = (2 * tp + self.smooth) / (2 * tp + fp + fn + self.smooth)\n        dc = dc.mean()\n        \n        return 1 - dc\n\nbce_fn = nn.BCEWithLogitsLoss()\n# bce_fn = nn.BCELoss()\ndice_fn = SoftDiceLoss()\n    \ndef loss_fn(y_pred, y_true, ratio=0.8, hard=False):\n    bce = bce_fn(y_pred, y_true)\n    if hard:\n        dice = dice_fn((y_pred.sigmoid()).float() > 0.5, y_true)\n    else:\n        dice = dice_fn(y_pred.sigmoid(), y_true)\n    return ratio*bce + (1-ratio)*dice\n","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"start_time":"2020-12-14T09:44:03.139Z"},"scrolled":true,"trusted":true},"cell_type":"code","source":"EPOCHES = 5\nBATCH_SIZE = 8\n\nWINDOW=1024\nMIN_OVERLAP=40\nNEW_SIZE=256\n\ntrain_trfm = A.Compose([\n    # A.RandomCrop(NEW_SIZE*3, NEW_SIZE*3),\n    A.Resize(NEW_SIZE, NEW_SIZE),\n    A.HorizontalFlip(p=0.5),\n    A.VerticalFlip(p=0.5),\n    A.RandomRotate90(),\n    A.OneOf([\n        A.RandomContrast(),\n        A.RandomGamma(),\n        A.RandomBrightness(),\n        A.ColorJitter(brightness=0.07, contrast=0.07,\n                   saturation=0.1, hue=0.1, always_apply=False, p=0.3),\n        ], p=0.3),\n#     A.OneOf([\n#         A.OpticalDistortion(p=0.5),\n#         A.GridDistortion(p=0.5),\n#         A.IAAPiecewiseAffine(p=0.5),\n#     ], p=0.3),\n#     A.ShiftScaleRotate(),\n])\n\nval_trfm = A.Compose([\n    # A.CenterCrop(NEW_SIZE, NEW_SIZE),\n    A.Resize(NEW_SIZE,NEW_SIZE),\n    A.HorizontalFlip(p=0.5),\n    A.VerticalFlip(p=0.5),\n    A.RandomRotate90(),\n#     A.OneOf([\n#         A.RandomContrast(),\n#         A.RandomGamma(),\n#         A.RandomBrightness(),\n#         A.ColorJitter(brightness=0.07, contrast=0.07,\n#                    saturation=0.1, hue=0.1, always_apply=False, p=0.3),\n#         ], p=0.3),\n#     A.OneOf([\n#         A.OpticalDistortion(p=0.5),\n#         A.GridDistortion(p=0.5),\n#         A.IAAPiecewiseAffine(p=0.5),\n#     ], p=0.3),\n#     A.ShiftScaleRotate(),\n])\n\n# 每个file单独做一个验证集\ntiff_ids = np.array([x.split('/')[-1][:-5] for x in glob.glob('../input/hubmap-kidney-segmentation/train/*.tiff')])\nskf = KFold(n_splits=8)\n\nfor fold_idx, (train_idx, val_idx) in enumerate(skf.split(tiff_ids, tiff_ids)):\n    print(tiff_ids[val_idx])\n    \n    # break\n    train_ds = HubDataset(DATA_PATH, tiff_ids[train_idx], window=WINDOW, overlap=MIN_OVERLAP, \n                          threshold=100, transform=train_trfm)\n    valid_ds = HubDataset(DATA_PATH, tiff_ids[val_idx], window=WINDOW, overlap=MIN_OVERLAP, \n                          threshold=100, transform=val_trfm, isvalid=False)\n\n    print(len(train_ds), len(valid_ds))\n    \n    # define training and validation data loaders\n    train_loader = D.DataLoader(\n        train_ds, batch_size=BATCH_SIZE, shuffle=True, num_workers=12)\n\n    val_loader = D.DataLoader(\n        valid_ds, batch_size=BATCH_SIZE, shuffle=False, num_workers=12)\n    \n    # model = get_model()\n    # model = Unet(encoder_name=\"resnet34\",classes=1,activation=None)\n   \n    import segmentation_models_pytorch as smp\n\n    model = smp.Unet(\n        encoder_name=\"efficientnet-b1\",        # choose encoder, e.g. mobilenet_v2 or efficientnet-b7\n        encoder_weights=\"imagenet\",     # use `imagenet` pretreined weights for encoder initialization\n        in_channels=3,                  # model input channels (1 for grayscale images, 3 for RGB, etc.)\n        classes=1,                      # model output channels (number of classes in your dataset)\n    )\n\n    model.to(DEVICE);\n    \n    optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-3)\n    # lr_step = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizer, 2)\n    lr_step = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, factor=0.5, patience=5)\n    \n    header = r'''\n            Train | Valid\n    Epoch |  Loss |  Dice (Best) | Time\n    '''\n    print(header)\n    #          Epoch         metrics            time\n    raw_line = '{:6d}' + '\\u2502{:7.4f}'*3 + '\\u2502{:6.2f}'\n    \n    best_dice = 0\n    for epoch in range(1, EPOCHES+1):\n        start_time = time.time()\n        model.train()\n        train_loss = train(model, train_loader, loss_fn, optimizer)\n        val_dice = validation(model, val_loader, loss_fn)\n        lr_step.step(val_dice)\n\n        if val_dice > best_dice:\n            best_dice = val_dice\n            torch.save(model.state_dict(), 'fold_{0}.pth'.format(fold_idx))\n        \n        logging.info(raw_line.format(epoch, train_loss, val_dice, best_dice, (time.time()-start_time)/60**1))\n        \n    \n    del train_loader, val_loader, train_ds, valid_ds\n    gc.collect();\n    \n    break","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"start_time":"2020-12-14T08:24:26.949Z"},"execution":{"iopub.execute_input":"2020-11-29T18:58:17.874886Z","iopub.status.busy":"2020-11-29T18:58:17.874066Z","iopub.status.idle":"2020-11-29T19:07:56.220451Z","shell.execute_reply":"2020-11-29T19:07:56.219671Z"},"papermill":{"duration":578.390711,"end_time":"2020-11-29T19:07:56.220608","exception":false,"start_time":"2020-11-29T18:58:17.829897","status":"completed"},"scrolled":true,"tags":[],"trusted":true},"cell_type":"code","source":"\nmodel.load_state_dict(torch.load(\"./fold_0.pth\"))\nmodel.eval()\n\nvalid_ds = HubDataset(DATA_PATH, tiff_ids[val_idx], window=WINDOW, overlap=MIN_OVERLAP, \n                          threshold=100, transform=val_trfm, isvalid=False)","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-01T03:27:08.935748Z","start_time":"2020-12-01T03:27:08.298000Z"},"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(16,8))\nplt.subplot(241)\nplt.imshow(image[0]);\n\n# flip1\nplt.subplot(242)\nimage1 = torch.flip(image, [0, 1])\nplt.imshow(image1[0])\n\nplt.subplot(246)\nimage1 = torch.flip(image, [0, 1])\nplt.imshow(torch.flip(image1, [1, 0])[0])\n\n# flip2\nplt.subplot(243)\nimage1 = torch.flip(image, [0, -1])\nplt.imshow(image1[0])\n\nplt.subplot(247)\nimage1 = torch.flip(image, [0, -1])\nplt.imshow(torch.flip(image1, [-1, 0])[0])\n\n# flip3\nplt.subplot(244)\nimage1 = torch.flip(image, [1, -1])\nplt.imshow(image1[0])\n\nplt.subplot(248)\nimage1 = torch.flip(image, [1, -1])\nplt.imshow(torch.flip(image1, [-1, 1])[0])","execution_count":null,"outputs":[]},{"metadata":{"ExecuteTime":{"end_time":"2020-12-01T03:46:14.972026Z","start_time":"2020-12-01T03:46:10.542022Z"},"scrolled":true,"trusted":true},"cell_type":"code","source":"c = 1\nfor idx in range(80, 200):\n    \n    image, mask = valid_ds[idx]\n    if mask.max() == 0:\n        continue\n    \n    c += 1\n    if c > 10:\n        continue\n    \n    plt.figure(figsize=(16,8))\n    plt.subplot(141)\n    plt.imshow(mask[0], cmap='gray')\n    plt.subplot(142)\n    plt.imshow(image[0]);\n\n    with torch.no_grad():\n        image = image.to(DEVICE)[None]\n\n        score = model(image)[0][0]\n\n        score2 = model(torch.flip(image, [0, 3]))\n        score2 = torch.flip(score2, [3, 0])[0][0]\n\n        score3 = model(torch.flip(image, [1, 2]))\n        score3 = torch.flip(score3, [2, 1])[0][0]\n\n\n        score_mean = (score + score2 + score3) / 3.0\n\n        score_sigmoid = score_mean.sigmoid().cpu().numpy()\n        score_sigmoid = cv2.resize(score_sigmoid, (WINDOW, WINDOW))\n\n        score = score.sigmoid().cpu().numpy()\n        score = cv2.resize(score, (WINDOW, WINDOW))\n\n\n    plt.subplot(143)\n    plt.imshow((score_sigmoid > 0.5).astype(int));\n\n    plt.subplot(144)\n    plt.imshow((score > 0.5).astype(int));","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}