{"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":"## Imports","metadata":{}},{"cell_type":"code","source":"!pip install efficientnet","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-05-20T17:25:35.387204Z","iopub.execute_input":"2022-05-20T17:25:35.387587Z","iopub.status.idle":"2022-05-20T17:25:45.740084Z","shell.execute_reply.started":"2022-05-20T17:25:35.387484Z","shell.execute_reply":"2022-05-20T17:25:45.738974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf, re, math\nimport tensorflow_addons as tfa\n\nfrom tensorflow.keras import layers, optimizers, losses, metrics, callbacks, initializers\nfrom tensorflow.keras import Sequential, Model, Input\n\nimport efficientnet.tfkeras as efn\n\nimport os\nimport sys\nimport glob\nimport json\nimport gc\n\nfrom functools import partial\n\nimport random\nimport numpy as np\nimport pandas as pd \n\nfrom sklearn.model_selection import train_test_split, StratifiedKFold\nfrom sklearn.preprocessing import LabelEncoder\n\nfrom tqdm.notebook import tqdm\n\nimport matplotlib.pyplot as plt\nplt.style.use(\"ggplot\")\n%matplotlib inline\n\nimport seaborn as sns\n\nimport cv2\nfrom PIL import Image\n\nprint(f'tensorflow version: {tf.__version__}')\nprint(f'python version: P{sys.version}')\n\ndef seed_everything(seed):\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    random.seed(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)    \n    \nseed_everything(42)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:25:47.375306Z","iopub.execute_input":"2022-05-20T17:25:47.375701Z","iopub.status.idle":"2022-05-20T17:25:57.68447Z","shell.execute_reply.started":"2022-05-20T17:25:47.375662Z","shell.execute_reply":"2022-05-20T17:25:57.683474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TPU&GPU Check","metadata":{}},{"cell_type":"code","source":"try:\n    TPU = tf.distribute.cluster_resolver.TPUClusterResolver()  # TPU detection. No parameters necessary if TPU_NAME environment variable is set. On Kaggle this is always the case.\n    print('Running on TPU ', TPU.master())\nexcept ValueError:\n    print('Running on GPU')\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    strategy = tf.distribute.get_strategy() # default distribution strategy in Tensorflow. Works on CPU and single GPU.\n\nREPLICAS = strategy.num_replicas_in_sync\nprint(f'REPLICAS: {REPLICAS}')\n\nAUTO = tf.data.experimental.AUTOTUNE","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:26:05.163682Z","iopub.execute_input":"2022-05-20T17:26:05.164535Z","iopub.status.idle":"2022-05-20T17:26:10.877556Z","shell.execute_reply.started":"2022-05-20T17:26:05.16449Z","shell.execute_reply":"2022-05-20T17:26:10.876297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('../input/sorghum-id-fgvc-9/train_cultivar_mapping.csv')\ntrain = train.dropna().reset_index(drop=True)\ndisplay(train.head())","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:26:10.879888Z","iopub.execute_input":"2022-05-20T17:26:10.880222Z","iopub.status.idle":"2022-05-20T17:26:10.95593Z","shell.execute_reply.started":"2022-05-20T17:26:10.880179Z","shell.execute_reply":"2022-05-20T17:26:10.954961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Parameters","metadata":{}},{"cell_type":"code","source":"# Input Image Shape\nIMG_SIZE = 512\nN_CHANNELS = 3\nINPUT_SHAPE = (IMG_SIZE, IMG_SIZE, N_CHANNELS)\nN_SAMPLES = len(train)\n\nN_EPOCHS = 15\n\nBATCH_SIZE_BASE = 16\nBATCH_SIZE = BATCH_SIZE_BASE * REPLICAS\n\n# ImageNet Normalization\nIMAGENET_MEAN = tf.constant([0.485, 0.456, 0.406], dtype=tf.float32)\nIMAGENET_STD = tf.constant([0.229, 0.224, 0.225], dtype=tf.float32)\n\nCUTOUT = True\n\nAUTO = tf.data.experimental.AUTOTUNE\nEPS = tf.keras.backend.epsilon()\n\nval_fold = 0\nN_SPLITS = 5\n\nprint(f'N_SAMPLES: {N_SAMPLES}, BATCH_SIZE: {BATCH_SIZE}')","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:26:22.946206Z","iopub.execute_input":"2022-05-20T17:26:22.946509Z","iopub.status.idle":"2022-05-20T17:26:22.955604Z","shell.execute_reply.started":"2022-05-20T17:26:22.946479Z","shell.execute_reply":"2022-05-20T17:26:22.954563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train CSV","metadata":{}},{"cell_type":"code","source":"from kaggle_datasets import KaggleDatasets\n# You can learn GCS Patsh for every datasets. Sometimes you can get error due to large data (look at Version 1). \n#GCS_DS_PATH = KaggleDatasets().get_gcs_path('sorghum-id-fgvc-9') \n\nGCS_DS_PATH = 'gs://kds-61791860f9a09f446243cd1f60e8ed71b3743aa148e9c9092cdbdea3'","metadata":{"execution":{"iopub.status.busy":"2022-05-20T18:11:55.802617Z","iopub.execute_input":"2022-05-20T18:11:55.803178Z","iopub.status.idle":"2022-05-20T18:11:56.339636Z","shell.execute_reply.started":"2022-05-20T18:11:55.803132Z","shell.execute_reply":"2022-05-20T18:11:56.33872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"image_path\"] = train[\"image\"].apply(lambda image: GCS_DS_PATH + '/train_images/' + image)\n\nencoder = LabelEncoder()\nlabels2ids = {l: i for (i, l) in enumerate(encoder.fit(train[\"cultivar\"]).classes_)}\nids2labels = {x[1]: x[0] for x in labels2ids.items()}\n\ntrain[\"cultivar_id\"] = encoder.fit_transform(train[\"cultivar\"])\n\nskf = StratifiedKFold(n_splits=N_SPLITS)\nfor fold, (_, val_) in enumerate(skf.split(X=train, y=train.cultivar)):\n    train.loc[val_, \"kfold\"] = fold\n    \ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:26:42.245539Z","iopub.execute_input":"2022-05-20T17:26:42.246455Z","iopub.status.idle":"2022-05-20T17:26:42.346793Z","shell.execute_reply.started":"2022-05-20T17:26:42.246412Z","shell.execute_reply":"2022-05-20T17:26:42.346134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Number of Labels","metadata":{}},{"cell_type":"code","source":"N_CULTIVAR = train['cultivar'].nunique()\nprint(f'N_INDIVIDUAL_IDS: {N_CULTIVAR}')","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:26:45.737647Z","iopub.execute_input":"2022-05-20T17:26:45.738394Z","iopub.status.idle":"2022-05-20T17:26:45.746738Z","shell.execute_reply.started":"2022-05-20T17:26:45.738352Z","shell.execute_reply":"2022-05-20T17:26:45.745856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Augmentation","metadata":{}},{"cell_type":"code","source":"def data_augment(image, label): \n    if tf.random.uniform([])>0.5 and CUTOUT:\n        N_CUTOUT = 1\n        for cutouts in range(N_CUTOUT):\n            if tf.random.uniform([])>0.5:\n                DIM = IMG_SIZE\n                CUTOUT_LENGTH = int(DIM * 0.4)\n                x1 = tf.cast( tf.random.uniform([],0,DIM-CUTOUT_LENGTH),tf.int32)\n                x2 = tf.cast( tf.random.uniform([],0,DIM-CUTOUT_LENGTH),tf.int32)\n                filter_ = tf.concat([tf.zeros((x1,CUTOUT_LENGTH)),tf.ones((CUTOUT_LENGTH,CUTOUT_LENGTH)),tf.zeros((DIM-x1-CUTOUT_LENGTH,CUTOUT_LENGTH))],axis=0)\n                filter_ = tf.concat([tf.zeros((DIM,x2)),filter_,tf.zeros((DIM,DIM-x2-CUTOUT_LENGTH))],axis=1)\n                cutout = tf.reshape(1-filter_,(DIM,DIM,1))\n                image = cutout*image\n                \n    image = tf.image.random_flip_left_right(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_brightness(image, 0.10)\n    return image, label","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:26:47.193079Z","iopub.execute_input":"2022-05-20T17:26:47.193367Z","iopub.status.idle":"2022-05-20T17:26:47.205366Z","shell.execute_reply.started":"2022-05-20T17:26:47.193339Z","shell.execute_reply":"2022-05-20T17:26:47.204033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset Utils","metadata":{}},{"cell_type":"code","source":"def decode_image(filename, label=None, image_size=IMG_SIZE):\n    bits = tf.io.read_file(filename)\n    image = tf.image.decode_jpeg(bits, channels=3)\n    image = tf.image.resize(image, [image_size, image_size])\n    image = tf.cast(image, tf.float32) / 255.0\n    #image = (image - IMAGENET_MEAN) / IMAGENET_STD\n    return image, label\n\ndef view_image(ds):\n    image, label = next(iter(ds)) # extract 1 batch from the dataset\n    image = image.numpy()\n    label = label.numpy()\n    \n    fig = plt.figure(figsize=(22, 22))\n    for i in range(20):\n        ax = fig.add_subplot(4, 5, i+1, xticks=[], yticks=[])\n        ax.imshow(image[i])\n        ax.set_title(f\"Label: {label[i]}\")","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:26:49.272429Z","iopub.execute_input":"2022-05-20T17:26:49.272773Z","iopub.status.idle":"2022-05-20T17:26:49.283184Z","shell.execute_reply.started":"2022-05-20T17:26:49.272721Z","shell.execute_reply":"2022-05-20T17:26:49.282034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train and Valid Dataset","metadata":{}},{"cell_type":"code","source":"train_df = train[train.kfold%N_SPLITS != val_fold].reset_index(drop=True)\n\nval_df = train[train.kfold%N_SPLITS == val_fold].reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:26:50.221193Z","iopub.execute_input":"2022-05-20T17:26:50.221458Z","iopub.status.idle":"2022-05-20T17:26:50.238113Z","shell.execute_reply.started":"2022-05-20T17:26:50.22143Z","shell.execute_reply":"2022-05-20T17:26:50.236898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = (\n    tf.data.Dataset\n    .from_tensor_slices((train_df.image_path, train_df.cultivar_id))\n    .map(decode_image, num_parallel_calls=AUTO)\n    .map(data_augment, num_parallel_calls = AUTO)\n    .repeat()\n    .shuffle(1024)\n    .batch(BATCH_SIZE)\n    .prefetch(AUTO)\n)\n\nvalid_dataset = (\n    tf.data.Dataset\n    .from_tensor_slices((val_df.image_path, val_df.cultivar_id))\n    .map(decode_image, num_parallel_calls=AUTO)\n    .batch(BATCH_SIZE)\n    .prefetch(AUTO)\n)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:52:12.149014Z","iopub.execute_input":"2022-05-20T17:52:12.149299Z","iopub.status.idle":"2022-05-20T17:52:12.314334Z","shell.execute_reply.started":"2022-05-20T17:52:12.149272Z","shell.execute_reply":"2022-05-20T17:52:12.313616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"view_image(train_dataset)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:52:13.587622Z","iopub.execute_input":"2022-05-20T17:52:13.587949Z","iopub.status.idle":"2022-05-20T17:52:42.893351Z","shell.execute_reply.started":"2022-05-20T17:52:13.587916Z","shell.execute_reply":"2022-05-20T17:52:42.891847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"view_image(valid_dataset)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:52:42.89571Z","iopub.execute_input":"2022-05-20T17:52:42.89609Z","iopub.status.idle":"2022-05-20T17:52:48.401228Z","shell.execute_reply.started":"2022-05-20T17:52:42.896033Z","shell.execute_reply":"2022-05-20T17:52:48.400295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model","metadata":{}},{"cell_type":"code","source":"def get_model():\n    \n    tf.config.optimizer.set_jit(True)\n\n    with strategy.scope():\n        \n        image = Input(INPUT_SHAPE, name='image', dtype=tf.float32)\n        backbone = efn.EfficientNetB3(weights = 'noisy-student', include_top = False)(image)\n        avg_pool = tf.keras.layers.GlobalAveragePooling2D()(backbone)\n        max_pool = tf.keras.layers.GlobalMaxPooling2D()(backbone)\n        pretrained_out = tf.keras.layers.Concatenate()([avg_pool, max_pool])\n        \n        # You can choose one of the pooling layers.\n        \n        outputs = layers.Dropout(0.25)(pretrained_out)\n        \n        outputs = layers.Dense(N_CULTIVAR, activation=\"softmax\", name='predictions')(outputs)\n        \n        model = Model(inputs=image, outputs=outputs)\n        \n        # OPTIMIZER\n        #optimizer = optimizers.Adam()\n        optimizer = tfa.optimizers.AdamW(weight_decay=1e-8)\n        \n        # LOSS\n        loss = {\n            'predictions': losses.SparseCategoricalCrossentropy(),\n        }\n \n        # METRICS\n        metricsx =[\n            metrics.SparseTopKCategoricalAccuracy(k=1, name='top1acc'),\n        ]\n\n        # Compile Model\n        model.compile(optimizer=optimizer, loss=loss, metrics=metricsx)\n\n        return model","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:52:48.40252Z","iopub.execute_input":"2022-05-20T17:52:48.402783Z","iopub.status.idle":"2022-05-20T17:52:48.414142Z","shell.execute_reply.started":"2022-05-20T17:52:48.402753Z","shell.execute_reply":"2022-05-20T17:52:48.413245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = get_model()","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:52:48.416167Z","iopub.execute_input":"2022-05-20T17:52:48.416979Z","iopub.status.idle":"2022-05-20T17:53:12.669302Z","shell.execute_reply.started":"2022-05-20T17:52:48.416938Z","shell.execute_reply":"2022-05-20T17:53:12.668506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:53:12.670306Z","iopub.execute_input":"2022-05-20T17:53:12.670652Z","iopub.status.idle":"2022-05-20T17:53:12.713619Z","shell.execute_reply.started":"2022-05-20T17:53:12.670624Z","shell.execute_reply":"2022-05-20T17:53:12.712888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Learning Rate Scheduler","metadata":{}},{"cell_type":"code","source":"class CosineScheduler():\n    def __init__(self, max_update, base_lr=0.01, final_lr=0,\n               warmup_steps=0, warmup_begin_lr=0):\n        self.base_lr_orig = base_lr\n        self.max_update = max_update\n        self.final_lr = final_lr\n        self.warmup_steps = warmup_steps\n        self.warmup_begin_lr = warmup_begin_lr\n        self.max_steps = self.max_update - self.warmup_steps\n\n    def get_warmup_lr(self, epoch):\n        increase = (self.base_lr_orig - self.warmup_begin_lr) \\\n                       * float(epoch) / float(self.warmup_steps)\n        return self.warmup_begin_lr + increase\n\n    def __call__(self, epoch):\n        if epoch < self.warmup_steps:\n            return self.get_warmup_lr(epoch)\n        if epoch <= self.max_update:\n            self.base_lr = self.final_lr + (\n                self.base_lr_orig - self.final_lr) * (1 + math.cos(\n                math.pi * (epoch - self.warmup_steps) / self.max_steps)) / 2\n        return self.base_lr\n\nscheduler = CosineScheduler(max_update=N_EPOCHS, base_lr=1e-3, final_lr=1e-4, warmup_steps=3, warmup_begin_lr=1e-4)\nplt.plot([scheduler(t) for t in range(N_EPOCHS)])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:27:32.152391Z","iopub.execute_input":"2022-05-20T17:27:32.153229Z","iopub.status.idle":"2022-05-20T17:27:32.392515Z","shell.execute_reply.started":"2022-05-20T17:27:32.153192Z","shell.execute_reply":"2022-05-20T17:27:32.391847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Callbacks","metadata":{}},{"cell_type":"code","source":"model_checkpoint_callback = callbacks.ModelCheckpoint(\n    'model_best.h5', \n    monitor='loss', \n    verbose=1, \n    save_best_only=True, \n    save_weights_only=True\n)\n\nmodel_checkpoint_callback.set_model(model)\n\nlearning_rate_callback = callbacks.LearningRateScheduler(scheduler, verbose=1)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:27:33.533513Z","iopub.execute_input":"2022-05-20T17:27:33.534437Z","iopub.status.idle":"2022-05-20T17:27:33.540173Z","shell.execute_reply.started":"2022-05-20T17:27:33.534392Z","shell.execute_reply":"2022-05-20T17:27:33.539243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train","metadata":{}},{"cell_type":"code","source":"STEPS_PER_EPOCH = len(train_df) // BATCH_SIZE\n\nSTEPS_PER_EPOCH","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:27:34.824423Z","iopub.execute_input":"2022-05-20T17:27:34.824699Z","iopub.status.idle":"2022-05-20T17:27:34.832159Z","shell.execute_reply.started":"2022-05-20T17:27:34.82467Z","shell.execute_reply":"2022-05-20T17:27:34.830878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(train_dataset,\n                    validation_data=valid_dataset,\n                    epochs=N_EPOCHS,\n                    callbacks=[learning_rate_callback,\n                              model_checkpoint_callback,],\n                    steps_per_epoch=STEPS_PER_EPOCH\n                   )","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:53:28.971103Z","iopub.execute_input":"2022-05-20T17:53:28.971434Z","iopub.status.idle":"2022-05-20T17:56:21.203511Z","shell.execute_reply.started":"2022-05-20T17:53:28.971401Z","shell.execute_reply":"2022-05-20T17:56:21.202171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training History\n","metadata":{}},{"cell_type":"code","source":"def plot_history_metric(metric, f_best=np.argmax, yscale='linear'):\n    x = np.arange(1, len(history.history[metric]) + 1)\n    y_train = history.history[metric]\n    plt.figure(figsize=(20, 8))\n    # TRAIN\n    plt.plot(x, y_train, color='tab:blue', lw=3, label='train')\n    plt.title(f'Training {metric}', fontsize=24, pad=10)\n    plt.ylabel(metric, fontsize=20, labelpad=10)\n    plt.xlabel('epoch', fontsize=20, labelpad=10)\n    plt.xticks([1] + np.arange(5, N_EPOCHS + 1, 5).tolist(), fontsize=16) # set tick step to 1 and let x axis start at 1\n    plt.yticks(fontsize=16)\n    plt.yscale(yscale)\n    \n    # Train Best Marker\n    x_best = f_best(y_train)\n    y_best = y_train[x_best]\n    plt.scatter(x_best + 1, y_best, color='purple', s=100, marker='o', label=f'train best: {y_best:.4f}')\n \n    if f'val_{metric}' in history.history:\n        y_val = history.history[f'val_{metric}']\n       # Validation Best Marker\n        plt.plot(x, y_val, color='tab:orange', lw=3, label='validation')\n        # VALIDATION\n        x_best = f_best(y_val)\n        y_best = y_val[x_best]\n        plt.scatter(x_best + 1, y_best, color='red', s=100, marker='o', label=f'validation best: {y_best:.4f}')\n    \n    plt.grid()\n    plt.legend(prop={'size': 18})\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:43:08.428597Z","iopub.execute_input":"2022-05-20T17:43:08.429038Z","iopub.status.idle":"2022-05-20T17:43:08.442424Z","shell.execute_reply.started":"2022-05-20T17:43:08.429Z","shell.execute_reply":"2022-05-20T17:43:08.441464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_history_metric('loss', f_best=np.argmin)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:43:10.770791Z","iopub.execute_input":"2022-05-20T17:43:10.771375Z","iopub.status.idle":"2022-05-20T17:43:10.821332Z","shell.execute_reply.started":"2022-05-20T17:43:10.771321Z","shell.execute_reply":"2022-05-20T17:43:10.820077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_history_metric('top1acc', f_best=np.argmax)","metadata":{"execution":{"iopub.status.busy":"2022-04-12T00:12:14.057377Z","iopub.status.idle":"2022-04-12T00:12:14.057723Z","shell.execute_reply.started":"2022-04-12T00:12:14.057535Z","shell.execute_reply":"2022-04-12T00:12:14.057555Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prediction","metadata":{}},{"cell_type":"code","source":"model.load_weights('./model_best.h5')\n\ndef predict_on_batch(images):\n    return model(images, training=False)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:56:25.893818Z","iopub.execute_input":"2022-05-20T17:56:25.894573Z","iopub.status.idle":"2022-05-20T17:56:29.768841Z","shell.execute_reply.started":"2022-05-20T17:56:25.894531Z","shell.execute_reply":"2022-05-20T17:56:29.767897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.read_csv('../input/sorghum-id-fgvc-9/sample_submission.csv')\n\ntest_df[\"image_path\"] = test_df[\"filename\"].apply(lambda image: GCS_DS_PATH + '/test/' + image)\n\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:56:30.186798Z","iopub.execute_input":"2022-05-20T17:56:30.187079Z","iopub.status.idle":"2022-05-20T17:56:30.23778Z","shell.execute_reply.started":"2022-05-20T17:56:30.187047Z","shell.execute_reply":"2022-05-20T17:56:30.237026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = (\n    tf.data.Dataset\n    .from_tensor_slices((test_df.image_path, test_df.filename))\n    .map(decode_image, num_parallel_calls=AUTO)                 \n    .batch(BATCH_SIZE)\n    .prefetch(AUTO)\n)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:56:31.444031Z","iopub.execute_input":"2022-05-20T17:56:31.444327Z","iopub.status.idle":"2022-05-20T17:56:31.485683Z","shell.execute_reply.started":"2022-05-20T17:56:31.444297Z","shell.execute_reply":"2022-05-20T17:56:31.48486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = []\nfile_names = []\n\nwith strategy.scope():\n    for (images, image_ids) in (tqdm(test_dataset)):\n        preds = predict_on_batch(images)\n        preds = np.argmax(preds ,axis=1)\n        preds = [ids2labels[x] for x in preds]\n        files = [i.decode() for i in image_ids.numpy()]\n        \n        predictions.extend(preds)\n        file_names.extend(files)","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:56:32.785947Z","iopub.execute_input":"2022-05-20T17:56:32.786628Z","iopub.status.idle":"2022-05-20T17:57:19.017097Z","shell.execute_reply.started":"2022-05-20T17:56:32.786579Z","shell.execute_reply":"2022-05-20T17:57:19.014897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Submission","metadata":{}},{"cell_type":"code","source":"sub = pd.DataFrame({\n    \"filename\":file_names,\n    \"cultivar\":predictions,\n})\n\nsub.to_csv(\"submission.csv\", index=False)\ndisplay(sub.head(5))","metadata":{"execution":{"iopub.status.busy":"2022-05-20T17:49:14.293592Z","iopub.execute_input":"2022-05-20T17:49:14.293958Z","iopub.status.idle":"2022-05-20T17:49:14.312524Z","shell.execute_reply.started":"2022-05-20T17:49:14.293914Z","shell.execute_reply":"2022-05-20T17:49:14.311873Z"},"trusted":true},"execution_count":null,"outputs":[]}]}