{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\nos.listdir('/kaggle/input/understanding_cloud_organization')\n# Any results you write to the current directory are saved as output.\n\npath_train_images = '/kaggle/input/understanding_cloud_organization/train_images'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, models\n\nfrom multiprocessing import cpu_count, Pool\nprint('Number of CPU: {}'.format(cpu_count()))\n\nfrom IPython.display import display\n\nimport albumentations as albu\n\nfrom PIL import Image\n\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm_notebook\nfrom collections import Counter\nimport pdb\n\nimport seaborn as sns","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from skmultilearn.model_selection import iterative_train_test_split\nfrom skmultilearn.model_selection.measures import get_combination_wise_output_matrix\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train_df = pd.read_csv('/kaggle/input/understanding_cloud_organization/train.csv')\n\ndisplay(train_df.head())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n\ndef split_image_label(x):\n    res = x.split('_')\n    return (x, res[0], res[1])\n    \npool = Pool(cpu_count())\n\nresults = [pool.apply_async(split_image_label, args=(x,)) for x in train_df['Image_Label']]\n\nimage_label_pairs = []\nfor res in results:\n    image_label_pairs.append(res.get())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.merge(train_df, \n                    pd.DataFrame(image_label_pairs, columns=['Image_Label', 'Image', 'Label']), \n                    on=['Image_Label'])\n\n\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['Label'] = train_df['Label'].astype('category')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\ntrain_df['Label_Encoded'] = train_df['Label'].cat.codes\n\ndisplay(train_df.head())\n\ntrain_df.to_csv('train_encoded.csv', index=False)\n\ntrain_image_ids = train_df['Image'].unique()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Convert Pivot Table to DataFrame"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n\ntrain_mask_df = train_df.pivot(index='Image', columns='Label', values='EncodedPixels')\ntrain_mask_df = pd.DataFrame(train_mask_df.to_records()).set_index('Image')\n\ndisplay(train_mask_df.head(2))\n\ntrain_mask_df.to_csv('train_mask.csv', index=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Multi-Label Train/Test Split"},{"metadata":{"trusted":true},"cell_type":"code","source":"# One Hot Encoding  \ntrain_label_df = train_mask_df.notnull().reset_index(drop=True).values\n\nprint(train_label_df[:5])\n\n# print(train_mask_df.reset_index().values[:1])\nprint()\nprint(train_mask_df.shape)\nprint(train_label_df.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X_train, y_train, X_valid, y_valid = iterative_train_test_split(train_mask_df.reset_index().values, train_label_df, test_size = 0.2)\n\ncount_org = Counter(combination for row in get_combination_wise_output_matrix(train_label_df, order=2) for combination in row)\nprint(count_org)\nprint()\ncount_train = Counter(combination for row in get_combination_wise_output_matrix(y_train, order=2) for combination in row)\nprint(count_train)\nprint()\ncount_valid = Counter(combination for row in get_combination_wise_output_matrix(y_valid, order=2) for combination in row)\nprint(count_valid)\n\n\ncolumns = train_mask_df.reset_index().columns\nX_train = pd.DataFrame(X_train, columns=columns)\nX_train = X_train.set_index('Image')\n\nX_valid = pd.DataFrame(X_valid, columns=columns).set_index('Image')\n\n\nprint()\nprint('train shape={}'.format(X_train.shape))\nprint('valid shape={}'.format(X_valid.shape))\nprint()\ndisplay(X_train.head(2))\ndisplay(X_valid.head(2))\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Plot Grouped Bars\nReference: [scikit.ml](http://scikit.ml/api/0.1.0/stratification.html)"},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.DataFrame({'org': Counter(str(combination) for row in get_combination_wise_output_matrix(train_label_df, order=2) for combination in row),\n              'train': Counter(str(combination) for row in get_combination_wise_output_matrix(y_train, order=2) for combination in row),\n             'valid': Counter(str(combination) for row in get_combination_wise_output_matrix(y_valid, order=2) for combination in row)\n                }).plot.bar()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for col in X_train.columns:\n    print('{:8s}: X_train = {:,}, X_valid = {:,}'.format(col,\n                                             X_train[col].notnull().sum(),\n                                             X_valid[col].notnull().sum()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def rle_to_mask(rle_string, width, height):\n    '''\n    convert RLE(run length encoding) string to numpy array\n\n    Parameters: \n    rle_string (str): string of rle encoded mask\n    height (int): height of the mask\n    width (int): width of the mask\n\n    Returns: \n    numpy.array: numpy array of the mask\n    '''\n    \n    rows, cols = height, width\n    \n    if rle_string == -1:\n        return np.zeros((height, width))\n    else:\n        rle_numbers = [int(num_string) for num_string in rle_string.split(' ')]\n        rle_pairs = np.array(rle_numbers).reshape(-1,2)\n        img = np.zeros(rows*cols, dtype=np.uint8)\n        for index, length in rle_pairs:\n            index -= 1\n            img[index:index+length] = 255\n        img = img.reshape(cols,rows)\n        img = img.T\n        return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class ImageDataset(Dataset):\n    def __init__(self, filenames, root, transform=None, to_tensor=False):\n        super().__init__()\n        self.filenames = filenames\n        self.root = root\n        self.transform = transform\n        self.to_tensor = to_tensor\n        \n        self.tensor = transforms.ToTensor()\n        \n    \n    def __len__(self):\n        return len(self.filenames)\n    \n    \n    def __getitem__(self, index):\n        filename = self.filenames[index]\n        filename = os.path.join(self.root, filename)\n        image = np.array(Image.open(filename))\n        \n        if self.transform is not None:\n            image = self.transform(image=image)['image']\n            \n        if self.to_tensor is True:\n            image = self.tensor(image)\n            \n        return image\n    \n\nclass MaskDataset(Dataset):\n    def __init__(self, shape_type, image_ids, mask_df, width, height):\n        super().__init__()\n        self.shape_type = shape_type\n        self.image_ids = image_ids\n        self.mask_df = mask_df\n        self.width = width\n        self.height = height\n        \n    def __len__(self):\n        return len(self.image_ids)\n    \n    \n    def __getitem__(self, index):\n        image_id = self.image_ids[index]\n        \n        rle = self.mask_df.loc[image_id, self.shape_type]\n        \n        \n        if isinstance(rle, str):\n            mask_image = rle_to_mask(rle, width=self.width, height=self.height)\n            mask_image = np.expand_dims(mask_image, axis=-1)\n        else:\n            mask_image = np.zeros((self.height, self.width, 1))\n            \n        return mask_image\n    \n    @property\n    def label(self):\n        return self.shape_type\n    \n    @property\n    def labels(self):\n        return self.mask_df.columns.to_list()\n    \n    \nclass MultiMaskDataset(Dataset):\n    def __init__(self, image_ids, mask_df, width, height):\n        super().__init__()\n        self.image_ids = image_ids\n        self.mask_df = mask_df\n        self.width = width\n        self.height = height\n        \n        \n    def __len__(self):\n        return len(self.image_ids)\n    \n    \n    def __getitem__(self, index):\n        image_id = self.image_ids[index]\n        \n        rle_masks = self.mask_df.loc[image_id]\n        \n        masks = None\n        for shape_type, rle in rle_masks.iteritems():\n#             print(type(rle))\n            if isinstance(rle, str):\n                mask_image = rle_to_mask(rle, width=self.width, height=self.height)\n                mask_image = np.expand_dims(mask_image, axis=-1)\n            else:\n                mask_image = np.zeros((self.height, self.width, 1))\n            \n            if masks is None:\n                masks = mask_image\n            else:\n                masks = np.concatenate((masks, mask_image), axis=-1)\n            \n        return masks\n    \n    @property\n    def labels(self):\n        return self.mask_df.columns.to_list()\n    \n    \nclass MaskLabelDataset(Dataset):\n    def __init__(self, image_ids, mask_df, to_tensor=False):\n        self.image_ids = image_ids\n        self.mask_df = mask_df\n        self.to_tensor = to_tensor\n        \n    def __getitem__(self, index):\n        image_id = self.image_ids[index]\n        rle_masks = self.mask_df.loc[image_id]\n        \n        labels = []\n        for shape_type, rle in rle_masks.iteritems():\n            if isinstance(rle, str):\n                labels.append(1)\n            else:\n                labels.append(0)\n        \n        if self.to_tensor is True:\n            labels = torch.tensor(labels)\n            \n            \n        return labels\n    \n    @property\n    def labels(self):\n        return self.mask_df.columns.to_list()\n    \n    \nclass ImageMaskDataset(Dataset):\n    def __init__(self, image_dataset: ImageDataset, \n                     mask_dataset,\n                    transform=None,\n                    to_tensor=True):\n        \n        super().__init__()\n        self.image_dataset = image_dataset\n        self.mask_dataset = mask_dataset\n        self.transform = transform\n        self.to_tensor = to_tensor\n        self.tensor = transforms.ToTensor()\n        \n        \n    def __len__(self):\n        return len(self.image_dataset)\n        \n    def __getitem__(self, index):\n        image = self.image_dataset[index]\n        masks = self.mask_dataset[index]\n        \n#         pdb.set_trace()\n        \n        if self.transform is not None:\n            data = {'image': image, 'mask': masks}\n            \n            res = self.transform(**data)\n            \n#             pdb.set_trace()\n            \n            image = res['image']\n            masks = res['mask']\n            \n        if self.to_tensor is True:\n            image, masks = self.tensor(image), self.tensor(masks)\n        \n        return image, masks\n    \n    @property\n    def labels(self):\n        return self.mask_dataset.labels\n        \n\n# ## test image dataset\nimage_dataset = ImageDataset(X_train.index, #train_image_ids,\n                            root=path_train_images)\n\n# img = image_dataset[0]\n\n# fig, axes = plt.subplots(1, 1, figsize=(6, 6))\n# axes.imshow(img)\n\n# print(np.array(img).shape)\n\n\n## Test mask dataset\nmask_dataset = MultiMaskDataset(X_train.index,\n                           train_mask_df,\n                           width=2100,\n                           height=1400)\n\n\nmasks = mask_dataset[0]\n\nfig, axes = plt.subplots(1, 4, figsize=(20, 5))\n\nfor index, shape_type in enumerate(mask_dataset.labels):\n    print(shape_type)\n    mask_image = masks[:, :, index]\n    axes[index].imshow(mask_image)\n    axes[index].set_title(shape_type)\n    \n    \n    \n# label_dataset = MaskLabelDataset(train_image_ids,\n#                                    train_mask_df)\n\n# print(label_dataset[0])\n# print(label_dataset.labels)\n\n\n### test cloud dataset\n\ntransform = albu.Compose([albu.Resize(224, 224, always_apply=True),\n                         ])\n\ncloud_dataset = ImageMaskDataset(image_dataset, mask_dataset, transform=transform, to_tensor=False)\nimage, masks = cloud_dataset[0]\n\nfig, axes = plt.subplots(1, 5, figsize=(20, 5))\naxes[0].imshow(image)\n\nfor index, label in enumerate(cloud_dataset.labels):\n    mask = masks[:, :, index]\n    axes[index+1].imshow(mask)\n    axes[index+1].set_title(label)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class ImageLabelDataset(Dataset):\n    def __init__(self, image_dataset: ImageDataset,\n                        mask_label_dataset: MaskLabelDataset):\n        super().__init__()\n        self.image_dataset = image_dataset\n        self.mask_label_dataset = mask_label_dataset\n        \n        \n    def __len__(self):\n        return len(self.image_dataset)\n    \n    def __getitem__(self, index):\n        image, label = self.image_dataset[index], self.mask_label_dataset[index]\n        \n        return image, label\n        \n    ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Multi-Label Training"},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 8\n\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_train_dataloader(shape_type, image_ids, train_mask_df, path_root, batch_size, to_tensor=True):\n    transform = albu.Compose([albu.HorizontalFlip(),\n                                    albu.OneOf([\n                                        albu.RandomContrast(),\n                                        albu.RandomGamma(),\n                                        albu.RandomBrightness(),\n                                        ], p=0.3),\n                                    albu.OneOf([\n                                        albu.ElasticTransform(alpha=120, sigma=120 * 0.05, alpha_affine=120 * 0.03),\n                                        albu.GridDistortion(),\n                                        albu.OpticalDistortion(distort_limit=2, shift_limit=0.5),\n                                        ], p=0.3),\n                                    albu.Resize(512, 512, always_apply=True)\n                                    ])\n\n    image_dataset = ImageDataset(image_ids,\n                                    root=path_root,\n                                    to_tensor=False)\n\n    mask_dataset = MaskDataset(shape_type,\n                                image_ids,\n                               train_mask_df,\n                               width=2100,\n                               height=1400)\n    \n    image_mask_dataset = ImageMaskDataset(image_dataset,\n                                            mask_dataset,\n                                            transform=transform,\n                                            to_tensor=to_tensor)\n    \n    loader = DataLoader(dataset=image_mask_dataset,\n                             batch_size=batch_size,\n                             shuffle=True,\n                             num_workers=cpu_count(),\n                             pin_memory=True,\n                             drop_last=True)\n    \n    \n    return loader\n\n\n# image_ids = X_train[X_train['Fish'].notnull()].index\n# train_loader = get_train_dataloader('Fish',\n#                                     image_ids, \n#                                     train_mask_df, \n#                                     path_train_images,\n#                                    batch_size,\n#                                    to_tensor=False)\n\n\n# img, mask = next(iter(train_loader))\n# img = img.numpy().squeeze()\n# mask = mask.numpy().squeeze()\n\n# fig, axes = plt.subplots(1, 2, figsize=(6, 3))\n# axes[0].imshow(img)\n# axes[1].imshow(mask)\n# axes[1].set_title('Fish')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_valid_dataloader(shape_type, image_ids, train_mask_df, path_root, batch_size, to_tensor=True):\n    \n    transform = albu.Compose([albu.Resize(512, 512, always_apply=True)\n                                    ])\n\n    image_dataset = ImageDataset(image_ids,\n                                root=path_root,\n                                to_tensor=False)\n\n    mask_dataset = MaskDataset(shape_type,\n                               image_ids,\n                               train_mask_df,\n                               width=2100,\n                               height=1400)\n    \n    image_mask_dataset = ImageMaskDataset(image_dataset,\n                                        mask_dataset,\n                                        transform=transform,\n                                         to_tensor=to_tensor)\n    \n    loader = DataLoader(dataset=image_mask_dataset,\n                             batch_size=batch_size,\n                             shuffle=False,\n                             num_workers=cpu_count(),\n                             pin_memory=True,\n                             drop_last=True)\n    \n    return loader\n\n\n# image_ids = X_valid[X_valid['Fish'].notnull()].index\n# valid_loader = get_valid_dataloader('Fish',\n#                                     image_ids, \n#                                     train_mask_df, \n#                                     path_train_images,\n#                                    batch_size,\n#                                    to_tensor=False)\n\n\n# img, mask = next(iter(valid_loader))\n# img = img.numpy().squeeze()\n# mask = mask.numpy().squeeze()\n\n# fig, axes = plt.subplots(1, 2, figsize=(6, 3))\n# axes[0].imshow(img)\n# axes[1].imshow(mask)\n# axes[1].set_title('Fish')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_one_epoch(model, dataloader, optimizer, criterion, device):\n    model.train()\n    \n    running_loss = torch.tensor(0.0).to(device)\n    batch_num = 0\n    \n    for images, masks in dataloader:\n        \n#         print(type(images))\n#         print(images.shape)\n#         print(type(labels))\n#         break\n        \n        images, masks = images.to(device), masks.to(device, dtype=torch.float)\n        \n        y_preds = model(images)\n        \n        loss = criterion(y_preds, masks)\n        \n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        running_loss += loss.detach()\n        batch_num += 1\n        \n    return running_loss.to('cpu').item() / batch_num\n\n\n@torch.no_grad()\ndef evaluate(model, dataloader, criterion, device):\n    model.eval()\n    \n    running_loss = torch.tensor(0.0).to(device)\n    batch_num = 0\n    \n    for images, masks in dataloader:\n        images, masks = images.to(device), masks.to(device)\n        \n        y_preds = model(images)\n        \n        loss = criterion(y_preds, masks)\n        \n        running_loss += loss.detach()\n        batch_num += 1\n        \n    return running_loss.to('cpu').item() / batch_num","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model for Segmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"class ResnetBlock(nn.Module):\n    def __init__(self, in_channels, out_channels, kernel_size=3, padding=1):\n        super().__init__()\n        \n        self.conv1 = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, padding=padding)\n        self.conv2 = nn.Conv2d(in_channels=out_channels, out_channels=out_channels, kernel_size=kernel_size, padding=padding)\n        self.conv3 = nn.Conv2d(in_channels=out_channels, out_channels=out_channels, kernel_size=kernel_size, padding=padding)\n        \n    def forward(self, X):\n        \n        y = F.relu(self.conv1(X))\n        y_direct = y\n        \n        y = F.relu(self.conv2(y))\n        y = y_direct + F.relu(self.conv3(y))\n        return y\n    \n\nclass DownBlock(nn.Module):\n    def __init__(self, in_channels, out_channels):\n        super().__init__()\n        self.conv = ResnetBlock(in_channels, out_channels)\n        \n    def forward(self, X):\n        y = self.conv(X)\n        y_middle = y\n        \n        y = F.max_pool2d(y, kernel_size=2)\n        \n        return y, y_middle\n    \n    \nclass UpBlock(nn.Module):\n    def __init__(self, in_up_features, in_middle_features, out_channels):\n        super().__init__()\n        \n        self.conv = ResnetBlock(in_channels=(in_up_features+in_middle_features), \n                                out_channels=out_channels)\n        \n    def forward(self, X, X_middle):\n#         print('X:{}, X_middle:{}'.format(X.shape,\n#                                         X_middle.shape))\n              \n        y = F.interpolate(X, scale_factor=2, mode='bilinear', align_corners=True)\n        y = torch.cat([y, X_middle], dim=1)\n        \n        y = self.conv(y)\n        \n        return y\n    \n\nclass UNet(nn.Module):\n    def __init__(self, in_channels, down_layer_channels, bottom_channels, up_layer_channels, out_channels=1):\n        super().__init__()\n        \n        self.down_layers = self.init_down_layers(in_channels,\n                                                down_layer_channels)\n        \n        self.bottom_layer = self.init_bottom_layer(in_channels=down_layer_channels[-1],\n                                                  out_channels=bottom_channels)\n        \n        self.up_layers = self.init_up_layers(in_channels=bottom_channels,\n                                            up_layer_channels=up_layer_channels,\n                                            down_layer_channels=down_layer_channels)\n        \n        self.output_layer = self.init_output_layer(in_channels=up_layer_channels[0],\n                                                  out_channels=out_channels)\n        \n        \n    def init_down_layers(self, in_channels, down_layer_channels):\n        layers = nn.ModuleList()\n        \n        ch_in = in_channels\n        for ch_out in down_layer_channels:\n            layers.append(DownBlock(in_channels=ch_in,\n                                     out_channels=ch_out))\n            \n            ch_in = ch_out\n        \n        return layers\n    \n    \n    def init_bottom_layer(self, in_channels, out_channels):\n        return ResnetBlock(in_channels, out_channels)\n    \n    \n    def init_up_layers(self, in_channels, up_layer_channels, down_layer_channels):\n        layers = nn.ModuleList()\n        \n        ch_in = in_channels\n        for ch_out, ch_middle in zip(reversed(up_layer_channels), reversed(down_layer_channels)):\n            layers.append(UpBlock(ch_in, ch_middle, out_channels=ch_out))\n            ch_in = ch_out\n        \n        return layers\n    \n    \n    def init_output_layer(self, in_channels, out_channels, kernel_size=3, padding=1):\n        \n        return nn.Sequential(nn.Conv2d(in_channels=in_channels, out_channels=in_channels, kernel_size=kernel_size, padding=padding),\n                             nn.ReLU(),\n                             nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, padding=padding),\n                            )\n    \n        \n    def forward(self, X):\n        y = X\n        \n        y_middles = []\n        for layer in self.down_layers:\n            y, y_m = layer(y)\n            y_middles.append(y_m)\n            \n        y = self.bottom_layer(y)\n        \n        for index, (layer, y_m) in enumerate(zip(self.up_layers, reversed(y_middles))):\n#             print('layer {}'.format(index))\n            y = layer(y, X_middle=y_m)\n        \n        y = self.output_layer(y)\n        \n        return y\n    \n    \nmodel = UNet(in_channels=3,\n             out_channels=1,\n             down_layer_channels=[32, 64, 128, 256],\n             bottom_channels=512,\n             up_layer_channels=[32, 64, 128, 256])\n\n\n# # print(model)\n# model = model.to(device)\n# for image, label in train_loader:\n#     image, label = image.to(device), label.to(device, dtype=torch.float)\n#     y_pred = model(image)\n    \n#     break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# print(model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Train"},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"epochs = 10\n\nloss_dict = {}\n\nfor shape_type in train_mask_df.columns:\n    print('####### {}'.format(shape_type))\n    filename_model = 'model_classifier_{}.pth'.format(shape_type)\n\n    model = UNet(in_channels=3,\n             out_channels=1,\n             down_layer_channels=[32, 64, 128, 256],\n             bottom_channels=512,\n             up_layer_channels=[32, 64, 128, 256])\n    \n\n    optimizer = optim.Adam(model.parameters(), lr=1e-4)\n    criterion = nn.BCEWithLogitsLoss() # multi-label classification\n    lr_scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,\n                                                       patience=3,\n                                                       mode='min',\n                                                       verbose=True)\n\n    losses = []\n    min_loss = 99999.0\n    model = model.to(device)\n\n    image_ids = X_train[X_train[shape_type].notnull()].index\n    train_loader = get_train_dataloader(shape_type,\n                                        image_ids, \n                                        train_mask_df, \n                                        path_train_images,\n                                       batch_size,\n                                       to_tensor=True)\n\n    image_ids = X_valid[X_valid[shape_type].notnull()].index\n    valid_loader = get_valid_dataloader(shape_type,\n                                        image_ids, \n                                        train_mask_df, \n                                        path_train_images,\n                                       batch_size,\n                                       to_tensor=True)\n\n\n    for i_epoch in tqdm_notebook(range(epochs)):\n        train_loss = train_one_epoch(model, train_loader, optimizer, criterion, device)\n        lr_scheduler.step(train_loss)\n\n        valid_loss = evaluate(model, valid_loader, criterion, device)\n\n        losses.append((train_loss, valid_loss))\n\n        print('Epoch {}: train loss={}, valid loss={}'.format(i_epoch,\n                                                             train_loss,\n                                                             valid_loss))\n\n\n        if train_loss < min_loss:\n            min_loss = train_loss\n\n            print('Save model')\n            torch.save(model.state_dict(), filename_model)\n        \n\n\n    loss_dict[shape_type] = losses\n    \n    pd.DataFrame(losses, columns=['train', 'valid']).plot.line()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, axes = plt.subplots(1, 4, figsize=(20, 5))\nfor index, (shape_type, losses) in enumerate(loss_dict.items()):\n    ax = axes[index]\n    ax = pd.DataFrame(losses, columns=['train', 'valid']).plot.line(ax=ax)\n    ax.set_title(shape_type)","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":1}