{"cells":[{"metadata":{},"cell_type":"markdown","source":"# End to End Multiclass Dog Breed Classification \n \nThis notebook builds an end to end multi-class image classifier using TensorFlow and TensorFlow Hub"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport tensorflow as tf\nimport tensorflow_hub as hub\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","collapsed":true,"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":false},"cell_type":"markdown","source":"### Prepping data: turning images into tensors"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Take a look at labels\nlabels = pd.read_csv('/kaggle/input/dog-breed-identification/labels.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels.describe()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# How many images are there of each breed\nlabels['breed'].value_counts().plot.bar(figsize=(20,10))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# On average, how many instances of each class?\nlabels['breed'].value_counts().median()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# View an image \nfrom IPython.display import Image\nImage('/kaggle/input/dog-breed-identification/train/09839ef1c5a5a5b3acb61c4093cab07f.jpg')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Make a list of filenames \nfilenames = ['/kaggle/input/dog-breed-identification/train/' + fname + '.jpg' for fname in labels['id']]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"filenames[:10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nif len(os.listdir('/kaggle/input/dog-breed-identification/train/')) == len(filenames): \n    print('okay')\nelse: \n    print('not okay')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Convert labels to numpy array\nlabels_np = labels['breed'].to_numpy()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels_np[:10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Check if length of filenames is same as length of labels_np\nlen(labels_np) == len(filenames)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unique_labels = np.unique(labels_np)\nunique_labels, len(unique_labels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Convert unique labels into arrays of booleans \nbool_labels = [label == unique_labels for label in labels_np]\nbool_labels[:2]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(bool_labels[0].astype(int))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"encoded_labels = [label.astype(int) for label in bool_labels]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"encoded_labels[:3]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Split into X and y\nX = filenames \ny = encoded_labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"NUM_IMAGES = 4000 #%param {type:\"slider\", min:1000, max:10000, step:1000} \n#only works in google colab\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Split data into train and valid\nfrom sklearn.model_selection import train_test_split\n\n\n# Out of total number, NUM_IMAGES\nX_train, X_valid, y_train, y_valid = train_test_split(X[:NUM_IMAGES], \n                                                      y[:NUM_IMAGES], \n                                                      test_size=0.2, \n                                                      random_state=42)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(X_train), len(X_valid)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"Preprocessing images into Tensors"},{"metadata":{"trusted":true},"cell_type":"code","source":"# convert an image to np array\nfrom matplotlib.pyplot import imread \nimage = imread(filenames[42])\nimage.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image[:2]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tf.constant(image)[:2] # use tensorflow to convert image from np array to tensor","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Function to preprocess image \nIMG_SIZE = 224\n\ndef process_image(img_path, img_size=IMG_SIZE): \n    image = tf.io.read_file(img_path)\n    image = tf.image.decode_jpeg(image, channels=3)\n    image = tf.image.convert_image_dtype(image, tf.float32)\n    image = tf.image.resize(image, size=[IMG_SIZE, IMG_SIZE])\n    \n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Fcn to return image and label as a tuple\n\ndef get_image_label(img_path, label): \n    image = process_image(img_path)\n    return image, label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"process_image(X[42], tf.constant(y[42]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Function to turn all data (X & y) into batches\n# Define the batch size (default to 32)\nBATCH_SIZE = 32\n\n# Create a function to turn data into batches \ndef create_data_batches(X, y=None, batch_size=BATCH_SIZE, valid_data=False, test_data=False): \n    '''\n    Creates batches of data out of image (X) and label (y) pairs.\n    Shuffles the data if it's training data but doesn't shuffle if it's validation data.\n    Also accepts test data as input (no lables).\n    '''\n    \n    # If test dataset, no labels (only filepaths)\n    if test_data: \n        print(\"Creating test data batches...\")\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(X))) \n        # Process each image and add it to a batch\n        data_batch = data.map(process_image).batch(BATCH_SIZE)\n        return data_batch \n    \n    # If valid dataset, no shuffling is necessary \n    elif valid_data: \n        print(\"Creating validation data batches...\")\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(X), #filepaths\n                                                   tf.constant(y))) #labels\n        data_batch = data.map(get_image_label).batch(BATCH_SIZE)\n        return data_batch \n    # If training dataset, shuffle \n    else: \n        print(\"Creating training data batches...\")\n        # turn filepaths and labels into tensors\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(X), \n                                                  tf.constant(y)))  \n        #Shuffling pathnames and labels before mapping image processor function is faster\n        data = data.shuffle(buffer_size=len(X))\n        \n        # Create (image, label) tuples (and also turn image path into a preprocessed image)\n        data = data.map(get_image_label)\n        \n        #Turn training data into batches\n        data_batch = data.batch(BATCH_SIZE)\n        \n    return data_batch\n                                                   \n                                    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create training and validation data batches\ntrain_data = create_data_batches(X_train, y_train)\nval_data = create_data_batches(X_valid, y_valid, valid_data=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# take a look at attributes of data batches\ntrain_data.element_spec, val_data.element_spec","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Visualizing data batches "},{"metadata":{"trusted":true},"cell_type":"code","source":"# create function for displaying images in a data batch, 25 images at a time\ndef show_25_images(images, labels): \n    plt.figure(figsize=(10,10))\n    # displaying 25 images\n    for i in range(25): \n        ax = plt.subplot(5, 5, i+1)\n        plt.imshow(images[i])\n        plt.title(unique_labels[labels[i].argmax()])\n        plt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Unbatch data to visualize it \ntrain_images, train_labels = next(train_data.as_numpy_iterator())\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Use function to visualize data in a training batch \nshow_25_images(train_images, train_labels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Visualization for validation set \nval_images, val_labels = next(val_data.as_numpy_iterator())\nshow_25_images(val_images, val_labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Building a model"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Setup shape of input\nINPUT_SHAPE = [None, IMG_SIZE, IMG_SIZE, 3] # for batch, height, width, color channel\n\n# Setup output shape\nOUTPUT_SHAPE = len(unique_labels)\n\n# Set up model URL from TF Hub \nMODEL_URL = 'https://tfhub.dev/google/imagenet/mobilenet_v2_130_224/classification/4'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Func to build Keras model \ndef create_model(input_shape=INPUT_SHAPE, output_shape=OUTPUT_SHAPE, model_url=MODEL_URL): \n    print('Building model with:', MODEL_URL)\n    \n    # Set up the model layers\n    model = tf.keras.Sequential([\n        hub.KerasLayer(MODEL_URL), # Layer 1 (input layer)\n        tf.keras.layers.Dense(units=OUTPUT_SHAPE,\n                              activation='softmax') # Layer 2 (output layer)\n    ])\n    \n    # Compile the model \n    model.compile(\n        loss=tf.keras.losses.CategoricalCrossentropy(),\n        optimizer=tf.keras.optimizers.Adam(),\n        metrics=['accuracy']\n    )\n    \n    # Build the model \n    model.build(INPUT_SHAPE)\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = create_model()\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## TensorBoard callback "},{"metadata":{},"cell_type":"markdown","source":"### Setting TensorBoard up to work within Kaggle"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Clear any logs from previous runs\n!rm -rf ./logs/ \n!mkdir ./logs/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Download Ngrok to tunnel the tensorboard port to an external port\n!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip\n!unzip ngrok-stable-linux-amd64.zip\n\n# Run tensorboard as well as Ngrox (for tunneling as non-blocking processes)\nimport os\nimport multiprocessing\n\n\npool = multiprocessing.Pool(processes = 10)\nresults_of_processes = [pool.apply_async(os.system, args=(cmd, ), callback = None )\n                        for cmd in [\n                        f\"tensorboard --logdir ./logs/ --host 0.0.0.0 --port 6006 &\",\n                        \"./ngrok http 6006 &\"\n                        ]]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"! curl -s http://localhost:4040/api/tunnels | python3 -c \\\n    \"import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Set up TensorBoard callback \nimport datetime \n\ndef create_tensorboard_callback(): \n    logdir = \"logs/fit/\" + datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n    \n    return tf.keras.callbacks.TensorBoard(logdir)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Early stopping callback"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Preserve model's generalization (prevent overfitting) by early stopping callback\n# Stop model if a certain eval metric stops improving \n\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_accuracy',\n                                                  patience=3)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Training a model (on subset of data)\n\nOur first model is only going to train on 1000 images to make sure everything is working before we train on 10,000 images"},{"metadata":{"trusted":true},"cell_type":"code","source":"NUM_EPOCHS = 50 # Up to 100 chances to go through training set and learn patterns and make guesses\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## DON'T FORGET TO MAKE SURE YOU ARE USING A GPU"},{"metadata":{"trusted":true},"cell_type":"code","source":"# function to train model \ndef train_model(): \n    # Instantiate model\n    model = create_model()\n    \n    #New tensorboard session whenever we train a model\n    tensorboard = create_tensorboard_callback()\n    \n    # Fit model to data passing in the callbacks \n    model.fit(x=train_data,\n              epochs=NUM_EPOCHS, \n              validation_data=val_data,\n              validation_freq=1,\n              callbacks=[tensorboard, early_stopping])\n    \n    # return fitted model \n    return model\n\n# fit the model to the data\nmodel = train_model()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Checking the TensorBoard logs \n\nThe TensorBoard Magic function will access the logs directory we created and visualize its contents \n"},{"metadata":{"trusted":true},"cell_type":"code","source":"%tensorboard --logdir","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Making and evaluating predictions using a trained model"},{"metadata":{"trusted":true},"cell_type":"code","source":"val_data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(val_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# make preds on the val data (not used to train on)\npredictions = model.predict(val_data,verbose=1)\npredictions \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predictions.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predictions[9]\n# shows us a probability value for every single label ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# first prediction \nindex = 7\nprint(predictions[index])\nprint(f'Max value (probability of prediction): {np.max(predictions[index])}')\nprint(f'Sum: {np.sum(predictions[index])}')\nprint(f'Max index: {np.argmax(predictions[index])}')\nprint(f'Predicted label: {unique_labels[np.argmax(predictions[index])]}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"Predictions also have confidence intervals/ prediction probabilities.\n* use everything over 75\n\nWe also want to see the image that the data is based on "},{"metadata":{"trusted":true},"cell_type":"code","source":"# turn prediction probablities into their respective labels \n\ndef get_pred_label(prediction_probabilities): \n    return unique_labels[np.argmax(prediction_probabilities)]\n\n\n# Get a predicted label based on an array of prediction probabilities \npred_label = get_pred_label(predictions[55])\npred_label ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Unbatch data to make predictions on the validation images and then compare those predictions to the validation labels (truth labels)\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef unbatchify(data):\n    '''Takes a batched dataset of (image, label) Tensors and returns separate arrays of images and labels'''\n    images_ = []\n    labels_ = []\n    # loop through unbatched data \n    for image, label in data.unbatch().as_numpy_iterator():\n        images_.append(image)\n        labels_.append(unique_labels[np.argmax(label)])\n        return images_, labels_\n    \n#Unbatchify the validation data\nval_images, val_labels = unbatchify(val_data)\nval_images[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(val_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(val_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"get_pred_label(val_labels[0])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Visualizing Model Predictions \n\nPresent it in a way that is usable to the user (e.g. if we are making the dog vision app) \n\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Function to visualize model predictions \n\n# Takes array of prediction probas, array of truth labels, array of images and integers\n# convert prediction probas to a predicted label \n# plot predicted label, its predicted proba, the truth label, and target image on a single plot\n\ndef plot_pred(prediction_probabilities, labels, images, n=0): \n    pred_prob, true_label, image = prediction_probabilities[n], labels[n], images[n]\n    \n    # get the pred label \n    pred_label = get_pred_label(pred_prob)\n    \n    if pred_label ==true_label: \n        color='green'\n    else: \n        color='red'\n    \n    # plot image and remove ticks \n    plt.imshow(image)\n    plt.xticks([])\n    plt.yticks([])\n    \n    # Change plot title to be predicted, probability of pred and truth label\n    plt.title('{} {:2.0f}% {}'.format(pred_label, \n                                      np.max(pred_prob)*100,\n                                      true_label), \n                                      color=color)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(val_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_pred(prediction_probabilities=predictions, \n          labels=val_labels, \n          images=val_images, \n          n=0)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### compare first 10 predictions to truth \n\nFunction will \n* Take an input of prediction probas array and a ground truth array and an integer\n* Find the prediction using `get_pred_label()`\n* Find the top 10 prediction probas indexes, pred proba values, pred labels\n* Plot the top 10 probas values and labels, w/ true label colored green "},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_pred_confidence(prediction_probabilities, labels, n=1): \n    pred_prob, true_label = prediction_probabilities[n], labels[n]\n    \n    # Get the predicted label\n    pred_label = get_pred_label(pred_prob)\n    \n    # Find top 10 prediction confidence indexes\n    top_10_pred_indexes = pred_prob.argsort()[-10:][::-1]\n    #find the top 10 prediction confidence values\n    top_10_pred_values = pred_prob[top_10_pred_indexes]\n    #Find the top 10 prediction labels \n    top_10_pred_labels = unique_labels[top_10_pred_indexes]\n    \n    # set up plot \n    top_plot = plt.bar(np.arange(len(top_10_pred_labels)),\n                       top_10_pred_values,\n                       color='grey')\n    plt.xticks(np.arange(len(top_10_pred_labels)),\n               labels=top_10_pred_labels,\n               rotation='vertical')\n    \n    # change color of true label \n    if np.isin(true_label, top_10_pred_labels): \n        top_plot[np.argmax(top_10_pred_labels == true_label)].set_color('green')\n    else: \n        pass\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_pred_confidence(prediction_probabilities=predictions, \n                     labels=val_labels, \n                     n=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Image compared to top 10 pred confidences \ni_multiplier = 0\nnum_rows = 3\nnum_cols = 2\nnum_images = num_rows*num_cols\nplt.figure(figsize=(10*num_cols, 5*num_rows))\n\nfor i in range(num_images): \n    plt.subplot(num_rows, 2*num_cols, 2*i+1)\n    plot_pred(prediction_probabilities=predictions,\n              labels=val_labels, \n              images=val_images, \n              n=i+i_multiplier)\n    plt.subplot(num_rows, 2*num_cols, 2*i+2)\n    plot_pred_confidence(prediction_probabilities=predictions, \n                   labels=val_labels, \n                   n=i+i_multiplier)\n    plt.tight_layout(h_pad=1.0)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Save and load trained model"},{"metadata":{"trusted":true},"cell_type":"code","source":"def save_model(model, suffix=None): \n    # Create a model directory pathname with current time (can't do that in Kaggle as far as I know)\n    # modeldir = os.path.join('pathname/models',\n                                #datetime.datetime.now().strftime('%Y%m%d-%H%M%s'))\n        #model_path = modeldir + '-' + suffix + '.h5' # save model format\n        model.save(model_path)\n        return model_path","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_model(model_path):\n    model = tf.keras.models.load_model(model_path, custom_objects={\"KerasLayer\": hub.KerasLayer})\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Save model \nsave_model(model, suffix='1000-images-mobilenetv2-Adam')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Evaluate the presaved model\nmodel.evaluate(val_data)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Training model on full dataset "},{"metadata":{"trusted":true},"cell_type":"code","source":"len(X), len(y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create a data batch with the full data \nfull_data = create_data_batches(X, y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(full_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_model = create_model()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create full model callbacks \n# skip tensorboard for now \n# full_model_tensorboard = create_tensorboard_callback()\n\n# No validation set when traiing on full data, so we can't monitor validation accuracy \n\nfull_model_early_stopping = tf.keras.callbacks.EarlyStopping(monitor='accuracy',\n                                                             patience=3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# fit the full model to the full data \nfull_model.fit(x=full_data,\n               epochs=NUM_EPOCHS, \n               callbacks=[full_model_early_stopping])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_model.save('my_model.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loaded_full_model = tf.keras.models.load_model('my_model.h5', custom_objects={\"KerasLayer\": hub.KerasLayer})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loaded_full_model.evaluate(val_data)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Making predictions on test dataset"},{"metadata":{},"cell_type":"markdown","source":"First must convert test data into the smae format at as the training data: \n1. Get the test image filenames\n2. convert the filenames into test data batches using `create_data_batches()` and setting the `test_data` parameter to True (since the test data doesn't have labels)\n3. Make a predictions array by passing the test batches to the predict() method colled on our model "},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load test image filenames \ntest_path = '/kaggle/input/dog-breed-identification/test/'\ntest_filenames = [test_path + fname for fname in os.listdir(test_path)]\ntest_filenames[:10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(test_filenames)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# create test data batch \ntest_data = create_data_batches(test_filenames, test_data=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(test_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Make predictions using loaded full model \ntest_predictions = loaded_full_model.predict(test_data, \n                                             verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_predictions","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(test_predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# save predictions to np arry \nnp.savetxt('my_preds.csv', test_predictions, delimiter=',')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_preds = np.loadtxt('my_preds.csv', delimiter=',')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_preds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_preds_df = pd.DataFrame(test_preds)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_preds_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(test_preds)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Loading data into a sample submission "},{"metadata":{"trusted":true},"cell_type":"code","source":"test_preds.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}