Dhrumit1314 commited on
Commit
a39e224
1 Parent(s): 4ce79e8

Upload 5 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
FoodVision_CV.py ADDED
@@ -0,0 +1,359 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Thu Feb 8 15:27:13 2024
4
+
5
+ @author: Dhrumit Patel
6
+ """
7
+
8
+ """
9
+ Get helper functions
10
+ """
11
+ # Import series of helper functions
12
+ from helper_functions import create_tensorboard_callback, plot_loss_curves, compare_historys
13
+
14
+ """
15
+ Use TensorFlow Datasets(TFDS) to download data
16
+ """
17
+ # Get TensorFlow Datasets
18
+ import tensorflow_datasets as tfds
19
+
20
+ # List all the available datasets
21
+ datasets_list = tfds.list_builders() # Get all available datasets in TFDS
22
+ print("food101" in datasets_list) # Is our target dataset in the list of TFDS datasets?
23
+
24
+ # Load in the data
25
+ (train_data, test_data), ds_info = tfds.load(name="food101",
26
+ split=["train", "validation"],
27
+ shuffle_files=True, # Data gets returned in tuple format (data, label)
28
+ with_info=True)
29
+ # Features of Food101 from TFDS
30
+ ds_info.features
31
+
32
+ # Get the class names
33
+ class_names = ds_info.features["label"].names
34
+ class_names[:10]
35
+
36
+ # Take one sample of the train data
37
+ train_one_sample = train_data.take(1) # samples are in format (image_tensor, label)
38
+ # What does one sample of our training data look like?
39
+ train_one_sample
40
+
41
+ # Output info about our training samples
42
+ for sample in train_one_sample:
43
+ image, label = sample["image"], sample["label"]
44
+ print(f"""
45
+ Image shape: {image.shape}
46
+ Image datatype: {image.dtype}
47
+ Target class from Food101 (tensor form): {label}
48
+ Class name (str form): {class_names[label.numpy()]}
49
+ """)
50
+
51
+ # What does our image tensor from TFDS's Food101 look like?
52
+ import tensorflow as tf
53
+ image
54
+ tf.reduce_min(image), tf.reduce_max(image)
55
+
56
+ """
57
+ Plot an image from TensorFlow Datasets
58
+ """
59
+ # Plot an image tensor
60
+ import matplotlib.pyplot as plt
61
+ plt.imshow(image)
62
+ plt.title(class_names[label.numpy()]) # Add title to verify the label is associated to right image
63
+ plt.axis(False)
64
+
65
+ (image, label)
66
+
67
+ # Make a function for preprocessing images
68
+ def preprocess_img(image, label, img_shape=224):
69
+ """
70
+ Converts image datatype from uint8 -> float32 and reshapes
71
+ image to [img_shape, img_shape, color_channels]
72
+ """
73
+ image = tf.image.resize(image, [img_shape, img_shape]) # reshape target image
74
+ # image = image/255. # scale image values (not required for EfficientNet models from tf.keras.applications)
75
+ return tf.cast(image, dtype=tf.float32), label # return a tuple of float32 image and a label tuple
76
+
77
+ # Preprocess a single sample image and check the outputs
78
+ preprocessed_img = preprocess_img(image, label)[0]
79
+ print(f"Image before preprocessing:\n {image[:2]}..., \n Shape: {image.shape},\nDatatype: {image.dtype}\n")
80
+ print(f"Image after preprocessing:]n {preprocessed_img[:2]}..., \n Shape: {preprocessed_img.shape}, \nDatatype: {preprocessed_img.dtype}")
81
+
82
+ """
83
+ Batch and preprare datasets
84
+
85
+ We are now going to make our data input pipeline run really fast.
86
+ """
87
+ # Map preprocessing function to training data (and parallelize)
88
+ train_data = train_data.map(map_func=lambda sample: preprocess_img(sample['image'], sample['label']), num_parallel_calls=tf.data.AUTOTUNE)
89
+ # Shuffle train_data and turned it into batches and prefetch it (load it faster)
90
+ train_data = train_data.shuffle(buffer_size=1000).batch(batch_size=32).prefetch(buffer_size=tf.data.AUTOTUNE)
91
+
92
+ # Map preprocessing function to test data
93
+ test_data = test_data.map(map_func=lambda sample: preprocess_img(sample['image'], sample['label']), num_parallel_calls=tf.data.AUTOTUNE)
94
+ # Turn the test data into batches (don't need to shuffle the test data)
95
+ test_data = test_data.batch(batch_size=32).prefetch(tf.data.AUTOTUNE)
96
+
97
+ train_data, test_data
98
+
99
+ """
100
+ Create modelling callbacks
101
+
102
+ We are going to create a couple of callbacks to help us while our model trains:
103
+ 1. TensorBoard callback to log training results (so we can visualize them later if need be)
104
+ 2. ModelCheckpoint callback to save our model's progress after feature extraction.
105
+ """
106
+ # Create tensorboard callback (import from helper_functions.py)
107
+ from helper_functions import create_tensorboard_callback
108
+
109
+ # Create a ModelCheckpoint callback to save a model's progress during training
110
+ checkpoint_path = "model_checkpoints/cp.ckpt"
111
+ model_checkpoint = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
112
+ monitor="val_acc",
113
+ save_best_only=True,
114
+ save_weights_only=True,
115
+ verbose=1)
116
+
117
+ # Turn on mixed precision training
118
+ from tensorflow.keras import mixed_precision
119
+ mixed_precision.set_global_policy("mixed_float16") # Set global data policy to mixed precision
120
+ mixed_precision.global_policy()
121
+
122
+ """
123
+ Build feature extraction model
124
+ """
125
+ from tensorflow.keras import layers
126
+ from tensorflow.keras.layers.experimental import preprocessing
127
+
128
+ # Create base model
129
+ input_shape = (224, 224, 3)
130
+ base_model = tf.keras.applications.efficientnet_v2.EfficientNetV2B0(include_top=False)
131
+ base_model.trainable = False
132
+
133
+ # Create functional model
134
+ inputs = layers.Input(shape=input_shape, name="input_layer")
135
+ # Note: EfficientNetV2B0 models have rescaling built-in but if your model doesn't you can have a layer like below
136
+ # x = preprocessing.Rescaling(1./255)(x)
137
+ x = base_model(inputs, training=False) # make sure layers which should be in inference mode only
138
+ x = layers.GlobalAveragePooling2D(name="global_pooling_layer")(x)
139
+ outputs = layers.Dense(len(class_names), activation="softmax", dtype=tf.float32, name="softmax_float32")(x) # This will be converted to float32
140
+
141
+ model = tf.keras.Model(inputs, outputs)
142
+
143
+ # Compile the model
144
+ model.compile(loss="sparse_categorical_crossentropy", # The labels are in integer form
145
+ optimizer=tf.keras.optimizers.Adam(),
146
+ metrics=["accuracy"])
147
+
148
+ model.summary()
149
+
150
+ # Check the dtype_policy attributes of layers in our model
151
+ for layer in model.layers:
152
+ print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy)
153
+
154
+
155
+ # Check the dtype_policy attributes for the base_model layer
156
+ for layer in model.layers[1].layers:
157
+ print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy)
158
+
159
+ # OR
160
+
161
+ for layer in base_model.layers:
162
+ print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy)
163
+
164
+ # Fit the feature extraction model with callbacks
165
+ history_101_food_classes_feature_extract = model.fit(train_data,
166
+ epochs=10,
167
+ steps_per_epoch=len(train_data),
168
+ validation_data=test_data,
169
+ validation_steps=int(0.15 * len(test_data)),
170
+ callbacks=[create_tensorboard_callback(dir_name="training_logs", experiment_name="efficientnetb0_101_classes_all_data_feature_extract"), model_checkpoint])
171
+
172
+
173
+ # Evaluate the model on the whole test data
174
+ results_feature_extract_model = model.evaluate(test_data)
175
+ results_feature_extract_model
176
+
177
+
178
+ # 1. Create a function to recreate the original model
179
+ def create_model():
180
+ # Create base model
181
+ input_shape = (224, 224, 3)
182
+ base_model = tf.keras.applications.efficientnet.EfficientNetB0(include_top=False)
183
+ base_model.trainable = False # freeze base model layers
184
+
185
+ # Create Functional model
186
+ inputs = layers.Input(shape=input_shape, name="input_layer")
187
+ # Note: EfficientNetBX models have rescaling built-in but if your model didn't you could have a layer like below
188
+ # x = layers.Rescaling(1./255)(x)
189
+ x = base_model(inputs, training=False) # set base_model to inference mode only
190
+ x = layers.GlobalAveragePooling2D(name="pooling_layer")(x)
191
+ x = layers.Dense(len(class_names))(x) # want one output neuron per class
192
+ # Separate activation of output layer so we can output float32 activations
193
+ outputs = layers.Activation("softmax", dtype=tf.float32, name="softmax_float32")(x)
194
+ model = tf.keras.Model(inputs, outputs)
195
+
196
+ return model
197
+
198
+ # 2. Create and compile a new version of the original model (new weights)
199
+ created_model = create_model()
200
+ created_model.compile(loss="sparse_categorical_crossentropy",
201
+ optimizer=tf.keras.optimizers.Adam(),
202
+ metrics=["accuracy"])
203
+
204
+ # 3. Load the saved weights
205
+ created_model.load_weights(checkpoint_path)
206
+
207
+ # 4. Evaluate the model with loaded weights
208
+ results_created_model_with_loaded_weights = created_model.evaluate(test_data)
209
+
210
+ # 5. Loaded checkpoint weights should return very similar results to checkpoint weights prior to saving
211
+ import numpy as np
212
+ assert np.isclose(results_feature_extract_model, results_created_model_with_loaded_weights).all(), "Loaded weights results are not close to original model." # check if all elements in array are close
213
+
214
+ # Check the layers in the base model and see what dtype policy they're using
215
+ for layer in created_model.layers[1].layers[:20]: # check only the first 20 layers to save printing space
216
+ print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy)
217
+
218
+ # Save model locally (if you're using Google Colab, your saved model will Colab instance terminates)
219
+ save_dir = "07_efficientnetb0_feature_extract_model_mixed_precision"
220
+ model.save(save_dir)
221
+
222
+ # Load model previously saved above
223
+ loaded_saved_model = tf.keras.models.load_model(save_dir)
224
+
225
+ # Load model previously saved above
226
+ loaded_saved_model = tf.keras.models.load_model(save_dir)
227
+
228
+
229
+ # Check the layers in the base model and see what dtype policy they're using
230
+ for layer in loaded_saved_model.layers[1].layers[:20]: # check only the first 20 layers to save output space
231
+ print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy)
232
+
233
+ results_loaded_saved_model = loaded_saved_model.evaluate(test_data)
234
+ results_loaded_saved_model
235
+
236
+ # The loaded model's results should equal (or at least be very close) to the model's results prior to saving
237
+ import numpy as np
238
+ assert np.isclose(results_feature_extract_model, results_loaded_saved_model).all()
239
+
240
+
241
+ """
242
+ Optional
243
+ """
244
+ # Download and unzip the saved model from Google Storage - https://drive.google.com/file/d/1-4BsHQyo3NIBGzlgqZgJNC5_3eIGcbVb/view?usp=sharing
245
+
246
+ # Unzip the SavedModel downloaded from Google Storage
247
+ # !mkdir downloaded_gs_model # create new dir to store downloaded feature extraction model
248
+ # !unzip 07_efficientnetb0_feature_extract_model_mixed_precision.zip -d downloaded_gs_model
249
+
250
+ # Load and evaluate downloaded GS model
251
+ loaded_gs_model = tf.keras.models.load_model("downloaded_gs_model/07_efficientnetb0_feature_extract_model_mixed_precision")
252
+
253
+ # Get a summary of our downloaded model
254
+ loaded_gs_model.summary()
255
+
256
+ # How does the loaded model perform?
257
+ results_loaded_gs_model = loaded_gs_model.evaluate(test_data)
258
+ results_loaded_gs_model
259
+
260
+ # Are any of the layers in our model frozen?
261
+ for layer in loaded_gs_model.layers:
262
+ layer.trainable = True # set all layers to trainable
263
+ print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy) # make sure loaded model is using mixed precision dtype_policy ("mixed_float16")
264
+
265
+
266
+ # Check the layers in the base model and see what dtype policy they're using
267
+ for layer in loaded_gs_model.layers[1].layers[:20]:
268
+ print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy)
269
+
270
+ # Setup EarlyStopping callback to stop training if model's val_loss doesn't improve for 3 epochs
271
+ early_stopping = tf.keras.callbacks.EarlyStopping(monitor="val_loss", # watch the val loss metric
272
+ patience=3) # if val loss decreases for 3 epochs in a row, stop training
273
+
274
+ # Create ModelCheckpoint callback to save best model during fine-tuning
275
+ checkpoint_path = "fine_tune_checkpoints/"
276
+ model_checkpoint = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
277
+ save_best_only=True,
278
+ monitor="val_loss")
279
+ # Creating learning rate reduction callback
280
+ reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor="val_loss",
281
+ factor=0.2, # multiply the learning rate by 0.2 (reduce by 5x)
282
+ patience=2,
283
+ verbose=1, # print out when learning rate goes down
284
+ min_lr=1e-7)
285
+
286
+ # Compile the model
287
+ loaded_gs_model.compile(loss="sparse_categorical_crossentropy", # sparse_categorical_crossentropy for labels that are *not* one-hot
288
+ optimizer=tf.keras.optimizers.Adam(0.0001), # 10x lower learning rate than the default
289
+ metrics=["accuracy"])
290
+
291
+
292
+ # Start to fine-tune (all layers)
293
+ history_101_food_classes_all_data_fine_tune = loaded_gs_model.fit(train_data,
294
+ epochs=100, # fine-tune for a maximum of 100 epochs
295
+ steps_per_epoch=len(train_data),
296
+ validation_data=test_data,
297
+ validation_steps=int(0.15 * len(test_data)), # validation during training on 15% of test data
298
+ callbacks=[create_tensorboard_callback("training_logs", "efficientb0_101_classes_all_data_fine_tuning"), # track the model training logs
299
+ model_checkpoint, # save only the best model during training
300
+ early_stopping, # stop model after X epochs of no improvements
301
+ reduce_lr]) # reduce the learning rate after X epochs of no improvements
302
+
303
+ # Save model locally (note: if you're using Google Colab and you save your model locally, it will be deleted when your Google Colab session ends)
304
+ loaded_gs_model.save("07_efficientnetb0_fine_tuned_101_classes_mixed_precision")
305
+
306
+
307
+ """
308
+ Optional
309
+ """
310
+ # Download and evaluate fine-tuned model from Google Storage - https://drive.google.com/file/d/1owx3maxBae1P2I2yQHd-ru_4M7RyoGpB/view?usp=sharing
311
+
312
+ # Unzip fine-tuned model
313
+ # !mkdir downloaded_fine_tuned_gs_model # create separate directory for fine-tuned model downloaded from Google Storage
314
+ # !unzip 07_efficientnetb0_fine_tuned_101_classes_mixed_precision -d downloaded_fine_tuned_gs_model
315
+
316
+ # Load in fine-tuned model and evaluate
317
+ loaded_fine_tuned_gs_model = tf.keras.models.load_model("downloaded_fine_tuned_gs_model/07_efficientnetb0_fine_tuned_101_classes_mixed_precision")
318
+
319
+ # Get a model summary
320
+ loaded_fine_tuned_gs_model.summary()
321
+
322
+ # Note: Even if you're loading in the model from Google Storage, you will still need to load the test_data variable for this cell to work
323
+ results_downloaded_fine_tuned_gs_model = loaded_fine_tuned_gs_model.evaluate(test_data)
324
+ results_downloaded_fine_tuned_gs_model
325
+
326
+ """
327
+ # Upload experiment results to TensorBoard (uncomment to run)
328
+ # !tensorboard dev upload --logdir ./training_logs \
329
+ # --name "Fine-tuning EfficientNetB0 on all Food101 Data" \
330
+ # --description "Training results for fine-tuning EfficientNetB0 on Food101 Data with learning rate 0.0001" \
331
+ # --one_shot
332
+
333
+ # View past TensorBoard experiments
334
+ # !tensorboard dev list
335
+
336
+
337
+ # Delete past TensorBoard experiments
338
+ # !tensorboard dev delete --experiment_id YOUR_EXPERIMENT_ID
339
+
340
+ # Example
341
+ # !tensorboard dev delete --experiment_id OAE6KXizQZKQxDiqI3cnUQ
342
+ """
343
+
344
+
345
+
346
+
347
+
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+
358
+
359
+
helper_functions.py ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+
3
+ # Create a function to import an image and resize it to be able to be used with our model
4
+ def load_and_prep_image(filename, img_shape=224, scale=True):
5
+ """
6
+ Reads in an image from filename, turns it into a tensor and reshapes into
7
+ (224, 224, 3).
8
+
9
+ Parameters
10
+ ----------
11
+ filename (str): string filename of target image
12
+ img_shape (int): size to resize target image to, default 224
13
+ scale (bool): whether to scale pixel values to range(0, 1), default True
14
+ """
15
+ # Read in the image
16
+ img = tf.io.read_file(filename)
17
+ # Decode it into a tensor
18
+ img = tf.image.decode_jpeg(img)
19
+ # Resize the image
20
+ img = tf.image.resize(img, [img_shape, img_shape])
21
+ if scale:
22
+ # Rescale the image (get all values between 0 and 1)
23
+ return img/255.
24
+ else:
25
+ return img
26
+
27
+ # Note: The following confusion matrix code is a remix of Scikit-Learn's
28
+ # plot_confusion_matrix function - https://scikit-learn.org/stable/modules/generated/sklearn.metrics.plot_confusion_matrix.html
29
+ import itertools
30
+ import matplotlib.pyplot as plt
31
+ import numpy as np
32
+ from sklearn.metrics import confusion_matrix
33
+
34
+ # Our function needs a different name to sklearn's plot_confusion_matrix
35
+ def make_confusion_matrix(y_true, y_pred, classes=None, figsize=(10, 10), text_size=15, norm=False, savefig=False):
36
+ """Makes a labelled confusion matrix comparing predictions and ground truth labels.
37
+
38
+ If classes is passed, confusion matrix will be labelled, if not, integer class values
39
+ will be used.
40
+
41
+ Args:
42
+ y_true: Array of truth labels (must be same shape as y_pred).
43
+ y_pred: Array of predicted labels (must be same shape as y_true).
44
+ classes: Array of class labels (e.g. string form). If `None`, integer labels are used.
45
+ figsize: Size of output figure (default=(10, 10)).
46
+ text_size: Size of output figure text (default=15).
47
+ norm: normalize values or not (default=False).
48
+ savefig: save confusion matrix to file (default=False).
49
+
50
+ Returns:
51
+ A labelled confusion matrix plot comparing y_true and y_pred.
52
+
53
+ Example usage:
54
+ make_confusion_matrix(y_true=test_labels, # ground truth test labels
55
+ y_pred=y_preds, # predicted labels
56
+ classes=class_names, # array of class label names
57
+ figsize=(15, 15),
58
+ text_size=10)
59
+ """
60
+ # Create the confustion matrix
61
+ cm = confusion_matrix(y_true, y_pred)
62
+ cm_norm = cm.astype("float") / cm.sum(axis=1)[:, np.newaxis] # normalize it
63
+ n_classes = cm.shape[0] # find the number of classes we're dealing with
64
+
65
+ # Plot the figure and make it pretty
66
+ fig, ax = plt.subplots(figsize=figsize)
67
+ cax = ax.matshow(cm, cmap=plt.cm.Blues) # colors will represent how 'correct' a class is, darker == better
68
+ fig.colorbar(cax)
69
+
70
+ # Are there a list of classes?
71
+ if classes:
72
+ labels = classes
73
+ else:
74
+ labels = np.arange(cm.shape[0])
75
+
76
+ # Label the axes
77
+ ax.set(title="Confusion Matrix",
78
+ xlabel="Predicted label",
79
+ ylabel="True label",
80
+ xticks=np.arange(n_classes), # create enough axis slots for each class
81
+ yticks=np.arange(n_classes),
82
+ xticklabels=labels, # axes will labeled with class names (if they exist) or ints
83
+ yticklabels=labels)
84
+
85
+ # Make x-axis labels appear on bottom
86
+ ax.xaxis.set_label_position("bottom")
87
+ ax.xaxis.tick_bottom()
88
+
89
+ # Set the threshold for different colors
90
+ threshold = (cm.max() + cm.min()) / 2.
91
+
92
+ # Plot the text on each cell
93
+ for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
94
+ if norm:
95
+ plt.text(j, i, f"{cm[i, j]} ({cm_norm[i, j]*100:.1f}%)",
96
+ horizontalalignment="center",
97
+ color="white" if cm[i, j] > threshold else "black",
98
+ size=text_size)
99
+ else:
100
+ plt.text(j, i, f"{cm[i, j]}",
101
+ horizontalalignment="center",
102
+ color="white" if cm[i, j] > threshold else "black",
103
+ size=text_size)
104
+
105
+ # Save the figure to the current working directory
106
+ if savefig:
107
+ fig.savefig("confusion_matrix.png")
108
+
109
+ # Make a function to predict on images and plot them (works with multi-class)
110
+ def pred_and_plot(model, filename, class_names):
111
+ """
112
+ Imports an image located at filename, makes a prediction on it with
113
+ a trained model and plots the image with the predicted class as the title.
114
+ """
115
+ # Import the target image and preprocess it
116
+ img = load_and_prep_image(filename)
117
+
118
+ # Make a prediction
119
+ pred = model.predict(tf.expand_dims(img, axis=0))
120
+
121
+ # Get the predicted class
122
+ if len(pred[0]) > 1: # check for multi-class
123
+ pred_class = class_names[pred.argmax()] # if more than one output, take the max
124
+ else:
125
+ pred_class = class_names[int(tf.round(pred)[0][0])] # if only one output, round
126
+
127
+ # Plot the image and predicted class
128
+ plt.imshow(img)
129
+ plt.title(f"Prediction: {pred_class}")
130
+ plt.axis(False);
131
+
132
+ import datetime
133
+
134
+ def create_tensorboard_callback(dir_name, experiment_name):
135
+ """
136
+ Creates a TensorBoard callback instance to store log files.
137
+
138
+ Stores log files with the filepath:
139
+ "dir_name/experiment_name/current_datetime/"
140
+
141
+ Args:
142
+ dir_name: target directory to store TensorBoard log files
143
+ experiment_name: name of experiment directory (e.g. efficientnet_model_1)
144
+ """
145
+ log_dir = dir_name + "/" + experiment_name + "/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
146
+ tensorboard_callback = tf.keras.callbacks.TensorBoard(
147
+ log_dir=log_dir
148
+ )
149
+ print(f"Saving TensorBoard log files to: {log_dir}")
150
+ return tensorboard_callback
151
+
152
+ # Plot the validation and training data separately
153
+ import matplotlib.pyplot as plt
154
+
155
+ def plot_loss_curves(history):
156
+ """
157
+ Returns separate loss curves for training and validation metrics.
158
+
159
+ Args:
160
+ history: TensorFlow model History object (see: https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/History)
161
+ """
162
+ loss = history.history['loss']
163
+ val_loss = history.history['val_loss']
164
+
165
+ accuracy = history.history['accuracy']
166
+ val_accuracy = history.history['val_accuracy']
167
+
168
+ epochs = range(len(history.history['loss']))
169
+
170
+ # Plot loss
171
+ plt.plot(epochs, loss, label='training_loss')
172
+ plt.plot(epochs, val_loss, label='val_loss')
173
+ plt.title('Loss')
174
+ plt.xlabel('Epochs')
175
+ plt.legend()
176
+
177
+ # Plot accuracy
178
+ plt.figure()
179
+ plt.plot(epochs, accuracy, label='training_accuracy')
180
+ plt.plot(epochs, val_accuracy, label='val_accuracy')
181
+ plt.title('Accuracy')
182
+ plt.xlabel('Epochs')
183
+ plt.legend();
184
+
185
+ def compare_historys(original_history, new_history, initial_epochs=5):
186
+ """
187
+ Compares two TensorFlow model History objects.
188
+
189
+ Args:
190
+ original_history: History object from original model (before new_history)
191
+ new_history: History object from continued model training (after original_history)
192
+ initial_epochs: Number of epochs in original_history (new_history plot starts from here)
193
+ """
194
+
195
+ # Get original history measurements
196
+ acc = original_history.history["accuracy"]
197
+ loss = original_history.history["loss"]
198
+
199
+ val_acc = original_history.history["val_accuracy"]
200
+ val_loss = original_history.history["val_loss"]
201
+
202
+ # Combine original history with new history
203
+ total_acc = acc + new_history.history["accuracy"]
204
+ total_loss = loss + new_history.history["loss"]
205
+
206
+ total_val_acc = val_acc + new_history.history["val_accuracy"]
207
+ total_val_loss = val_loss + new_history.history["val_loss"]
208
+
209
+ # Make plots
210
+ plt.figure(figsize=(8, 8))
211
+ plt.subplot(2, 1, 1)
212
+ plt.plot(total_acc, label='Training Accuracy')
213
+ plt.plot(total_val_acc, label='Validation Accuracy')
214
+ plt.plot([initial_epochs-1, initial_epochs-1],
215
+ plt.ylim(), label='Start Fine Tuning') # reshift plot around epochs
216
+ plt.legend(loc='lower right')
217
+ plt.title('Training and Validation Accuracy')
218
+
219
+ plt.subplot(2, 1, 2)
220
+ plt.plot(total_loss, label='Training Loss')
221
+ plt.plot(total_val_loss, label='Validation Loss')
222
+ plt.plot([initial_epochs-1, initial_epochs-1],
223
+ plt.ylim(), label='Start Fine Tuning') # reshift plot around epochs
224
+ plt.legend(loc='upper right')
225
+ plt.title('Training and Validation Loss')
226
+ plt.xlabel('epoch')
227
+ plt.show()
228
+
229
+ # Create function to unzip a zipfile into current working directory
230
+ # (since we're going to be downloading and unzipping a few files)
231
+ import zipfile
232
+
233
+ def unzip_data(filename):
234
+ """
235
+ Unzips filename into the current working directory.
236
+
237
+ Args:
238
+ filename (str): a filepath to a target zip folder to be unzipped.
239
+ """
240
+ zip_ref = zipfile.ZipFile(filename, "r")
241
+ zip_ref.extractall()
242
+ zip_ref.close()
243
+
244
+
245
+ # Download and unzip file
246
+ import zipfile
247
+ import requests
248
+ import os
249
+
250
+ def download_and_unzip(url, target_folder):
251
+ # Download the file from url and save it
252
+ filename = os.path.join(target_folder, os.path.basename(url))
253
+ with open(filename, 'wb') as f:
254
+ r = requests.get(url)
255
+ f.write(r.content)
256
+
257
+ # Unzip the downloaded file
258
+ with zipfile.ZipFile(filename, 'r') as zip_ref:
259
+ zip_ref.extractall(target_folder)
260
+
261
+ # Walk through an image classification directory and find out how many files (images)
262
+ # are in each subdirectory.
263
+ import os
264
+
265
+ def walk_through_dir(dir_path):
266
+ """
267
+ Walks through dir_path returning its contents.
268
+
269
+ Args:
270
+ dir_path (str): target directory
271
+
272
+ Returns:
273
+ A print out of:
274
+ number of subdiretories in dir_path
275
+ number of images (files) in each subdirectory
276
+ name of each subdirectory
277
+ """
278
+ for dirpath, dirnames, filenames in os.walk(dir_path):
279
+ print(f"There are {len(dirnames)} directories and {len(filenames)} images in '{dirpath}'.")
280
+
281
+ # Function to evaluate: accuracy, precision, recall, f1-score
282
+ from sklearn.metrics import accuracy_score, precision_recall_fscore_support
283
+
284
+ def calculate_results(y_true, y_pred):
285
+ """
286
+ Calculates model accuracy, precision, recall and f1 score of a binary classification model.
287
+
288
+ Args:
289
+ y_true: true labels in the form of a 1D array
290
+ y_pred: predicted labels in the form of a 1D array
291
+
292
+ Returns a dictionary of accuracy, precision, recall, f1-score.
293
+ """
294
+ # Calculate model accuracy
295
+ model_accuracy = accuracy_score(y_true, y_pred) * 100
296
+ # Calculate model precision, recall and f1 score using "weighted average
297
+ model_precision, model_recall, model_f1, _ = precision_recall_fscore_support(y_true, y_pred, average="weighted")
298
+ model_results = {"accuracy": model_accuracy,
299
+ "precision": model_precision,
300
+ "recall": model_recall,
301
+ "f1": model_f1}
302
+ return model_results
saved_model.pb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:03f2eab4db7e3bda054c33266e097bb52a70b45ae545ef050b8ce5c0c64a3d84
3
+ size 7614129
variables.data-00000-of-00001 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a31076ec09c49eb2ed725ee21f0303868cbd8fd23646c14433b2476a0bfa9b65
3
+ size 50017227
variables.index ADDED
Binary file (49.6 kB). View file