{"cells":[{"metadata":{},"cell_type":"markdown","source":"**Training Notebook- https://www.kaggle.com/iamprateek/cassava-tpu/notebook**"},{"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/keras-efficientnet-whl/Keras_Applications-1.0.8-py3-none-any.whl\n! pip install ../input/keras-efficientnet-whl/efficientnet-1.1.1-py3-none-any.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import 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":"AUTO = tf.data.experimental.AUTOTUNE","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Configuration\nEPOCHS = 20\nBATCH_SIZE = 32 * strategy.num_replicas_in_sync\nIMAGE_SIZE = [512, 512]\n# Seed\nSEED = 123\n# Learning rate\nLR = 0.0001\n# Test time augmentation rounds\nTTA = 10\n# Verbosity\nVERBOSE = 2\n# Number of classes\nN_CLASSES = 5\n\n# Test filenames directory\nTEST_FILENAMES = '../input/cassava-leaf-disease-classification/test_images/*.jpg'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def data_augment(image, image_name):\n    p_spatial = tf.random.uniform([], 0, 1.0, dtype = tf.float32)\n    p_rotate = tf.random.uniform([], 0, 1.0, dtype = tf.float32)\n    p_pixel_1 = tf.random.uniform([], 0, 1.0, dtype = tf.float32)\n    p_pixel_2 = tf.random.uniform([], 0, 1.0, dtype = tf.float32)\n    p_pixel_3 = tf.random.uniform([], 0, 1.0, dtype = tf.float32)\n    p_crop = tf.random.uniform([], 0, 1.0, dtype = tf.float32)\n            \n    # Flips\n    image = tf.image.random_flip_left_right(image)\n    image = tf.image.random_flip_up_down(image)\n    if p_spatial > 0.75:\n        image = tf.image.transpose(image)\n        \n    # Rotates\n    if p_rotate > 0.75:\n        image = tf.image.rot90(image, k = 3) # rotate 270º\n    elif p_rotate > 0.5:\n        image = tf.image.rot90(image, k = 2) # rotate 180º\n    elif p_rotate > 0.25:\n        image = tf.image.rot90(image, k = 1) # rotate 90º\n        \n    # Pixel-level transforms\n    if p_pixel_1 >= 0.4:\n        image = tf.image.random_saturation(image, lower = 0.7, upper = 1.3)\n    if p_pixel_2 >= 0.4:\n        image = tf.image.random_contrast(image, lower = 0.8, upper = 1.2)\n    if p_pixel_3 >= 0.4:\n        image = tf.image.random_brightness(image, max_delta = 0.1)\n        \n    # Crops\n    if p_crop > 0.7:\n        if p_crop > 0.9:\n            image = tf.image.central_crop(image, central_fraction = 0.7)\n        elif p_crop > 0.8:\n            image = tf.image.central_crop(image, central_fraction = 0.8)\n        else:\n            image = tf.image.central_crop(image, central_fraction = 0.9)\n    elif p_crop > 0.4:\n        crop_size = tf.random.uniform([], int(IMAGE_SIZE[0] * 0.8), IMAGE_SIZE[0], dtype = tf.int32)\n        image = tf.image.random_crop(image, size = [crop_size, crop_size, 3])\n\n    image = tf.image.resize(image, size = IMAGE_SIZE)\n    image = tf.reshape(image, [*IMAGE_SIZE, 3])\n    \n    return image, image_name\n\n# Function to decode our images (normalize and reshape)\ndef decode_image(image_data):\n    image = tf.image.decode_jpeg(image_data, channels = 3)\n    # Resize image to be aligned with the inference phase\n    image = tf.image.resize(image, IMAGE_SIZE)\n    # convert image to floats in [0, 1] range\n    image = tf.cast(image, tf.float32) / 255.0\n    # explicit size needed for TPU\n    image = tf.reshape(image, [*IMAGE_SIZE, 3])\n    return image\n\ndef get_image_name(file_path):\n    parts = tf.strings.split(file_path, os.path.sep)\n    image_name = parts[-1]\n    return image_name\n\ndef read_image(file_path):\n    image_name = get_image_name(file_path)\n    image = tf.io.read_file(file_path)\n    image = decode_image(image)\n    return image, image_name\n\ndef get_test_dataset(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    # The test dataset must repeat if we want to predict with test time augmentation\n    if tta:\n        dataset = dataset.repeat() \n    dataset = dataset.batch(BATCH_SIZE)\n    # prefetch next batch while predicting (autotune prefetch buffer size)\n    dataset = dataset.prefetch(AUTO)\n    return dataset\n\n\nNUM_TESTING_IMAGES = len(os.listdir('../input/cassava-leaf-disease-classification/test_images/'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_model():\n    \n    with strategy.scope():\n        \n        inp = tf.keras.layers.Input(shape = (*IMAGE_SIZE, 3))\n\n        x = efn.EfficientNetB5(weights = None, include_top = False)(inp)\n        x = tf.keras.layers.GlobalAveragePooling2D()(x)\n        x = tf.keras.layers.Dropout(0.2)(x)\n        output = tf.keras.layers.Dense(N_CLASSES, activation = 'softmax')(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 = [tf.keras.losses.CategoricalCrossentropy(label_smoothing = 0.4)],\n            metrics = [tf.keras.metrics.CategoricalAccuracy()]\n        )\n\n        return model\n    \ndef inference(model_paths):\n    \n    # Create a numpy array to store predictions\n    prediction = np.zeros((NUM_TESTING_IMAGES, N_CLASSES))\n    \n    print('Extracting test image names...')\n    # Get the test dataset without tta to extract image names\n    test_dataset = get_test_dataset(TEST_FILENAMES, tta = False)\n    image_name = test_dataset.map(lambda image, image_name: image_name).unbatch()\n    image_name = next(iter(image_name.batch(NUM_TESTING_IMAGES))).numpy().astype('U')\n    print('Test image names 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        # Add 1 to the steps because we only have a sample for public inference\n        steps = TTA * ((NUM_TESTING_IMAGES / BATCH_SIZE) + 1)\n        # Get the test dataset with tta to extract image\n        test_dataset = get_test_dataset(TEST_FILENAMES, tta = True)\n        image = test_dataset.map(lambda image, image_name: 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        prediction += probabilities / len(model_paths)\n        \n    sub = pd.DataFrame({'image_id': image_name, 'label': np.argmax(prediction, axis = -1)})\n    sub.to_csv('submission.csv', index = False)\n        \n    return image_name, prediction, sub\n        \n# Get pretrained models list for inference\nmodel_paths = glob.glob('../input/trained-cassava-weights/*.h5')\nimage_name, prediction, sub = inference(model_paths)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}