{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.8.17","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Importing the libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nimport re\nimport math","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:21:49.620465Z","iopub.execute_input":"2023-09-05T11:21:49.621453Z","iopub.status.idle":"2023-09-05T11:21:49.626656Z","shell.execute_reply.started":"2023-09-05T11:21:49.621413Z","shell.execute_reply":"2023-09-05T11:21:49.625245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Connect to TPU","metadata":{}},{"cell_type":"code","source":"try:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\nexcept ValueError:\n    tpu = None\n    print(\"Failed to connect to TPU.\")\n    \nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.TPUStrategy(tpu)\nelse:\n    strategy = tf.distribute.get_strategy() \n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:21:52.707149Z","iopub.execute_input":"2023-09-05T11:21:52.707979Z","iopub.status.idle":"2023-09-05T11:21:58.799475Z","shell.execute_reply.started":"2023-09-05T11:21:52.707940Z","shell.execute_reply":"2023-09-05T11:21:58.798101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Defining helper functions for tfdata files preprocessing","metadata":{}},{"cell_type":"code","source":"IMAGE_SIZE = (512, 512)\nAUTO = tf.data.AUTOTUNE\nINPUT_PATH = \"/kaggle/input/tpu-getting-started/tfrecords-jpeg-512x512\"\nCLASSES = ['pink primrose',    'hard-leaved pocket orchid', 'canterbury bells', 'sweet pea',     'wild geranium',     'tiger lily',           'moon orchid',              'bird of paradise', 'monkshood',        'globe thistle',         # 00 - 09\n           'snapdragon',       \"colt's foot\",               'king protea',      'spear thistle', 'yellow iris',       'globe-flower',         'purple coneflower',        'peruvian lily',    'balloon flower',   'giant white arum lily', # 10 - 19\n           'fire lily',        'pincushion flower',         'fritillary',       'red ginger',    'grape hyacinth',    'corn poppy',           'prince of wales feathers', 'stemless gentian', 'artichoke',        'sweet william',         # 20 - 29\n           'carnation',        'garden phlox',              'love in the mist', 'cosmos',        'alpine sea holly',  'ruby-lipped cattleya', 'cape flower',              'great masterwort', 'siam tulip',       'lenten rose',           # 30 - 39\n           'barberton daisy',  'daffodil',                  'sword lily',       'poinsettia',    'bolero deep blue',  'wallflower',           'marigold',                 'buttercup',        'daisy',            'common dandelion',      # 40 - 49\n           'petunia',          'wild pansy',                'primula',          'sunflower',     'lilac hibiscus',    'bishop of llandaff',   'gaura',                    'geranium',         'orange dahlia',    'pink-yellow dahlia',    # 50 - 59\n           'cautleya spicata', 'japanese anemone',          'black-eyed susan', 'silverbush',    'californian poppy', 'osteospermum',         'spring crocus',            'iris',             'windflower',       'tree poppy',            # 60 - 69\n           'gazania',          'azalea',                    'water lily',       'rose',          'thorn apple',       'morning glory',        'passion flower',           'lotus',            'toad lily',        'anthurium',             # 70 - 79\n           'frangipani',       'clematis',                  'hibiscus',         'columbine',     'desert-rose',       'tree mallow',          'magnolia',                 'cyclamen ',        'watercress',       'canna lily',            # 80 - 89\n           'hippeastrum ',     'bee balm',                  'pink quill',       'foxglove',      'bougainvillea',     'camellia',             'mallow',                   'mexican petunia',  'bromelia',         'blanket flower',        # 90 - 99\n           'trumpet creeper',  'blackberry lily',           'common tulip',     'wild rose']                                                                                                                                               # 100 - 102\n\ndef decode_image(data):\n    image = tf.io.decode_jpeg(data, channels=3)\n#     image = tf.cast(image, tf.float32) / 255.0 # using preprocessing layers at the moment, will uncomment if needed\n    image = tf.reshape(image, [*IMAGE_SIZE, 3])\n    return image\n\ndef read_labelled_tfrecord(record):\n    LABELED_RECORD_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"class\": tf.io.FixedLenFeature([], tf.int64)\n    }\n    record = tf.io.parse_single_example(record, LABELED_RECORD_FORMAT)\n    image = decode_image(record[\"image\"])\n    label = tf.cast(record[\"class\"], tf.int32)\n    return image, label\n\ndef read_unlabelled_tfrecord(record):\n    UNLABELED_RECORD_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"id\": tf.io.FixedLenFeature([], tf.string)\n    }\n    record = tf.io.parse_single_example(record, UNLABELED_RECORD_FORMAT)\n    image = decode_image(record[\"image\"])\n    ID = record[\"id\"]\n    return image, ID\n\ndef load_dataset(folder, labeled=True, ordered=False):\n    options = tf.data.Options()\n    if not ordered:\n        options.experimental_deterministic = False # ignore order\n    dataset = tf.data.TFRecordDataset(tf.io.gfile.glob(INPUT_PATH + '/' + folder + \"/*.tfrec\"), num_parallel_reads=AUTO)\n    dataset = dataset.with_options(options)\n    dataset = dataset.map(read_labelled_tfrecord if labeled else read_unlabelled_tfrecord, num_parallel_calls=AUTO)\n    return dataset\n","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:22:01.809523Z","iopub.execute_input":"2023-09-05T11:22:01.809892Z","iopub.status.idle":"2023-09-05T11:22:01.831681Z","shell.execute_reply.started":"2023-09-05T11:22:01.809862Z","shell.execute_reply":"2023-09-05T11:22:01.830291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Loading the datasets","metadata":{}},{"cell_type":"code","source":"BATCH_SIZE = 16 * strategy.num_replicas_in_sync\n\ndef augment_image(image, label):\n    image = tf.image.random_flip_left_right(image)\n    return image, label\n\ndef load_train_data():\n    dataset = load_dataset(\"train\")\n    dataset = dataset.map(augment_image, num_parallel_calls=AUTO)\n    dataset = dataset.shuffle(1024)\n    dataset = dataset.repeat()\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.prefetch(AUTO)\n    return dataset\n    \ndef load_val_data():\n    dataset = load_dataset(\"val\")\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.cache()\n    dataset = dataset.prefetch(AUTO)\n    return dataset\n\ndef load_test_data():\n    dataset = load_dataset(\"test\", labeled=False, ordered=True)\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.prefetch(AUTO)\n    return dataset\n\ndef count_entries(folder):\n    paths = tf.io.gfile.glob(INPUT_PATH + '/' + folder + \"/*.tfrec\")\n    count = [int(re.search(f'(\\d+)(?=\\.)', path)[0]) for path in paths]\n    return sum(count)\n    \n    \ntrain_dataset = load_train_data()\nTRAIN_ENTRIES = count_entries(\"train\")\nval_dataset = load_val_data()\nVAL_ENTRIES = count_entries(\"val\")\ntest_dataset = load_test_data()\nTEST_ENTRIES = count_entries(\"test\")\nprint(\"Found\", TRAIN_ENTRIES, \"train entries,\", VAL_ENTRIES, \"val_entries,\", TEST_ENTRIES, \"test_entries.\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:22:05.882913Z","iopub.execute_input":"2023-09-05T11:22:05.883280Z","iopub.status.idle":"2023-09-05T11:22:06.123263Z","shell.execute_reply.started":"2023-09-05T11:22:05.883250Z","shell.execute_reply":"2023-09-05T11:22:06.121843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Functions for exploring the images","metadata":{}},{"cell_type":"code","source":"import math\n\ndef tfdata_to_numpy(data):\n    images, labels = data\n    numpy_images = images.numpy()\n    numpy_labels = labels.numpy()\n    if numpy_labels.dtype == object:\n        numpy_labels = [None for i in range(len(numpy_labels))]\n    return numpy_images, numpy_labels\n\n# simpler version just to display images without comparing labels\ndef display_images(batch):\n    images, labels = tfdata_to_numpy(batch)\n    rows = int(math.sqrt(len(images)))\n    cols = len(images) // rows\n    plt.figure(figsize=(16,16))\n    plt.tight_layout()\n    for i in range(rows * cols):\n        plt.subplot(rows, cols, i+1)\n        if labels[i] is not None:\n            plt.title(CLASSES[labels[i]], fontsize=10)\n        plt.axis(\"off\")\n        plt.imshow(images[i])\n    plt.show()\n\ndef title_from_label_and_target(label, correct_label):\n    if correct_label is None:\n        return CLASSES[label], True\n    correct = (label == correct_label)\n    return \"{} [{}{}{}]\".format(CLASSES[label], 'OK' if correct else 'NO', u\"\\u2192\" if not correct else '',\n                                CLASSES[correct_label] if not correct else ''), correct\n\ndef display_one_flower(image, title, subplot, red=False, titlesize=16):\n    plt.subplot(*subplot)\n    plt.axis('off')\n    plt.imshow(image)\n    if len(title) > 0:\n        plt.title(title, fontsize=int(titlesize) if not red else int(titlesize/1.2), color='red' if red else 'black', fontdict={'verticalalignment':'center'}, pad=int(titlesize/1.5))\n    return (subplot[0], subplot[1], subplot[2]+1)\n    \ndef display_batch_of_images(databatch, predictions=None):\n    \"\"\"This will work with:\n    display_batch_of_images(images)\n    display_batch_of_images(images, predictions)\n    display_batch_of_images((images, labels))\n    display_batch_of_images((images, labels), predictions)\n    \"\"\"\n    # data\n    images, labels = tfdata_to_numpy(databatch)\n    if labels is None:\n        labels = [None for _ in enumerate(images)]\n        \n    # auto-squaring: this will drop data that does not fit into square\n    # or square-ish rectangle\n    rows = int(math.sqrt(len(images)))\n    cols = len(images)//rows\n        \n    # size and spacing\n    FIGSIZE = 13.0\n    SPACING = 0.1\n    subplot=(rows,cols,1)\n    if rows < cols:\n        plt.figure(figsize=(FIGSIZE,FIGSIZE/cols*rows))\n    else:\n        plt.figure(figsize=(FIGSIZE/rows*cols,FIGSIZE))\n    \n    # display\n    for i, (image, label) in enumerate(zip(images[:rows*cols], labels[:rows*cols])):\n        title = '' if label is None else CLASSES[label]\n        correct = True\n        if predictions is not None:\n            title, correct = title_from_label_and_target(predictions[i], label)\n        dynamic_titlesize = FIGSIZE*SPACING/max(rows,cols)*40+3 # magic formula tested to work from 1x1 to 10x10 images\n        subplot = display_one_flower(image, title, subplot, not correct, titlesize=dynamic_titlesize)\n    \nds_iter = iter(train_dataset.unbatch().batch(20))\none_batch = next(ds_iter)\ndisplay_batch_of_images(one_batch)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:22:09.490493Z","iopub.execute_input":"2023-09-05T11:22:09.490885Z","iopub.status.idle":"2023-09-05T11:22:12.684938Z","shell.execute_reply.started":"2023-09-05T11:22:09.490854Z","shell.execute_reply":"2023-09-05T11:22:12.683417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Defining the model","metadata":{}},{"cell_type":"code","source":"MAX_LR = 0.00005 * strategy.num_replicas_in_sync\n\ndef exponential_lr(epoch,\n                   start_lr = 0.00001, min_lr = 0.00001, max_lr = MAX_LR,\n                   rampup_epochs = 5, sustain_epochs = 2,\n                   exp_decay = 0.8):\n\n    def lr(epoch, start_lr, min_lr, max_lr, rampup_epochs, sustain_epochs, exp_decay):\n        # linear increase from start to rampup_epochs\n        if epoch < rampup_epochs:\n            lr = ((max_lr - start_lr) /\n                  rampup_epochs * epoch + start_lr)\n        # constant max_lr during sustain_epochs\n        elif epoch < rampup_epochs + sustain_epochs:\n            lr = max_lr\n        # exponential decay towards min_lr\n        else:\n            lr = ((max_lr - min_lr) *\n                  exp_decay**(epoch - rampup_epochs - sustain_epochs) +\n                  min_lr)\n        return lr\n    return lr(epoch,\n              start_lr,\n              min_lr,\n              max_lr,\n              rampup_epochs,\n              sustain_epochs,\n              exp_decay)\n\nlr_callback = tf.keras.callbacks.LearningRateScheduler(exponential_lr, verbose=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:22:18.286301Z","iopub.execute_input":"2023-09-05T11:22:18.286691Z","iopub.status.idle":"2023-09-05T11:22:18.296990Z","shell.execute_reply.started":"2023-09-05T11:22:18.286659Z","shell.execute_reply":"2023-09-05T11:22:18.295584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Plotting the learning rate for 30 epochs","metadata":{}},{"cell_type":"code","source":"epochs = np.arange(1, 30, 1)\nplt.plot(epochs, [exponential_lr(x) for x in epochs])\nplt.ylabel(\"Learning rate\")\nplt.xlabel(\"Epoch\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:22:22.035010Z","iopub.execute_input":"2023-09-05T11:22:22.035388Z","iopub.status.idle":"2023-09-05T11:22:22.236158Z","shell.execute_reply.started":"2023-09-05T11:22:22.035345Z","shell.execute_reply":"2023-09-05T11:22:22.234751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def compile_model(preprocess_layer, base_model):\n    with strategy.scope():\n        img_preprocess = tf.keras.layers.Lambda(getattr(tf.keras.applications, preprocess_layer).preprocess_input, input_shape=([*IMAGE_SIZE, 3]))\n        base_model = getattr(tf.keras.applications, base_model)(weights=\"imagenet\", include_top=False)\n        base_model.trainable = False\n        \n        inputs = tf.keras.layers.Input(shape=([*IMAGE_SIZE, 3]))\n        x = img_preprocess(inputs)\n        x = base_model(x, training=False)\n        x = tf.keras.layers.GlobalAveragePooling2D()(x)\n        outputs = tf.keras.layers.Dense(len(CLASSES), activation=\"softmax\")(x)\n\n        model = tf.keras.Model(inputs, outputs)\n\n        model.compile(optimizer=\"adam\",\n                      loss=tf.keras.losses.SparseCategoricalCrossentropy(),\n                      metrics=[\"sparse_categorical_accuracy\"])\n        print(\"done\")\n        return model","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:27:05.715530Z","iopub.execute_input":"2023-09-05T11:27:05.716290Z","iopub.status.idle":"2023-09-05T11:27:05.726803Z","shell.execute_reply.started":"2023-09-05T11:27:05.716246Z","shell.execute_reply":"2023-09-05T11:27:05.725422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Transfer learning the models","metadata":{}},{"cell_type":"code","source":"STEPS_PER_EPOCH = TRAIN_ENTRIES // BATCH_SIZE\nVAL_STEPS = VAL_ENTRIES // BATCH_SIZE\nmodel_layers = [(\"densenet\", \"DenseNet201\"),\n                (\"resnet50\", \"ResNet50\"),\n                (\"xception\", \"Xception\")]\n\nmodels = []\n\nfor layers in model_layers:\n    models.append(compile_model(*layers))\n\nprint(len(models))\n","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:27:08.146310Z","iopub.execute_input":"2023-09-05T11:27:08.146780Z","iopub.status.idle":"2023-09-05T11:28:11.637359Z","shell.execute_reply.started":"2023-09-05T11:27:08.146744Z","shell.execute_reply":"2023-09-05T11:28:11.635959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models[2].layers[2].trainable","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:29:44.110410Z","iopub.execute_input":"2023-09-05T11:29:44.111547Z","iopub.status.idle":"2023-09-05T11:29:44.119243Z","shell.execute_reply.started":"2023-09-05T11:29:44.111501Z","shell.execute_reply":"2023-09-05T11:29:44.117920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"histories = []\n\nfor model in models:\n    history = model.fit(train_dataset,\n                    steps_per_epoch=STEPS_PER_EPOCH,\n                    validation_data=val_dataset,\n                    validation_steps=VAL_STEPS,\n                    epochs=15,\n                    callbacks=[lr_callback])\n    histories.append(history)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:29:57.002743Z","iopub.execute_input":"2023-09-05T11:29:57.003643Z","iopub.status.idle":"2023-09-05T11:47:06.252119Z","shell.execute_reply.started":"2023-09-05T11:29:57.003601Z","shell.execute_reply":"2023-09-05T11:47:06.250605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Plotting the learning processes of models","metadata":{}},{"cell_type":"code","source":"def plot_graphs(axs, history, metric):\n  axs.plot(history.history[metric])\n  axs.plot(history.history['val_'+metric], '')\n  axs.set_xlabel(\"Epochs\")\n  axs.set_ylabel(metric)\n  axs.legend([metric, 'val_'+metric])","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:48:50.908547Z","iopub.execute_input":"2023-09-05T11:48:50.909048Z","iopub.status.idle":"2023-09-05T11:48:50.915595Z","shell.execute_reply.started":"2023-09-05T11:48:50.909007Z","shell.execute_reply":"2023-09-05T11:48:50.914408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_histories(histories):\n    _, axs = plt.subplots(len(histories), 2, figsize=(12,12))\n    model_names = [model_tuple[1] for model_tuple in model_layers]\n    for i in range(len(histories)):\n        axs[i, 0].set_title(model_names[i] + \" \" + 'sparse_categorical_accuracy')\n        axs[i, 1].set_title(model_names[i] + \" \" + 'loss')\n        plot_graphs(axs[i, 0], histories[i], 'sparse_categorical_accuracy')\n        plot_graphs(axs[i, 1], histories[i], 'loss')\n    plt.tight_layout()\n    plt.show()\nplot_histories(histories)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:52:18.683091Z","iopub.execute_input":"2023-09-05T11:52:18.683999Z","iopub.status.idle":"2023-09-05T11:52:20.208279Z","shell.execute_reply.started":"2023-09-05T11:52:18.683957Z","shell.execute_reply":"2023-09-05T11:52:20.206955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"According to the graphs I am going to fine-tune Xception and DenseNet201","metadata":{}},{"cell_type":"markdown","source":"### Fine tuning of models","metadata":{}},{"cell_type":"code","source":"def tune_model(model):\n    model.layers[2].trainable = True\n    model.compile(optimizer=tf.keras.optimizers.Adam(1e-5),\n                  loss=tf.keras.losses.SparseCategoricalCrossentropy(),\n                  metrics=\"sparse_categorical_accuracy\")\n\n    model.fit(train_dataset, steps_per_epoch=STEPS_PER_EPOCH, validation_data=val_dataset, validation_steps=VAL_STEPS, epochs=5)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:54:34.602424Z","iopub.execute_input":"2023-09-05T11:54:34.603295Z","iopub.status.idle":"2023-09-05T11:54:34.610474Z","shell.execute_reply.started":"2023-09-05T11:54:34.603251Z","shell.execute_reply":"2023-09-05T11:54:34.609066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Tuning DenseNet201\ntune_model(models[0])\n# Tuning Xception\ntune_model(models[2])","metadata":{"execution":{"iopub.status.busy":"2023-09-05T11:55:38.843115Z","iopub.execute_input":"2023-09-05T11:55:38.843996Z","iopub.status.idle":"2023-09-05T12:06:08.409776Z","shell.execute_reply.started":"2023-09-05T11:55:38.843950Z","shell.execute_reply":"2023-09-05T12:06:08.408040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Predicting the classes of images in the validation set to see how each model performs individually","metadata":{}},{"cell_type":"code","source":"val_sample = val_dataset.unbatch().shuffle(350).batch(30)\nimages, labels = next(iter(val_sample))\nfor model in models:\n    preds = model.predict(images)\n    preds = np.argmax(preds, axis=-1)\n    display_batch_of_images((images, labels), preds)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T12:23:39.723567Z","iopub.execute_input":"2023-09-05T12:23:39.724033Z","iopub.status.idle":"2023-09-05T12:23:53.041701Z","shell.execute_reply.started":"2023-09-05T12:23:39.723995Z","shell.execute_reply":"2023-09-05T12:23:53.040250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Making predictions on a test set","metadata":{}},{"cell_type":"code","source":"test_images_ds = test_dataset.map(lambda image, idnum: image)\npredictions = []\nfor model in models:\n    probabilities = model.predict(test_images_ds)\n    predictions.append(np.argmax(probabilities, axis=-1))\n","metadata":{"execution":{"iopub.status.busy":"2023-09-05T12:33:15.301421Z","iopub.execute_input":"2023-09-05T12:33:15.302331Z","iopub.status.idle":"2023-09-05T12:34:27.298198Z","shell.execute_reply.started":"2023-09-05T12:33:15.302285Z","shell.execute_reply":"2023-09-05T12:34:27.296703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Function for declaring the best prediction among ensembled predictions","metadata":{}},{"cell_type":"code","source":"def vote_preds(predictions):\n    voters_amt = len(predictions)\n    preds_len = len(predictions[0])\n    best = []\n    for i in range(preds_len):\n        one_pred = []\n        for j in range(voters_amt):\n            one_pred.append(predictions[j][i])\n        best.append(np.bincount(np.array(one_pred)).argmax())\n    return best","metadata":{"execution":{"iopub.status.busy":"2023-09-05T12:40:00.477409Z","iopub.execute_input":"2023-09-05T12:40:00.477915Z","iopub.status.idle":"2023-09-05T12:40:00.485340Z","shell.execute_reply.started":"2023-09-05T12:40:00.477872Z","shell.execute_reply":"2023-09-05T12:40:00.483941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Creating a submission.csv file","metadata":{}},{"cell_type":"code","source":"ids = test_dataset.map(lambda image, idnum: idnum).unbatch()\nids = next(iter(ids.batch(TEST_ENTRIES))).numpy().astype(\"U\")\npredictions = vote_preds(predictions)\nsubm_df = pd.DataFrame({\"id\": ids, \"label\": predictions})\nsubm_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T12:40:06.114468Z","iopub.execute_input":"2023-09-05T12:40:06.115281Z","iopub.status.idle":"2023-09-05T12:40:07.267431Z","shell.execute_reply.started":"2023-09-05T12:40:06.115239Z","shell.execute_reply":"2023-09-05T12:40:07.265730Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subm_df.to_csv(\"/kaggle/working/submission.csv\", index=False)\nprint(\"done!\")","metadata":{"execution":{"iopub.status.busy":"2023-09-04T17:47:15.641412Z","iopub.execute_input":"2023-09-04T17:47:15.642482Z","iopub.status.idle":"2023-09-04T17:47:15.664055Z","shell.execute_reply.started":"2023-09-04T17:47:15.642437Z","shell.execute_reply":"2023-09-04T17:47:15.662731Z"},"trusted":true},"execution_count":null,"outputs":[]}],"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"}}