{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Comments\n\nThis is an update of the previous version where we had a CV score of 0.946, it was a blend model using effb6 and effb7.\n\nIn this script we will only use effb6, remember that we stratified our tf records using the client id to avoid leakage, that is why previous version have a better cv score.\n\nOut of folds score in this version is 0.951, their were 2 major changes, the first one is to use image size of 768 x 768 and the second one is to use Binary Focal Loss.\n\nPrevious ensemble score without client ids stratification:\n\nPublic leaderboard: 0.959 \nCV Ensemble: 0.9563\n\nYou can find the link of the dataset here: \n\n* https://www.kaggle.com/ragnar123/ranzcr-tf-records-768-stratified. \n\nUsed a tf.data pipeline with tpu for training in kaggle, you can find the link of the script here: \n\n* https://www.kaggle.com/ragnar123/ranzcr-efficientnetb6-baseline\n\nFinally, this is the inference pipeline where we also use tf.data but we extract each image directly from the directory (not using tf records because of hidden test set)\n\nI hope this help tensorflow users because high lb score are mainly pytorch scripts."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport re\nimport numpy as np\nimport pandas as pd\nimport random\nimport math\nfrom sklearn import metrics\nfrom sklearn.model_selection import KFold\nimport tensorflow as tf\nfrom tensorflow.keras import backend as K\nimport tensorflow_addons as tfa\nfrom kaggle_datasets import KaggleDatasets\n!pip install ../input/cassava-models/Keras_Applications-1.0.8-py3-none-any.whl\n!pip install ../input/cassava-models/efficientnet-1.1.0-py3-none-any.whl\nimport efficientnet.tfkeras as efn\nimport glob","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"try:\n    # TPU detection. No parameters necessary if TPU_NAME environment variable is\n    # set: this is always the case on Kaggle.\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nelse:\n    # Default distribution strategy in Tensorflow. Works on CPU and single GPU.\n    strategy = tf.distribute.get_strategy()\n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# For tf.dataset\nAUTO = tf.data.experimental.AUTOTUNE\n\n# Configuration\nEPOCHS = 15\nBATCH_SIZE = 16 * strategy.num_replicas_in_sync\nIMAGE_SIZE = [768, 768]\n# Seed\nSEED = 123\n# Learning rate\nLR = 0.001\n# Test time augmentation rounds\nTTA = 5\n# Verbosity\nVERBOSE = 2\n# Number of classes\nN_CLASSES = 11\n\n# Training filenames directory\nTEST_FILENAMES = '../input/ranzcr-clip-catheter-line-classification/test/*.jpg'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Data augmentation function\ndef data_augment(image, StudyInstanceUID):\n    image = tf.image.random_flip_left_right(image)\n    image = tf.image.random_flip_up_down(image)\n    image = tf.image.random_hue(image, 0.01)\n    image = tf.image.random_saturation(image, 0.70, 1.30)\n    image = tf.image.random_contrast(image, 0.80, 1.20)\n    image = tf.image.random_brightness(image, 0.10)\n    return image, StudyInstanceUID\n\n# Function to decode our images\ndef decode_image(image_data):\n    image = tf.image.decode_jpeg(image_data, channels = 3)\n    image = tf.image.resize(image, IMAGE_SIZE)\n    image = tf.cast(image, tf.float32) / 255.0\n    return image\n\n# Function to get StudyInstanceUID\ndef get_image_name(file_path):\n    parts = tf.strings.split(file_path, os.path.sep)\n    StudyInstanceUID = parts[-1]\n    return StudyInstanceUID\n\n# Function to read our image and get our StudyInstanceUID\ndef read_image(file_path):\n    StudyInstanceUID = get_image_name(file_path)\n    image = tf.io.read_file(file_path)\n    image = decode_image(image)\n    return image, StudyInstanceUID\n\n# Function to get our test data were we add a flag for test time augmentation\ndef get_tta(filenames, tta = False):\n    dataset = tf.data.Dataset.list_files(filenames, shuffle = False)\n    dataset = dataset.map(read_image, num_parallel_calls = AUTO)\n    dataset = dataset.map(data_augment, num_parallel_calls = AUTO)\n    if tta:\n        dataset = dataset.repeat() \n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.prefetch(AUTO)\n    return dataset\n\nNUM_TESTING_IMAGES = len(os.listdir('../input/ranzcr-clip-catheter-line-classification/test/'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Function to create our EfficientNetB6 model\ndef get_model():\n    \n    with strategy.scope():\n        \n        inp = tf.keras.layers.Input(shape = (*IMAGE_SIZE, 3))\n        x = efn.EfficientNetB6(include_top = False, weights = None)(inp)\n        x = tf.keras.layers.GlobalAveragePooling2D()(x)\n        output = tf.keras.layers.Dense(N_CLASSES, activation = 'sigmoid')(x)\n        \n        model = tf.keras.models.Model(inputs = [inp], outputs = [output])\n\n        opt = tf.keras.optimizers.Adam(learning_rate = LR)\n\n        model.compile(\n            optimizer = opt,\n            loss = [tfa.losses.SigmoidFocalCrossEntropy(alpha = 0.50, gamma = 2.0)],\n            metrics = [tf.keras.metrics.AUC(multi_label = True)]\n        )\n\n        return model\n    \ndef inference(model_paths):\n    \n    # Create a numpy array to store predictions\n    predictions = np.zeros((NUM_TESTING_IMAGES, N_CLASSES))\n    \n    print('Extracting test image StudyInstanceUID...')\n    # Get the test dataset without tta to extract image names\n    test_dataset = get_tta(TEST_FILENAMES, tta = False)\n    StudyInstanceUID = test_dataset.map(lambda image, StudyInstanceUID: StudyInstanceUID).unbatch()\n    StudyInstanceUID = next(iter(StudyInstanceUID.batch(NUM_TESTING_IMAGES))).numpy().astype('U')\n    print('Test image StudyInstanceUID completed...')\n    \n    for fold, model_path in enumerate(model_paths):\n        print('\\n')\n        print('-'*50)\n        print(f'Predicting fold {fold + 1}')\n        K.clear_session()\n        model = get_model()\n        # Load weights of pretrained model\n        model.load_weights(model_path)\n        \n        steps = TTA * ((NUM_TESTING_IMAGES / BATCH_SIZE) + 1)\n        # Get the test dataset with tta to extract image\n        test_dataset = get_tta(TEST_FILENAMES, tta = True)\n        image = test_dataset.map(lambda image, StudyInstanceUID: image)\n        probabilities = model.predict(image, steps = steps)[: TTA * NUM_TESTING_IMAGES]\n        probabilities = np.mean(probabilities.reshape((NUM_TESTING_IMAGES, TTA, N_CLASSES), order = 'F'), axis = 1)\n        predictions += probabilities / len(model_paths)\n        \n    target_columns = [\"ETT - Abnormal\", \"ETT - Borderline\", \"ETT - Normal\", \"NGT - Abnormal\", \"NGT - Borderline\", \"NGT - Incompletely Imaged\", \"NGT - Normal\", \"CVC - Abnormal\", \"CVC - Borderline\", \n                      \"CVC - Normal\", \"Swan Ganz Catheter Present\"]\n    predictions_df = pd.DataFrame(predictions, columns = target_columns)\n        \n    sub = pd.DataFrame({'StudyInstanceUID': StudyInstanceUID})\n    sub['StudyInstanceUID'] = [StudyInstanceUID[:-4] for StudyInstanceUID in sub['StudyInstanceUID']]\n    sub = pd.concat([sub, predictions_df], axis = 1)\n    sub.to_csv('submission.csv', index = False)\n        \n    return sub\n        \n# Get pretrained models list for inference\nmodel_paths = glob.glob('../input/ranzcr-effb6-model/*.h5')\nsub = inference(model_paths)\nsub.head()","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}