{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Initialize:","metadata":{"_uuid":"a37e1b79-235a-4e66-b092-d34e1c372502","_cell_guid":"fca5acf1-b288-4bf2-92a8-5db9126e6500","trusted":true}},{"cell_type":"code","source":"!pip install -q pydot\n!pip install -q pydotplus\n!apt-get install -q graphviz\n\nimport tensorflow_addons as tfa\nimport tensorflow as tf\nimport pandas as pd\npd.options.mode.chained_assignment = None\nimport numpy as np\nimport scipy\n\nfrom collections import Counter\nfrom datetime import datetime\nimport multiprocessing\nfrom glob import glob\nimport warnings\nimport requests\nimport imageio\nimport IPython\nimport urllib\nimport zipfile\nimport pickle\nimport random\nimport shutil\nimport string\nimport math\nimport tqdm\nimport time\nimport gzip\nimport io\nimport os\nimport gc\nimport re\n\nfrom matplotlib.colors import ListedColormap\nimport matplotlib.patches as patches\nimport plotly.graph_objects as go\nimport matplotlib.pyplot as plt\nfrom tqdm.notebook import tqdm\nimport plotly.express as px\nimport seaborn as sns\nfrom PIL import Image\nimport matplotlib\nimport plotly\nimport PIL\nimport cv2\nimport ast","metadata":{"_uuid":"f707c3b8-dd80-4756-bb97-39e386b3986f","_cell_guid":"9f3cd333-4e2b-407a-807f-25864e4d5d85","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CLASS_LABELS = [\"Nucleoplasm\", \"Nuclear Membrane\", \"Nucleoli\", \"Nucleoli Fibrillar Center\", \"Nuclear Speckles\", \"Nuclear Bodies\", \"Endoplasmic Reticulum\", \"Golgi Apparatus\", \"Intermediate Filaments\", \"Actin Filaments\", \"Microtubules\", \"Mitotic Spindle\", \"Centrosome\", \"Plasma Membrane\", \"Mitochondria\", \"Aggresome\", \"Cytosol\", \"Vesicles\", \"Negative\"]\nINT_2_STR = {i:CLASS_LABELS[i] for i in np.arange(19)}\nINT_2_STR_LOWER = {i:j.lower().replace(\" \", \"_\") for i,j in INT_2_STR.items()}\nSTR_2_INT_LOWER = {j:i for i,j in INT_2_STR_LOWER.items()}\nSTR_2_INT = {j:i for i,j in INT_2_STR.items()}\nFIG_FONT = dict(family=\"Helvetica, Arial\", size=14, color=\"#7f7f7f\")\nLABEL_COLORS = [px.colors.label_rgb(px.colors.convert_to_RGB_255(i)) for i in sns.color_palette(\"Spectral\", len(CLASS_LABELS))]\nLABEL_COL_MAP = {str(i):j for i,j in enumerate(LABEL_COLORS)}\n\nprint(CLASS_LABELS)\nprint(INT_2_STR)\nprint(INT_2_STR_LOWER)\nprint(STR_2_INT_LOWER)\nprint(STR_2_INT)","metadata":{"_uuid":"c22fab7c-0d90-478f-914f-070d109ad5d8","_cell_guid":"e3277ac8-2057-4ff5-a186-7d40f354575f","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_image_path = '../input/hpa-single-cell-image-classification/train'\ntest_image_path = '../input/hpa-single-cell-image-classification/test'\ntrain_tf_path = '../input/hpa-single-cell-image-classification/train_tfrecords'\ntest_tf_path = '../input/hpa-single-cell-image-classification/test_tf_records'\n\ntrain_red_path = '../input/human-protein-atlas-red-cell-tile-dataset'\ntrain_green_path = '../input/human-protein-atlas-green-cell-tile-dataset'\ntrain_blue_path = '../input/human-protein-atlas-blue-cell-tile-dataset'\ntrain_yellow_path = '../input/human-protein-atlas-yellow-cell-tile-dataset'\n\ntrain_image = sorted([os.path.join(train_image_path, i) for i in os.listdir(train_image_path)])\ntest_image = sorted([os.path.join(test_image_path, i) for i in os.listdir(test_image_path)])\ntrain_label = pd.read_csv('../input/hpa-single-cell-image-classification/train.csv')\nprint(train_label.head())","metadata":{"_uuid":"61a4fd2c-f038-48f4-a960-27899bb8d80c","_cell_guid":"3aeb0b29-7ff0-4ac8-8110-66a7e3642234","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper functions:","metadata":{"_uuid":"cc5298ae-6cfd-48a6-99e5-6b9a6ca7eafd","_cell_guid":"85cb0aad-e2a2-40c9-a5d3-21c17ddb1d8e","trusted":true}},{"cell_type":"code","source":"def load_image_scaled(img_id, img_dir, img_size=512, load_style=\"tf\"):\n    \"\"\" Load An Image Using ID and Directory Path - Composes 4 Individual Images \"\"\"\n    def __load_with_tf(path, img_size=512):\n        img = tf.io.read_file(path)\n        img = tf.image.decode_png(img, channels=1)\n        return tf.image.resize(img, (img_size, img_size))[..., 0]\n    \n    def __load_with_pil(path, img_size=512):\n        img = Image.open(path)\n        img = img.resize((img_size, img_size))\n        return np.asarray(img)\n    \n    def __load_with_cv2(path, img_size=512):\n        img = cv2.imread(path, 0)\n        img = cv2.resize(img, (img_size, img_size))\n        return img\n        \n    if load_style is \"tf\":\n        load_fn = __load_with_tf\n    elif load_style is \"PIL\":\n        load_fn = __load_with_pil\n    else:\n        load_fn = __load_with_cv2\n    \n    return np.stack(\n        [np.asarray(load_fn(os.path.join(img_dir, img_id+f\"_{c}.png\"), img_size)/255.) for c in [\"red\", \"yellow\", \"blue\"]], axis=2\n    )\n\n\ndef decode_img(img, img_size=(224,224)):\n    \"\"\"TBD\"\"\"\n    \n    # convert the compressed string to a 3D uint8 tensor\n    img = tf.image.decode_png(img, channels=1)\n\n    # resize the image to the desired size\n    return tf.cast(tf.image.resize(img, img_size), tf.uint8)\n\n\ndef get_color_path_maps(color_dirs, tp_id_map):\n    c_p_maps = [{k:[] for k in INT_2_STR.keys()} for _ in range(len(color_dirs))]\n    color_d_paths = [\n        [d_path for d_path in os.listdir(color_dir) if d_path.endswith(\"_256\")] \\\n        for color_dir in color_dirs\n    ]\n    for c in tqdm(color_d_paths[0], total=len(color_d_paths[0])):\n        \n        # Get class stuff\n        cls = c.split(\"_\", 1)[1].rsplit(\"_\",1)[0]\n        cls_idx = STR_2_INT_LOWER[cls]\n        \n        # Get the relevant color directories\n        c_dirs = [\n            os.path.join(color_dir, c.replace(\"red\", clr), \"data\", \"train_tiles\", cls) \\\n            for clr, color_dir in zip([\"red\", \"green\", \"blue\", \"yellow\"], color_dirs)\n        ]\n\n        # Update map\n        for f_name in tqdm(os.listdir(c_dirs[0]), total=len(os.listdir(c_dirs[0]))):\n            # get the relevant full paths\n            full_paths = [os.path.join(c_dir, f_name.replace(\"red\", clr)) for clr, c_dir in zip([\"red\", \"green\", \"blue\", \"yellow\"], c_dirs)]\n            if tp_id_map==None:\n                for c_p_map, full_path in zip(c_p_maps, full_paths):\n                    c_p_map[cls_idx].append(full_path)\n            elif (f_name.endswith(\".png\") and (\"negative\" in full_paths[0] or f_name.rsplit(\"_\", 1)[0] in tp_id_map[cls_idx])):\n                for c_p_map, full_path in zip(c_p_maps, full_paths):\n                    c_p_map[cls_idx].append(full_path)\n            else:\n                for c_p_map, full_path in zip(c_p_maps, full_paths):\n                    c_p_map[STR_2_INT[\"Negative\"]].append(full_path)\n    return [{k:sorted(v) for k,v in c_p_map.items()} for c_p_map in c_p_maps]\n\n\ndef get_tp_id_map(pkl_dir):\n    \"\"\" TBD \"\"\"\n    # Capture all relevant paths\n    pkl_paths = [\n        os.path.join(pkl_dir, f_name) \\\n        for f_name in os.listdir(pkl_dir) \\\n        if f_name.endswith(\".pkl\")\n    ]\n    \n    # REMOVE AFTER UPDATING CLASSBASED NOTEBOOK\n    pkl_paths.append(\"/kaggle/input/tmp-intermediate-filaments-pkl-file/intermediate_filaments_tp_list.pkl\")\n    \n    # Initialize\n    tp_id_map = {}\n    for path in pkl_paths:\n        class_id = STR_2_INT_LOWER[path.rsplit(\"/\", 1)[1].replace(\"_tp_list.pkl\", \"\")]\n        with open(path, \"rb\") as f:\n            tp_id_map[class_id] = pickle.load(f)\n    return tp_id_map\n\n    \ndef plot_rgb(arr, figsize=(12,12)):\n    \"\"\" Plot 3 Channel Microscopy Image \"\"\"\n    plt.figure(figsize=figsize)\n    plt.title(f\"RGB Composite Image\", fontweight=\"bold\")\n    plt.imshow(arr)\n    plt.axis(False)\n    plt.show()    \n\n    \ndef convert_rgby_to_rgb(arr):\n    \"\"\" Convert a 4 channel (RGBY) image to a 3 channel RGB image.\n    \n    Advice From Competition Host/User: lnhtrang\n\n    For annotation (by experts) and for the model, I guess we agree that individual \n    channels with full range px values are better. \n    In annotation, we toggled the channels. \n    For visualization purpose only, you can try blending the channels. \n    For example, \n        - red = red + yellow\n        - green = green + yellow/2\n        - blue=blue.\n        \n    Args:\n        arr (numpy array): The RGBY, 4 channel numpy array for a given image\n    \n    Returns:\n        RGB Image\n    \"\"\"\n    \n    rgb_arr = np.zeros_like(arr[..., :-1])\n    rgb_arr[..., 0] = arr[..., 0]\n    rgb_arr[..., 1] = arr[..., 1]+arr[..., 3]/2\n    rgb_arr[..., 2] = arr[..., 2]\n    \n    return rgb_arr\n    \n    \ndef plot_ex(arr, figsize=(20,6), title=None, plot_merged=True, rgb_only=False):\n    \"\"\" Plot 4 Channels Side by Side \"\"\"\n    if plot_merged and not rgb_only:\n        n_images=5 \n    elif plot_merged and rgb_only:\n        n_images=4\n    elif not plot_merged and rgb_only:\n        n_images=4\n    else:\n        n_images=3\n    plt.figure(figsize=figsize)\n    if type(title) == str:\n        plt.suptitle(title, fontsize=20, fontweight=\"bold\")\n\n    for i, c in enumerate([\"Red Channel – Microtubles\", \"Green Channel – Protein of Interest\", \"Blue - Nucleus\", \"Yellow – Endoplasmic Reticulum\"]):\n        if not rgb_only:\n            ch_arr = np.zeros_like(arr[..., :-1])        \n        else:\n            ch_arr = np.zeros_like(arr)\n        if c in [\"Red Channel – Microtubles\", \"Green Channel – Protein of Interest\", \"Blue - Nucleus\"]:\n            ch_arr[..., i] = arr[..., i]\n        else:\n            if rgb_only:\n                continue\n            ch_arr[..., 0] = arr[..., i]\n            ch_arr[..., 1] = arr[..., i]\n        plt.subplot(1,n_images,i+1)\n        plt.title(f\"{c.title()}\", fontweight=\"bold\")\n        plt.imshow(ch_arr)\n        plt.axis(False)\n        \n    if plot_merged:\n        plt.subplot(1,n_images,n_images)\n        \n        if rgb_only:\n            plt.title(f\"Merged RGB\", fontweight=\"bold\")\n            plt.imshow(arr)\n        else:\n            plt.title(f\"Merged RGBY into RGB\", fontweight=\"bold\")\n            plt.imshow(convert_rgby_to_rgb(arr))\n        plt.axis(False)\n        \n    plt.tight_layout(rect=[0, 0.2, 1, 0.97])\n    plt.show()\n    \n    \ndef flatten_list_of_lists(l_o_l):\n    return [item for sublist in l_o_l for item in sublist]\n\n\ndef create_input_list(crp, cgp, cbp, cyp, shuffle=True, val_split=0.025):\n    lbl_arr = flatten_list_of_lists([[k,]*len(v) for k, v in sorted(crp.items())])\n    cr_arr = flatten_list_of_lists([v for k,v in sorted(crp.items())])\n    cg_arr = flatten_list_of_lists([v for k,v in sorted(cgp.items())])\n    cb_arr = flatten_list_of_lists([v for k,v in sorted(cbp.items())])\n    cy_arr = flatten_list_of_lists([v for k,v in sorted(cyp.items())])\n    \n    if val_split is not None:\n        val_lbl_arr = lbl_arr[:int(len(lbl_arr)*val_split)]\n        lbl_arr = lbl_arr[int(len(lbl_arr)*val_split):]\n        \n        val_cr_arr = cr_arr[:int(len(cr_arr)*val_split)]\n        cr_arr = cr_arr[int(len(cr_arr)*val_split):]\n        \n        val_cg_arr = cg_arr[:int(len(cg_arr)*val_split)]\n        cg_arr = cg_arr[int(len(cg_arr)*val_split):]\n        \n        val_cb_arr = cb_arr[:int(len(cb_arr)*val_split)]\n        cb_arr = cb_arr[int(len(cb_arr)*val_split):]\n\n        val_cy_arr = cy_arr[:int(len(cy_arr)*val_split)]\n        cy_arr = cy_arr[int(len(cy_arr)*val_split):]\n        \n    if shuffle:\n        to_shuffle = list(zip(cr_arr, cg_arr, cb_arr, cy_arr, lbl_arr))\n        random.shuffle(to_shuffle)\n        cr_arr, cg_arr, cb_arr, cy_arr, lbl_arr = zip(*to_shuffle)\n        \n        if val_split is not None:\n            val_to_shuffle = list(zip(val_cr_arr, val_cg_arr, val_cb_arr, val_cy_arr, val_lbl_arr))\n            random.shuffle(val_to_shuffle)\n            val_cr_arr, val_cg_arr, val_cb_arr, val_cy_arr, val_lbl_arr = zip(*val_to_shuffle)\n    \n    if val_split is None:\n        return list(cr_arr), list(cg_arr), list(cb_arr), list(cy_arr), list(lbl_arr)\n    else:\n        return (list(cr_arr), list(cg_arr), list(cb_arr), list(cy_arr), list(lbl_arr)), \\\n               (list(val_cr_arr), list(val_cg_arr), list(val_cb_arr), list(val_cy_arr), list(val_lbl_arr))\n\n\ndef get_class_wts(single_ch_paths, n_classes=19, exclude_mitotic=True, multiplier=10, return_counts=False):\n    \"\"\" TBD \"\"\"\n    # Get class counts\n    class_counts = {c_idx:len(single_ch_paths[c_idx]) for c_idx in range(n_classes)}\n\n    # Exclude mitotic spindle\n    if exclude_mitotic:\n        real_min_count = list(sorted(class_counts.values(), reverse=True))[-2]\n    else:\n        real_min_count = list(sorted(class_counts.values(), reverse=True))[-1]\n\n    # Calculate weights\n    class_wts = {k:min(1, multiplier*(real_min_count/v)) for k,v in class_counts.items()}\n\n    if exclude_mitotic:\n        # Manually adjust mitotic spindle to a more appropriate value\n        class_wts[min(class_counts, key=class_counts.get)] = 1.0\n\n    if return_counts:\n        return class_wts, class_counts\n    else:\n        return class_wts","metadata":{"_uuid":"4bba0f8f-1ccf-445b-a8a0-54024bf5bbb5","_cell_guid":"c8122a8c-fedf-42d9-9709-de95b4ea2c46","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preparing the data and model:","metadata":{"_uuid":"2e320f4c-52ff-48fb-94b8-51ae5ed8efe6","_cell_guid":"8542e8bb-8e91-4c73-a06a-bd0a5137a53b","trusted":true}},{"cell_type":"code","source":"train_each_path = [train_red_path, train_green_path, train_blue_path, train_yellow_path]\nprint(train_each_path)\n\n# Define the paths to the training files for the tile dataset as a map from class index to list of paths\ntrain_red_map, train_green_map, train_blue_map, train_yellow_map = get_color_path_maps(train_each_path, None)","metadata":{"_uuid":"0bce8516-1ecb-4d8e-ac4f-5b6368e8ba3e","_cell_guid":"129d5931-ae90-4f62-aef5-c597b99b5c25","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# red_inputs, green_inputs, blue_inputs, yellow_inputs, labels\ntrain_inputs, val_inputs = create_input_list(\n    train_red_map, \n    train_green_map, \n    train_blue_map, \n    train_yellow_map, \n    shuffle=True,\n    val_split=0.075,\n)","metadata":{"_uuid":"7299198b-9de9-432c-bdf6-7bb3666b98d7","_cell_guid":"12e0f1e8-ddee-4cc7-9ff1-9c46d47d1051","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_weights, class_counts = get_class_wts(train_red_map, return_counts=True, multiplier=50)\nprint(class_weights)\nprint(class_counts)","metadata":{"_uuid":"625639eb-de7a-4203-8798-5e9454f4937c","_cell_guid":"b0afcade-165c-41e5-ba66-b8b85091edf6","collapsed":false,"scrolled":true,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Using an LR ramp up because fine-tuning a pre-trained model.\nN_EPOCHS=15\nLR_START = 0.001\nLR_MAX = 0.0011\nLR_MIN = 0.0005\nLR_RAMPUP_EPOCHS = 3\nLR_SUSTAIN_EPOCHS = 2\nLR_EXP_DECAY = 0.75\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        lr = (LR_MAX - LR_MIN) * LR_EXP_DECAY**(epoch - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS) + LR_MIN\n    return lr\n\n# VIEW SCHEDULE\nrng = [i for i in range(N_EPOCHS)]\ny = [lrfn(x) for x in rng]\n\nplt.figure(figsize=(10,4))\nplt.plot(rng, y)\nplt.title(\"CUSTOM LR SCHEDULE\", fontweight=\"bold\")\nplt.show()\n\nprint(f\"Learning rate schedule: {y[0]:.3g} to {max(y):.3g} to {y[-1]:.3g}\")","metadata":{"_uuid":"1b7134ed-71ee-4664-9c11-c19b6002b150","_cell_guid":"bca0aa85-bb8e-4da1-bfba-1ebdebd46d71","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#PARAMS\nMODEL_CKPT_DIR = \"/kaggle/working/ebnet_b2_wdensehead\"\nDROP_YELLOW = True\nNO_NEG_CLASS = False\n\nif NO_NEG_CLASS:\n    class_wts = {k:v for k,v in class_wts.items() if k!=18}\n    class_cnts = {k:v for k,v in class_cnts.items() if k!=18}\n    n_classes = 18\nelse:\n    n_classes=19\n    \nBATCH_SIZE=32\nOPTIMIZER = tf.keras.optimizers.Adam(lr=LR_START)\nLOSS_FN = \"binary_crossentropy\"\nSHUFF_BUFF = 500\n\n\n# AUTO-CALCULATED\nN_EX = len(train_red_map[0])\nN_VAL = int(0.075*N_EX)\nN_TRAIN = N_EX-N_VAL\n\nif not os.path.isdir(MODEL_CKPT_DIR):\n    os.makedirs(MODEL_CKPT_DIR, exist_ok=True)\n    \nprint(f\"{N_TRAIN:<7} TRAINING EXAMPLES\")\nprint(f\"{N_VAL:<7} VALIDATION EXAMPLES\")","metadata":{"_uuid":"e2c5a390-1159-4253-b5a9-e49c2365d742","_cell_guid":"e491a27f-3550-469f-9e72-d93f50949151","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# TRAIN DATASET\ntrain_path_ds = tf.data.Dataset.zip(\n    tuple([tf.data.Dataset.from_tensor_slices(input_ds) for input_ds in train_inputs])\n)\n\n# VALIDATION DATASET\nval_path_ds = tf.data.Dataset.zip(\n    tuple([tf.data.Dataset.from_tensor_slices(input_ds) for input_ds in val_inputs])\n)\n\nprint(f\"\\n ... THERE ARE {N_EX} CELL TILES IN OUR FULL DATASET ... \")\nprint(f\" ... THERE ARE {N_TRAIN} CELL TILES IN OUR TRAIN DATASET ... \")\nprint(f\" ... THERE ARE {N_VAL} CELL TILES IN OUR VALIDATION DATASET ... \\n\")\n\nprint(train_path_ds)\n\nfor a,b,c,d,e in train_path_ds.take(1): \n    print(f\"\\tRed Path      --> {a}\\n\\t\" \\\n          f\"Green Path    --> {b}\\n\\t\" \\\n          f\"Blue Path     --> {c}\\n\\t\" \\\n          f\"Yellow Path   --> {d}\\n\\t\" \\\n          f\"Example Label --> {e} ({INT_2_STR[e.numpy()]})\\n\")","metadata":{"_uuid":"e346f8ca-bbe6-4c06-bb20-1dde88a3d5a7","_cell_guid":"7d2c2536-a65e-4c0a-b264-b60f017ddeb4","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper functions:","metadata":{"_uuid":"bffb586f-fd3a-4982-bc73-136aabc15a37","_cell_guid":"9fed2a62-fb03-48df-99c2-4f30b9367d6a","trusted":true}},{"cell_type":"code","source":"def preprocess_path_ds(rp, gp, bp, yp, lbl, img_size=(224,224), combine=True, drop_yellow=True, no_neg=True):\n    \"\"\" TBD \"\"\"\n    \n    # Adjust class output expectation\n    if no_neg:\n        if lbl==18:\n            lbl_arr = tf.zeros((18,), dtype=tf.uint8)\n        else:\n            lbl_arr = tf.one_hot(lbl, 18, dtype=tf.uint8)\n    else:\n        lbl_arr = tf.one_hot(lbl, 19, dtype=tf.uint8)\n    \n    ri = decode_img(tf.io.read_file(rp), img_size)\n    gi = decode_img(tf.io.read_file(gp), img_size)\n    bi = decode_img(tf.io.read_file(bp), img_size)\n\n    if combine and drop_yellow:\n        return tf.stack([ri[..., 0], gi[..., 0], bi[..., 0]], axis=-1), lbl_arr\n    elif combine:\n        yi = decode_img(tf.io.read_file(yp), img_size)\n        return tf.stack([ri[..., 0], gi[..., 0], bi[..., 0], yi[..., 0]], axis=-1), lbl_arr\n    elif drop_yellow:\n        return ri, gi, bi, lbl_arr\n    else:\n        yi = decode_img(tf.io.read_file(yp), img_size)\n        return ri, gi, bi, yi, lbl_arr\n    \n\ndef augment(img_batch, lbl_batch):\n    # SEEDING & KERNEL INIT\n    K = tf.random.uniform((1,), minval=0, maxval=4, dtype=tf.dtypes.int32)[0]\n    \n    img_batch = tf.image.random_flip_left_right(img_batch)\n    img_batch = tf.image.random_flip_up_down(img_batch)\n    img_batch = tf.image.rot90(img_batch, K)\n    \n    img_batch = tf.image.random_saturation(img_batch, 0.85, 1.15)\n    img_batch = tf.image.random_brightness(img_batch, 0.1)\n    img_batch = tf.image.random_contrast(img_batch, 0.85, 1.15)\n        \n    # Can't figure this out right now\n    #     # Apply a random crop\n    #     img_batch = tf.where(K==0, tf.map_fn(\n    #         fn=lambda img: tf.image.resize(tf.image.random_crop(tf.cast(img, tf.float32), (192,192,3)), (224,224)),\n    #         elems=img_batch,), img_batch)\n\n    return img_batch, lbl_batch","metadata":{"_uuid":"15dfc04c-47b7-44bc-b9ff-67accb329f01","_cell_guid":"751f7d24-81b7-4964-ac7e-47f81b0e07a4","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Validation set","metadata":{"_uuid":"9ab83363-7ea9-4255-9331-2b12f8034307","_cell_guid":"b6fbf5ca-3117-422a-b1f4-3fd409700d41","trusted":true}},{"cell_type":"code","source":"TRAIN_CACHE_DIR = \"/kaggle/train_cache\"\nVAL_CACHE_DIR = \"/kaggle/val_cache\"\n\nif not os.path.isdir(TRAIN_CACHE_DIR):\n    os.makedirs(TRAIN_CACHE_DIR, exist_ok=True)\nif not os.path.isdir(VAL_CACHE_DIR):\n    os.makedirs(VAL_CACHE_DIR, exist_ok=True)\n\ntrain_ds = train_path_ds.map(\n    lambda r,g,b,y,l: preprocess_path_ds(r,g,b,y,l, drop_yellow=DROP_YELLOW, no_neg=NO_NEG_CLASS), \n    num_parallel_calls=tf.data.AUTOTUNE\n)\nval_ds = val_path_ds.map(\n    lambda r,g,b,y,l: preprocess_path_ds(r,g,b,y,l, drop_yellow=DROP_YELLOW, no_neg=NO_NEG_CLASS), \n    num_parallel_calls=tf.data.AUTOTUNE\n)\n    \ntrain_ds = train_ds.cache(TRAIN_CACHE_DIR) \\\n                   .shuffle(SHUFF_BUFF) \\\n                   .batch(BATCH_SIZE) \\\n                   .map(augment, num_parallel_calls=tf.data.AUTOTUNE) \\\n                   .prefetch(tf.data.AUTOTUNE)\n\nval_ds = val_ds.cache(VAL_CACHE_DIR) \\\n               .batch(BATCH_SIZE) \\\n               .prefetch(tf.data.AUTOTUNE)","metadata":{"_uuid":"4105a6a7-e57e-4088-bd2f-1df7326c10a5","_cell_guid":"cea5253d-81bf-40c9-9da1-d61608fa4974","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training the model:","metadata":{"_uuid":"5d84117d-eca3-4e75-bd73-c5587f35300a","_cell_guid":"1c74d110-3b31-4f0d-9680-7e0cac44bee9","trusted":true}},{"cell_type":"code","source":" def get_backbone(efficientnet_name=\"efficientnet_b0\", input_shape=(224,224,3), include_top=False, weights=\"imagenet\", pooling=\"avg\"):\n     if \"b0\" in efficientnet_name:\n         eb = tf.keras.applications.EfficientNetB0(\n             include_top=include_top, weights=weights, pooling=pooling, input_shape=input_shape\n             )\n     elif \"b1\" in efficientnet_name:\n         eb = tf.keras.applications.EfficientNetB1(\n             include_top=include_top, weights=weights, pooling=pooling, input_shape=input_shape\n             )\n     elif \"b2\" in efficientnet_name:\n         eb = tf.keras.applications.EfficientNetB2(\n             include_top=include_top, weights=weights, pooling=pooling, input_shape=input_shape\n             )\n     elif \"b3\" in efficientnet_name:\n         eb = tf.keras.applications.EfficientNetB3(\n             include_top=include_top, weights=weights, pooling=pooling, input_shape=input_shape\n             )\n     elif \"b4\" in efficientnet_name:\n         eb = tf.keras.applications.EfficientNetB4(\n             include_top=include_top, weights=weights, pooling=pooling, input_shape=input_shape\n             )\n     elif \"b5\" in efficientnet_name:\n         eb = tf.keras.applications.EfficientNetB5(\n             include_top=include_top, weights=weights, pooling=pooling, input_shape=input_shape\n             )\n     elif \"b6\" in efficientnet_name:\n         eb = tf.keras.applications.EfficientNetB6(\n             include_top=include_top, weights=weights, pooling=pooling, input_shape=input_shape\n             )\n     elif \"b7\" in efficientnet_name:\n         eb = tf.keras.applications.EfficientNetB7(\n             include_top=include_top, weights=weights, pooling=pooling, input_shape=input_shape\n             )\n     else:\n         raise ValueError(\"Invalid EfficientNet Name!!!\")\n     return eb\n\n\n def add_head_to_bb(bb, n_classes=19, dropout=0.05, head_layer_nodes=(512,)):\n     x = tf.keras.layers.BatchNormalization()(bb.output)\n     x = tf.keras.layers.Dropout(dropout)(x)\n   \n     for n_nodes in head_layer_nodes:\n         x = tf.keras.layers.Dense(n_nodes, activation=\"relu\")(x)\n         x = tf.keras.layers.BatchNormalization()(x)\n         x = tf.keras.layers.Dropout(dropout/2)(x)\n   \n     output = tf.keras.layers.Dense(n_classes, activation=\"sigmoid\")(x)\n     return tf.keras.Model(inputs=bb.inputs, outputs=output)\n\n eb = get_backbone(\"b2\")\n eb = add_head_to_bb(eb, n_classes, dropout=0.5)\n eb.compile(optimizer=OPTIMIZER, loss=LOSS_FN, metrics=[\"acc\", tf.keras.metrics.AUC(name=\"auc\", multi_label=True)])\n\n tf.keras.utils.plot_model(eb, show_shapes=True, show_dtype=True, dpi=55)","metadata":{"_uuid":"60fafc4c-4eee-4b5f-9ca9-5d934a97e7ab","_cell_guid":"82c93fd9-4ee9-452d-9d73-88922a4cda64","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = eb.fit(\n    train_ds, \n    validation_data=val_ds, \n    callbacks=[\n        tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=5, verbose=1, restore_best_weights=True),\n        tf.keras.callbacks.ModelCheckpoint(filepath=os.path.join(MODEL_CKPT_DIR, \"ckpt-{epoch:04d}-{val_loss:.4f}.ckpt\"), verbose=1),\n        tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=1)\n    ], \n    class_weight=class_weights, \n    epochs=N_EPOCHS\n)\neb.save(\"./model_efficientnet_b2\")","metadata":{"_uuid":"d50f1ac5-8086-4d09-8ea9-1917e81751a8","_cell_guid":"4e22ee76-59d4-4877-943d-ef98eae97134","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]}]}