{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.8.17","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"This notebook tries to run the aux loss model explained in the discussion [Easy Trick to Add Aux Loss](https://www.kaggle.com/c/siim-covid19-detection/discussion/263676).","metadata":{}},{"cell_type":"code","source":"%env SM_FRAMEWORK=tf.keras\n!pip install -U segmentation-models","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:18:38.125738Z","iopub.execute_input":"2023-09-05T14:18:38.126038Z","iopub.status.idle":"2023-09-05T14:18:47.714822Z","shell.execute_reply.started":"2023-09-05T14:18:38.126012Z","shell.execute_reply":"2023-09-05T14:18:47.713668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DEBUG = False","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:18:47.716676Z","iopub.execute_input":"2023-09-05T14:18:47.716960Z","iopub.status.idle":"2023-09-05T14:18:47.721405Z","shell.execute_reply.started":"2023-09-05T14:18:47.716931Z","shell.execute_reply":"2023-09-05T14:18:47.720659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport tensorflow as tf\nimport tensorflow.keras.layers as L\nimport matplotlib.pyplot as plt\nfrom kaggle_datasets import KaggleDatasets\nimport math\nimport pandas as pd\nimport tensorflow_addons as tfa\nimport segmentation_models as sm\n\nprint(tf.__version__)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-09-05T14:18:47.722364Z","iopub.execute_input":"2023-09-05T14:18:47.722638Z","iopub.status.idle":"2023-09-05T14:19:30.114753Z","shell.execute_reply.started":"2023-09-05T14:18:47.722613Z","shell.execute_reply":"2023-09-05T14:19:30.113730Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SEG_MODEL = sm.FPN\nBACKBONE = 'efficientnetb4'\nIMAGE_SIZE = 512\nBATCH_SIZE = 128\nINIT_LR = 1e-4\nWARMUP_EPO = 2\nCOSINE_EPO = 28 if not DEBUG else 2\nN_EPOCHS = WARMUP_EPO + COSINE_EPO\nN_FOLDS = 5\n\nVID = 'V03'\n# FOLD_I_LIST = [0, 1, 2, 3, 4]\nFOLD_I_LIST = [0]\nFOLD_I_LIST = FOLD_I_LIST[ :1 ] if DEBUG else FOLD_I_LIST","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:30.117079Z","iopub.execute_input":"2023-09-05T14:19:30.117637Z","iopub.status.idle":"2023-09-05T14:19:30.124129Z","shell.execute_reply.started":"2023-09-05T14:19:30.117606Z","shell.execute_reply":"2023-09-05T14:19:30.123206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data_name = 'siim-covid19-tfrecord-for-training'\nMAX_BBOXES = 8\nN_STUDY_LABELS = 4","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:30.125174Z","iopub.execute_input":"2023-09-05T14:19:30.125459Z","iopub.status.idle":"2023-09-05T14:19:30.142421Z","shell.execute_reply.started":"2023-09-05T14:19:30.125419Z","shell.execute_reply":"2023-09-05T14:19:30.141620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TPU","metadata":{}},{"cell_type":"code","source":"try:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect() \n    strategy = tf.distribute.TPUStrategy(tpu)\nexcept ValueError: # otherwise detect GPUs\n    strategy = tf.distribute.MirroredStrategy() # single-GPU or multi-GPU\n    \nprint(f\"Running on {strategy.num_replicas_in_sync} replicas\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:30.143526Z","iopub.execute_input":"2023-09-05T14:19:30.143819Z","iopub.status.idle":"2023-09-05T14:19:37.879673Z","shell.execute_reply.started":"2023-09-05T14:19:30.143792Z","shell.execute_reply":"2023-09-05T14:19:37.878770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"GCS_DS_PATH = KaggleDatasets().get_gcs_path(train_data_name)\n\nGCS_DS_PATH","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:37.880781Z","iopub.execute_input":"2023-09-05T14:19:37.881053Z","iopub.status.idle":"2023-09-05T14:19:37.890908Z","shell.execute_reply.started":"2023-09-05T14:19:37.881028Z","shell.execute_reply":"2023-09-05T14:19:37.890068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset","metadata":{}},{"cell_type":"code","source":"def decode_image(image_bytes):\n    image = tf.image.decode_jpeg(image_bytes, channels=3)\n    image = tf.reshape(image, [IMAGE_SIZE, IMAGE_SIZE, 3])\n    return image\n\ndef read_tfrecord(example):\n    TFREC_FORMAT = {\n        'image_id': tf.io.FixedLenFeature([], tf.string),\n        'study_id': tf.io.FixedLenFeature([], tf.string),\n        'fold': tf.io.FixedLenFeature([], tf.int64),\n        'image': tf.io.FixedLenFeature([], tf.string),\n        'xray_height': tf.io.FixedLenFeature([], tf.int64),\n        'xray_width': tf.io.FixedLenFeature([], tf.int64),\n        'bbox_label': tf.io.FixedLenFeature([MAX_BBOXES], tf.string),\n        'confidence': tf.io.FixedLenFeature([MAX_BBOXES], tf.float32),\n        'left': tf.io.FixedLenFeature([MAX_BBOXES], tf.float32),\n        'top': tf.io.FixedLenFeature([MAX_BBOXES], tf.float32),\n        'right': tf.io.FixedLenFeature([MAX_BBOXES], tf.float32),\n        'bottom': tf.io.FixedLenFeature([MAX_BBOXES], tf.float32),\n        'Negative for Pneumonia': tf.io.FixedLenFeature([], tf.int64),\n        'Typical Appearance': tf.io.FixedLenFeature([], tf.int64),\n        'Indeterminate Appearance': tf.io.FixedLenFeature([], tf.int64),\n        'Atypical Appearance': tf.io.FixedLenFeature([], tf.int64),\n    }\n    \n    example = tf.io.parse_single_example(example, TFREC_FORMAT)\n    ids = [example['image_id'], example['study_id']]\n    fold = example['fold']\n    image = decode_image(example['image'])\n    bbox_label = example['bbox_label']\n\n    xray_height = tf.cast(example['xray_height'], dtype=tf.float32)\n    xray_width = tf.cast(example['xray_width'], dtype=tf.float32)\n    def _calc_bbox_pos(example_pos, xray_size):\n        pos = example_pos * IMAGE_SIZE / xray_size\n        pos = tf.cast(tf.math.round(pos), dtype=tf.int64)\n        pos = tf.clip_by_value(pos, 0, IMAGE_SIZE - 1)\n        return pos\n    left = _calc_bbox_pos(example['left'], xray_width)\n    top = _calc_bbox_pos(example['top'], xray_height)\n    right = _calc_bbox_pos(example['right'], xray_width)\n    bottom = _calc_bbox_pos(example['bottom'], xray_height)\n    bbox_pos = [left, top, right, bottom]\n\n    study_label = [\n        example['Negative for Pneumonia'], example['Typical Appearance'],\n        example['Indeterminate Appearance'], example['Atypical Appearance']]\n    return ids, fold, image, bbox_label, bbox_pos, study_label","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:37.891956Z","iopub.execute_input":"2023-09-05T14:19:37.892228Z","iopub.status.idle":"2023-09-05T14:19:37.911254Z","shell.execute_reply.started":"2023-09-05T14:19:37.892204Z","shell.execute_reply":"2023-09-05T14:19:37.910383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"opacity_label = tf.constant(\"opacity\".encode('utf-8'))\n\ndef process_bbox(ids, fold, image, bbox_label, bbox_pos, study_label):\n    # opacity => 1.0, none => 0.0\n    bbox_label = tf.cast(\n        bbox_label == opacity_label, dtype=tf.float32)\n    return ids, fold, image, bbox_label, bbox_pos, study_label","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:37.912275Z","iopub.execute_input":"2023-09-05T14:19:37.912655Z","iopub.status.idle":"2023-09-05T14:19:37.927713Z","shell.execute_reply.started":"2023-09-05T14:19:37.912628Z","shell.execute_reply":"2023-09-05T14:19:37.926913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_mask(ids, fold, image, bbox_label, bbox_pos, study_label):\n    lefts   = bbox_pos[0]\n    tops    = bbox_pos[1]\n    rights  = bbox_pos[2]\n    bottoms = bbox_pos[3]\n\n    def _make_one_mask(i):\n        mask_height = bottoms[i] - tops[i] + 1\n        mask_width = rights[i] - lefts[i] + 1\n        mask_shape = [mask_height, mask_width]\n        mask = bbox_label[i] * tf.ones(mask_shape, dtype=tf.float32)\n\n        paddings = [\n            [tops[i], IMAGE_SIZE - bottoms[i] - 1],\n            [lefts[i], IMAGE_SIZE - rights[i] - 1]]\n        mask = tf.pad(mask, paddings, mode='CONSTANT')\n        return mask\n\n    num_masks_rng = tf.range(MAX_BBOXES, dtype=tf.int64)\n    masks = tf.map_fn(\n        _make_one_mask, num_masks_rng,\n        fn_output_signature=tf.float32)\n    mask = tf.math.reduce_sum(masks, axis=0)\n    mask = tf.math.minimum(1.0, mask)\n    mask = tf.reshape(mask, [IMAGE_SIZE, IMAGE_SIZE, 1])\n    return ids, fold, image, mask, study_label","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:37.931137Z","iopub.execute_input":"2023-09-05T14:19:37.931408Z","iopub.status.idle":"2023-09-05T14:19:37.941774Z","shell.execute_reply.started":"2023-09-05T14:19:37.931384Z","shell.execute_reply":"2023-09-05T14:19:37.940949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dataset(filenames):\n    dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=None)\n    dataset = dataset.map(read_tfrecord, num_parallel_calls=None)\n    dataset = dataset.map(process_bbox, num_parallel_calls=None)\n    dataset = dataset.map(make_mask, num_parallel_calls=None)\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:37.942768Z","iopub.execute_input":"2023-09-05T14:19:37.943070Z","iopub.status.idle":"2023-09-05T14:19:37.956197Z","shell.execute_reply.started":"2023-09-05T14:19:37.943044Z","shell.execute_reply":"2023-09-05T14:19:37.955365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tfrec_file_names = sorted(tf.io.gfile.glob(GCS_DS_PATH + '/*.tfrec'))\ntfrec_file_names = \\\n    [ tfrec_file_names[ :4 ] ] if DEBUG else tfrec_file_names\nraw_ds = load_dataset(tfrec_file_names)\n\nprint(raw_ds)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:37.957282Z","iopub.execute_input":"2023-09-05T14:19:37.957575Z","iopub.status.idle":"2023-09-05T14:19:38.897416Z","shell.execute_reply.started":"2023-09-05T14:19:37.957550Z","shell.execute_reply":"2023-09-05T14:19:38.896443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Fold Information","metadata":{}},{"cell_type":"code","source":"study_id_list = []\nfold_batch_list = []\nfor ids_batch, fold_batch, _, _, _ in raw_ds.batch(256):\n    print('.', end='', flush=True)\n    study_id_bin_array = ids_batch[ :, 1].numpy()\n    for study_id_bin in study_id_bin_array:\n        study_id_str = study_id_bin.decode('utf-8')\n        study_id_list.append(study_id_str)\n    fold_batch_list.append(fold_batch.numpy())\n\nprint()\nfold_array = np.concatenate(fold_batch_list, axis=0)\nfold_info_df = pd.DataFrame({\n    'study_id': study_id_list,\n    'fold': fold_array })\n\nfold_info_df","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:38.898574Z","iopub.execute_input":"2023-09-05T14:19:38.898869Z","iopub.status.idle":"2023-09-05T14:19:46.926935Z","shell.execute_reply.started":"2023-09-05T14:19:38.898843Z","shell.execute_reply":"2023-09-05T14:19:46.925842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fold_info_df['fold'].value_counts().sort_index()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:46.928103Z","iopub.execute_input":"2023-09-05T14:19:46.928479Z","iopub.status.idle":"2023-09-05T14:19:46.936321Z","shell.execute_reply.started":"2023-09-05T14:19:46.928451Z","shell.execute_reply":"2023-09-05T14:19:46.935374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_train_count(fold_i):\n    return sum(fold_info_df['fold'] != fold_i)\n\ndef get_val_count(fold_i):\n    return sum(fold_info_df['fold'] == fold_i)\n\ndef get_val_study_ids(fold_i):\n    fold_mask = (fold_info_df['fold'] == fold_i)\n    val_study_ids = fold_info_df.loc[fold_mask, 'study_id']\n    return val_study_ids.values","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:46.937413Z","iopub.execute_input":"2023-09-05T14:19:46.937707Z","iopub.status.idle":"2023-09-05T14:19:46.955310Z","shell.execute_reply.started":"2023-09-05T14:19:46.937681Z","shell.execute_reply":"2023-09-05T14:19:46.954368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Augmentation","metadata":{}},{"cell_type":"code","source":"def image_to_float_0_1(image):\n    image = tf.cast(image, dtype=tf.float32) / 255.0\n    return image","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:46.956498Z","iopub.execute_input":"2023-09-05T14:19:46.956857Z","iopub.status.idle":"2023-09-05T14:19:46.965580Z","shell.execute_reply.started":"2023-09-05T14:19:46.956831Z","shell.execute_reply":"2023-09-05T14:19:46.964611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def check_aug(aug_fun, with_mask):\n    rows = 2\n    cols = 5\n    n_imgs = rows * cols\n\n    _, _, images, masks, _ = next(iter(\n        raw_ds.take(1).repeat(n_imgs).batch(n_imgs)))\n    images = image_to_float_0_1(images)\n    \n    plt.figure(figsize=(12, 4))\n    aug_images, aug_masks = aug_fun(images, masks)\n    for i, aug_image in enumerate(aug_images):\n        plt.subplot(rows, cols, i+1)\n        plt.imshow(aug_image)\n        plt.axis(\"off\")\n    plt.tight_layout()\n    plt.show()        \n    \n    if with_mask:\n        plt.figure(figsize=(12, 4))\n        for i, aug_mask in enumerate(aug_masks):\n            plt.subplot(rows, cols, i+1)\n            plt.imshow(aug_mask, cmap='gray')\n            plt.axis(\"off\")\n        plt.tight_layout()\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:46.966696Z","iopub.execute_input":"2023-09-05T14:19:46.966968Z","iopub.status.idle":"2023-09-05T14:19:46.977719Z","shell.execute_reply.started":"2023-09-05T14:19:46.966944Z","shell.execute_reply":"2023-09-05T14:19:46.976882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def random_int(shape=[], minval=0, maxval=1):\n    return tf.random.uniform(\n        shape=shape, minval=minval, maxval=maxval, dtype=tf.int32)\n\ndef random_float(shape=[], minval=0.0, maxval=1.0):\n    rnd = tf.random.uniform(\n        shape=shape, minval=minval, maxval=maxval, dtype=tf.float32)\n    return rnd","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:46.978722Z","iopub.execute_input":"2023-09-05T14:19:46.978993Z","iopub.status.idle":"2023-09-05T14:19:46.988389Z","shell.execute_reply.started":"2023-09-05T14:19:46.978969Z","shell.execute_reply":"2023-09-05T14:19:46.987590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BaseAug():\n    def __init__(self, p):\n        self.p = p\n        \n    def __call__(self, images, masks):\n        def _aug_one_data(i):\n            image = images[i]\n            mask = masks[i]\n            rnd = random_float()\n            return tf.cond(\n                rnd <= self.p, \n                lambda: self.aug_data(image, mask),\n                lambda: self._no_aug(image, mask))\n        \n        batch = tf.shape(images)[0]\n        batch_rng = tf.range(batch, dtype=tf.int64)\n        aug_images, aug_masks = tf.map_fn(\n            _aug_one_data, batch_rng,\n            fn_output_signature=(tf.float32, tf.float32))\n        return aug_images, aug_masks\n\n    def aug_data(self, image, mask):\n        raise NotImplemented(\"aug_data() needs to implement\")\n        \n    def _no_aug(self, image, mask):\n        return image, mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:46.989443Z","iopub.execute_input":"2023-09-05T14:19:46.989776Z","iopub.status.idle":"2023-09-05T14:19:47.000234Z","shell.execute_reply.started":"2023-09-05T14:19:46.989749Z","shell.execute_reply":"2023-09-05T14:19:46.999462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def mirror_boundary(v, max_v):\n    # v % (max_v*2.0-2.0) ==> v % (512*2-2) ==> [0..1022]\n    # [0..1022] - (max_v-1.0) ==> [0..1022] - 511 ==> [-511..511]\n    # -1.0 * abs([-511..511]) ==> [-511..0]\n    # [-511..0] + max_v - 1.0 ==> [-511..0] + 511 ==> [0..511]\n    mirror_v = -1.0 * tf.math.abs(\n        v % (max_v*2.0-2.0) - (max_v-1.0)) + max_v-1.0\n    return mirror_v\n\ndef clip_boundary(v, max_v):\n    clip_v = tf.clip_by_value(v, 0.0, max_v-1.0)\n    return clip_v\n\ndef interpolate_bilinear(image, map_x, map_y):\n    def _gather(image, map_x, map_y):\n        map_stack = tf.stack([map_x, map_y]) # [ 2, height, width ]\n        map_indices = tf.transpose(\n            map_stack, perm=[1, 2, 0])       # [ height, width, 2 ]\n        map_indices = tf.cast(map_indices, dtype=tf.int32)\n        gather_image = tf.gather_nd(image, map_indices)\n        return gather_image\n    \n    ll = _gather(image, tf.math.floor(map_x), tf.math.floor(map_y))\n    lr = _gather(image, tf.math.ceil(map_x), tf.math.floor(map_y))\n    ul = _gather(image, tf.math.floor(map_x), tf.math.ceil(map_y))\n    ur = _gather(image, tf.math.ceil(map_x), tf.math.ceil(map_y))\n    \n    fraction_x = tf.expand_dims(map_x % 1.0, axis=-1) # [h, w, 1]\n    int_l = (lr - ll) * fraction_x + ll\n    int_u = (ur - ul) * fraction_x + ul\n    \n    fraction_y = tf.expand_dims(map_y % 1.0, axis=-1) # [h, w, 1]\n    interpolate_image = (int_u - int_l) * fraction_y + int_l\n    return interpolate_image\n\ndef remap(image, height, width, map_x, map_y, mode):\n    assert \\\n        mode in ('mirror', 'constant'), \\\n        \"mode is neither 'mirror' nor 'constant'\"\n\n    height_f = tf.cast(height, dtype=tf.float32)\n    width_f = tf.cast(width, dtype=tf.float32)\n    map_x = tf.reshape(map_x, shape=[height, width])\n    map_y = tf.reshape(map_y, shape=[height, width])\n    if mode == 'mirror':\n        b_map_x = mirror_boundary(map_x, width_f)\n        b_map_y = mirror_boundary(map_y, height_f)\n    else:\n        b_map_x = clip_boundary(map_x, width_f)\n        b_map_y = clip_boundary(map_y, height_f)\n        \n    image_remap = interpolate_bilinear(image, b_map_x, b_map_y)\n    \n    if mode == 'constant':\n        map_stack = tf.stack([map_x, map_y])\n        map_indices = tf.transpose(map_stack, perm=[1, 2, 0])\n        x_ge_0 = (0.0 <= map_indices[ : , : , 0])    # [h, w]\n        x_lt_w = (map_indices[ : , : , 0] < width_f)\n        y_ge_0 = (0.0 <= map_indices[ : , : , 1])\n        y_lt_h = (map_indices[ : , : , 1] < height_f)\n        inside_boundary = tf.math.reduce_all(\n            tf.stack([x_ge_0, x_lt_w, y_ge_0, y_lt_h]), axis=0) # [h, w]\n        inside_boundary = inside_boundary[ : , : , tf.newaxis]  # [h, w, 1]\n        image_remap = tf.where(inside_boundary, image_remap, 0.0)\n\n    return image_remap","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:47.001355Z","iopub.execute_input":"2023-09-05T14:19:47.001656Z","iopub.status.idle":"2023-09-05T14:19:47.022567Z","shell.execute_reply.started":"2023-09-05T14:19:47.001631Z","shell.execute_reply":"2023-09-05T14:19:47.021708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Transpose","metadata":{}},{"cell_type":"code","source":"class Transpose(BaseAug):\n    def __init__(self, p):\n        super(Transpose, self).__init__(p)\n        \n    def aug_data(self, image, mask):\n        aug_image = tf.transpose(image, perm=[1, 0, 2])\n        aug_mask = tf.transpose(mask, perm=[1, 0, 2])\n        return aug_image, aug_mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:47.023653Z","iopub.execute_input":"2023-09-05T14:19:47.023924Z","iopub.status.idle":"2023-09-05T14:19:47.037716Z","shell.execute_reply.started":"2023-09-05T14:19:47.023900Z","shell.execute_reply":"2023-09-05T14:19:47.036834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transpose = Transpose(p=0.5)\ncheck_aug(transpose, with_mask=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:47.038723Z","iopub.execute_input":"2023-09-05T14:19:47.038994Z","iopub.status.idle":"2023-09-05T14:19:49.204473Z","shell.execute_reply.started":"2023-09-05T14:19:47.038970Z","shell.execute_reply":"2023-09-05T14:19:49.203323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### VerticalFlip","metadata":{}},{"cell_type":"code","source":"class VerticalFlip(BaseAug):\n    def __init__(self, p):\n        super(VerticalFlip, self).__init__(p)\n        \n    def aug_data(self, image, mask):\n        aug_image = tf.image.flip_up_down(image)\n        aug_mask = tf.image.flip_up_down(mask)\n        return aug_image, aug_mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:49.205758Z","iopub.execute_input":"2023-09-05T14:19:49.206093Z","iopub.status.idle":"2023-09-05T14:19:49.211891Z","shell.execute_reply.started":"2023-09-05T14:19:49.206064Z","shell.execute_reply":"2023-09-05T14:19:49.211037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vertical_flip = VerticalFlip(p=0.5)\ncheck_aug(vertical_flip, with_mask=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:49.212970Z","iopub.execute_input":"2023-09-05T14:19:49.213262Z","iopub.status.idle":"2023-09-05T14:19:51.286135Z","shell.execute_reply.started":"2023-09-05T14:19:49.213236Z","shell.execute_reply":"2023-09-05T14:19:51.285010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### HorizontalFlip","metadata":{}},{"cell_type":"code","source":"class HorizontalFlip(BaseAug):\n    def __init__(self, p):\n        super(HorizontalFlip, self).__init__(p)\n        \n    def aug_data(self, image, mask):\n        aug_image = tf.image.flip_left_right(image)\n        aug_mask = tf.image.flip_left_right(mask)\n        return aug_image, aug_mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:51.287372Z","iopub.execute_input":"2023-09-05T14:19:51.287695Z","iopub.status.idle":"2023-09-05T14:19:51.293742Z","shell.execute_reply.started":"2023-09-05T14:19:51.287670Z","shell.execute_reply":"2023-09-05T14:19:51.292716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"horizontal_flip = HorizontalFlip(p=0.5)\ncheck_aug(horizontal_flip, with_mask=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:51.294887Z","iopub.execute_input":"2023-09-05T14:19:51.295249Z","iopub.status.idle":"2023-09-05T14:19:53.064140Z","shell.execute_reply.started":"2023-09-05T14:19:51.295219Z","shell.execute_reply":"2023-09-05T14:19:53.063019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### RandomBrightness","metadata":{}},{"cell_type":"code","source":"class RandomBrightness(BaseAug):\n    def __init__(self, max_delta, p):\n        super(RandomBrightness, self).__init__(p)\n        self.max_delta = max_delta\n        \n    def aug_data(self, image, mask):\n        aug_image = tf.image.random_brightness(image, self.max_delta)\n        return aug_image, mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:53.065496Z","iopub.execute_input":"2023-09-05T14:19:53.065839Z","iopub.status.idle":"2023-09-05T14:19:53.071713Z","shell.execute_reply.started":"2023-09-05T14:19:53.065810Z","shell.execute_reply":"2023-09-05T14:19:53.070783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"random_brightness = RandomBrightness(max_delta=0.2, p=0.75)\ncheck_aug(random_brightness, with_mask=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:53.079855Z","iopub.execute_input":"2023-09-05T14:19:53.080212Z","iopub.status.idle":"2023-09-05T14:19:54.361142Z","shell.execute_reply.started":"2023-09-05T14:19:53.080185Z","shell.execute_reply":"2023-09-05T14:19:54.360158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### RandomContrast","metadata":{}},{"cell_type":"code","source":"class RandomContrast(BaseAug):\n    def __init__(self, lower, upper, p):\n        super(RandomContrast, self).__init__(p)\n        self.lower = lower\n        self.upper = upper\n\n    def aug_data(self, image, mask):\n        aug_image = tf.image.random_contrast(\n            image, self.lower, self.upper)\n        return aug_image, mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:54.362145Z","iopub.execute_input":"2023-09-05T14:19:54.362479Z","iopub.status.idle":"2023-09-05T14:19:54.368837Z","shell.execute_reply.started":"2023-09-05T14:19:54.362451Z","shell.execute_reply":"2023-09-05T14:19:54.367857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"random_contrast = RandomContrast(lower=0.2, upper=0.8, p=0.75)\ncheck_aug(random_contrast, with_mask=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:54.369944Z","iopub.execute_input":"2023-09-05T14:19:54.370230Z","iopub.status.idle":"2023-09-05T14:19:55.759131Z","shell.execute_reply.started":"2023-09-05T14:19:54.370205Z","shell.execute_reply":"2023-09-05T14:19:55.757974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Blur","metadata":{}},{"cell_type":"code","source":"class Blur(BaseAug):\n    def __init__(self, blur_limit, p):\n        super(Blur, self).__init__(p)\n        self.blur_limit = blur_limit\n        \n    def aug_data(self, image, mask):\n        filter_size = random_int([], 3, self.blur_limit + 1)\n        filter_shape = (filter_size, filter_size)\n        aug_image = tfa.image.gaussian_filter2d(\n            image, filter_shape=filter_shape)\n        aug_image = tf.reshape(aug_image, [IMAGE_SIZE, IMAGE_SIZE, 3])\n        return aug_image, mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:55.760394Z","iopub.execute_input":"2023-09-05T14:19:55.760736Z","iopub.status.idle":"2023-09-05T14:19:55.768466Z","shell.execute_reply.started":"2023-09-05T14:19:55.760706Z","shell.execute_reply":"2023-09-05T14:19:55.767578Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"blur = Blur(blur_limit=5, p=1.0)\ncheck_aug(blur, with_mask=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:55.769548Z","iopub.execute_input":"2023-09-05T14:19:55.769844Z","iopub.status.idle":"2023-09-05T14:19:58.695474Z","shell.execute_reply.started":"2023-09-05T14:19:55.769819Z","shell.execute_reply":"2023-09-05T14:19:58.694376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### MedianBlur","metadata":{}},{"cell_type":"code","source":"class MedianBlur(BaseAug):\n    def __init__(self, blur_limit, p):\n        super(MedianBlur, self).__init__(p)\n        self.blur_limit = blur_limit\n        \n    def aug_data(self, image, mask):\n#         filter_size = random_int([], 3, self.blur_limit + 1)\n#         filter_shape = (filter_size, filter_size)\n        filter_shape = (3, 3)\n        aug_image = tfa.image.median_filter2d(\n            image, filter_shape=filter_shape)\n        aug_image = tf.reshape(aug_image, [IMAGE_SIZE, IMAGE_SIZE, 3])\n        return aug_image, mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:58.697053Z","iopub.execute_input":"2023-09-05T14:19:58.697750Z","iopub.status.idle":"2023-09-05T14:19:58.704933Z","shell.execute_reply.started":"2023-09-05T14:19:58.697707Z","shell.execute_reply":"2023-09-05T14:19:58.703846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"median_blur = MedianBlur(blur_limit=3, p=1.0)\ncheck_aug(median_blur, with_mask=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:19:58.706391Z","iopub.execute_input":"2023-09-05T14:19:58.706847Z","iopub.status.idle":"2023-09-05T14:20:00.356206Z","shell.execute_reply.started":"2023-09-05T14:19:58.706805Z","shell.execute_reply":"2023-09-05T14:20:00.354898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### OneOf","metadata":{}},{"cell_type":"code","source":"class OneOf(BaseAug):\n    def __init__(self, trans1, trans2, p):\n        super(OneOf, self).__init__(p)\n        self.trans1 = trans1\n        self.trans2 = trans2\n        \n    def aug_data(self, image, mask):\n        rnd = random_float()\n        aug_image, aug_mask = tf.cond(\n            rnd <= 0.5,\n            lambda: self.trans1.aug_data(image, mask),\n            lambda: self.trans2.aug_data(image, mask))\n        return aug_image, aug_mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:00.357754Z","iopub.execute_input":"2023-09-05T14:20:00.358127Z","iopub.status.idle":"2023-09-05T14:20:00.366854Z","shell.execute_reply.started":"2023-09-05T14:20:00.358093Z","shell.execute_reply":"2023-09-05T14:20:00.365612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"one_of_blur_median_blur = OneOf(\n    blur, median_blur, p=0.7)\ncheck_aug(one_of_blur_median_blur, with_mask=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:00.368355Z","iopub.execute_input":"2023-09-05T14:20:00.369256Z","iopub.status.idle":"2023-09-05T14:20:01.665142Z","shell.execute_reply.started":"2023-09-05T14:20:00.369216Z","shell.execute_reply":"2023-09-05T14:20:01.663775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### JpegCompression","metadata":{}},{"cell_type":"code","source":"class JpegCompression(BaseAug):\n    def __init__(self, quality_lower, quality_upper, p):\n        super(JpegCompression, self).__init__(p)\n        self.quality_lower = quality_lower\n        self.quality_upper = quality_upper\n        \n    def aug_data(self, image, mask):\n        jpeg_quality = random_int(\n            [], self.quality_lower, self.quality_upper + 1)\n        aug_image = tf.image.adjust_jpeg_quality(image, jpeg_quality)\n        aug_image = tf.reshape(aug_image, [IMAGE_SIZE, IMAGE_SIZE, 3])\n        return aug_image, mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:01.667031Z","iopub.execute_input":"2023-09-05T14:20:01.667999Z","iopub.status.idle":"2023-09-05T14:20:01.677070Z","shell.execute_reply.started":"2023-09-05T14:20:01.667954Z","shell.execute_reply":"2023-09-05T14:20:01.675719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"jpeg_compression = JpegCompression(\n    quality_lower=85, quality_upper=95, p=0.5)\ncheck_aug(jpeg_compression, with_mask=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:01.678500Z","iopub.execute_input":"2023-09-05T14:20:01.678903Z","iopub.status.idle":"2023-09-05T14:20:03.036029Z","shell.execute_reply.started":"2023-09-05T14:20:01.678865Z","shell.execute_reply":"2023-09-05T14:20:03.034925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### OpticalDistortion","metadata":{}},{"cell_type":"code","source":"def initUndistortRectifyMap(height, width, k, dx, dy):\n    height = tf.cast(height, dtype=tf.float32)\n    width = tf.cast(width, dtype=tf.float32)\n    \n    f_x = width\n    f_y = height\n    c_x = width * 0.5 + dx\n    c_y = height * 0.5 + dy\n    \n    f_dash_x = f_x\n    c_dash_x = (width - 1.0) * 0.5\n    f_dash_y = f_y\n    c_dash_y = (height - 1.0) * 0.5\n\n    h_rng = tf.range(height, dtype=tf.float32)\n    w_rng = tf.range(width, dtype=tf.float32)\n    v, u = tf.meshgrid(h_rng, w_rng)\n    \n    x = (u - c_dash_x) / f_dash_x\n    y = (v - c_dash_y) / f_dash_y\n    x_dash = x\n    y_dash = y\n    \n    r_2 = x_dash * x_dash + y_dash * y_dash\n    r_4 = r_2 * r_2\n    x_dash_dash = x_dash * (1 + k*r_2 + k*r_4)\n    y_dash_dash = y_dash * (1 + k*r_2 + k*r_4)\n\n    map_x = x_dash_dash * f_x + c_x\n    map_y = y_dash_dash * f_y + c_y\n    return map_x, map_y","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:03.037244Z","iopub.execute_input":"2023-09-05T14:20:03.037577Z","iopub.status.idle":"2023-09-05T14:20:03.047627Z","shell.execute_reply.started":"2023-09-05T14:20:03.037551Z","shell.execute_reply":"2023-09-05T14:20:03.046590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class OpticalDistortion(BaseAug):\n    def __init__(self, distort_limit, shift_limit, p=1.0):\n        super(OpticalDistortion, self).__init__(p)\n        self.distort_limit = distort_limit\n        self.shift_limit= shift_limit\n        \n    def aug_data(self, image, mask):\n        k = random_float([], -self.distort_limit, self.distort_limit)\n        dx = random_float([], -self.shift_limit, self.shift_limit)\n        dy = random_float([], -self.shift_limit, self.shift_limit)\n        image_shape = tf.shape(image)\n        height = image_shape[0]\n        width = image_shape[1]\n        map_x, map_y = initUndistortRectifyMap(\n            height, width, k, dx, dy)\n        aug_image = remap(\n            image, height, width, map_x, map_y, mode='mirror')\n        aug_mask = remap(\n            mask, height, width, map_x, map_y, mode='mirror')\n        return aug_image, aug_mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:03.048625Z","iopub.execute_input":"2023-09-05T14:20:03.048889Z","iopub.status.idle":"2023-09-05T14:20:03.060973Z","shell.execute_reply.started":"2023-09-05T14:20:03.048865Z","shell.execute_reply":"2023-09-05T14:20:03.060095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"optical_distortion = OpticalDistortion(\n    distort_limit=1.0, shift_limit=0.05, p=0.75)\ncheck_aug(optical_distortion, with_mask=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:03.061915Z","iopub.execute_input":"2023-09-05T14:20:03.062174Z","iopub.status.idle":"2023-09-05T14:20:06.135676Z","shell.execute_reply.started":"2023-09-05T14:20:03.062151Z","shell.execute_reply":"2023-09-05T14:20:06.134689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### GridDistortion","metadata":{}},{"cell_type":"code","source":"def make_grid_distorted_maps(height, width, num_steps, xsteps, ysteps):\n    def _make_maps_before_last(size, step, steps): # size=512, step=102,\n                                                   # steps.shape=[num_steps]\n        step_rep = tf.repeat(step, num_steps)  # [102, 102, 102, 102, 102]\n        step_rep_f = tf.cast(step_rep, dtype=tf.float32)\n        step_inc = step_rep_f * steps          # [102*s_0, ..., 102*s_4]\n        cur = tf.math.cumsum(step_inc)         # [si_0, si_0 + si_1, ... ]\n        zero = tf.zeros([1], dtype=tf.float32)\n        prev = tf.concat([ zero, cur[ :-1] ], axis=0) # [0, c_0, ..., c_3]\n        prev_cur = tf.stack([prev, cur])       # [[p_0, p_1, ...], [c_0, c_1, ...]]\n        ranges = tf.transpose(prev_cur)        # [[p_0, c_0], [p_1, c_1], ... ]\n\n        def _linspace_range(rng):\n            return tf.linspace(rng[0], rng[1], step)\n \n        maps_stack = tf.map_fn(_linspace_range, ranges)\n        maps = tf.reshape(maps_stack, [-1])    # [-1] flatten into 1-D\n        return maps\n    \n    def _make_last_map(size, step, last_start):\n        last_step = size - step * num_steps  # 512 - 102*5 = 2 \n        size_f = tf.cast(size, dtype=tf.float32)\n        last_map = tf.linspace(last_start, size_f-1.0, last_step)\n        return last_map\n    \n    def _make_distorted_map(size, steps):\n        step = size // num_steps               # step=102 \n        maps_before_last = _make_maps_before_last(size, step, steps[ :-1 ])\n        last_map = _make_last_map(size, step, maps_before_last[-1])\n        distorted_map = tf.concat([maps_before_last, last_map], axis=0)\n        return distorted_map\n\n    xx = _make_distorted_map(width, xsteps)\n    yy = _make_distorted_map(height, ysteps)\n    map_y, map_x = tf.meshgrid(xx, yy)\n    return map_x, map_y\n\nclass GridDistortion(BaseAug):\n    def __init__(self, num_steps, distort_limit, p=1.0):\n        super(GridDistortion, self).__init__(p)\n        self.num_steps = num_steps\n        self.distort_limit = distort_limit\n        \n    def aug_data(self, image, mask):\n        xsteps = tf.random.uniform(\n            [self.num_steps + 1],\n            minval=1.0 - self.distort_limit,\n            maxval=1.0 + self.distort_limit)\n        ysteps = tf.random.uniform(\n            [self.num_steps + 1],\n            minval=1.0 - self.distort_limit,\n            maxval=1.0 + self.distort_limit)\n\n        image_shape = tf.shape(image)\n        height = image_shape[0]\n        width = image_shape[1]\n        map_x, map_y = make_grid_distorted_maps(\n            height, width, self.num_steps, xsteps, ysteps)\n        aug_image = remap(\n            image, height, width, map_x, map_y, mode='mirror')\n        aug_mask = remap(\n            mask, height, width, map_x, map_y, mode='mirror')\n        return aug_image, aug_mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:06.136996Z","iopub.execute_input":"2023-09-05T14:20:06.137409Z","iopub.status.idle":"2023-09-05T14:20:06.156620Z","shell.execute_reply.started":"2023-09-05T14:20:06.137378Z","shell.execute_reply":"2023-09-05T14:20:06.155674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"grid_distortion = GridDistortion(\n    num_steps=5, distort_limit=1.0, p=0.75)\ncheck_aug(grid_distortion, with_mask=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:06.157803Z","iopub.execute_input":"2023-09-05T14:20:06.158093Z","iopub.status.idle":"2023-09-05T14:20:09.142294Z","shell.execute_reply.started":"2023-09-05T14:20:06.158067Z","shell.execute_reply":"2023-09-05T14:20:09.140952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### OneOf","metadata":{}},{"cell_type":"code","source":"one_of_opt_grid_distortion = OneOf(\n    optical_distortion, grid_distortion, p=0.75)\ncheck_aug(one_of_opt_grid_distortion, with_mask=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:09.143836Z","iopub.execute_input":"2023-09-05T14:20:09.144187Z","iopub.status.idle":"2023-09-05T14:20:11.383719Z","shell.execute_reply.started":"2023-09-05T14:20:09.144158Z","shell.execute_reply":"2023-09-05T14:20:11.382689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### HeuSaturationValue","metadata":{}},{"cell_type":"code","source":"class HueSaturationValue(BaseAug):\n    def __init__(\n            self, hue_shift_limit, sat_shift_limit,\n            val_shift_limit, p):\n        super(HueSaturationValue, self).__init__(p)\n        self.hue_shift_limit = hue_shift_limit\n        self.sat_shift_limit = sat_shift_limit\n        self.val_shift_limit = val_shift_limit\n        \n    def aug_data(self, image, mask):\n        hue_shift = random_float(\n            [], -self.hue_shift_limit, self.hue_shift_limit)\n        sat_shift = random_float(\n            [], -self.sat_shift_limit, self.sat_shift_limit)\n        val_shift = random_float(\n            [], -self.val_shift_limit, self.val_shift_limit)\n\n        hsv_image = tf.image.rgb_to_hsv(image)\n        hue_value = (hsv_image[ ... , :1 ] + hue_shift) % 1.0\n        sat_value = tf.clip_by_value(\n            hsv_image[ ... , 1:2 ] + sat_shift, 0.0, 1.0)\n        val_value = tf.clip_by_value(\n            hsv_image[ ... , 2: ] + val_shift, 0.0, 1.0)\n        hsv_image = tf.concat(\n            [hue_value, sat_value, val_value], axis=-1)\n        aug_image = tf.image.hsv_to_rgb(hsv_image)\n        return aug_image, mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:11.384901Z","iopub.execute_input":"2023-09-05T14:20:11.385182Z","iopub.status.idle":"2023-09-05T14:20:11.395441Z","shell.execute_reply.started":"2023-09-05T14:20:11.385155Z","shell.execute_reply":"2023-09-05T14:20:11.394599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hue_saturation_value = HueSaturationValue(\n    hue_shift_limit=0.2, sat_shift_limit=0.3,\n    val_shift_limit=0.2, p=0.75)\ncheck_aug(hue_saturation_value, with_mask=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:11.396543Z","iopub.execute_input":"2023-09-05T14:20:11.396853Z","iopub.status.idle":"2023-09-05T14:20:12.724900Z","shell.execute_reply.started":"2023-09-05T14:20:11.396825Z","shell.execute_reply":"2023-09-05T14:20:12.723839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ShiftScaleRotate","metadata":{}},{"cell_type":"code","source":"def affine_transform(height, width, tx, ty, z, theta):\n    cx = (width - 1.0) * 0.5\n    cy = (height - 1.0) * 0.5\n    \n    center_shift_mat = tf.convert_to_tensor([\n        [1.0, 0.0, -cx],\n        [0.0, 1.0, -cy],\n        [0.0, 0.0, 1.0]], dtype=tf.float32)\n    trans_mat = center_shift_mat\n    \n    rot_rad = -2.0 * math.pi * theta / 360.0\n    roration_mat = tf.convert_to_tensor([\n        [tf.math.cos(rot_rad), tf.math.sin(rot_rad), 0.0],\n        [-tf.math.sin(rot_rad), tf.math.cos(rot_rad), 0.0],\n        [0.0, 0.0, 1.0]], dtype=tf.float32)\n    trans_mat = tf.linalg.matmul(roration_mat, trans_mat)\n\n    zoom_mat = tf.convert_to_tensor([\n        [1.0 / z, 0.0, 0.0],\n        [0.0, 1.0 / z, 0.0],\n        [0.0, 0.0, 1.0]], dtype=tf.float32)\n    trans_mat = tf.linalg.matmul(zoom_mat, trans_mat)\n    \n    shift_mat = tf.convert_to_tensor([\n        [1.0, 0.0, cx - tx],\n        [0.0, 1.0, cy - ty],\n        [0.0, 0.0, 1.0]], dtype=tf.float32)\n    trans_mat = tf.linalg.matmul(shift_mat, trans_mat)\n    \n    h_rng = tf.range(height, dtype=tf.float32)\n    w_rng = tf.range(width, dtype=tf.float32)\n    y, x = tf.meshgrid(h_rng, w_rng)\n    x = tf.reshape(x, [-1])\n    y = tf.reshape(y, [-1])\n    ones = tf.ones_like(x)\n    coord_mat = tf.stack([x, y, ones])\n    \n    res_mat = tf.linalg.matmul(trans_mat, coord_mat)\n    map_x = res_mat[0]\n    map_y = res_mat[1]\n    return map_x, map_y","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:12.726093Z","iopub.execute_input":"2023-09-05T14:20:12.726441Z","iopub.status.idle":"2023-09-05T14:20:12.741366Z","shell.execute_reply.started":"2023-09-05T14:20:12.726398Z","shell.execute_reply":"2023-09-05T14:20:12.740219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ShiftScaleRotate(BaseAug):\n    def __init__(\n            self, shift_limit, scale_limit, rotate_limit, p):\n        super(ShiftScaleRotate, self).__init__(p)\n        self.shift_limit = shift_limit\n        self.scale_limit = scale_limit\n        self.rotate_limit = rotate_limit\n\n    def aug_data(self, image, mask):\n        image_shape = tf.shape(image)\n        height_i = image_shape[0]\n        width_i = image_shape[1]\n        height_f = tf.cast(height_i, dtype=tf.float32)\n        width_f = tf.cast(width_i, dtype=tf.float32)\n        rnd_shift = random_float(\n            [2], -self.shift_limit, self.shift_limit)\n        tx = width_f * rnd_shift[0]\n        ty = height_f * rnd_shift[1]\n        z = random_float(\n            [], 1.0 - self.scale_limit, 1.0 + self.scale_limit)\n        theta = random_float(\n            [], -self.rotate_limit, self.rotate_limit)\n\n        map_x, map_y = affine_transform(\n            height_f, width_f, tx, ty, z, theta)\n        aug_image = remap(\n            image, height_i, width_i, map_x, map_y, mode='constant')\n        aug_mask = remap(\n            mask, height_i, width_i, map_x, map_y, mode='constant')\n        return aug_image, aug_mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:12.742557Z","iopub.execute_input":"2023-09-05T14:20:12.742876Z","iopub.status.idle":"2023-09-05T14:20:12.860977Z","shell.execute_reply.started":"2023-09-05T14:20:12.742849Z","shell.execute_reply":"2023-09-05T14:20:12.859732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shift_scale_rotate = ShiftScaleRotate(\n    shift_limit=0.2, scale_limit=0.3, rotate_limit=30, p=0.75)\ncheck_aug(shift_scale_rotate, with_mask=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:12.862291Z","iopub.execute_input":"2023-09-05T14:20:12.862616Z","iopub.status.idle":"2023-09-05T14:20:15.899687Z","shell.execute_reply.started":"2023-09-05T14:20:12.862587Z","shell.execute_reply":"2023-09-05T14:20:15.898459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Cutout","metadata":{}},{"cell_type":"code","source":"class Cutout(BaseAug):\n    def __init__(self, num_cuts, mask_factor, p):\n        super(Cutout, self).__init__(p)\n        self.num_cuts = num_cuts\n        self.mask_factor = mask_factor\n\n    def aug_data(self, image, mask):\n        image_shape = tf.shape(image)\n        height_i = image_shape[0]\n        width_i = image_shape[1]\n        height_f = tf.cast(height_i, dtype=tf.float32)\n        width_f = tf.cast(width_i, dtype=tf.float32)\n        cut_h = tf.cast(height_f * self.mask_factor, dtype=tf.int32)\n        cut_w = tf.cast(width_f * self.mask_factor, dtype=tf.int32)\n\n        y_centers = random_int([self.num_cuts], 0, height_i)\n        x_centers = random_int([self.num_cuts], 0, width_i)\n        tops = tf.math.maximum(y_centers - cut_h//2, 0)\n        lefts = tf.math.maximum(x_centers - cut_w//2, 0)\n        bottoms = tf.math.minimum(tops + cut_h, height_i - 1)\n        rights = tf.math.minimum(lefts + cut_w, width_i - 1)\n\n        def _make_one_mask(i):\n            mask_height = bottoms[i] - tops[i] + 1\n            mask_width = rights[i] - lefts[i] + 1\n            mask_shape = [mask_height, mask_width]\n            mask = tf.ones(mask_shape, dtype=tf.bool)\n\n            paddings = [\n                [tops[i], height_i - bottoms[i] - 1],\n                [lefts[i], width_i - rights[i] - 1]]\n            mask = tf.pad(mask, paddings, mode='CONSTANT')\n            return mask\n\n        num_cuts_rng = tf.range(self.num_cuts, dtype=tf.int64)\n        cut_masks = tf.map_fn(\n            _make_one_mask, num_cuts_rng,\n            fn_output_signature=tf.bool)\n        cut_mask = tf.reduce_any(cut_masks, axis=0)\n        cut_mask = cut_mask[ ..., tf.newaxis ]\n\n        mask_value = tf.constant(0.0, dtype=tf.float32)\n        aug_image = tf.where(cut_mask, mask_value, image)\n        return aug_image, mask","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:15.901114Z","iopub.execute_input":"2023-09-05T14:20:15.901739Z","iopub.status.idle":"2023-09-05T14:20:15.919028Z","shell.execute_reply.started":"2023-09-05T14:20:15.901707Z","shell.execute_reply":"2023-09-05T14:20:15.917953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cut_out = Cutout(num_cuts=1, mask_factor=0.4, p=0.75)\ncheck_aug(cut_out, with_mask=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:15.920213Z","iopub.execute_input":"2023-09-05T14:20:15.920535Z","iopub.status.idle":"2023-09-05T14:20:17.552904Z","shell.execute_reply.started":"2023-09-05T14:20:15.920508Z","shell.execute_reply":"2023-09-05T14:20:17.551734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Do Augment","metadata":{}},{"cell_type":"code","source":"def do_augment(image, mask, labels):\n    image, mask = transpose(image, mask)\n    image, mask = vertical_flip(image, mask)\n    image, mask = horizontal_flip(image, mask)\n    image, mask = random_brightness(image, mask)\n    image, mask = random_contrast(image, mask)\n    image, mask = one_of_blur_median_blur(image, mask)\n    image, mask = jpeg_compression(image, mask)\n    image, mask = one_of_opt_grid_distortion(image, mask)\n    image, mask = hue_saturation_value(image, mask)\n    image, mask = shift_scale_rotate(image, mask)\n    image, mask = cut_out(image, mask)\n    return image, mask, labels","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:17.554171Z","iopub.execute_input":"2023-09-05T14:20:17.554484Z","iopub.status.idle":"2023-09-05T14:20:17.562553Z","shell.execute_reply.started":"2023-09-05T14:20:17.554457Z","shell.execute_reply":"2023-09-05T14:20:17.561484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset 2","metadata":{}},{"cell_type":"code","source":"def select_train(ds, fold_i):\n    ds = ds.filter(\n        lambda ids, fold, image, mask, study_label: fold != fold_i)\n    return ds\n    \ndef select_val(ds, fold_i):\n    ds = ds.filter(\n        lambda ids, fold, image, mask, study_label: fold == fold_i)\n    return ds","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:17.563626Z","iopub.execute_input":"2023-09-05T14:20:17.563889Z","iopub.status.idle":"2023-09-05T14:20:17.581690Z","shell.execute_reply.started":"2023-09-05T14:20:17.563864Z","shell.execute_reply":"2023-09-05T14:20:17.580677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_data(ids, fold, image, mask, study_label):\n    return image, mask, study_label\n\ndef rescale_image(image, mask, study_label):\n    image = image_to_float_0_1(image)\n    return image, mask, study_label","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:17.582936Z","iopub.execute_input":"2023-09-05T14:20:17.583342Z","iopub.status.idle":"2023-09-05T14:20:17.593342Z","shell.execute_reply.started":"2023-09-05T14:20:17.583312Z","shell.execute_reply":"2023-09-05T14:20:17.592407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def reform_for_model(image, mask, labels):\n    return image, {'sigmoid': mask, 'study_label': labels}","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:17.594415Z","iopub.execute_input":"2023-09-05T14:20:17.594735Z","iopub.status.idle":"2023-09-05T14:20:17.604194Z","shell.execute_reply.started":"2023-09-05T14:20:17.594709Z","shell.execute_reply":"2023-09-05T14:20:17.603247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"AUTOTUNE = tf.data.experimental.AUTOTUNE\n\ndef build_dataset(\n        dset, augment=True, repeat=True, shuffle=1024):\n    dset = dset.map(get_data, num_parallel_calls=AUTOTUNE)\n    dset = dset.repeat() if repeat else dset\n    dset = dset.shuffle(shuffle) if shuffle else dset\n    dset = dset.batch(BATCH_SIZE)\n    dset = dset.map(\n        rescale_image, num_parallel_calls=AUTOTUNE)\n    dset = dset.map(\n        do_augment, num_parallel_calls=AUTOTUNE) if augment else dset\n    dset = dset.map(\n        reform_for_model, num_parallel_calls=AUTOTUNE)\n    dset = dset.prefetch(AUTOTUNE)\n    return dset","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:17.605342Z","iopub.execute_input":"2023-09-05T14:20:17.605788Z","iopub.status.idle":"2023-09-05T14:20:17.617397Z","shell.execute_reply.started":"2023-09-05T14:20:17.605757Z","shell.execute_reply":"2023-09-05T14:20:17.616349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_datasets(fold_i):\n    train_ds = select_train(raw_ds, fold_i)\n    train_ds = build_dataset(\n        train_ds, augment=True, repeat=True, shuffle=1024)\n\n    val_ds = select_val(raw_ds, fold_i)\n    val_ds = build_dataset(\n        val_ds, augment=False, repeat=False, shuffle=None)\n\n    train_steps = get_train_count(fold_i) // BATCH_SIZE\n    val_steps = get_val_count(fold_i) // BATCH_SIZE\n\n    return train_ds, val_ds, train_steps, val_steps","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:17.618700Z","iopub.execute_input":"2023-09-05T14:20:17.619022Z","iopub.status.idle":"2023-09-05T14:20:17.628582Z","shell.execute_reply.started":"2023-09-05T14:20:17.618997Z","shell.execute_reply":"2023-09-05T14:20:17.627558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualization","metadata":{}},{"cell_type":"code","source":"train_ds, val_ds, train_steps, val_steps = make_datasets(0)\n\nprint(train_ds)\nprint(val_ds)\nprint(train_steps)\nprint(val_steps)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:17.629638Z","iopub.execute_input":"2023-09-05T14:20:17.629945Z","iopub.status.idle":"2023-09-05T14:20:19.966458Z","shell.execute_reply.started":"2023-09-05T14:20:17.629920Z","shell.execute_reply":"2023-09-05T14:20:19.965275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_images(ds):\n    rows = 4\n    cols = 5\n    n_imgs = (rows//2) * cols\n\n    images, label_dict = next(iter(\n        ds.unbatch().take(n_imgs).batch(n_imgs)))\n    masks = label_dict['sigmoid']\n    plt.figure(figsize=(12, 8))\n    for i, image in enumerate(images):\n        plt.subplot(rows, cols, i+1)\n        plt.imshow(image)\n        plt.axis(\"off\")\n    for i, mask in enumerate(masks):\n        plt.subplot(rows, cols, n_imgs+i+1)\n        plt.imshow(mask, cmap='gray')\n        plt.axis(\"off\")\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:19.967821Z","iopub.execute_input":"2023-09-05T14:20:19.968138Z","iopub.status.idle":"2023-09-05T14:20:19.976991Z","shell.execute_reply.started":"2023-09-05T14:20:19.968110Z","shell.execute_reply":"2023-09-05T14:20:19.975930Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images(train_ds)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:20:19.978179Z","iopub.execute_input":"2023-09-05T14:20:19.978497Z","iopub.status.idle":"2023-09-05T14:21:01.636383Z","shell.execute_reply.started":"2023-09-05T14:20:19.978468Z","shell.execute_reply":"2023-09-05T14:21:01.635269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images(val_ds)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:01.637633Z","iopub.execute_input":"2023-09-05T14:21:01.637921Z","iopub.status.idle":"2023-09-05T14:21:06.460057Z","shell.execute_reply.started":"2023-09-05T14:21:01.637896Z","shell.execute_reply":"2023-09-05T14:21:06.458919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model","metadata":{}},{"cell_type":"code","source":"def make_model():\n    base_model = SEG_MODEL(\n        BACKBONE, encoder_weights='imagenet', \n        input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3),\n        classes=1, activation='sigmoid')\n    \n    x = base_model.get_layer(name='top_activation').output \n    x = L.GlobalAveragePooling2D(name='avgpool')(x)\n    study_label = L.Dense(\n        N_STUDY_LABELS, activation='sigmoid', name='study_label')(x)\n\n    model = tf.keras.Model(\n        inputs=base_model.input, \n        outputs=[base_model.output, study_label]) \n    \n    pr_auc = tf.keras.metrics.AUC(\n        curve=\"PR\", multi_label=True, name=\"pr_auc\")\n    model.compile(\n        optimizer=tf.keras.optimizers.Adam(),\n        loss={\n            'sigmoid': sm.losses.bce_jaccard_loss,\n            'study_label': \"binary_crossentropy\" },\n        loss_weights = [1.0, 1.0],\n        metrics={\n            'sigmoid': sm.metrics.iou_score,\n            'study_label': pr_auc },\n        # overheads and allows the XLA compiler to unroll the loop on TPU\n        # and optimize hardware utilization.\n        # needs to be commented out for Tensorflow 2.3\n        steps_per_execution=8)\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:06.461550Z","iopub.execute_input":"2023-09-05T14:21:06.461889Z","iopub.status.idle":"2023-09-05T14:21:06.471924Z","shell.execute_reply.started":"2023-09-05T14:21:06.461860Z","shell.execute_reply":"2023-09-05T14:21:06.470859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope(): \n    model = make_model()\n    \ninitial_weights = model.get_weights()\n# model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:06.473186Z","iopub.execute_input":"2023-09-05T14:21:06.473586Z","iopub.status.idle":"2023-09-05T14:21:51.929716Z","shell.execute_reply.started":"2023-09-05T14:21:06.473558Z","shell.execute_reply":"2023-09-05T14:21:51.928561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{}},{"cell_type":"code","source":"LR_START = INIT_LR\nLR_MAX = 1e-3\nLR_MIN = 1e-5\nLR_RAMPUP_EPOCHS = WARMUP_EPO\nLR_SUSTAIN_EPOCHS = 0\nEPOCHS = N_EPOCHS\n\ndef lrfn(epoch):\n    if epoch < LR_RAMPUP_EPOCHS:\n        lr = (LR_MAX - LR_START) / LR_RAMPUP_EPOCHS * epoch + LR_START\n    elif epoch < LR_RAMPUP_EPOCHS + LR_SUSTAIN_EPOCHS:\n        lr = LR_MAX\n    else:\n        decay_total_epochs = EPOCHS - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS - 1\n        decay_epoch_index = epoch - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS\n        phase = math.pi * decay_epoch_index / decay_total_epochs\n        cosine_decay = 0.5 * (1 + math.cos(phase))\n        lr = (LR_MAX - LR_MIN) * cosine_decay + LR_MIN\n    return lr\n\nrng = [i for i in range(EPOCHS)]\nlr_y = [lrfn(x) for x in rng]\nplt.figure(figsize=(10, 4))\nplt.plot(rng, lr_y)\nprint(\"Learning rate schedule: {:.3g} to {:.3g} to {:.3g}\". \\\n      format(lr_y[0], max(lr_y), lr_y[-1]))","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:51.931043Z","iopub.execute_input":"2023-09-05T14:21:51.931363Z","iopub.status.idle":"2023-09-05T14:21:52.177182Z","shell.execute_reply.started":"2023-09-05T14:21:51.931335Z","shell.execute_reply":"2023-09-05T14:21:52.176013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cb_monitor = 'val_study_label_pr_auc'\n\nclass RestoreBestWeights(tf.keras.callbacks.Callback):\n    def __init__(self):\n        super(RestoreBestWeights, self).__init__()\n        self.best_monitor = -np.Inf\n        self.best_weights = None\n        self.best_epoch = None\n        \n    def on_epoch_end(self, epoch, logs=None):\n        current_monitor = logs.get(cb_monitor)\n        if current_monitor > self.best_monitor:\n            self.best_monitor = current_monitor\n            self.best_weights = self.model.get_weights()\n            self.best_epoch = epoch\n            \n    def on_train_end(self, logs=None):\n        print(\"Restoring best weights on epoch {0}, {1} was {2:.5f}\".format(\n            self.best_epoch + 1, cb_monitor, self.best_monitor))\n        self.model.set_weights(self.best_weights)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.178602Z","iopub.execute_input":"2023-09-05T14:21:52.178936Z","iopub.status.idle":"2023-09-05T14:21:52.189238Z","shell.execute_reply.started":"2023-09-05T14:21:52.178906Z","shell.execute_reply":"2023-09-05T14:21:52.188052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_callbacks(fold_i):\n    best_model_file_name = \\\n        \"study_aux_loss_model_{0}_{1}.hdf5\".format(VID, fold_i)\n    cb_mode = 'max'\n    cb_min_delta = 1e-4\n    cb_verbose = 1\n\n    checkpoint = tf.keras.callbacks.ModelCheckpoint(\n        best_model_file_name, save_best_only=True,\n        save_weights_only=False, monitor=cb_monitor, mode=cb_mode,\n        verbose=cb_verbose)\n    lr_callback = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose = False)\n    restore_best_weights = RestoreBestWeights()\n    \n    return checkpoint, lr_callback, restore_best_weights","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.190410Z","iopub.execute_input":"2023-09-05T14:21:52.190728Z","iopub.status.idle":"2023-09-05T14:21:52.211483Z","shell.execute_reply.started":"2023-09-05T14:21:52.190699Z","shell.execute_reply":"2023-09-05T14:21:52.210589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def fit_one_fold(fold_i):\n    train_dataset, val_dataset, train_steps, val_steps = \\\n        make_datasets(fold_i)\n    checkpoint, lr_callback, restore_best_weights = \\\n        make_callbacks(fold_i)\n    history = model.fit(\n        train_dataset, \n        epochs=EPOCHS,\n        verbose=1,\n        callbacks=[checkpoint, lr_callback, restore_best_weights],\n        steps_per_epoch=train_steps,\n        validation_data=val_dataset,\n        validation_steps=val_steps)\n    return history, val_dataset, val_steps","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.212720Z","iopub.execute_input":"2023-09-05T14:21:52.213036Z","iopub.status.idle":"2023-09-05T14:21:52.236210Z","shell.execute_reply.started":"2023-09-05T14:21:52.213009Z","shell.execute_reply":"2023-09-05T14:21:52.235230Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_history(history, title, labels, subplot):\n    plt.subplot(*subplot)\n    plt.title(title)\n    for label in labels:\n        plt.plot(history.history[label], label=label)\n    plt.legend()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.237372Z","iopub.execute_input":"2023-09-05T14:21:52.237700Z","iopub.status.idle":"2023-09-05T14:21:52.248976Z","shell.execute_reply.started":"2023-09-05T14:21:52.237674Z","shell.execute_reply":"2023-09-05T14:21:52.247937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_fit_result(history):\n    plt.figure(figsize=(12, 8))\n    plot_history(\n        history, \"Loss\",\n        ['loss', 'val_loss'],\n        (2, 2, 1))\n    plot_history(\n        history, \"PR_AUC\", \n        ['study_label_pr_auc', 'val_study_label_pr_auc'],\n        (2, 2, 2))\n    plot_history(\n        history, \"IOU\", \n        ['sigmoid_iou_score', 'val_sigmoid_iou_score'],\n        (2, 2, 3))\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.250240Z","iopub.execute_input":"2023-09-05T14:21:52.250709Z","iopub.status.idle":"2023-09-05T14:21:52.262642Z","shell.execute_reply.started":"2023-09-05T14:21:52.250679Z","shell.execute_reply":"2023-09-05T14:21:52.261666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict_one_fold(model, val_dataset, val_steps):\n    val_true_list = [] \n    for _, label_dict in val_dataset:\n        study_labels = label_dict['study_label']\n        val_true_list.append(study_labels)\n    val_true = np.concatenate(val_true_list, axis=0)\n   \n    val_pred_list = []\n    for images, _ in val_dataset:\n        pred_list = model(images, training=False)\n        val_preds = pred_list[1]\n        val_pred_list.append(val_preds)\n    val_pred = np.concatenate(val_pred_list, axis=0)\n    \n    val_true = val_true[ : len(val_pred) ]\n    return val_true, val_pred","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.263785Z","iopub.execute_input":"2023-09-05T14:21:52.264085Z","iopub.status.idle":"2023-09-05T14:21:52.275703Z","shell.execute_reply.started":"2023-09-05T14:21:52.264058Z","shell.execute_reply":"2023-09-05T14:21:52.274618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_labels = [\n    'Negative for Pneumonia',\n    'Typical Appearance',\n    'Indeterminate Appearance',\n    'Atypical Appearance',\n]","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.276852Z","iopub.execute_input":"2023-09-05T14:21:52.277164Z","iopub.status.idle":"2023-09-05T14:21:52.292141Z","shell.execute_reply.started":"2023-09-05T14:21:52.277139Z","shell.execute_reply":"2023-09-05T14:21:52.291207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import average_precision_score\n\ndef show_average_precision_score(val_true, val_pred):\n    average_precision_list = []\n    for i in range(val_true.shape[-1]):\n        average_precision = average_precision_score(\n            val_true[ : , i], val_pred[ : , i])\n        print(\"{0:30s}: {1:.4f}\".format(\n            study_labels[i], average_precision))\n        average_precision_list.append(average_precision)\n\n    mean_average_precision = np.mean(average_precision_list)\n    print(\"{0:30s}: {1:.4f}\".format(\n        \"Mean\", mean_average_precision))\n    \n    plt.figure(figsize=(8, 4))\n    plt.plot(average_precision_list)\n    ticks = np.arange(len(study_labels))\n    plt.xticks(ticks=ticks, labels=study_labels, rotation=45)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.293277Z","iopub.execute_input":"2023-09-05T14:21:52.293861Z","iopub.status.idle":"2023-09-05T14:21:52.501085Z","shell.execute_reply.started":"2023-09-05T14:21:52.293830Z","shell.execute_reply":"2023-09-05T14:21:52.499836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_pred_str(pred):\n    labels = ['negative', 'typical', 'indeterminate', 'atypical']\n    pred_list = []\n    for i, label in enumerate(labels):\n        s = \"{0} {1:.6f} 0 0 1 1\".format(label, pred[i])\n        pred_list.append(s)\n    return ' '.join(pred_list)\n\ndef make_submission(fold_i, val_pred):\n    val_study_ids = get_val_study_ids(fold_i)\n    fold_sub_list = []\n    for study_id, pred in zip(val_study_ids, val_pred):\n        pred_str = make_pred_str(pred)\n        fold_sub_list.append([study_id + \"_study\", pred_str])\n    return fold_sub_list","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.502884Z","iopub.execute_input":"2023-09-05T14:21:52.504111Z","iopub.status.idle":"2023-09-05T14:21:52.512861Z","shell.execute_reply.started":"2023-09-05T14:21:52.504071Z","shell.execute_reply":"2023-09-05T14:21:52.511773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_sub_list = []\nfor fold_i in FOLD_I_LIST:\n    print(\"####################\")\n    print(\"# Fold {0}\".format(fold_i))\n    model.set_weights(initial_weights)\n    history, val_dataset, val_steps = fit_one_fold(fold_i)\n    plot_fit_result(history)\n    val_true, val_pred = predict_one_fold(model, val_dataset, val_steps)\n    show_average_precision_score(val_true, val_pred)\n    fold_sub_list = make_submission(fold_i, val_pred)\n    study_sub_list.extend(fold_sub_list)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T14:21:52.514148Z","iopub.execute_input":"2023-09-05T14:21:52.514488Z","iopub.status.idle":"2023-09-05T15:18:09.575486Z","shell.execute_reply.started":"2023-09-05T14:21:52.514457Z","shell.execute_reply":"2023-09-05T15:18:09.574067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_sub_df = pd.DataFrame(\n    study_sub_list, columns=['id', 'PredictionString'])\n\nstudy_sub_df","metadata":{"execution":{"iopub.status.busy":"2023-09-05T15:18:09.577023Z","iopub.execute_input":"2023-09-05T15:18:09.577346Z","iopub.status.idle":"2023-09-05T15:18:09.590909Z","shell.execute_reply.started":"2023-09-05T15:18:09.577319Z","shell.execute_reply":"2023-09-05T15:18:09.589823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_sub_file_name = \"study_sub_{0}.csv\".format(VID)\nstudy_sub_df.to_csv(study_sub_file_name, index=False)\n\n! head study_sub_*.csv","metadata":{"execution":{"iopub.status.busy":"2023-09-05T15:18:09.592084Z","iopub.execute_input":"2023-09-05T15:18:09.592365Z","iopub.status.idle":"2023-09-05T15:18:12.319102Z","shell.execute_reply.started":"2023-09-05T15:18:09.592340Z","shell.execute_reply":"2023-09-05T15:18:12.317367Z"},"trusted":true},"execution_count":null,"outputs":[]}],"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"}}