{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np \nimport pandas as pd \nimport os\nimport PIL\nimport re\nimport matplotlib.pyplot as plt\n%matplotlib inline\nfrom sklearn.model_selection import StratifiedKFold,KFold\nfrom sklearn.metrics import roc_auc_score\nfrom tqdm import tqdm\nfrom kaggle_datasets import KaggleDatasets\n\nimport tensorflow as tf\nprint(\"Tensorflow version \" + tf.__version__)\nfrom tensorflow.keras.applications import ResNet50,MobileNetV2,InceptionV3\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nimport tensorflow.keras.backend as K\n\n!pip install -q tfa-nightly   # only nightly build supports tfa image augmentations with TPU model training\nimport tensorflow_addons as tfa\ntfa.register_all(custom_kernels=False) # otherwise TPU throws up error\n\n! pip install -q efficientnet\nimport efficientnet.tfkeras as efn","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Configuration","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"DEVICE = 'TPU'\nif DEVICE == \"TPU\":\n    print(\"connecting to TPU...\")\n    try:\n        tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n        print('Running on TPU ', tpu.master())\n    except ValueError:\n        print(\"Could not connect to TPU\")\n        tpu = None\n\n    if tpu:\n        try:\n            print(\"initializing  TPU ...\")\n            tf.config.experimental_connect_to_cluster(tpu)\n            tf.tpu.experimental.initialize_tpu_system(tpu)\n            strategy = tf.distribute.experimental.TPUStrategy(tpu)\n            print(\"TPU initialized\")\n        except _:\n            print(\"failed to initialize TPU\")\n    else: DEVICE = \"GPU\"\n\n\nif DEVICE != \"TPU\":\n    print(\"Using default strategy for CPU and single GPU\")\n    strategy = tf.distribute.get_strategy()\n\nif DEVICE == \"GPU\":\n    print(\"Num GPUs Available: \", len(tf.config.experimental.list_physical_devices('GPU')))\n    \n\nAUTO     = tf.data.experimental.AUTOTUNE\nREPLICAS = strategy.num_replicas_in_sync\nprint('REPLICAS: {}'.format(REPLICAS))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Config","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_PATH = '../input/siim-isic-melanoma-classification/'\nIMAGE_PATH= DATA_PATH+'jpeg/train/'\nINCLUDE_2019_DATA = True  # whether to use image of ISIC 2019 competition\nINCLUDE_2018_DATA = True  # whether to use image of 2018 + 2017 competitions\nINCLUDE_CD_MALIGNANT = True # include extra malignant images shared by Chris Deotte\nUPSAMPLE = True             # Upsample malignant images from the current competition data only\n\nDIM = 192  # image size to use for training, choose among 128,192,256\nBATCH_SIZE = 32 * REPLICAS\nEPOCHS = 15\nVERBOSE = 1\nTTA = 10    #  number of test-time augmentations, the same value is used for validation-time augmentation \ntf.random.set_seed(250688)\n    \n    \n# augmentation params\nMAX_ROT_ANGLE = 180.0\nMAX_SHEAR_LEVEL = 0.1\nHSHIFT, VSHIFT = 5., 5. # max. number of pixels to shift(translation) horizontally and vertically\nMAX_ROT_ANGLE = np.pi*MAX_ROT_ANGLE/180 # in radians\nAUGMENT_FRAC = 0.7 # probability that an image will go through the augmentation pipeline\nNUM_CUTOUTS = 10 # how many cutouts to be inserted on each image\nCUTOUT_SIZE = 15 # cutout square dimension (in number of pixels)\nCUTOUT_FRAC = 0.8 # probability of cutout augmentation being applied to an image (if augmentation is turned on via AUGMENT_FRAC)\n\n# Loss parameters\nLR = 1e-3  # learning rate with Adam/RectifiedAdam\nLOSS_TYPE = \"FOCAL\" # BCE or FOCAL\nGAMMA = 2. # focal loss\nALPHA = 0.8  # focal loss\n\n# Optimizer\nOPT_TYPE = \"RAdam\" # \"Adam\" or \"RAdam\"\n\n#For using TPU's, you must read data from a GCS bucket for high throughput. For using GPU's you can skip reading from GCS an.\nGCS_PATH_ORG = KaggleDatasets().get_gcs_path(\"siim-isic-melanoma-classification\")\nGCS_PATH = KaggleDatasets().get_gcs_path(\"melanoma-{}x{}\".format(DIM,DIM)) # for resized TFrecords (triple stratified)\nGCS_PATH_2019 = KaggleDatasets().get_gcs_path(\"isic2019-{}x{}\".format(DIM,DIM)) \nGCS_PATH_M = KaggleDatasets().get_gcs_path(\"malignant-v2-{}x{}\".format(DIM,DIM))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Data files access\n\ntrain_files = tf.io.gfile.glob(GCS_PATH+'/train*.tfrec')\nif INCLUDE_2019_DATA:\n    train_files+= tf.io.gfile.glob([f\"{GCS_PATH_2019}/train{(2*x +1):02d}-*.tfrec\" for x in range(14)])  # odd-numbered tfrecords\nif INCLUDE_2018_DATA:\n    train_files+= tf.io.gfile.glob([f\"{GCS_PATH_2019}/train{(2*x):02d}-*.tfrec\" for x in range(15)]) # even numbered tfrecords\nif INCLUDE_CD_MALIGNANT:\n    new_malignant_tfrecords = np.arange(15,30).tolist()\n    train_files+= tf.io.gfile.glob([f\"{GCS_PATH_M}/train{x}-*.tfrec\" for x in new_malignant_tfrecords])\ntest_files = tf.io.gfile.glob(GCS_PATH+'/test*.tfrec')\n\nnp.random.shuffle(train_files)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = pd.read_csv(DATA_PATH+\"train.csv\")\npos = data[data.target==1].shape[0]\nneg = data[data.target==0].shape[0]\ntotal = data.shape[0]\n\n# for setting class weights if required\nweight_for_0 = (1 / neg)*(total)/2.0 \nweight_for_1 = (1 / pos)*(total)/2.0\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Augmentation\n- Rotate, shear, translation, cutout, crop and some colour operations.","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"RESIZE = 256\n\n\ndef test_aug_pipeline(img_path, rotate=True,shear=True, translate=True, colour_ops=True, cutout=True, num_cutouts=10,crop=True):\n    img_raw = tf.io.read_file(img_path)\n    image = tf.image.decode_jpeg(img_raw, channels=3)  #tf.io.decode_image(img_raw)\n    \n    image = tf.image.resize(image, [RESIZE,RESIZE])\n    image = tf.cast(image, tf.float32) / 255.0\n    \n    image = tf.image.random_flip_left_right(image)\n    if colour_ops:\n        image = tf.image.random_brightness(image, max_delta= 0.05)\n        image = tf.image.random_saturation(image, lower=0.5, upper=1.5)\n        image = tf.image.random_hue(image, 0.05)\n        image = tf.image.random_contrast(image, 0.8, 1.2)\n    \n    if crop:\n        tf.cond(tf.random.uniform([], 0, 1) > 0.5, lambda: tf.image.central_crop(image, central_fraction= 0.7+0.3*tf.random.uniform(shape=[])), lambda : tf.image.central_crop(image,central_fraction=1.0))\n        image = tf.image.resize(image, [RESIZE,RESIZE])\n    \n    if shear:\n        image =  tfa.image.transform(image, [1.0, MAX_SHEAR_LEVEL * tf.random.uniform(shape=[],minval=-1,maxval=1), 0.0, MAX_SHEAR_LEVEL * tf.random.uniform(shape=[],minval=-1,maxval=1), 1.0, 0.0, 0.0, 0.0])\n\n    if rotate:\n        image = tfa.image.rotate(image, MAX_ROT_ANGLE * tf.random.uniform([], dtype=tf.float32)) # rotation\n    if translate:\n        image = tfa.image.translate(image, [HSHIFT * tf.random.uniform(shape=[],minval=-1, maxval=1), VSHIFT * tf.random.uniform(shape=[],minval=-1, maxval=1)]) # [dx dy] shift/translation\n    if cutout:\n        image = tfa.image.random_cutout(tf.expand_dims(image, axis=0),mask_size=10,constant_values= 0) # cutout\n        for _ in range(num_cutouts-1):\n               image = tfa.image.random_cutout(image,mask_size=10,constant_values= 0) # cutout\n    image = tf.clip_by_value(image, 0, 1)\n    _ = plt.imshow(tf.squeeze(image))\n    return image\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"file = np.random.choice(tf.io.gfile.glob(GCS_PATH_ORG+\"/jpeg/train/*.jpg\"))\n_=test_aug_pipeline(file, translate=True,rotate=True,crop=True,cutout=True,colour_ops=True,shear=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Loader (input pipeline)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def count_data_items(filenames):\n    '''\n    Extract the image count from the tfrecord filenames\n    '''\n    num_files = [int(re.compile(r\"-([0-9]*)\\.\").search(filename).group(1)) \n         for filename in filenames]\n    return np.sum(num_files)\n\ndef decode_image(image_string, label=None): # label or return_image_name\n    '''\n    Convert the image from byte string to jpeg and scale it \n    '''\n    image = tf.image.decode_jpeg(image_string, channels=3)\n    image = tf.cast(image, tf.float32) / 255.0\n    # uncomment the line below if you wan't to resize on the fly in memory, I'm using resized images already\n    #image = tf.image.resize(image, [64, 64])\n    if DEVICE== 'TPU':\n        image = tf.reshape(image, [DIM,DIM, 3])  # explicit size needed for TPU\n    if label is not None:\n        return image, label\n    else:\n        return image\n\ndef read_labelled_tfrecord(example, return_meta_data = False):\n    tfrec_format = {\n        'image'                        : tf.io.FixedLenFeature([], tf.string),\n        'image_name'                   : tf.io.FixedLenFeature([], tf.string),\n        'patient_id'                   : tf.io.FixedLenFeature([], tf.int64),\n        'sex'                          : tf.io.FixedLenFeature([], tf.int64),\n        'age_approx'                   : tf.io.FixedLenFeature([], tf.int64),\n        'anatom_site_general_challenge': tf.io.FixedLenFeature([], tf.int64),\n        'diagnosis'                    : tf.io.FixedLenFeature([], tf.int64),\n        'target'                       : tf.io.FixedLenFeature([], tf.int64)\n    }           \n    example = tf.io.parse_single_example(example, tfrec_format)   \n    if return_meta_data:\n        return example['image'], example['target'],example['sex'], example['age_approx'],example['anatom_site_general_challenge']\n    else:\n        return example['image'], example['target']\n    \n\ndef read_unlabelled_tfrecord(example, return_image_names = True):\n    tfrec_format = {\n        'image'                        : tf.io.FixedLenFeature([], tf.string),\n        'image_name'                   : tf.io.FixedLenFeature([], tf.string),\n    }           \n    example = tf.io.parse_single_example(example, tfrec_format)    \n    if return_image_names:\n        return example['image'], example['image_name']\n    else:\n        return example['image']\n \n\ndef crop_resize(x, label=None):   # dataset = dataset.map(lambda x,y: tf.py_function(crop_resize, [x,y], [tf.float32, tf.int64] ))\n    image = tf.image.central_crop(x, central_fraction= 0.7+0.3*tf.random.uniform(shape=[]).numpy())\n    image = tf.image.resize(image, [DIM,DIM]) \n\n    return image,label\n  \ndef do_augmentation(image,label=None):  \n    if (tf.random.uniform([],0,1)<AUGMENT_FRAC): # if AUGMENT_FRAC=0.4, then only 40% of the images will be augmented\n        image = tf.image.random_flip_left_right(image)\n        # Colour op transformations\n        image = tf.image.random_brightness(image, max_delta= 0.05)\n        image = tf.image.random_saturation(image, lower=0.5, upper=1.5)\n        image = tf.image.random_hue(image, 0.05)\n        image = tf.image.random_contrast(image, 0.8, 1.2)\n        \n        # crop(central) and resize (zoom)\n        image = tf.image.resize_with_crop_or_pad(image, tf.random.uniform(shape=[], minval= tf.cast(0.7*DIM, tf.int32), maxval=DIM, dtype=tf.int32), target_width= tf.random.uniform(shape=[], minval=tf.cast(0.7*DIM, tf.int32), maxval=DIM, dtype=tf.int32))\n        image = tf.image.resize(image, [DIM,DIM])\n#        image = tf.image.central_crop([image], central_fraction= 0.7+0.3*tf.random.uniform(shape=[]))  \n        \n        # shear\n        shear_x = MAX_SHEAR_LEVEL* tf.random.uniform(shape=[],minval=-1,maxval=1)\n        shear_y = MAX_SHEAR_LEVEL * tf.random.uniform(shape=[],minval=-1,maxval=1)\n        image =  tfa.image.transform(image, [1.0, shear_x, 0.0, shear_y, 1.0, 0.0, 0.0, 0.0])\n        # rotation\n        image = tfa.image.rotate(image, MAX_ROT_ANGLE * tf.random.uniform([], dtype=tf.float32)) # rotation\n        # translation\n        image = tfa.image.translate(image, [HSHIFT * tf.random.uniform(shape=[],minval=-1, maxval=1), VSHIFT * tf.random.uniform(shape=[],minval=-1, maxval=1)]) # [dx dy] shift/translation\n        # cutout\n        if (tf.random.uniform([],0,1)< CUTOUT_FRAC): \n            image = tfa.image.random_cutout(tf.expand_dims(image, axis=0),mask_size=CUTOUT_SIZE,constant_values= 0) \n            for _ in range(NUM_CUTOUTS-1):\n                image = tfa.image.random_cutout(image,mask_size=CUTOUT_SIZE,constant_values= 0) \n        \n        image = tf.clip_by_value(image, 0, 1)\n     \n    image = tf.reshape(image, [DIM,DIM, 3])\n    if label is not None:\n        return tf.squeeze(image),label\n    else:\n        return tf.squeeze(image)\n\ndef data_loader(filenames, labelled=True, augment=True, repeat=True, shuffle=True,ordered=True,return_image_names=True, batch_size = BATCH_SIZE):\n    \"\"\"\n    Create tf Dataset for training and validation sets\n    \"\"\"\n    option_no_order = tf.data.Options()\n    if not ordered:\n        option_no_order.experimental_deterministic = False\n    \n    dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTO)\n    dataset.with_options(option_no_order)  # automatically interleaves reads from multiple files\n    if labelled:\n        dataset = dataset.map(read_labelled_tfrecord, num_parallel_calls=AUTO)\n    else:\n        dataset = dataset.map(lambda example: read_unlabelled_tfrecord(example,return_image_names=return_image_names), num_parallel_calls=AUTO)\n    \n    dataset = dataset.cache()\n    dataset = dataset.map(decode_image, num_parallel_calls=AUTO)\n\n    if shuffle:\n        dataset = dataset.shuffle(2048)\n    if repeat:\n        dataset = dataset.repeat()\n        \n    if augment:\n        dataset = dataset.map(do_augmentation, num_parallel_calls=AUTO)\n#        dataset = dataset.map(tf.cond(tf.random.uniform([], 0, 1) > AUGMENT_FRAC, lambda: do_augmentation, lambda : do_nothing),  num_parallel_calls=AUTO)\n    dataset = dataset.batch(batch_size)\n    dataset = dataset.prefetch(buffer_size = AUTO)\n    return dataset\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Verify pipeline","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(12,10))\nfor idx,(img, _) in enumerate(data_loader(train_files, labelled=True, augment=True).unbatch().take(9)):\n    plt.subplot(3,3,idx+1)\n    plt.imshow(img.numpy())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# test training data loading pipeline \nfor img_batch, label in data_loader(train_files, labelled=True, augment=True).take(1):\n    print(img_batch.shape, label)\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# test unlabelled data pipeline with return image name \nfor img, img_name in data_loader(train_files, labelled=False, augment=True, return_image_names=True).unbatch().take(2):\n    print(img.shape, img_name.numpy().decode(\"utf-8\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# test unlabelled data pipeline without return image name \nfor img_batch in data_loader(train_files, labelled=False, augment=True, return_image_names=False).take(1):\n    print(img_batch.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"c=1\nfor img,label in data_loader(train_files[:2], labelled=True, shuffle=False, augment=False, repeat=False, ordered=True).unbatch():\n    if c==1:\n        print(img[2,3].numpy(),label.numpy())\n    c+=1","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef get_lr_callback(PLOT_LR = False): # LR scheduler\n    lr_start   = 5e-6\n    lr_max     = 1.4e-6 * BATCH_SIZE\n    lr_min     =  1e-6\n    lr_ramp_ep = 5\n    lr_sus_ep  = 2\n    lr_decay   = 0.8\n   \n    def lrfn(epoch):\n        if epoch < lr_ramp_ep:\n            lr = (lr_max - lr_start) / lr_ramp_ep * epoch + lr_start\n            \n        elif epoch < lr_ramp_ep + lr_sus_ep:\n            lr = lr_max\n            \n        else:\n            lr = (lr_max - lr_min) * lr_decay**(epoch - lr_ramp_ep - lr_sus_ep) + lr_min\n            \n        return lr\n    if PLOT_LR:\n        plt.figure(figsize=(15, 5))\n        plt.subplot(1, 2, 1)\n        plt.plot([lrfn(e) for e in range(EPOCHS)]);\n        plt.xlabel('Epoch'); plt.ylabel('LR');\n        plt.subplot(1, 2, 2);\n        plt.plot([lrfn(e) for e in range(EPOCHS)]);\n        plt.xlabel('Epoch'); plt.ylabel('Log LR');\n        plt.yscale('log');\n\n    lr_callback = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=False)\n    return lr_callback\n\ndef build_model(input_shape = (192,192,3), pretrained_model= efn.EfficientNetB2, loss_type=LOSS_TYPE, opt = OPT_TYPE): \n    inp = tf.keras.layers.Input(shape=input_shape)\n    base_model = pretrained_model(include_top=False, weights='imagenet', input_shape=input_shape)\n    print(\"Using {} as the base model\".format(base_model.name))\n# weight freezing for Resnet50  \n    if base_model.name == \"resnet50\":\n        for layer in base_model.layers[:143]:\n            layer.trainable = False   # freezing weights of deeper layers\n        for layer in base_model.layers[143:]:\n            layer.trainable = True   # fine-tuning last part of Resnet50\n    x = base_model(inp)\n    x = tf.keras.layers.GlobalAveragePooling2D()(x)\n    x = tf.keras.layers.Dense(256, activation = 'relu')(x)\n    x = tf.keras.layers.Dropout(0.3)(x)\n    x = tf.keras.layers.Dense(128, activation = 'relu')(x)\n    x = tf.keras.layers.Dense(1, activation = 'sigmoid')(x)\n    model = tf.keras.Model(inputs= inp, outputs = x)\n    if OPT_TYPE == \"Adam\":\n        optimizer = tf.keras.optimizers.Adam(learning_rate= LR)\n    elif OPT_TYPE == \"RAdam\":\n        optimizer =  tfa.optimizers.RectifiedAdam(lr=LR)\n    if loss_type == 'BCE':\n        loss = tf.keras.losses.BinaryCrossentropy(label_smoothing=0.05)\n    elif loss_type == 'FOCAL':\n        loss= tfa.losses.SigmoidFocalCrossEntropy(gamma = GAMMA, alpha = ALPHA)\n    model.compile(optimizer= optimizer,loss= loss, metrics= ['AUC'])\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"build_model().summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"_ = get_lr_callback(PLOT_LR=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def display_training_curves(training, validation, title, subplot):\n    if subplot%10==1: # set up the subplots on the first call\n        plt.subplots(figsize=(10,10), facecolor='#F0F0F0')\n        plt.tight_layout()\n    ax = plt.subplot(subplot)\n    ax.set_facecolor('#F8F8F8')\n    ax.plot(training)\n    ax.plot(validation)\n    ax.set_title('model '+ title)\n    ax.set_ylabel(title)\n    #ax.set_ylim(0.28,1.05)\n    ax.set_xlabel('epoch')\n    ax.legend(['train', 'valid.'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"NUM_TEST_IMAGES = count_data_items(test_files)\n\ndef train_model(kfold_n_splits=5,train_set_aug=True, valid_set_aug=True,test_set_aug=True, pretrained_model= MobileNetV2, display_training_curve = True ):       \n\n    preds = np.zeros(shape=(NUM_TEST_IMAGES,))\n    oof_labels = []\n    oof_preds = []\n    kf = KFold(n_splits=kfold_n_splits,shuffle=True,random_state= 1357)\n    if DEVICE=='TPU':\n        print('using TPU')\n\n    for fold,(idxT,idxV) in enumerate(kf.split(np.arange(15))):\n\n        print('#'*25)\n        print('### FOLD {}'.format(fold+1))\n        print('#'*25)\n\n\n        K.clear_session()\n        with strategy.scope():\n            model = build_model(input_shape = (DIM,DIM,3), pretrained_model = pretrained_model)\n        train_tfrecords = tf.io.gfile.glob([\"{}/train{:02d}-*.tfrec\".format(GCS_PATH,i) for i in idxT])\n\n        if INCLUDE_2018_DATA:\n            train_tfrecords += tf.io.gfile.glob([f\"{GCS_PATH_2019}/train{(2*x):02d}-*.tfrec\" for x in range(15)])\n        if INCLUDE_2019_DATA:\n            train_tfrecords += tf.io.gfile.glob([f\"{GCS_PATH_2019}/train{(2*x +1):02d}-*.tfrec\" for x in range(14)])  \n        if INCLUDE_CD_MALIGNANT:\n            new_malignant_tfrecords = np.arange(15,30).tolist()\n            train_tfrecords += tf.io.gfile.glob([f\"{GCS_PATH_M}/train{x}-*.tfrec\" for x in new_malignant_tfrecords])\n        if UPSAMPLE:\n            train_tfrecords += tf.io.gfile.glob([f\"{GCS_PATH_M}/train{x:02d}-*.tfrec\" for x in idxT])\n        \n        np.random.shuffle(train_tfrecords) # shuffle the tfrecord files\n        val_tfrecords = tf.io.gfile.glob([\"{}/train{:02d}-*.tfrec\".format(GCS_PATH,i) for i in idxV])\n\n        train_dataset = data_loader(train_tfrecords, labelled=True, augment=train_set_aug, repeat=True, shuffle=True, ordered=False)\n        valid_dataset = data_loader(val_tfrecords, labelled = True, augment=False, repeat=False, shuffle=False, ordered=False)\n\n        NUM_TRAINING_IMAGES = count_data_items(train_tfrecords)\n        NUM_VALIDATION_IMAGES = count_data_items(val_tfrecords)\n\n\n        model_best_epoch = tf.keras.callbacks.ModelCheckpoint(\n            \"fold{}.h5\".format(fold+1), monitor='val_auc', verbose=1, save_best_only=True,\n            save_weights_only=True, mode='max', save_freq='epoch')\n\n        history = model.fit(train_dataset,epochs = EPOCHS,  #class_weight = {0: weight_for_0, 1: (weight_for_1)/2},\n                            steps_per_epoch= np.ceil(NUM_TRAINING_IMAGES/BATCH_SIZE),\n                            verbose= 1, callbacks=[model_best_epoch, get_lr_callback()],validation_data = valid_dataset)\n\n        print(\"#\"*5+\" Loading model weights from best epoch \"+\"#\"*5)\n        model.load_weights(\"fold{}.h5\".format(fold+1))\n\n        if valid_set_aug:\n            print(f\"### With validation set augmentation size = {TTA} ###\")\n            valid_dataset_tta = data_loader(val_tfrecords,  labelled=True, augment=True, shuffle=False, repeat=True)\n            valid_images = valid_dataset_tta.map(lambda image, label: image)\n            ypred_valid = model.predict(valid_images, steps = np.ceil(TTA*NUM_VALIDATION_IMAGES/BATCH_SIZE), verbose=1)\n            ypred_valid = ypred_valid[:NUM_VALIDATION_IMAGES * TTA].reshape((NUM_VALIDATION_IMAGES,TTA), order = 'F') # Fortran like indexing, augmentations in columns\n            ypred_valid = ypred_valid.mean(axis = 1) # take the average across number of augmentations\n        else:\n            print('#'*5+\" Without validation set augmentation \"+'#'*5)\n            valid_dataset_no_tta = data_loader(val_tfrecords, labelled=True, augment=False,  shuffle=False,repeat=False)\n            valid_images = valid_dataset_no_tta.map(lambda image, label: image)\n            ypred_valid = model.predict(valid_images,steps = NUM_VALIDATION_IMAGES/BATCH_SIZE, verbose =1)\n\n        valid_labels = np.array([label.numpy() for label in data_loader(val_tfrecords, labelled=True, augment=False,  shuffle=False,repeat=False).map(lambda image, label: label).unbatch()] )\n        auc_valid = roc_auc_score(valid_labels, ypred_valid)        \n        print(f'AUC of validation fold {fold+1} (with TTA = {TTA}) = {auc_valid}')\n        oof_labels.append(valid_labels)\n        oof_preds.append(ypred_valid)\n\n        if test_set_aug:\n            print(f\"### Using test set augmentation with TTA = {TTA} ###\")\n            test_data = data_loader(test_files, labelled=False, augment=True, shuffle=False, repeat=True, return_image_names=False, batch_size = BATCH_SIZE*8)\n            ypred_test = model.predict(test_data, steps = TTA*NUM_TEST_IMAGES/(BATCH_SIZE*8), verbose=1)\n            ypred_test = ypred_test[:NUM_TEST_IMAGES * TTA].reshape((NUM_TEST_IMAGES,TTA), order = 'F') # Fortran like indexin\n            ypred_test = ypred_test.mean(axis = 1) \n        else:\n            print(\"### Without test set augmentation ###\")\n            test_data = data_loader(test_files, labelled=False, augment=False, shuffle=False, repeat=False, return_image_names=False)\n            ypred_test = model.predict(test_data, verbose=1)\n        preds += (ypred_test/kfold_n_splits)\n\n        if display_training_curve:\n            print(\"Fold: {}\".format(fold+1))\n            display_training_curves(history.history['loss'], history.history['val_loss'], 'loss', 211)\n            display_training_curves(history.history['auc'], history.history['val_auc'], 'AUC', 212)\n            \n    return preds, oof_labels,oof_preds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pretrained_model = InceptionV3#efn.EfficientNetB2\n\npreds, oof_labels,oof_preds =  train_model(train_set_aug=True,pretrained_model = pretrained_model, display_training_curve=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(np.concatenate(oof_preds).shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Out-of-fold AUC score on the full 2020 training data (with TTA if applicable)\nroc_auc_score(np.concatenate(oof_labels),np.concatenate(oof_preds))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get image names in the test set\ntest_img_names = []\ntest_dataset = data_loader(test_files, labelled=False, augment=False, shuffle=False, repeat=False, return_image_names=True, ordered=True)\nfor _,image_name in test_dataset.unbatch():\n    test_img_names.append(image_name.numpy().decode(\"utf-8\"))\n    \nsample_sub = pd.read_csv(DATA_PATH+'/sample_submission.csv')\nsample_sub.loc[:,'image_name' ] = test_img_names\nsample_sub.loc[:,'target' ] = preds\n\n# submit \nsample_sub.to_csv(\"submission.csv\",index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_sub.sort_values('image_name').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}