{"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":"# Step 1: Imports #\n\nWe begin by importing several Python packages.","metadata":{}},{"cell_type":"code","source":"!pip install -q efficientnet","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:37:17.006455Z","iopub.execute_input":"2022-12-14T19:37:17.006850Z","iopub.status.idle":"2022-12-14T19:37:28.056026Z","shell.execute_reply.started":"2022-12-14T19:37:17.006750Z","shell.execute_reply":"2022-12-14T19:37:28.055143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math, re, os\nimport numpy as np\nimport tensorflow as tf\n\nprint(\"Tensorflow version \" + tf.__version__)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:37:31.617788Z","iopub.execute_input":"2022-12-14T19:37:31.618724Z","iopub.status.idle":"2022-12-14T19:37:38.166646Z","shell.execute_reply.started":"2022-12-14T19:37:31.618675Z","shell.execute_reply":"2022-12-14T19:37:38.165559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow import keras\nfrom kaggle_datasets import KaggleDatasets\nfrom matplotlib import pyplot as plt\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.layers import Dense, Flatten,GlobalAveragePooling2D\nfrom tensorflow.keras.layers import Dropout, BatchNormalization, GaussianDropout\nfrom tensorflow.keras.applications import EfficientNetB7\nimport efficientnet.tfkeras as efficientnet","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:37:48.578609Z","iopub.execute_input":"2022-12-14T19:37:48.579083Z","iopub.status.idle":"2022-12-14T19:37:49.479854Z","shell.execute_reply.started":"2022-12-14T19:37:48.579052Z","shell.execute_reply":"2022-12-14T19:37:49.478383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 2: Distribution Strategy #\n\nA TPU has eight different *cores* and each of these cores acts as its own accelerator. (A TPU is sort of like having eight GPUs in one machine.) We tell TensorFlow how to make use of all these cores at once through a **distribution strategy**. Run the following cell to create the distribution strategy that we'll later apply to our model.","metadata":{}},{"cell_type":"code","source":"# Detect TPU, return appropriate distribution strategy\ntry:\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    strategy = tf.distribute.get_strategy() \n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:37:52.852914Z","iopub.execute_input":"2022-12-14T19:37:52.853226Z","iopub.status.idle":"2022-12-14T19:37:58.781074Z","shell.execute_reply.started":"2022-12-14T19:37:52.853196Z","shell.execute_reply":"2022-12-14T19:37:58.780093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We'll use the distribution strategy when we create our neural network model. Then, TensorFlow will distribute the training among the eight TPU cores by creating eight different *replicas* of the model, one for each core.\n\n# Step 3: Loading the Competition Data #\n\n## Get GCS Path ##\n\nWhen used with TPUs, datasets need to be stored in a [Google Cloud Storage bucket](https://cloud.google.com/storage/). You can use data from any public GCS bucket by giving its path just like you would data from `'/kaggle/input'`. The following will retrieve the GCS path for this competition's dataset.","metadata":{}},{"cell_type":"code","source":"GCS_DS_PATH = KaggleDatasets().get_gcs_path('tpu-getting-started')\nprint(GCS_DS_PATH) # what do gcs paths look like?","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:37:58.784356Z","iopub.execute_input":"2022-12-14T19:37:58.784633Z","iopub.status.idle":"2022-12-14T19:37:59.192592Z","shell.execute_reply.started":"2022-12-14T19:37:58.784605Z","shell.execute_reply":"2022-12-14T19:37:59.191573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"You can use data from any public dataset here on Kaggle in just the same way. If you'd like to use data from one of your private datasets, see [here](https://www.kaggle.com/docs/tpu#tpu3pt5).\n\n## Load Data ##\n\nWhen used with TPUs, datasets are often serialized into [TFRecords](https://www.kaggle.com/ryanholbrook/tfrecords-basics). This is a format convenient for distributing data to each of the TPUs cores. We've hidden the cell that reads the TFRecords for our dataset since the process is a bit long. You could come back to it later for some guidance on using your own datasets with TPUs.","metadata":{}},{"cell_type":"code","source":"\nIMAGE_SIZE = [512, 512]\nGCS_PATH = GCS_DS_PATH + '/tfrecords-jpeg-512x512'\nAUTO = tf.data.experimental.AUTOTUNE\n\nTRAINING_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/train/*.tfrec')\nVALIDATION_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/val/*.tfrec')\nTEST_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/test/*.tfrec') ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-12-14T19:38:03.349272Z","iopub.execute_input":"2022-12-14T19:38:03.349737Z","iopub.status.idle":"2022-12-14T19:38:03.589934Z","shell.execute_reply.started":"2022-12-14T19:38:03.349708Z","shell.execute_reply":"2022-12-14T19:38:03.589168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CLASSES = ['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\n","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:38:06.060694Z","iopub.execute_input":"2022-12-14T19:38:06.061666Z","iopub.status.idle":"2022-12-14T19:38:06.073024Z","shell.execute_reply.started":"2022-12-14T19:38:06.061625Z","shell.execute_reply":"2022-12-14T19:38:06.071810Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def decode_image(image_data):\n    image = tf.image.decode_jpeg(image_data, channels=3)\n    image = tf.cast(image, tf.float32) / 255.0  # convert image to floats in [0, 1] range\n    image = tf.reshape(image, [*IMAGE_SIZE, 3]) # explicit size needed for TPU\n    return image\n\ndef read_labeled_tfrecord(example):\n    LABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string), # tf.string means bytestring\n        \"class\": tf.io.FixedLenFeature([], tf.int64),  # shape [] means single element\n    }\n    example = tf.io.parse_single_example(example, LABELED_TFREC_FORMAT)\n    image = decode_image(example['image'])\n    label = tf.cast(example['class'], tf.int32)\n    return image, label # returns a dataset of (image, label) pairs\n\ndef read_unlabeled_tfrecord(example):\n    UNLABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string), # tf.string means bytestring\n        \"id\": tf.io.FixedLenFeature([], tf.string),  # shape [] means single element\n        # class is missing, this competitions's challenge is to predict flower classes for the test dataset\n    }\n    example = tf.io.parse_single_example(example, UNLABELED_TFREC_FORMAT)\n    image = decode_image(example['image'])\n    idnum = example['id']\n    return image, idnum # returns a dataset of image(s)\n\ndef load_dataset(filenames, labeled=True, ordered=False):\n    # Read from TFRecords. For optimal performance, reading from multiple files at once and\n    # disregarding data order. Order does not matter since we will be shuffling the data anyway.\n\n    ignore_order = tf.data.Options()\n    if not ordered:\n        ignore_order.experimental_deterministic = False # disable order, increase speed\n\n    dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTO) # automatically interleaves reads from multiple files\n    dataset = dataset.with_options(ignore_order) # uses data as soon as it streams in, rather than in its original order\n    dataset = dataset.map(read_labeled_tfrecord if labeled else read_unlabeled_tfrecord, num_parallel_calls=AUTO)\n    # returns a dataset of (image, label) pairs if labeled=True or (image, id) pairs if labeled=False\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:38:08.836347Z","iopub.execute_input":"2022-12-14T19:38:08.836829Z","iopub.status.idle":"2022-12-14T19:38:08.847067Z","shell.execute_reply.started":"2022-12-14T19:38:08.836778Z","shell.execute_reply":"2022-12-14T19:38:08.846325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create Data Pipelines ##\n\nIn this final step we'll use the `tf.data` API to define an efficient data pipeline for each of the training, validation, and test splits.","metadata":{}},{"cell_type":"code","source":"\ndef data_augment(image, label):\n    # Thanks to the dataset.prefetch(AUTO)\n    # statement in the next function (below), this happens essentially\n    # for free on TPU. Data pipeline code is executed on the \"CPU\"\n    # part of the TPU while the TPU itself is computing gradients.\n    image = tf.image.random_flip_left_right(image)\n    #image = tf.image.random_saturation(image, 0, 2)\n    return image, label   \n\ndef get_training_dataset():\n    dataset = load_dataset(TRAINING_FILENAMES, labeled=True)\n    dataset = dataset.map(data_augment, num_parallel_calls=AUTO)\n    dataset = dataset.repeat() # the training dataset must repeat for several epochs\n    dataset = dataset.shuffle(2048)\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.prefetch(AUTO) # prefetch next batch while training (autotune prefetch buffer size)\n    return dataset\n\ndef get_validation_dataset(ordered=False):\n    dataset = load_dataset(VALIDATION_FILENAMES, labeled=True, ordered=ordered)\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.cache()\n    dataset = dataset.prefetch(AUTO)\n    return dataset\n\ndef get_test_dataset(ordered=False):\n    dataset = load_dataset(TEST_FILENAMES, labeled=False, ordered=ordered)\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.prefetch(AUTO)\n    return dataset\n\ndef count_data_items(filenames):\n    # the number of data items is written in the name of the .tfrec\n    # files, i.e. flowers00-230.tfrec = 230 data items\n    n = [int(re.compile(r\"-([0-9]*)\\.\").search(filename).group(1)) for filename in filenames]\n    return np.sum(n)\n\nNUM_TRAINING_IMAGES = count_data_items(TRAINING_FILENAMES)\nNUM_VALIDATION_IMAGES = count_data_items(VALIDATION_FILENAMES)\nNUM_TEST_IMAGES = count_data_items(TEST_FILENAMES)\nprint('Dataset: {} training images, {} validation images, {} unlabeled test images'.format(NUM_TRAINING_IMAGES, NUM_VALIDATION_IMAGES, NUM_TEST_IMAGES))\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-12-14T19:38:44.526745Z","iopub.execute_input":"2022-12-14T19:38:44.527228Z","iopub.status.idle":"2022-12-14T19:38:44.543114Z","shell.execute_reply.started":"2022-12-14T19:38:44.527197Z","shell.execute_reply":"2022-12-14T19:38:44.542080Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This next cell will create the datasets that we'll use with Keras during training and inference. Notice how we scale the size of the batches to the number of TPU cores.","metadata":{}},{"cell_type":"code","source":"# Define the batch size. This will be 16 with TPU off and 128 (=16*8) with TPU on\nBATCH_SIZE = 16 * strategy.num_replicas_in_sync\n\nds_train = get_training_dataset()\nds_valid = get_validation_dataset()\nds_test = get_test_dataset()\n\nprint(\"Training:\", ds_train)\nprint (\"Validation:\", ds_valid)\nprint(\"Test:\", ds_test)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:38:47.299114Z","iopub.execute_input":"2022-12-14T19:38:47.299829Z","iopub.status.idle":"2022-12-14T19:38:47.618116Z","shell.execute_reply.started":"2022-12-14T19:38:47.299795Z","shell.execute_reply":"2022-12-14T19:38:47.617162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"These datasets are `tf.data.Dataset` objects. You can think about a dataset in TensorFlow as a *stream* of data records. The training and validation sets are streams of `(image, label)` pairs.","metadata":{}},{"cell_type":"code","source":"np.set_printoptions(threshold=15, linewidth=80)\n\nprint(\"Training data shapes:\")\nfor image, label in ds_train.take(3):\n    print(image.numpy().shape, label.numpy().shape)\nprint(\"Training data label examples:\", label.numpy())","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:38:50.578116Z","iopub.execute_input":"2022-12-14T19:38:50.578742Z","iopub.status.idle":"2022-12-14T19:38:55.875861Z","shell.execute_reply.started":"2022-12-14T19:38:50.578707Z","shell.execute_reply":"2022-12-14T19:38:55.874709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The test set is a stream of `(image, idnum)` pairs; `idnum` here is the unique identifier given to the image that we'll use later when we make our submission as a `csv` file.","metadata":{}},{"cell_type":"code","source":"print(\"Test data shapes:\")\nfor image, idnum in ds_test.take(3):\n    print(image.numpy().shape, idnum.numpy().shape)\nprint(\"Test data IDs:\", idnum.numpy().astype('U')) # U=unicode string","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:38:59.843406Z","iopub.execute_input":"2022-12-14T19:38:59.843954Z","iopub.status.idle":"2022-12-14T19:39:03.594006Z","shell.execute_reply.started":"2022-12-14T19:38:59.843921Z","shell.execute_reply":"2022-12-14T19:39:03.593017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 4: Explore Data #\n\nLet's take a moment to look at some of the images in the dataset.","metadata":{}},{"cell_type":"code","source":"def batch_to_numpy_images_and_labels(data):\n    images, labels = data\n    numpy_images = images.numpy()\n    numpy_labels = labels.numpy()\n    if numpy_labels.dtype == object: # binary string in this case,\n                                     # these are image ID strings\n        numpy_labels = [None for _ in enumerate(numpy_images)]\n    # If no labels, only image IDs, return None for labels (this is\n    # the case for test data)\n    return numpy_images, numpy_labels\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 = batch_to_numpy_images_and_labels(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    \n    #layout\n    plt.tight_layout()\n    if label is None and predictions is None:\n        plt.subplots_adjust(wspace=0, hspace=0)\n    else:\n        plt.subplots_adjust(wspace=SPACING, hspace=SPACING)\n    plt.show()\n\n\ndef 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.'])","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-12-14T19:39:07.372867Z","iopub.execute_input":"2022-12-14T19:39:07.373233Z","iopub.status.idle":"2022-12-14T19:39:07.392712Z","shell.execute_reply.started":"2022-12-14T19:39:07.373195Z","shell.execute_reply":"2022-12-14T19:39:07.391637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"You can display a single batch of images from a dataset with another of our helper functions. The next cell will turn the dataset into an iterator of batches of 20 images.","metadata":{}},{"cell_type":"code","source":"ds_iter = iter(ds_train.unbatch().batch(20))","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:39:13.855093Z","iopub.execute_input":"2022-12-14T19:39:13.855454Z","iopub.status.idle":"2022-12-14T19:39:13.871605Z","shell.execute_reply.started":"2022-12-14T19:39:13.855419Z","shell.execute_reply":"2022-12-14T19:39:13.870608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Use the Python `next` function to pop out the next batch in the stream and display it with the helper function.","metadata":{}},{"cell_type":"code","source":"one_batch = next(ds_iter)\ndisplay_batch_of_images(one_batch)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:39:16.802510Z","iopub.execute_input":"2022-12-14T19:39:16.803103Z","iopub.status.idle":"2022-12-14T19:39:21.119308Z","shell.execute_reply.started":"2022-12-14T19:39:16.803057Z","shell.execute_reply":"2022-12-14T19:39:21.117677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"By defining `ds_iter` and `one_batch` in separate cells, you only need to rerun the cell above to see a new batch of images.","metadata":{}},{"cell_type":"code","source":"data = get_validation_dataset()\ndata = data.unbatch()\nbatch1 = iter(data)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:39:26.671486Z","iopub.execute_input":"2022-12-14T19:39:26.672295Z","iopub.status.idle":"2022-12-14T19:39:26.711085Z","shell.execute_reply.started":"2022-12-14T19:39:26.672260Z","shell.execute_reply":"2022-12-14T19:39:26.710207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = []\nfor image,label in batch1:\n    labels.append(int(label))","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:39:29.274555Z","iopub.execute_input":"2022-12-14T19:39:29.275430Z","iopub.status.idle":"2022-12-14T19:39:42.660881Z","shell.execute_reply.started":"2022-12-14T19:39:29.275379Z","shell.execute_reply":"2022-12-14T19:39:42.659979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import collections\nimport matplotlib.pyplot as plt\nimport plotly.graph_objects as go\nfrom plotly.offline import init_notebook_mode, iplot\ninit_notebook_mode(connected=True)\n\n\nc = collections.Counter(labels)\nc = sorted(c.items(), key = lambda t: t[1] , reverse = True )\nclass_num = [CLASSES[i[0]] for i in c]\nfreq = [i[1] for i in c]\nfig = go.Figure([go.Bar(x=class_num, y=freq)])\n\niplot(fig)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:40:57.117451Z","iopub.execute_input":"2022-12-14T19:40:57.118453Z","iopub.status.idle":"2022-12-14T19:40:58.159120Z","shell.execute_reply.started":"2022-12-14T19:40:57.118368Z","shell.execute_reply":"2022-12-14T19:40:58.157961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The above graph shows Top-50 classes in the training dataset and their distribution.","metadata":{}},{"cell_type":"markdown","source":"# Step 5: Define Model #\n\nNow we're ready to create a neural network for classifying images! We'll use what's known as **transfer learning**. With transfer learning, you reuse part of a pretrained model to get a head-start on a new dataset.\n\n\n\nThe distribution strategy we created earlier contains a [context manager](https://docs.python.org/3/reference/compound_stmts.html#with), `strategy.scope`. This context manager tells TensorFlow how to divide the work of training among the eight TPU cores. When using TensorFlow with a TPU, it's important to define your model in a `strategy.scope()` context.","metadata":{}},{"cell_type":"markdown","source":"The `'sparse_categorical'` versions of the loss and metrics are appropriate for a classification task with more than two labels, like this one.","metadata":{}},{"cell_type":"markdown","source":"## EfficientNetB3","metadata":{}},{"cell_type":"code","source":"\nwith strategy.scope():    \n    \n    base_model=tf.keras.applications.efficientnet.EfficientNetB3(include_top=False, weights=\"imagenet\",input_shape=(*IMAGE_SIZE, 3), pooling='max') \n    base_model.trainable= True\n    x =base_model.output\n    x = Dense(1024, kernel_regularizer = keras.regularizers.l2(l = 0.016),activity_regularizer=keras.regularizers.l1(0.006),\n                bias_regularizer=keras.regularizers.l2(0.006) ,activation='sigmoid')(x)\n    x=Dropout(rate=.3, seed=123)(x)  \n    x=Dense(104, activation='softmax')(x)\n\n    eff3 = Model(inputs=base_model.input, outputs=x)\n","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:41:08.691574Z","iopub.execute_input":"2022-12-14T19:41:08.691912Z","iopub.status.idle":"2022-12-14T19:41:27.985406Z","shell.execute_reply.started":"2022-12-14T19:41:08.691882Z","shell.execute_reply":"2022-12-14T19:41:27.984346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lr=.001 # start with this learning rate\neff3.compile(tf.keras.optimizers.Adamax(lr=0.001), loss='sparse_categorical_crossentropy', metrics=['sparse_categorical_accuracy'])\n\nepochs=30\nrlronp=tf.keras.callbacks.ReduceLROnPlateau(monitor=\"val_loss\", factor=0.5, patience=2,verbose=1)\nestop=tf.keras.callbacks.EarlyStopping(monitor=\"val_loss\", patience= 4 , verbose=1,restore_best_weights=True)\ncallbacks=[rlronp, estop]\n    ","metadata":{"execution":{"iopub.status.busy":"2022-12-14T15:19:24.883004Z","iopub.execute_input":"2022-12-14T15:19:24.883328Z","iopub.status.idle":"2022-12-14T15:19:24.934819Z","shell.execute_reply.started":"2022-12-14T15:19:24.883296Z","shell.execute_reply":"2022-12-14T15:19:24.933849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## EfficientNetB7","metadata":{}},{"cell_type":"code","source":"def create_EfficientNet_model():\n    pretrained_model = efficientnet.EfficientNetB7(weights = 'noisy-student', include_top = False, input_shape = [*IMAGE_SIZE, 3])\n    pretrained_model.trainable = True\n\n    model = tf.keras.Sequential([\n        pretrained_model,\n        tf.keras.layers.GlobalAveragePooling2D(),\n        tf.keras.layers.Dense(len(CLASSES), activation = 'softmax')\n    ])\n\n    return model\nwith strategy.scope():\n      eff = create_EfficientNet_model()\neff.compile(\n    optimizer='adam',\n    loss = 'sparse_categorical_crossentropy',\n    metrics=['sparse_categorical_accuracy']\n)       ","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:41:37.288665Z","iopub.execute_input":"2022-12-14T19:41:37.289619Z","iopub.status.idle":"2022-12-14T19:42:19.785851Z","shell.execute_reply.started":"2022-12-14T19:41:37.289554Z","shell.execute_reply":"2022-12-14T19:42:19.784817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eff.summary()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:42:36.020895Z","iopub.execute_input":"2022-12-14T19:42:36.021625Z","iopub.status.idle":"2022-12-14T19:42:36.075742Z","shell.execute_reply.started":"2022-12-14T19:42:36.021585Z","shell.execute_reply":"2022-12-14T19:42:36.074751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 6: Training #\n\n## Learning Rate Schedule ##\n\nWe'll train this network with a special learning rate schedule.","metadata":{}},{"cell_type":"code","source":"EPOCHS = 20\n# Learning Rate Schedule for Fine Tuning #\ndef exponential_lr(epoch,\n                   start_lr = 0.00001, min_lr = 0.00001, max_lr = 0.00005 * strategy.num_replicas_in_sync,\n                   rampup_epochs = 5, sustain_epochs = 0,\n                   exp_decay = 0.80):\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)\n\nrng = [i for i in range(EPOCHS)]\ny = [exponential_lr(x) for x in rng]\nplt.plot(rng, y)\nprint(\"Learning rate schedule: {:.3g} to {:.3g} to {:.3g}\".format(y[0], max(y), y[-1]))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-12-14T19:42:55.268550Z","iopub.execute_input":"2022-12-14T19:42:55.268878Z","iopub.status.idle":"2022-12-14T19:42:55.534945Z","shell.execute_reply.started":"2022-12-14T19:42:55.268845Z","shell.execute_reply":"2022-12-14T19:42:55.534034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Fit Model ##\n\nAnd now we're ready to train the model. After defining a few parameters, we're good to go!","metadata":{}},{"cell_type":"markdown","source":"### EfficientNetB7 with Noisy-student weights","metadata":{}},{"cell_type":"code","source":"# Define training epochs\nfrom tensorflow.keras.callbacks import EarlyStopping\nSTEPS_PER_EPOCH = NUM_TRAINING_IMAGES // BATCH_SIZE\nhistory = eff.fit(ds_train, \n          steps_per_epoch=STEPS_PER_EPOCH, \n          epochs=EPOCHS, \n          callbacks=[lr_callback, EarlyStopping(patience=5, restore_best_weights=True)],\n          validation_data=get_validation_dataset(),\n          workers=3)","metadata":{"_kg_hide-output":false,"execution":{"iopub.status.busy":"2022-12-14T19:43:00.745805Z","iopub.execute_input":"2022-12-14T19:43:00.746394Z","iopub.status.idle":"2022-12-14T20:10:43.170692Z","shell.execute_reply.started":"2022-12-14T19:43:00.746353Z","shell.execute_reply":"2022-12-14T20:10:43.169992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_training_curves(\n    history.history['loss'],\n    history.history['val_loss'],\n    'loss',\n    211,\n)\ndisplay_training_curves(\n    history.history['sparse_categorical_accuracy'],\n    history.history['val_sparse_categorical_accuracy'],\n    'accuracy',\n    212,\n)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T20:11:44.440104Z","iopub.execute_input":"2022-12-14T20:11:44.440457Z","iopub.status.idle":"2022-12-14T20:11:45.028737Z","shell.execute_reply.started":"2022-12-14T20:11:44.440424Z","shell.execute_reply":"2022-12-14T20:11:45.027814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### EfficientNetB3 imagenet","metadata":{}},{"cell_type":"code","source":"# Define training epochs\nhistory_eff3 = eff3.fit(\n    ds_train,\n    validation_data=ds_valid,\n    epochs=epochs,\n    steps_per_epoch=STEPS_PER_EPOCH,\n    callbacks=[rlronp, estop],\n)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T15:19:31.445510Z","iopub.execute_input":"2022-12-14T15:19:31.445783Z","iopub.status.idle":"2022-12-14T15:43:34.415729Z","shell.execute_reply.started":"2022-12-14T15:19:31.445756Z","shell.execute_reply":"2022-12-14T15:43:34.414960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_training_curves(\n    history_eff3.history['loss'],\n    history_eff3.history['val_loss'],\n    'loss',\n    211,\n)\ndisplay_training_curves(\n    history_eff3.history['sparse_categorical_accuracy'],\n    history_eff3.history['val_sparse_categorical_accuracy'],\n    'accuracy',\n    212,\n)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T15:50:15.343296Z","iopub.execute_input":"2022-12-14T15:50:15.343556Z","iopub.status.idle":"2022-12-14T15:50:15.736137Z","shell.execute_reply.started":"2022-12-14T15:50:15.343530Z","shell.execute_reply":"2022-12-14T15:50:15.735017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"![image.png](attachment:78865451-9be2-4a66-8d3a-1d1cb515891a.png)","metadata":{},"attachments":{"78865451-9be2-4a66-8d3a-1d1cb515891a.png":{"image/png":"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W7dardaBAwfa7fZrDzOZTFUfRFGsqKioT8WmfFcjymYlonP59foBAQAANHY+Pj4lJdc/mikqKvL397darYcPH96xY4d21ZvyXQ0fs+RvNZwrQNQAAACP1qxZs169enXs2NFisQQHB1dtHDp06KxZs+Li4mJiYnr06KFd9aYcNYgoymZB1AAAAJg3b951W0wm0+rVq6/bePLkSSIKDAzct29f1ZZnn322nqWb8gMUIopG1AAAANBVE48aUTbL+UK7rKh6NwIAAOChmnjUiLRZZJVnF1ez6BwAAABopIlHjegACxFl4hkKAACATpp41MB4VwAAAH018agR4msyiOxsASYMBQAA0EcTjxqiwCL8MQgFAACgGr6+vkR0/vz5e++997pdAwcO3LlzZ52v7OKo8eSTT7Zp06Znz57Xbvzwww/9/f0vXbrk2lo1FGWz4AEKAABATYSHhy9evNi113Rx1Jg0adK333577ZbMzMwNGzZERka6tlDNRQfgrgYAAHi0F1988ZNPPqn6/Prrr7/55pt33HFHUlJSp06dVqxYce2Rp0+f7tixIxFVVFRMnDgxLi5uzJgx9VwDxcWzhfbu3fu69d9eeuml119/fdKkSa4tVHNRNkuxXS6qcPpZDHr1AAAAUC32/YuUs7/u54fG8yFv3XTPuHHjnnnmmSeeeIKIFi9evGbNmhkzZvj6+l68eLFXr1533303Y+y6Uz777DOr1Xrw4MF9+/YlJSXVvSutJyZftWpVWFhYfHz8TffOnTt37ty5RKTps5XL67vmV8RHIGoAAIAn6ty5c25u7vnz5/Py8mw2W2ho6DPPPLN582ZBELKysi5cuBAaGnrdKZs2bZoxYwYRdezYseo+R51pGDXKy8vffffdpUuX3uqAKVOmTJkyhYgGDhyoXRtRAVYiOldQER/hq10VAACAerrVPQmXGDt27JIlS3JycsaNGzdv3ry8vLz09HSDwdCqVavrlo93OQ1HoJw6derMmTN9+vSJj48/f/58//79L1y4oF25W4n0NxNm8QIAAM82bty4RYsWLVmyZOzYscXFxcHBwQaDYcOGDde99nBVv379FixYQEQHDhy4uvRa3WgYNeLi4o4fP75///79+/eHh4dv3LgxJCREu3K34mWSmnkZz+Zjag0AAPBccXFxJSUlERERYWFhkyZN2rVrV6dOnb7++ut2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wIYQNQAAAMCGEDUAQGY7duyYNWuW3FUAgK0gagAAAIANIWoAQIf88MMPY8aMGTly5COPPCIIQlhY2NNPP52YmDhp0qTS0lJCSHp6+k033TR8+PA77rhD6sgnKytr8uTJI0aMGDVqVHZ2NmkalmLw4MGLFi1ijMn8IwGAVSFqAED7nTlz5scff9y8efPOnTt5nl+zZk1dXV18fPzevXtHjBjx6quvEkKWLFnywgsv7N69u0+fPq+88gohZNGiRQsXLty1a9eWLVu6du1KCDl27Njy5cv37duXk5Ozd+9emX8qALAqhdwFAIAT27Zt29GjR0ePHk0I0Wq1gYGBHMdNmzaNEDJr1qw777yzqqqqurp65MiRhJC5c+feddddNTU1RUVFEydOJIRoNBppPQkJCWFhYYSQuLi4vLy8YcOGyfYjAYC1IWoAQPsxxubMmfP888+bWl5//XXTdOsHNDcNoMDzvDRcJAC4DFxAAYD2u+GGG3766aeSkhJCSEVFRV5eniiK0niPa9euTUxM9PHx8fHx2b17NyHk+++/HzFihJeXV2ho6MaNGwkhOp2uvr5e3h8BAGwNZzUAoP169er173//e+rUqaIoKpXKN954w8PDIy0t7Y033ggMDPziiy8IIR999NFjjz1WX18fHR394YcfEkI+/vjjRx55ZNmyZUql8ssvv5T7hwAA28LIrgBgTWFhYYWFhXJXAQAOBBdQAAAAwIZwVgMAAABsCGc1AAAAwIYQNQAAAMCGEDUAAADAhhA1AAAAwIYQNQAAAMCGEDUAAADAhhA1AAAAwIYQNQAAAMCGEDUAAADAhhA1AAAAwIYQNQAAAMCGEDUAAADAhhA1AAAAwIYQNQAAAMCGEDUA4Bruu+++l156ycICcXFxqampdqsHAJwLogYAAADYEKIGADglo9EodwkA0CqIGgCuLC4u7t133x0+fHhoaOiDDz548eLFGTNmhIeHT548ubKyUlpm06ZNiYmJkZGR48ePP3PmjNR49OjRUaNGhYeH33333TqdzrTC33//feTIkZGRkWPHjj1+/LiFTW/evDkpKSkiIqJv377Lly83te/Zs2fs2LGRkZF9+/b99ttvCSENDQ3PPPNMv379IiMjb7311oaGhh07dvTp08f8p5Au0CxfvnzevHn33ntvRETEd999l5aWdvPNN0dGRl533XVPPvmk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APqizlyNFStWrFixovfP7du3ux4EBATs3r1blSHc45oLAm7AqXMbTp17cN7chlPnNpw69wz2vDG73a5RKQAAAADYmBwAAAA0hKgBAAAAGjJy1LheZxa4oenTpy9YsCAtLS09Pd3btejAY489NnHixPnz57v+bGxsvOOOO1JSUu644w7coOxHn/P24osvJicnp6WlpaWlHTp0yLu1DWcVFRWrV6++5ZZb5s2b98orrxC+cgN29anDt26AOjs7ly1btnDhwnnz5r3wwgtEVFpaunz5covFsnnz5u7u7v4/bti5GrIsz549+4MPPoiLi1u6dOnrr78+ZcoUbxelG9OnT7dardjZZoCOHTsWHBz86KOP5uTkENEzzzwTGRn5xBNP7Nq1y263P//8894ucJjqc95efPHFkJCQn/70p96ua7irqampqamZNWtWS0tLenr6O++88+c//xlfuYG4+tS9//77+NYNhBCira0tJCTE4XDcdtttL7300u9+97vbb789IyPjiSeemDZt2pYtW/r5uGGvavTTmQVAXQsXLoyMjOz9s7f1z/r16z/66CPv1TXc9TlvMECjR4+eNWsWEYWGhiYlJVVXV+MrN0BXnzpvV6QbjLGQkBAicjgcDoeDMfbZZ5+tXbuWBvatM2zU6KczC9wQY2zdunVLlizJzMz0di36c/HixdGjRxPRqFGjLl686O1y9OS1115bsGDBY489ZtSrreoqKysrLi6ePXs2vnKD1XvqCN+6AZNlOS0tbdKkSUuXLp0wYUJ4eLjJZKKB/cIaNmrAUBw8ePCzzz7Lysr64x//eOzYMW+Xo1eMMeyQO3BbtmwpKio6evTo6NGje/fmgetpbW3dsGHDCy+8EBYW1vskvnIDceWpw7du4CRJOnr06FdffZWfn19SUjKozxo2avTTmQVuKC4ujohiYmJWr15dUFDg7XJ0ZuTIkTU1NURUU1MTExPj7XJ0Y+TIkZIkcc43bNiAb13/HA7Hhg0b7r777jVr1hC+coNx9anDt25QIiIiFi1adPz48aamJqfTSQP7hTVs1OinMwv0r62traWlxfXg8OHDycnJ3q5IZ3pb/+zZs2fVqlXeLkc3XD+WRPThhx/iW9cPIcTjjz+elJT0+OOPu57BV26Arj51+NYNUF1dnesGU0dHh9VqTUpKWrRo0f79+2lg3zrDrkAhokOHDj311FOuzizbtm3zdjm6UVpa+sADDxCRLMt33XUXTt0Nbdmy5ejRo/X19SNHjvzP//zP1atXb9q0qaKiYuzYsZmZmZj5eD19ztvRo0dPnjxJROPGjfvNb37jmnwAV8vJyVm5cuXUqVM550T0zDPPpKam4is3EFefuqysLHzrBuLkyZOPPvqoLMtCiDvuuOMXv/hFaWnpww8/3NjYOGPGjNdee83f37+fjxs5agAAAIDXGfYGCgAAAAwHiBoAAACgIUQNAAAA0BCiBgAAAGgIUQMAAAA0hKgBAF72+eef33vvvd6uAgC0gqgBAAAAGkLUAIAheffdd5ctW5aWlrZ161ZZluPj45966ql58+atWbOmrq6OiL788stbb711wYIFDzzwgGsjn/Pnz69du3bhwoWLFy/+9ttv6VJbijlz5jzyyCNCCC//kwBAVYgaAOC+M2fO/PWvf/3kk0+OHj0qSdJ7773X1tZmsVhyc3MXLlz4q1/9ioh+/OMfP/fcc9nZ2VOnTn3ppZeI6JFHHvnhD3947NixQ4cOjRo1ioiKi4tffPHFvLy80tLS3NxcL/+rAEBVJm8XAAA6duTIkRMnTixdupSIOjs7o6OjOed33nknEd17770PPvhgU1NTc3NzWloaEd1///0bN25saWmprq6+/fbbiSggIMB1nJSUlPj4eCKaPn26zWabP3++1/5JAKA2RA0AcJ8QYv369c8++2zvMzt37ux9PPCG5r0NFCRJcrWLBADDwA0UAHDfkiVL9u/fX1tbS0SNjY02m01RFFe/x7/85S/z5s0LDw8PDw/Pzs4mor179y5cuDA0NDQuLu7DDz8koq6urvb2du/+EwBAa7iqAQDumzJlytNPP71u3TpFUcxm88svvxwcHJyfn//yyy9HR0e/+eabRPTKK688+eST7e3t48eP//3vf09Er7766tatW1944QWz2bx7925v/yMAQFvo7AoAaoqPj6+srPR2FQAwjOAGCgAAAGgIVzUAAABAQ7iqAQAAABpC1AAAAAANIWoAAACAhhA1AAAAQEOIGgAAAKCh/w/lX6z6u2avBAAAAABJRU5ErkJggg=="}}},{"cell_type":"markdown","source":"The EfficientNetB7 model with noisy-student weights have ","metadata":{}},{"cell_type":"markdown","source":"# Step 7: Evaluate Predictions #\n\nBefore making your final predictions on the test set, it's a good idea to evaluate your model's predictions on the validation set. This can help you diagnose problems in training or suggest ways your model could be improved. We'll look at two common ways of validation: plotting the **confusion matrix** and **visual validation**.","metadata":{}},{"cell_type":"code","source":"\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import f1_score, precision_score, recall_score, confusion_matrix\n\ndef display_confusion_matrix(cmat, score, precision, recall):\n    plt.figure(figsize=(15,15))\n    ax = plt.gca()\n    ax.matshow(cmat, cmap='Reds')\n    ax.set_xticks(range(len(CLASSES)))\n    ax.set_xticklabels(CLASSES, fontdict={'fontsize': 7})\n    plt.setp(ax.get_xticklabels(), rotation=45, ha=\"left\", rotation_mode=\"anchor\")\n    ax.set_yticks(range(len(CLASSES)))\n    ax.set_yticklabels(CLASSES, fontdict={'fontsize': 7})\n    plt.setp(ax.get_yticklabels(), rotation=45, ha=\"right\", rotation_mode=\"anchor\")\n    titlestring = \"\"\n    if score is not None:\n        titlestring += 'f1 = {:.3f} '.format(score)\n    if precision is not None:\n        titlestring += '\\nprecision = {:.3f} '.format(precision)\n    if recall is not None:\n        titlestring += '\\nrecall = {:.3f} '.format(recall)\n    if len(titlestring) > 0:\n        ax.text(101, 1, titlestring, fontdict={'fontsize': 18, 'horizontalalignment':'right', 'verticalalignment':'top', 'color':'#804040'})\n    plt.show()\n    ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-12-14T20:11:55.081832Z","iopub.execute_input":"2022-12-14T20:11:55.082361Z","iopub.status.idle":"2022-12-14T20:11:55.302121Z","shell.execute_reply.started":"2022-12-14T20:11:55.082318Z","shell.execute_reply":"2022-12-14T20:11:55.301245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Confusion Matrix ##\n\nA [confusion matrix](https://en.wikipedia.org/wiki/Confusion_matrix) shows the actual class of an image tabulated against its predicted class. It is one of the best tools you have for evaluating the performance of a classifier.\n\nThe following cell does some processing on the validation data and then creates the matrix with the `confusion_matrix` function included in [`scikit-learn`](https://scikit-learn.org/stable/index.html).","metadata":{}},{"cell_type":"code","source":"cmdataset = get_validation_dataset(ordered=True)\nimages_ds = cmdataset.map(lambda image, label: image)\nlabels_ds = cmdataset.map(lambda image, label: label).unbatch()\n\ncm_correct_labels = next(iter(labels_ds.batch(NUM_VALIDATION_IMAGES))).numpy()\ncm_probabilities = eff.predict(images_ds)\ncm_predictions = np.argmax(cm_probabilities, axis=-1)\n\nlabels = range(len(CLASSES))\ncmat = confusion_matrix(\n    cm_correct_labels,\n    cm_predictions,\n    labels=labels,\n)\ncmat = (cmat.T / cmat.sum(axis=1)).T # normalize","metadata":{"execution":{"iopub.status.busy":"2022-12-14T20:11:59.364689Z","iopub.execute_input":"2022-12-14T20:11:59.365023Z","iopub.status.idle":"2022-12-14T20:12:23.219261Z","shell.execute_reply.started":"2022-12-14T20:11:59.364990Z","shell.execute_reply":"2022-12-14T20:12:23.218183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"You might be familiar with metrics like [F1-score](https://en.wikipedia.org/wiki/F1_score) or [precision and recall](https://en.wikipedia.org/wiki/Precision_and_recall). This cell will compute these metrics and display them with a plot of the confusion matrix. (These metrics are defined in the Scikit-learn module `sklearn.metrics`; we've imported them in the helper script for you.)","metadata":{}},{"cell_type":"code","source":"score = f1_score(\n    cm_correct_labels,\n    cm_predictions,\n    labels=labels,\n    average='macro',\n)\nprecision = precision_score(\n    cm_correct_labels,\n    cm_predictions,\n    labels=labels,\n    average='macro',\n)\nrecall = recall_score(\n    cm_correct_labels,\n    cm_predictions,\n    labels=labels,\n    average='macro',\n)\ndisplay_confusion_matrix(cmat, score, precision, recall)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T20:12:49.696723Z","iopub.execute_input":"2022-12-14T20:12:49.697832Z","iopub.status.idle":"2022-12-14T20:12:54.774693Z","shell.execute_reply.started":"2022-12-14T20:12:49.697788Z","shell.execute_reply":"2022-12-14T20:12:54.773743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visual Validation ##\n\nIt can also be helpful to look at some examples from the validation set and see what class your model predicted. This can help reveal patterns in the kinds of images your model has trouble with.\n\nThis cell will set up the validation set to display 20 images at a time -- you can change this to display more or fewer, if you like.","metadata":{}},{"cell_type":"code","source":"dataset = get_validation_dataset()\ndataset = dataset.unbatch().batch(20)\nbatch = iter(dataset)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T20:13:07.306577Z","iopub.execute_input":"2022-12-14T20:13:07.306903Z","iopub.status.idle":"2022-12-14T20:13:07.347833Z","shell.execute_reply.started":"2022-12-14T20:13:07.306867Z","shell.execute_reply":"2022-12-14T20:13:07.346908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"And here is a set of flowers with their predicted species. Run the cell again to see another set.","metadata":{}},{"cell_type":"code","source":"images, labels = next(batch)\nprobabilities = eff.predict(images)\npredictions = np.argmax(probabilities, axis=-1)\ndisplay_batch_of_images((images, labels), predictions)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T20:13:10.157916Z","iopub.execute_input":"2022-12-14T20:13:10.158412Z","iopub.status.idle":"2022-12-14T20:13:24.883789Z","shell.execute_reply.started":"2022-12-14T20:13:10.158376Z","shell.execute_reply":"2022-12-14T20:13:24.882281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 8: Make Test Predictions #\n\nOnce you're satisfied with everything, you're ready to make predictions on the test set.","metadata":{}},{"cell_type":"code","source":"test_ds = get_test_dataset(ordered=True)\n\nprint('Computing predictions...')\ntest_images_ds = test_ds.map(lambda image, idnum: image)\nprobabilities = eff.predict(test_images_ds)\npredictions = np.argmax(probabilities, axis=-1)\nprint(predictions)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T20:14:32.840159Z","iopub.execute_input":"2022-12-14T20:14:32.840522Z","iopub.status.idle":"2022-12-14T20:14:55.720390Z","shell.execute_reply.started":"2022-12-14T20:14:32.840488Z","shell.execute_reply":"2022-12-14T20:14:55.716226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We'll generate a file `submission.csv`. This file is what you'll submit to get your score on the leaderboard.","metadata":{}},{"cell_type":"code","source":"print('Generating submission.csv file...')\n\n# Get image ids from test set and convert to unicode\ntest_ids_ds = test_ds.map(lambda image, idnum: idnum).unbatch()\ntest_ids = next(iter(test_ids_ds.batch(NUM_TEST_IMAGES))).numpy().astype('U')\n\n# Write the submission file\nnp.savetxt(\n    'submission.csv',\n    np.rec.fromarrays([test_ids, predictions]),\n    fmt=['%s', '%d'],\n    delimiter=',',\n    header='id,label',\n    comments='',\n)\n\n# Look at the first few predictions\n!head submission.csv","metadata":{"execution":{"iopub.status.busy":"2022-12-14T20:16:55.803815Z","iopub.execute_input":"2022-12-14T20:16:55.804166Z","iopub.status.idle":"2022-12-14T20:16:59.677200Z","shell.execute_reply.started":"2022-12-14T20:16:55.804133Z","shell.execute_reply":"2022-12-14T20:16:59.676264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}