{"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":"The objective of this exercise is to test TPU EfficientUNet 512x512 with freeze-pretrained SUB EffUNet5. This exercise is to improve the existing algorithms used to detect functional tissue units (FTUs) across different tissue preparation pipelines.\n\nKudos to this kernels, used in the exercise.\n1. ISA's Kernel : https://www.kaggle.com/isakev/hubmap-freeze-pretrained-sub-effunet5-valloss/\n2. Wojtek' Kernel : https://www.kaggle.com/wrrosa/hubmap-tf-with-tpu-efficientunet-512x512-subm/data?scriptVersionId=51404430\n3. https://www.kaggle.com/joshi98kishan/hubmap-keras-pipeline-training-inference\n4. https://www.kaggle.com/leighplt/pytorch-fcn-resnet50","metadata":{}},{"cell_type":"code","source":"#mod_path = '/kaggle/input/hubmap-tf-with-tpu-efficientunet-512x512-train/'\n\nmod_path = '../input/hubmapb2h5/'\nimport yaml\nimport pprint\nwith open(mod_path+'params.yaml') as file:\n    P = yaml.load(file, Loader=yaml.FullLoader)\n    pprint.pprint(P)\n    \nTHRESHOLD = 0.4\nWINDOW = 1024\nMIN_OVERLAP = 300\nNEW_SIZE = P['DIM']\n\nSUBMISSION_MODE = 'PUBLIC_TFREC' \n# 'PUBLIC_TFREC' = use created tfrecords for public test set with MIN_OVERLAP = 300 tiling 1024-512, ignore other (private test) data\n# 'FULL' do not use tfrecords, just full submission \n\nCHECKSUM = True # compute mask sum for each image","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# METRICS\n\nimport json\n\nwith open(mod_path + 'metrics.json') as json_file:\n    M = json.load(json_file)\nprint('Model run datetime: '+M['datetime'])\nprint('OOF val_dice_coe: ' + str(M['oof_dice_coe']))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"! pip install ../input/kerasapplications/keras-team-keras-applications-3b180cb -f ./ --no-index -q\n! pip install ../input/efficientnet/efficientnet-1.1.0/ -f ./ --no-index -q\nimport numpy as np\nimport pandas as pd\nimport os\nimport glob\nimport gc\n\nimport rasterio\nfrom rasterio.windows import Window\n\nimport pathlib\nfrom tqdm.notebook import tqdm\nimport cv2\n\nimport tensorflow as tf\nimport efficientnet as efn\nimport efficientnet.tfkeras\n\nimport os, glob, gc\nimport json\n\nosj = os.path.join","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Functions from Wojteck Kernel","metadata":{}},{"cell_type":"code","source":"def rle_encode_less_memory(img):\n    pixels = img.T.flatten()\n    pixels[0] = 0\n    pixels[-1] = 0\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 2\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef make_grid(shape, window=256, min_overlap=32):\n    \"\"\"\n        Return Array of size (N,4), where N - number of tiles,\n        2nd axis represente slices: x1,x2,y1,y2 \n    \"\"\"\n    x, y = shape\n    nx = x // (window - min_overlap) + 1\n    x1 = np.linspace(0, x, num=nx, endpoint=False, dtype=np.int64)\n    x1[-1] = x - window\n    x2 = (x1 + window).clip(0, x)\n    ny = y // (window - min_overlap) + 1\n    y1 = np.linspace(0, y, num=ny, endpoint=False, dtype=np.int64)\n    y1[-1] = y - window\n    y2 = (y1 + window).clip(0, y)\n    slices = np.zeros((nx,ny, 4), dtype=np.int64)\n    \n    for i in range(nx):\n        for j in range(ny):\n            slices[i,j] = x1[i], x2[i], y1[j], y2[j]    \n    return slices.reshape(nx*ny,4)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"##MODEL\nidentity = rasterio.Affine(1, 0, 0, 0, 1, 0)\nfold_models_1 = []\nfor fold_model_path in glob.glob(mod_path+'*.h5'):\n    fold_models_1.append(tf.keras.models.load_model(fold_model_path,compile = False))\nprint(len(fold_models_1))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"TF Records added from Wojtek's Kernel","metadata":{}},{"cell_type":"code","source":"AUTO = tf.data.experimental.AUTOTUNE\nimage_feature = {\n    'image': tf.io.FixedLenFeature([], tf.string),\n    'x1': tf.io.FixedLenFeature([], tf.int64),\n    'y1': tf.io.FixedLenFeature([], tf.int64)\n}\ndef _parse_image(example_proto):\n    example = tf.io.parse_single_example(example_proto, image_feature)\n    image = tf.reshape( tf.io.decode_raw(example['image'],out_type=np.dtype('uint8')), (P['DIM'],P['DIM'], 3))\n    return image, example['x1'], example['y1']\n\ndef load_dataset(filenames, ordered=True):\n    ignore_order = tf.data.Options()\n    if not ordered:\n        ignore_order.experimental_deterministic = False\n    dataset = tf.data.TFRecordDataset(filenames)\n    dataset = dataset.with_options(ignore_order)\n    dataset = dataset.map(_parse_image)\n    return dataset\n\ndef get_dataset(FILENAME):\n    dataset = load_dataset(FILENAME)\n    dataset  = dataset.batch(64)\n    dataset = dataset.prefetch(AUTO)\n    return dataset","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Parameters from ISA's Kernel","metadata":{}},{"cell_type":"code","source":"debug = True # True False\nn_debug_images = 1 if debug else 1000000000\nn_debug_slices = 20 if debug else 1000000000\n\n# whether to run prediction when committing. WILL RUN predictions during submission in any case\ndo_predict = False  if not debug else True\n\n#models_dir = '../input/hubmap-models-cv-08848-pl-0847'\n#model_filepaths = [ os.path.join(models_dir, f\"model-fold-{i}.h5\") for i in range(4)]\n\nmodels_dir = '../input/hubmapb5h5'\nmodel_filepaths = [ os.path.join(models_dir, f\"model-fold-{i}.h5\") for i in range(5)]\n\nassert len(model_filepaths)==len(np.unique(model_filepaths))\n#folds_to_predict = [i for (i, fn) in enumerate(model_filepaths) if os.path.isfile(fn)]\nmodel_dirnames = [os.path.dirname(filepath) for filepath in model_filepaths]\n\n#check_order = [fn.split('.')[-2].split('-')[-1] == i for (i,fn) in enumerate(model_filepaths) if fn.strip()!='']\n#assert np.sum(check_order)==0, 'models should be in folds order or empty string'\n\nimport yaml\nimport pprint\nwith open(osj(model_dirnames[0],'params.yaml')) as file:\n    P = yaml.load(file, Loader=yaml.FullLoader)\n    pprint.pprint(P)\n\nTHRESHOLD = 0.30\nWINDOW = 1024\nMIN_OVERLAP = 32\nNEW_SIZE = P['DIM']\n\nassert sum([not os.path.isfile(path_) for path_ in model_filepaths]) == 0\nprint(\"\\n Number of models:: {}\".format(len(model_filepaths)))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ave_score = 0\nfor i, m_path in enumerate(model_filepaths):\n    fold_ = int(m_path.split('.')[-2].split('-')[-1])\n    with open(osj(model_dirnames[i],'metrics.json')) as json_file:\n        M = json.load(json_file)\n    print(f\"\\n ----------- \\nModel {model_dirnames[i].split('/')[-1]}\" +\n          '\\nval_dice_coe: '+ str(round(M['val_dice_coe'][fold_], 5)) +\n          '\\tval_loss: ' + str(round(M['val_loss'][fold_], 5)) +\n          '\\tval_accuracy: '+ str(round(M['val_accuracy'][fold_], 5))\n          )\n\n\n\nfor model_group in np.unique(model_dirnames):\n    with open(osj(model_group,'metrics.json')) as json_file:\n        M = json.load(json_file)\n        ave_dice = np.mean(M['val_dice_coe']) \n    ave_loss = np.mean(M['val_loss'])  # /len(folds_to_predict)\n    ave_accuracy = np.mean(M['val_accuracy'])\n    print(f\"\\n ============ MODEL GROUP {model_group} ==============\")\n    print(\" ------------ \\nAVERAGE DICE SCORE = {}\".format(round(ave_dice, 5)))\n    print(\" ------------ \\nAVERAGE VALIDATION LOSS = {}\".format(round(ave_loss, 5)))\n    print(\" ------------ \\nAVERAGE VALIDATION ACCURACY = {}\".format(round(ave_accuracy, 5)))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nif do_predict:\n    identity = rasterio.Affine(1, 0, 0, 0, 1, 0)\n    fold_models_2 = []\n    \n    for fold_model_path in model_filepaths:\n        fold_models_2.append(tf.keras.models.load_model(fold_model_path,compile = False))\n    print(len(fold_models_2))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Results","metadata":{}},{"cell_type":"code","source":"import pathlib\np = pathlib.Path('../input/hubmap-kidney-segmentation')\nsubm = {}\n\nfor i, filename in tqdm(enumerate(p.glob('test/*.tiff')), \n                        total = len(list(p.glob('test/*.tiff')))):\n    \n    print(f'{i+1} Predicting {filename.stem}')\n    \n    dataset = rasterio.open(filename.as_posix(), transform = identity)\n    preds = np.zeros(dataset.shape, dtype=np.uint8)    \n    slices = make_grid(dataset.shape, window=WINDOW, min_overlap=MIN_OVERLAP)\n\n    if dataset.count != 3:\n        print('Image file with subdatasets as channels')\n        layers = [rasterio.open(subd) for subd in dataset.subdatasets]\n            \n    for (x1,x2,y1,y2) in slices:\n        if dataset.count == 3:\n            image = dataset.read([1,2,3],\n                            window=Window.from_slices((x1,x2),(y1,y2)))\n            image = np.moveaxis(image, 0, -1)\n        else:\n            image = np.zeros((WINDOW, WINDOW, 3), dtype=np.uint8)\n            for fl in range(3):\n                image[:,:,fl] = layers[fl].read(window=Window.from_slices((x1,x2),(y1,y2)))\n                    \n        image = cv2.resize(image, (NEW_SIZE, NEW_SIZE),interpolation = cv2.INTER_AREA)\n        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)\n        image = np.expand_dims(image, 0)\n\n        pred_1 = None\n        pred_2 = None\n        \n        for fold_model in fold_models_1:\n            if pred_1 is None:\n                pred_1 = np.squeeze(fold_model.predict(image))\n            else:\n                pred_1 += np.squeeze(fold_model.predict(image))\n        \n        for fold_model in fold_models_2:\n            if pred_2 is None:\n                pred_2 = np.squeeze(fold_model.predict(image))\n            else:\n                pred_2 += np.squeeze(fold_model.predict(image))\n        \n        pred_1 = pred_1/len(fold_models_1)\n        pred_2 = pred_2/len(fold_models_2)\n        \n        pred = 0.5 * pred_1 + 0.5 * pred_2\n\n        pred = cv2.resize(pred, (WINDOW, WINDOW))\n        preds[x1:x2,y1:y2] += (pred > THRESHOLD).astype(np.uint8)\n\n    preds = (preds > 0.5).astype(np.uint8)\n    \n    subm[i] = {'id':filename.stem, 'predicted': rle_encode_less_memory(preds)}\n    \n    if CHECKSUM:\n        print('Checksum: '+ str(np.sum(preds)))\n    \n    del preds\n    gc.collect();","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame.from_dict(subm, orient='index')\nsubmission.to_csv('submission.csv', index=False)\nsubmission.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}