{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import re\nimport tensorflow as tf\nimport numpy as np\nfrom matplotlib import pyplot as plt\nprint(\"Tensorflow version \" + tf.__version__)\nAUTO = tf.data.experimental.AUTOTUNE\nfrom kaggle_datasets import KaggleDatasets\n# Detect hardware, return appropriate distribution strategy\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()  # TPU detection. No parameters necessary if TPU_NAME environment variable is set. On Kaggle this is always the case.\n    print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nelse:\n    strategy = tf.distribute.get_strategy() # default distribution strategy in Tensorflow. Works on CPU and single GPU.\n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a6cd9d5ad61ffe3b8858769f20a5f9493f024a56"},"cell_type":"markdown","source":"## Model Parameters\nWe might want to adjust these later (or do some hyperparameter optimizations)\n模型参数\n\n我们以后可能需要调整这些（或者做一些超参数优化）"},{"metadata":{"trusted":true,"_uuid":"301a5d939c566d1487a049bb2554d09b592b18b1"},"cell_type":"code","source":"BATCH_SIZE = 48\nEDGE_CROP = 16\nGAUSSIAN_NOISE = 0.1\nUPSAMPLE_MODE = 'SIMPLE'\n# downsampling inside the network\nNET_SCALING = (1, 1)\n# downsampling in preprocessing\nIMG_SCALING = (3, 3)\n# number of validation images to use\nVALID_IMG_COUNT = 900\n# maximum number of steps_per_epoch in training\nMAX_TRAIN_STEPS = 9\nMAX_TRAIN_EPOCHS = 99\nAUGMENT_BRIGHTNESS = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom skimage.io import imread\nimport matplotlib.pyplot as plt\nfrom matplotlib.cm import get_cmap\nfrom skimage.segmentation import mark_boundaries\n# from skimage.util import montage2d as montage\nfrom skimage.util import montage\nfrom skimage.morphology import binary_opening, disk, label\nimport gc; gc.enable() # memory is tight","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"montage_rgb = lambda x: np.stack([montage(x[:, :, :, i]) for i in range(x.shape[3])], -1)\nship_dir = '../input'\ntrain_image_dir = os.path.join(ship_dir, 'train_v2')\ntest_image_dir = os.path.join(ship_dir, 'test_v2')\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"def multi_rle_encode(img, **kwargs):\n    '''\n    Encode connected regions as separated masks\n    将连接区域编码为分离的掩码\n    '''\n    labels = label(img)\n    if img.ndim > 2:\n        return [rle_encode(np.sum(labels==k, axis=2), **kwargs) for k in np.unique(labels[labels>0])]\n    else:\n        return [rle_encode(labels==k, **kwargs) for k in np.unique(labels[labels>0])]\n\n# ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode\ndef rle_encode(img, min_max_threshold=1e-3, max_mean_threshold=None):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    if np.max(img) < min_max_threshold:\n        return '' ## no need to encode if it's all zeros\n    if max_mean_threshold and np.mean(img) > max_mean_threshold:\n        return '' ## ignore overfilled mask\n    pixels = img.T.flatten()\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=(768, 768)):\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    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).T  # Needed to align to RLE direction\n\ndef masks_as_image(in_mask_list):\n    # Take the individual ship masks and create a single mask array for all ships\n    all_masks = np.zeros((768, 768), dtype = np.uint8)\n    for mask in in_mask_list:\n        if isinstance(mask, str):\n            all_masks |= rle_decode(mask)\n    return all_masks\n\ndef masks_as_color(in_mask_list):\n    # Take the individual ship masks and create a color mask array for each ships\n    all_masks = np.zeros((768, 768), dtype = np.float)\n    scale = lambda x: (len(in_mask_list)+x+1) / (len(in_mask_list)*2) ## scale the heatmap image to shift \n    for i,mask in enumerate(in_mask_list):\n        if isinstance(mask, str):\n            all_masks[:,:] += scale(i) * rle_decode(mask)\n    return all_masks","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3ca7119188fbb4c6540d9df55f5833b55435287e"},"cell_type":"code","source":"masks = pd.read_csv(os.path.join('../input', 'train_ship_segmentations_v2.csv'))\nnot_empty = pd.notna(masks.EncodedPixels)\nprint(not_empty.sum(), 'masks in', masks[not_empty].ImageId.nunique(), 'images')#非空图片中的mask数量\nprint((~not_empty).sum(), 'empty images in', masks.ImageId.nunique(), 'total images')#所有图片中非空图片\nmasks.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fdedd5965f47f84aa8f3aab1cad978512781a1cc"},"cell_type":"markdown","source":"# Make sure encode/decode works\nGiven the process\n$$  RLE_0 \\stackrel{Decode}{\\longrightarrow} \\textrm{Image}_0 \\stackrel{Encode}{\\longrightarrow} RLE_1 \\stackrel{Decode}{\\longrightarrow} \\textrm{Image}_1 $$\nWe want to check if/that\n$ \\textrm{Image}_0 \\stackrel{?}{=} \\textrm{Image}_1 $\nWe could check the RLEs as well but that is more tedious. Also depending on how the objects have been labeled we might have different counts.\n\n"},{"metadata":{"trusted":true,"_uuid":"0081fd6f387abd7c05eb35f29575a2ee6ddc2236"},"cell_type":"code","source":"fig, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize = (16, 5))\n#划分图表分布\nrle_0 = masks.query('ImageId==\"00021ddc3.jpg\"')['EncodedPixels']\nimg_0 = masks_as_image(rle_0)\nax1.imshow(img_0)\nax1.set_title('Mask as image')\nrle_1 = multi_rle_encode(img_0)\nimg_1 = masks_as_image(rle_1)\nax2.imshow(img_1)\nax2.set_title('Re-encoded')\nimg_c = masks_as_color(rle_0)\nax3.imshow(img_c)\nax3.set_title('Masks in colors')\nimg_c = masks_as_color(rle_1)\nax4.imshow(img_c)\nax4.set_title('Re-encoded in colors')\nprint('Check Decoding->Encoding',\n      'RLE_0:', len(rle_0), '->',\n      'RLE_1:', len(rle_1))\nprint(np.sum(img_0 - img_1), 'error')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"40cb72e241c0c3d8bc245b4e3c663b4a835b0011"},"cell_type":"markdown","source":"# Split into training and validation groups\nWe stratify by the number of boats appearing so we have nice balances in each set\n#分成培训和验证组\n我们根据出现的船只数量进行分层，所以每套都有很好的平衡"},{"metadata":{"trusted":true},"cell_type":"code","source":"masks['ships'] = masks['EncodedPixels'].map(lambda c_row: 1 if isinstance(c_row, str) else 0)\nmasks.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unique_img_ids = masks.groupby('ImageId').agg({'ships': 'sum'}).reset_index()\nunique_img_ids.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unique_img_ids['has_ship'] = unique_img_ids['ships'].map(lambda x: 1.0 if x>0 else 0.0)\nunique_img_ids.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unique_img_ids['has_ship_vec'] = unique_img_ids['has_ship'].map(lambda x: [x])\nunique_img_ids['file_size_kb'] = unique_img_ids['ImageId'].map(lambda c_img_id: \n                                                               os.stat(os.path.join(train_image_dir, \n                                                                                    c_img_id)).st_size/1024)\nunique_img_ids.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c4f008bf6898518fd371de013418f936edaa09f8"},"cell_type":"code","source":"unique_img_ids = unique_img_ids[unique_img_ids['file_size_kb'] > 50] # keep only +50kb files\nunique_img_ids['file_size_kb'].hist()#绘制直方图\nmasks.drop(['ships'], axis=1, inplace=True)\nunique_img_ids.sample(7)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c21d5bff04bf9180463969ac120379345745ed03"},"cell_type":"markdown","source":"### Examine Number of Ship Images\nHere we examine how often ships appear and replace the ones without any ships with 0\n###检查船舶图像数量\n\n这里我们检查船只出现的频率，并用0替换没有船只的"},{"metadata":{"trusted":true,"_uuid":"2612fa47c7e9fdcaa7aa720c4e15fc86fd65d69a"},"cell_type":"code","source":"unique_img_ids['ships'].hist(bins=unique_img_ids['ships'].max())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unique_img_ids = unique_img_ids[unique_img_ids['ships']!=0]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ef8115a80749ac47f295e9a70217a5553970c2b3"},"cell_type":"markdown","source":"# Undersample Empty Images\nHere we undersample the empty images to get a better balanced group with more ships to try and segment\n#欠采样空图像\n在这里，我们对空图像进行欠采样，以获得一个更好的平衡组，其中有更多的船要尝试分割"},{"metadata":{"trusted":true,"_uuid":"0cf0bb261eda957cb0a12a330260e1390c57c8c9"},"cell_type":"code","source":"SAMPLES_PER_GROUP = 1800\nbalanced_train_df = unique_img_ids.groupby('ships').apply(lambda x: x.sample(SAMPLES_PER_GROUP) if len(x) > SAMPLES_PER_GROUP else x)\n#图片有相同船舶数量，但超出2000的不要\nbalanced_train_df['ships'].hist(bins=balanced_train_df['ships'].max())\nprint(balanced_train_df.shape[0], 'masks')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"balanced_train_df=balanced_train_df.reset_index(drop = True)#删除原来的索引。\nbalanced_train_df=balanced_train_df.sample(frac=1.0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a26cd030942c2cd763c6fcd08b370f886c93ecdf"},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain_ids, valid_ids = train_test_split(balanced_train_df, \n                 test_size = 0.2, \n                 stratify = balanced_train_df['ships'])\n#stratify使训练和测试的ships比例一样\ntrain_df = pd.merge(masks, train_ids)\nvalid_df = pd.merge(masks, valid_ids)\nprint(train_df.shape[0], 'training masks')\nprint(valid_df.shape[0], 'validation masks')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a3fb9fe33d81374c7bd836f5bc86a1df89190805"},"cell_type":"markdown","source":"# Decode all the RLEs into Images\nWe make a generator to produce batches of images\n#把所有的RLE解码成图像\n我们制造一个生成器来产生成批的图像"},{"metadata":{"trusted":true,"_uuid":"6181ac51577e5636995e38a9e29311cf47f513ca"},"cell_type":"code","source":"def make_image_gen(in_df, batch_size = BATCH_SIZE):\n    all_batches = list(in_df.groupby('ImageId'))\n    out_rgb = []\n    out_mask = []\n    while True:\n        np.random.shuffle(all_batches)\n        for c_img_id, c_masks in all_batches:\n            rgb_path = os.path.join(train_image_dir, c_img_id)\n            c_img = imread(rgb_path)\n            c_mask = np.expand_dims(masks_as_image(c_masks['EncodedPixels'].values), -1)\n            if IMG_SCALING is not None:\n                c_img = c_img[::IMG_SCALING[0], ::IMG_SCALING[1]]\n                c_mask = c_mask[::IMG_SCALING[0], ::IMG_SCALING[1]]\n            out_rgb += [c_img]\n            out_mask += [c_mask]\n            if len(out_rgb)>=batch_size:\n                yield np.stack(out_rgb, 0)/255.0, np.stack(out_mask, 0)\n                out_rgb, out_mask=[], []","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1983738da75b031f2bec8ba36db01c095e7c5d59"},"cell_type":"code","source":"train_gen = make_image_gen(train_df)\ntrain_x, train_y = next(train_gen) #返回迭代器的下一个项目。\nprint('x', train_x.shape, train_x.min(), train_x.max())\nprint('y', train_y.shape, train_y.min(), train_y.max())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b4396cd28ddd2e4c8076fcb165e9b61e3baeeeb7"},"cell_type":"code","source":"fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (30, 10))\nbatch_rgb = montage_rgb(train_x)\nbatch_seg = montage(train_y[:, :, :, 0])\nax1.imshow(batch_rgb)\nax1.set_title('Images')#标题\nax2.imshow(batch_seg)\nax2.set_title('Segmentations')\nax3.imshow(mark_boundaries(batch_rgb, batch_seg.astype(int)))#显示遮掩的边缘\nax3.set_title('Outlined Ships')\nfig.savefig('overview.png')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f47639c987a10ebcb53e51f55aa8a11c98fa860"},"cell_type":"markdown","source":"# Make the Validation Set\n#设置验证集"},{"metadata":{"trusted":true,"_uuid":"30cb02a2a7103a9d66e90f701991199de1e5b73e"},"cell_type":"code","source":"%%time\n#将会给出cell的代码运行一次所花费的时间。\nvalid_x, valid_y = next(make_image_gen(valid_df, VALID_IMG_COUNT))\nprint(valid_x.shape, valid_y.shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a8f65e7942816fb75b687a549dc1d5cc48d00e21"},"cell_type":"markdown","source":"# Augment Data\n#扩充数据"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\ndg_args = dict(featurewise_center = False, \n                  samplewise_center = False,\n                  rotation_range = 45, \n                  width_shift_range = 0.1, \n                  height_shift_range = 0.1, \n                  shear_range = 0.01,\n                  zoom_range = [0.9, 1.25],  \n                  horizontal_flip = True, \n                  vertical_flip = True,\n                  fill_mode = 'reflect',\n                   data_format = 'channels_last')\n# brightness can be problematic since it seems to change the labels differently from the images \n#亮度可能有问题，因为它似乎改变了不同于图像的标签\nif AUGMENT_BRIGHTNESS:\n    dg_args[' brightness_range'] = [0.5, 1.5]\nimage_gen = ImageDataGenerator(**dg_args)\n#**kwargs 表示关键字参数，它本质上是一个 dict\nif AUGMENT_BRIGHTNESS:\n    dg_args.pop('brightness_range')\nlabel_gen = ImageDataGenerator(**dg_args)\n#pop删除 arrayObject 的最后一个元素\n\ndef create_aug_gen(in_gen, seed = None):\n    np.random.seed(seed if seed is not None else np.random.choice(range(9999)))\n    for in_x, in_y in in_gen:\n        seed = np.random.choice(range(9999))\n        ##保持种子同步否则对图像的增强与遮罩不同\n        # keep the seeds syncronized otherwise the augmentation to the images is different from the masks\n        g_x = image_gen.flow(255*in_x, \n                             batch_size = in_x.shape[0], \n                             seed = seed, \n                             shuffle=True)\n        g_y = label_gen.flow(in_y, \n                             batch_size = in_x.shape[0], \n                             seed = seed, \n                             shuffle=True)\n\n        yield next(g_x)/255.0, next(g_y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6122ccb9e58bfac6fa5e11c86121e78d9e5151b1"},"cell_type":"code","source":"cur_gen = create_aug_gen(train_gen)\nt_x, t_y = next(cur_gen)\nprint('x', t_x.shape, t_x.dtype, t_x.min(), t_x.max())\nprint('y', t_y.shape, t_y.dtype, t_y.min(), t_y.max())\n# only keep first 9 samples to examine in detail\n#只保留前9个样本进行详细检查\nt_x = t_x[:9]\nt_y = t_y[:9]\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize = (20, 10))\nax1.imshow(montage_rgb(t_x), cmap='gray')\nax1.set_title('images')\nax2.imshow(montage(t_y[:, :, :, 0]), cmap='gray_r')\nax2.set_title('ships')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"33300c4f03b6600da7b418f775d11d7ebf76a35a"},"cell_type":"code","source":"gc.collect()#清理内存","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ba08494eb9736ec3556b7c879143cdcdea89febf"},"cell_type":"markdown","source":"# Build a Model\n\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing import image\nfrom keras.models import Model\nfrom keras import layers\nfrom keras.layers import Activation, AveragePooling2D, BatchNormalization, Concatenate\nfrom keras.layers import Conv2D, Dense, GlobalAveragePooling2D, GlobalMaxPooling2D, Input, Lambda, MaxPooling2D\nfrom keras.layers import SeparableConv2D, DepthwiseConv2D\nfrom keras.layers import Add, Multiply, Reshape\nfrom keras.applications.imagenet_utils import decode_predictions\nfrom keras.utils.data_utils import get_file\nfrom keras import backend as K\n\nfrom keras.utils.generic_utils import get_custom_objects\n\n\ndef relu6(x):\n    # relu函数\n    return K.relu(x, max_value=6.0)\n\n\nget_custom_objects().update({'relu6': Activation(relu6)})\n\n\ndef hard_swish(x):\n    # 利用relu函数乘上x模拟sigmoid\n    return x * K.relu(x + 3.0, max_value=6.0) / 6.0\n\n\nget_custom_objects().update({'hard_swish': Activation(hard_swish)})\n\n\ndef return_activation(x, nl):\n    # 用于判断使用哪个激活函数\n    if nl == 'HS':\n        x = Activation(hard_swish)(x)\n    if nl == 'RE':\n        x = Activation(relu6)(x)\n    return x\n\n\ndef channel_split(x, name=''):\n    in_channels = x.shape.as_list()[-1]\n    ip = in_channels // 2\n    c_hat = Lambda(lambda z: z[:, :, :, 0:ip])(x)\n    c = Lambda(lambda z: z[:, :, :, ip:])(x)\n\n    return c_hat, c\n\n\ndef channel_shuffle(x):\n    height, width, channels = x.shape.as_list()[1:]\n    channels_per_split = channels // 2\n\n    x = K.reshape(x, [-1, height, width, 2, channels_per_split])\n    x = K.permute_dimensions(x, (0, 1, 2, 4, 3))\n    x = K.reshape(x, [-1, height, width, channels])\n\n    return x\n\n\ndef squeeze(inputs):\n    # 注意力机制单元\n    input_channels = int(inputs.shape[-1])\n\n    x = GlobalAveragePooling2D()(inputs)\n    x = Dense(int(input_channels / 4))(x)\n    x = Activation(relu6)(x)\n    x = Dense(input_channels)(x)\n    x = Activation(hard_swish)(x)\n    x = Reshape((1, 1, input_channels))(x)\n    x = Multiply()([inputs, x])\n\n    return x\n\n\ndef _shuffle_unit(inputs, out_channels, sq, nl, strides=2, stage=1, block=1):\n    bn_axis = -1  # 通道在后还是在前\n    prefix = 'stage%d/block%d' % (stage, block)\n\n    branch_channels = out_channels // 2\n\n    if strides == 2:\n        x_1 = DepthwiseConv2D(kernel_size=3, strides=2, padding='same',\n                              use_bias=False, name='%s/3x3dwconv_1' % prefix)(inputs)\n        x_1 = BatchNormalization(axis=bn_axis, name='%s/bn_3x3dwconv_1' % prefix)(x_1)\n        x_1 = Conv2D(filters=branch_channels, kernel_size=1, strides=1, padding='same',\n                     use_bias=False, name='%s/1x1conv_1' % prefix)(x_1)\n        x_1 = BatchNormalization(axis=bn_axis, name='%s/bn_1x1conv_1' % prefix)(x_1)\n        x_1 = Activation('relu6')(x_1)\n\n        x_2 = Conv2D(filters=branch_channels, kernel_size=1, strides=1, padding='same',\n                     use_bias=False, name='%s/1x1conv_2' % prefix)(inputs)\n        x_2 = BatchNormalization(axis=bn_axis, name='%s/bn_1x1conv_2' % prefix)(x_2)\n        x_2 = Activation('relu6')(x_2)\n        x_2 = DepthwiseConv2D(kernel_size=3, strides=2, padding='same',\n                              use_bias=False, name='%s/3x3dwconv_2' % prefix)(x_2)\n        x_2 = BatchNormalization(axis=bn_axis, name='%s/bn_3x3dwconv_2' % prefix)(x_2)\n        x_2 = Conv2D(filters=branch_channels, kernel_size=1, strides=1, padding='same',\n                     use_bias=False, name='%s/1x1conv_3' % prefix)(x_2)\n        x_2 = BatchNormalization(axis=bn_axis, name='%s/bn_1x1conv_3' % prefix)(x_2)\n        x_2 = Activation('relu6')(x_2)\n\n        x = Concatenate(axis=bn_axis, name='%s/concat' % prefix)([x_1, x_2])\n\n    if strides == 1:\n        c_hat, c = channel_split(inputs, name='%s/split' % prefix)\n\n        c = Conv2D(filters=branch_channels, kernel_size=1, strides=1, padding='same',\n                   use_bias=False, name='%s/1x1conv_4' % prefix)(c)\n        # c = BatchNormalization(axis=bn_axis, name='%s/bn_1x1conv_4' % prefix)(c)\n        # c = Activation('relu6')(c)\n        c = DepthwiseConv2D(kernel_size=3, strides=1, padding='same',\n                            use_bias=False, name='%s/3x3dwconv_3' % prefix)(c)\n        c = BatchNormalization(axis=bn_axis, name='%s/bn_3x3dwconv_3' % prefix)(c)\n        # c = Activation('relu6')(c)\n        c = return_activation(c, nl)\n        # 引入注意力机制\n        if sq:\n            c = squeeze(c)\n        # 下降通道数\n        c = Conv2D(filters=branch_channels, kernel_size=1, strides=1, padding='same',\n                   use_bias=False, name='%s/1x1conv_5' % prefix)(c)\n        c = BatchNormalization(axis=bn_axis, name='%s/bn_1x1conv_4' % prefix)(c)\n        x = Concatenate(axis=bn_axis, name='%s/concat' % prefix)([c_hat, c])\n\n    x = Lambda(channel_shuffle, name='%s/channel_shuffle' % prefix)(x)\n\n    return x\n\n\ndef exblock(inputs, out_channels, sq, stage=1, block=1):\n    prefix = 'stage%d/block%d' % (stage, block)\n\n    residual = Conv2D(out_channels, (1, 1), strides=(2, 2), padding='same', use_bias=False)(inputs)\n    residual = BatchNormalization()(residual)\n\n    x = SeparableConv2D(out_channels, (3, 3), padding='same', use_bias=False, name='%s/_sepconv1' % prefix)(inputs)\n    x = BatchNormalization(name='%s/_sepconv1_bn' % prefix)(x)\n    x = Activation('hard_swish', name='%s/_sepconv2_ac_hs' % prefix)(x)\n    x = SeparableConv2D(out_channels, (3, 3), padding='same', use_bias=False, name='%s/_sepconv2' % prefix)(x)\n    # 引入注意力机制\n    if sq:\n        x = squeeze(x)\n\n    x = BatchNormalization(name='%s/_sepconv2_bn' % prefix)(x)\n\n    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same', name='%s/_pool' % prefix)(x)\n    x = layers.add([x, residual])\n\n    return x\n\n\ndef inception_unit(inputs, channel1, channel2, channel3, ):\n    branch_0 = Conv2D(channel1, (1, 1), strides=(1, 1), padding='same', use_bias=False)(inputs)\n    branch_0 = BatchNormalization(axis=-1, scale=False, name='stage1X1_1BN')(branch_0)\n    branch_0 = Activation('relu6', name='stage1X1_1ac')(branch_0)\n\n    branch_1 = Conv2D(channel2, (3, 3), strides=(1, 1), padding='same', use_bias=False)(inputs)\n    branch_1 = BatchNormalization(axis=-1, scale=False, name='stage3X3_1BN')(branch_1)\n    branch_1 = Activation('relu6', name='stage3X3_1ac')(branch_1)\n\n    branch_pool = AveragePooling2D(3, strides=1, padding='same')(inputs)\n    branch_pool = Conv2D(channel3, (1, 1), strides=(1, 1), padding='same', use_bias=False)(branch_pool)\n    branch_pool = BatchNormalization(axis=-1, scale=False, name='stagep1X1_1BN')(branch_pool)\n    branch_pool = Activation('relu6', name='stagep1X1_1ac')(branch_pool)\n\n    branches = [branch_0, branch_1, branch_pool]\n\n    x = Concatenate(name='mixed_5b')(branches)\n\n    return x\n\n\ndef qzynetnew(input_shape=[256, 256, 3], classes=2,target=1):\n    input_shape = [256, 256, 3]\n\n    img_input = Input(shape=input_shape)\n\n    x = Conv2D(32, (3, 3), strides=(1, 1), padding='same', use_bias=False)(img_input)\n    x = BatchNormalization(axis=-1, scale=False, name='stage0.1X1_1BN')(x)\n    x = Activation('relu6', name='stage0.1X1_1ac')(x)\n    x = Conv2D(64, (3, 3), strides=(2, 2), padding='same', use_bias=False)(x)\n    x = BatchNormalization(axis=-1, scale=False, name='stage00.1X1_1BN')(x)\n    x = Activation('relu6', name='stage00.1X1_1ac')(x)\n    x = MaxPooling2D(3, strides=1,padding='same')(x)#2\n    #   x=_shuffle_unit(x, 128, sq=False, nl='RE',strides=1, stage=2, block=1)\n    #   x=_shuffle_unit(x, 128, sq=False, nl='RE',strides=1, stage=2, block=2)\n\n    #   x=_shuffle_unit(x, 128, sq=False, nl='RE',strides=2, stage=2, block=3)#128,128,128 -> 64 x 64 x 128\n\n    #   x=_shuffle_unit(x, 128, sq=False, nl='RE',strides=1, stage=2, block=4)\n    #   x=_shuffle_unit(x, 128, sq=False, nl='RE',strides=1, stage=2, block=5)\n    f1=x\n    x = exblock(x, 128, sq=True, stage=1, block=1)\n    f2=x\n\n    x = exblock(x, 192, sq=True, stage=1, block=2)\n    # x=_shuffle_unit(x, 256, sq=False, nl='RE',strides=2, stage=2, block=6)#64,64,128 -> 32 x 32 x 256\n    x = inception_unit(x, 116, 116, 24)\n    x = _shuffle_unit(x, 256, sq=False, nl='RE', strides=1, stage=2, block=7)\n    x = _shuffle_unit(x, 256, sq=False, nl='RE', strides=1, stage=2, block=8)\n    f3= x\n\n    x = _shuffle_unit(x, 512, sq=False, nl='RE', strides=2, stage=2, block=9)  # 32,32,256 -> 16 x 16 x 512\n\n    x = _shuffle_unit(x, 512, sq=False, nl='RE', strides=1, stage=2, block=10)\n    x = _shuffle_unit(x, 512, sq=False, nl='RE', strides=1, stage=2, block=11)\n    x = _shuffle_unit(x, 512, sq=False, nl='RE', strides=1, stage=2, block=12)\n    f4= x\n\n    x = _shuffle_unit(x, 1024, sq=False, nl='RE', strides=2, stage=2, block=13)  # 16 x 16 x 512 -> 8 x 8 x 1024\n\n    x = _shuffle_unit(x, 1024, sq=False, nl='RE', strides=1, stage=2, block=14)\n    f5= x\n\n    if target == 1:\n         x = GlobalAveragePooling2D(name='global_max_pool')(x)\n         x = Dense(classes, name='fc')(x)\n         x = Activation('softmax')(x)\n\n         inputs = img_input\n    # 创建模型\n         model = Model(inputs, x, name='qzynet')\n         return model\n\n    if target == 2:\n         return img_input, [f1, f2, f3, f4, f5]\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing import image\nfrom keras.models import Model\nfrom keras import layers\nfrom keras.layers import Activation, AveragePooling2D, BatchNormalization, Concatenate\nfrom keras.layers import Conv2D, Dense, GlobalAveragePooling2D, GlobalMaxPooling2D, Input, Lambda, MaxPooling2D\nfrom keras.layers import SeparableConv2D, DepthwiseConv2D\nfrom keras.layers import Add, Multiply, Reshape\nfrom keras.layers import ZeroPadding2D, UpSampling2D, concatenate\nfrom keras.applications.imagenet_utils import decode_predictions\nfrom keras.utils.data_utils import get_file\nfrom keras import backend as K\n\n# from qzynetwork1 import qzynetnew\n\nIMAGE_ORDERING = 'channels_last'\nMERGE_AXIS = -1\n\ndef conv_block(tensor, num_filters, kernel_size, padding='same', strides=1, dilation_rate=1, w_init='he_normal'):\n    x = (Conv2D(filters=num_filters,\n                               kernel_size=kernel_size,\n                               padding=padding,\n                               strides=strides,\n                               dilation_rate=dilation_rate,\n                               kernel_initializer=w_init,\n                               use_bias=False))(tensor)\n    x = (BatchNormalization())(x)\n    x =  Activation('relu')(x)\n\n    return x\n\n\ndef sepconv_block(tensor, num_filters, kernel_size, padding='same', strides=1, dilation_rate=1, w_init='he_normal'):\n    x = (SeparableConv2D(filters=num_filters,\n                                        depth_multiplier=1,\n                                        kernel_size=kernel_size,\n                                        padding=padding,\n                                        strides=strides,\n                                        dilation_rate=dilation_rate,\n                                        depthwise_initializer=w_init,\n                                        use_bias=False))(tensor)\n    x =(BatchNormalization())(x)\n    x = Activation('relu')(x)\n    return x\n\n\n# def JPU(encoder=qzynetnew, out_channels=512):\n#     img_inputs, levels = encoder(input_shape=[256, 256, 3], classes=2,target=2)\n#     [f2, f3, f4, f5] = levels  # f5:8,f4:16,f3:32,f2:64\n#     #h=128\n#     #w=128\n#\n#     # yc = UpSampling2D(size=(2, 2), interpolation='bilinear')(yc)#得到128\n#     # for i in range(1, 4):\n#     #     levels[i] = conv_block(levels[i], out_channels, 3)\n#     #     if i != 1:\n#     #         h_t, w_t = levels[i].shape.as_list()[1:3]\n#     #         scale = (h // h_t, w // w_t)\n#     #         levels[i] = tf.keras.layers.UpSampling2D(\n#     #             size=scale, interpolation='bilinear')(levels[i])\n#     # yc = tf.keras.layers.Concatenate(axis=-1)(levels[1:])\n#     ym = []\n#     for rate in [1, 2]:\n#         ym.append(sepconv_block(yc, 512, 3, dilation_rate=rate))\n#     y = Concatenate(axis=-1)(ym)\n#\n#     y = conv_block(y, num_filters=128, kernel_size=1)\n#     # return  y\n#     model = Model(img_inputs,y,name='jpu')\n#\n#     return model\n\ndef _unet(n_classes=2, encoder=qzynetnew,  input_height=256, input_width=256):\n    img_input, levels = encoder(input_shape=[256, 256, 3], classes=2,target=2)\n    [f1, f2, f3, f4, f5] = levels#f5:8,f4:16,f3:32,f2:64\n\n    o = f5\n    # 8,8,512\n    o = (ZeroPadding2D((1, 1), data_format=IMAGE_ORDERING))(o)\n    o = (Conv2D(512, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(o)\n    o = (BatchNormalization())(o)\n\n    # 16,16,512\n    o = (UpSampling2D((2, 2), data_format=IMAGE_ORDERING))(o)\n    # 16,16,768\n    o = (concatenate([o, f4], axis=MERGE_AXIS))\n    o = (ZeroPadding2D((1, 1), data_format=IMAGE_ORDERING))(o)\n    # 16,16,256\n    o = (Conv2D(256, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(o)\n    o = (BatchNormalization())(o)\n\n    # 32,32,256\n    o = (UpSampling2D((2, 2), data_format=IMAGE_ORDERING))(o)\n    # 32,32,384\n    o = (concatenate([o, f3], axis=MERGE_AXIS))\n    o = (ZeroPadding2D((1, 1), data_format=IMAGE_ORDERING))(o)\n    # 32,32,128\n    o = (Conv2D(128, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(o)\n    o = (BatchNormalization())(o)\n    # 64,64,64\n    o = (UpSampling2D((2, 2), data_format=IMAGE_ORDERING))(o)\n\n    o = (concatenate([o, f2], axis=MERGE_AXIS))\n\n    o = (ZeroPadding2D((1, 1), data_format=IMAGE_ORDERING))(o)\n    o = (Conv2D(128, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(o)\n    o = (BatchNormalization())(o)\n\n    f5 = conv_block(f5, 96, 3)#8\n    f4 = conv_block(f4, 64, 3)#16\n    f3 = conv_block(f3, 32, 3)#32\n    f5 = UpSampling2D(size=(8, 8))(f5)\n    f4 = UpSampling2D(size=(4, 4))(f4)\n    f3 = UpSampling2D(size=(2, 2))(f3)\n    yc = Concatenate(axis=-1)([f3,f4,f5])\n    ym = []\n    for rate in [1, 2]:\n        ym.append(sepconv_block(yc, 64, 3, dilation_rate=rate))\n    y = Concatenate(axis=-1)(ym)\n    y = conv_block(y, num_filters=64, kernel_size=1)\n\n    z = concatenate([o, y])\n    z = (Conv2D(64, (3, 3), padding='same'))(z)#得到64*64*32\n    z = (BatchNormalization())(z)\n\n    z = UpSampling2D(size=(2,2))(z)\n\n    \n    z = (concatenate([z, f1], axis=MERGE_AXIS))\n    z = (ZeroPadding2D((1, 1), data_format=IMAGE_ORDERING))(z)\n    z = (Conv2D(32, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(z)\n    z = (BatchNormalization())(z)\n    z = (UpSampling2D((2, 2), data_format=IMAGE_ORDERING))(z)\n    \n    z = (Conv2D(1, (1, 1), padding='same'))(z)\n    z = Activation('sigmoid')(z)\n    model = Model(input=img_input, output=z, name='jpu_unet')\n\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# from keras import models, layers\n# # Build U-Net model\n# def upsample_conv(filters, kernel_size, strides, padding):\n#     return layers.Conv2DTranspose(filters, kernel_size, strides=strides, padding=padding)\n# def upsample_simple(filters, kernel_size, strides, padding):\n#     return layers.UpSampling2D(strides)\n\n# if UPSAMPLE_MODE=='DECONV':\n#     upsample=upsample_conv\n# else:\n#     upsample=upsample_simple\n    \n# input_img = layers.Input(t_x.shape[1:], name = 'RGB_Input')\n# pp_in_layer = input_img\n\n# if NET_SCALING is not None:\n#     pp_in_layer = layers.AvgPool2D(NET_SCALING)(pp_in_layer)\n    \n# pp_in_layer = layers.GaussianNoise(GAUSSIAN_NOISE)(pp_in_layer)\n# pp_in_layer = layers.BatchNormalization()(pp_in_layer)\n\n# c1 = layers.Conv2D(8, (3, 3), activation='relu', padding='same') (pp_in_layer)\n# c1 = layers.Conv2D(8, (3, 3), activation='relu', padding='same') (c1)\n# p1 = layers.MaxPooling2D((2, 2)) (c1)\n\n# c2 = layers.Conv2D(16, (3, 3), activation='relu', padding='same') (p1)\n# c2 = layers.Conv2D(16, (3, 3), activation='relu', padding='same') (c2)\n# p2 = layers.MaxPooling2D((2, 2)) (c2)\n\n# c3 = layers.Conv2D(32, (3, 3), activation='relu', padding='same') (p2)\n# c3 = layers.Conv2D(32, (3, 3), activation='relu', padding='same') (c3)\n# p3 = layers.MaxPooling2D((2, 2)) (c3)\n\n# c4 = layers.Conv2D(64, (3, 3), activation='relu', padding='same') (p3)\n# c4 = layers.Conv2D(64, (3, 3), activation='relu', padding='same') (c4)\n# p4 = layers.MaxPooling2D(pool_size=(2, 2)) (c4)\n\n\n# c5 = layers.Conv2D(128, (3, 3), activation='relu', padding='same') (p4)\n# c5 = layers.Conv2D(128, (3, 3), activation='relu', padding='same') (c5)\n\n# u6 = upsample(64, (2, 2), strides=(2, 2), padding='same') (c5)\n# u6 = layers.concatenate([u6, c4])\n# c6 = layers.Conv2D(64, (3, 3), activation='relu', padding='same') (u6)\n# c6 = layers.Conv2D(64, (3, 3), activation='relu', padding='same') (c6)\n\n# u7 = upsample(32, (2, 2), strides=(2, 2), padding='same') (c6)\n# u7 = layers.concatenate([u7, c3])\n# c7 = layers.Conv2D(32, (3, 3), activation='relu', padding='same') (u7)\n# c7 = layers.Conv2D(32, (3, 3), activation='relu', padding='same') (c7)\n\n# u8 = upsample(16, (2, 2), strides=(2, 2), padding='same') (c7)\n# u8 = layers.concatenate([u8, c2])\n# c8 = layers.Conv2D(16, (3, 3), activation='relu', padding='same') (u8)\n# c8 = layers.Conv2D(16, (3, 3), activation='relu', padding='same') (c8)\n\n# u9 = upsample(8, (2, 2), strides=(2, 2), padding='same') (c8)\n# u9 = layers.concatenate([u9, c1], axis=3)\n# c9 = layers.Conv2D(8, (3, 3), activation='relu', padding='same') (u9)\n# c9 = layers.Conv2D(8, (3, 3), activation='relu', padding='same') (c9)\n\n# d = layers.Conv2D(1, (1, 1), activation='sigmoid') (c9)\n# # d = layers.Cropping2D((EDGE_CROP, EDGE_CROP))(d)\n# # d = layers.ZeroPadding2D((EDGE_CROP, EDGE_CROP))(d)\n# if NET_SCALING is not None:\n#     d = layers.UpSampling2D(NET_SCALING)(d)\n\n# seg_model = models.Model(inputs=[input_img], outputs=[d])\n# seg_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"seg_model=_unet()\nseg_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1678069aa8013510264ba898291c6ae2dce88a76"},"cell_type":"code","source":"import keras.backend as K\nfrom keras.optimizers import Adam\nfrom keras.losses import binary_crossentropy\n\n\n\ndef IoU(y_true, y_pred, eps=1e-6):\n    intersection = K.sum(y_true * y_pred, axis=[1,2,3])\n    union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3]) - intersection\n    return K.mean( (intersection + eps) / (union + eps), axis=0)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def dice_coef(y_true, y_pred):\n    y_true_f = K.flatten(y_true)\n    y_pred = K.cast(y_pred, 'float32')\n    y_pred_f = K.cast(K.greater(K.flatten(y_pred), 0.5), 'float32')\n    intersection = y_true_f * y_pred_f\n    score = 2. * K.sum(intersection) / (K.sum(y_true_f) + K.sum(y_pred_f))\n    return score\n\ndef dice_loss(y_true, y_pred):\n    smooth = 1.\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n    intersection = y_true_f * y_pred_f\n    score = (2. * K.sum(intersection) + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n    return 1. - score\n\ndef bce_dice_loss(y_true, y_pred):\n    return binary_crossentropy(y_true, y_pred) + dice_loss(y_true, y_pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def tversky(y_true, y_pred):\n    smooth=1\n    y_true_pos = K.flatten(y_true)\n    y_pred_pos = K.flatten(y_pred)\n    true_pos = K.sum(y_true_pos * y_pred_pos)\n    false_neg = K.sum(y_true_pos * (1-y_pred_pos))\n    false_pos = K.sum((1-y_true_pos)*y_pred_pos)\n    alpha = 0.7\n    return (true_pos + smooth)/(true_pos + alpha*false_neg + (1-alpha)*false_pos + smooth)\n\ndef tversky_loss(y_true, y_pred):\n    return 1 - tversky(y_true,y_pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7282d18de3aff1cee12ff89b7d511a391702814f"},"cell_type":"code","source":"from keras.callbacks import ModelCheckpoint, LearningRateScheduler, EarlyStopping, ReduceLROnPlateau\nweight_path=\"{}_weights.best.hdf5\".format('seg_model')\n\ncheckpoint = ModelCheckpoint(weight_path, monitor='val_loss', verbose=1, save_best_only=True, mode='min', save_weights_only=True)\n#weight_path保存模型的路径，monitor：需要监视的值，verbose：信息展示模式，save_best_only：当设置为True时，监测值有改进时才会保存当前的模型\n#save_weights_only：若设置为True，则只保存模型权重，否则将保存整个模型（包括模型结构，配置信息等）\nreduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.33,\n                                   patience=1, verbose=1, mode='min',\n                                   min_delta=0.0001, cooldown=0, min_lr=1e-8)\n\n#当指标停止提升时，降低学习速率。\n#monitor：要监测的数量。patience：没有提升的epoch数，之后学习率将降低。verbose：int。0：安静，1：更新消息。\n#mode：{auto，min，max}之一。在min模式下，当监测量停止下降时，lr将减少；在max模式下，当监测数量停止增加时，它将减少；\n#在auto模式下，从监测数量的名称自动推断方向。\n#min_delta：对于测量新的最优化的阀值，仅关注重大变化。\n#cooldown：在学习速率被降低之后，重新恢复正常操作之前等待的epoch数量。\n#min_lr：学习率的下限。\n\n\nearly = EarlyStopping(monitor=\"val_loss\", mode=\"min\", verbose=2,\n                      patience=20) # probably needs to be more patient, but kaggle time is limited\n#目的：防止过拟合\n#monitor: 需要监视的量，val_loss，val_acc\n#patience: 当early stop被激活(如发现loss相比上一个epoch训练没有下降)，则经过patience个epoch后停止训练\n#verbose: 信息展示模式\n#mode: 'auto','min','max'之一，在min模式训练，如果检测值停止下降则终止训练。在max模式下，当检测值不再上升的时候则停止训练。\n\ncallbacks_list = [checkpoint, early, reduceLROnPlat]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MAX_TRAIN_EPOCHS=10\nBATCH_SIZE=50\nMAX_TRAIN_STEPS=300","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5b67d808c0b8c7e28bff41e6d3858ff6f09dd626","scrolled":false},"cell_type":"code","source":"# def fit():\n# with strategy.scope():\n#     seg_model.compile(optimizer=Adam(1e-3, decay=1e-6), loss=tversky_loss, metrics=[IoU,dice_coef,'binary_accuracy'])\n    \n#     step_count = min(MAX_TRAIN_STEPS, train_df.shape[0]//BATCH_SIZE)\n#     aug_gen = create_aug_gen(make_image_gen(train_df))\n#     loss_history = [seg_model.fit_generator(aug_gen,\n#                                  steps_per_epoch=step_count,\n#                                  epochs=MAX_TRAIN_EPOCHS,\n#                                  validation_data=(valid_x, valid_y),\n#                                  callbacks=callbacks_list,\n#                                 workers=1 # the generator is not very thread safe\n#                                            )]\n#     return loss_history\n\n# while True:\n#     loss_history = fit()\n#     if np.min([mh.history['val_loss'] for mh in loss_history]) < 0.01:\n#         break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with strategy.scope():\n     seg_model.compile(optimizer=Adam(1e-2, decay=1e-6), loss=tversky_loss, metrics=[IoU,dice_coef,'binary_accuracy'])#tversky_loss\n\nstep_count = min(MAX_TRAIN_STEPS, train_df.shape[0]//BATCH_SIZE)\naug_gen = create_aug_gen(make_image_gen(train_df))\nloss_history = [seg_model.fit_generator(aug_gen,\n                                 steps_per_epoch=step_count,\n                                 epochs=MAX_TRAIN_EPOCHS,\n                                 validation_data=(valid_x, valid_y),\n                                 callbacks=callbacks_list,\n                                workers=1 # the generator is not very thread safe\n                                           )]\n#     return loss_history\n\n# while True:\n#     loss_history = fit()\n#     if np.min([mh.history['val_loss'] for mh in loss_history]) < 0.01:\n#         break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a168c8b1af446b800f6129104906003ededd61c4"},"cell_type":"code","source":"def show_loss(loss_history):\n    epochs = np.concatenate([mh.epoch for mh in loss_history])\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(22, 10))\n    \n    _ = ax1.plot(epochs, np.concatenate([mh.history['loss'] for mh in loss_history]), 'b-',\n                 epochs, np.concatenate([mh.history['val_loss'] for mh in loss_history]), 'r-')\n    ax1.legend(['Training', 'Validation'])\n    ax1.set_title('Loss')\n    \n    _ = ax2.plot(epochs, np.concatenate([mh.history['binary_accuracy'] for mh in loss_history]), 'b-',\n                 epochs, np.concatenate([mh.history['val_binary_accuracy'] for mh in loss_history]), 'r-')\n    ax2.legend(['Training', 'Validation'])\n    ax2.set_title('Binary Accuracy (%)')\n\nshow_loss(loss_history)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ce1167e9f09200f537e61f93f486168a13be1711"},"cell_type":"code","source":"seg_model.load_weights(weight_path)\nseg_model.save_weights('seg_model111.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"275b411dc97a350aacaba46c8562efcf2658b1a7"},"cell_type":"code","source":"pred_y = seg_model.predict(valid_x)\nprint(pred_y.shape, pred_y.min(axis=0).max(), pred_y.max(axis=0).min(), pred_y.mean())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6a4fd2ca0cf47ba069a314356bf74c7b531c56ac"},"cell_type":"code","source":"fig, ax = plt.subplots(1, 1, figsize = (6, 6))\nax.hist(pred_y.ravel(), np.linspace(0, 1, 20))\nax.set_xlim(0, 1)\nax.set_yscale('log', nonposy='clip')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0018ab172d18936f8cc2c5df33d2f840dc16bf4f"},"cell_type":"markdown","source":"# Prepare Full Resolution Model\nHere we account for the scaling so everything can happen in the model itself\n#准备全分辨率模型\n#在这里，我们考虑了缩放，这样模型本身就可以发生任何事情"},{"metadata":{"_uuid":"17edb177402ae51651692511827a7e9d60646533"},"cell_type":"markdown","source":"# Visualize predictions\n#可视化预测"},{"metadata":{"trusted":true},"cell_type":"code","source":"def predict(img, path=test_image_dir):\n    c_img = imread(os.path.join(path, c_img_name))\n    c_img = c_img[::IMG_SCALING[0], ::IMG_SCALING[1]]\n    c_img = np.expand_dims(c_img, 0)/255.0\n    \n    cur_seg = seg_model.predict(c_img)[0]\n    cur_seg = binary_opening(cur_seg>1e3, np.expand_dims(disk(2), -1))\n    return cur_seg, c_img\n\ndef pred_encode(img):\n    cur_seg, _ = predict(img)\n    cur_rles = rle_encode(cur_seg)\n    return [img, cur_rles if len(cur_rles) > 0 else None]\n\n## Get a sample of each group of ship count\nsamples = train_df.groupby('ships').apply(lambda x: x.sample(2))#1\n\nfig, m_axs = plt.subplots(samples.shape[0], 3, figsize = (11, samples.shape[0]*4))\n[c_ax.axis('off') for c_ax in m_axs.flatten()]\n\nfor (ax1, ax2, ax3), c_img_name in zip(m_axs, samples.ImageId.values):\n    first_seg, first_img = predict(c_img_name, train_image_dir)\n    ax1.imshow(first_img[0])\n    ax1.set_title('Image')\n    ax2.imshow(first_seg[:, :, 0])\n    ax2.set_title('Prediction')\n    ground_truth = masks_as_color(masks.query('ImageId==\"{}\"'.format(c_img_name))['EncodedPixels'])\n    ax3.imshow(ground_truth)\n    ax3.set_title('Ground Truth')\n    \nfig.savefig('predictions.png')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":4}