| |
| """ |
| Created on Thu Feb 8 15:27:13 2024 |
| |
| @author: Dhrumit Patel |
| """ |
|
|
| """ |
| Get helper functions |
| """ |
| |
| from helper_functions import create_tensorboard_callback, plot_loss_curves, compare_historys |
|
|
| """ |
| Use TensorFlow Datasets(TFDS) to download data |
| """ |
| |
| import tensorflow_datasets as tfds |
|
|
| |
| datasets_list = tfds.list_builders() |
| print("food101" in datasets_list) |
|
|
| |
| (train_data, test_data), ds_info = tfds.load(name="food101", |
| split=["train", "validation"], |
| shuffle_files=True, |
| with_info=True) |
| |
| ds_info.features |
|
|
| |
| class_names = ds_info.features["label"].names |
| class_names[:10] |
|
|
| |
| train_one_sample = train_data.take(1) |
| |
| train_one_sample |
|
|
| |
| for sample in train_one_sample: |
| image, label = sample["image"], sample["label"] |
| print(f""" |
| Image shape: {image.shape} |
| Image datatype: {image.dtype} |
| Target class from Food101 (tensor form): {label} |
| Class name (str form): {class_names[label.numpy()]} |
| """) |
|
|
| |
| import tensorflow as tf |
| image |
| tf.reduce_min(image), tf.reduce_max(image) |
|
|
| """ |
| Plot an image from TensorFlow Datasets |
| """ |
| |
| import matplotlib.pyplot as plt |
| plt.imshow(image) |
| plt.title(class_names[label.numpy()]) |
| plt.axis(False) |
|
|
| (image, label) |
|
|
| |
| def preprocess_img(image, label, img_shape=224): |
| """ |
| Converts image datatype from uint8 -> float32 and reshapes |
| image to [img_shape, img_shape, color_channels] |
| """ |
| image = tf.image.resize(image, [img_shape, img_shape]) |
| |
| return tf.cast(image, dtype=tf.float32), label |
|
|
| |
| preprocessed_img = preprocess_img(image, label)[0] |
| print(f"Image before preprocessing:\n {image[:2]}..., \n Shape: {image.shape},\nDatatype: {image.dtype}\n") |
| print(f"Image after preprocessing:]n {preprocessed_img[:2]}..., \n Shape: {preprocessed_img.shape}, \nDatatype: {preprocessed_img.dtype}") |
|
|
| """ |
| Batch and preprare datasets |
| |
| We are now going to make our data input pipeline run really fast. |
| """ |
| |
| train_data = train_data.map(map_func=lambda sample: preprocess_img(sample['image'], sample['label']), num_parallel_calls=tf.data.AUTOTUNE) |
| |
| train_data = train_data.shuffle(buffer_size=1000).batch(batch_size=32).prefetch(buffer_size=tf.data.AUTOTUNE) |
|
|
| |
| test_data = test_data.map(map_func=lambda sample: preprocess_img(sample['image'], sample['label']), num_parallel_calls=tf.data.AUTOTUNE) |
| |
| test_data = test_data.batch(batch_size=32).prefetch(tf.data.AUTOTUNE) |
|
|
| train_data, test_data |
|
|
| """ |
| Create modelling callbacks |
| |
| We are going to create a couple of callbacks to help us while our model trains: |
| 1. TensorBoard callback to log training results (so we can visualize them later if need be) |
| 2. ModelCheckpoint callback to save our model's progress after feature extraction. |
| """ |
| |
| from helper_functions import create_tensorboard_callback |
|
|
| |
| checkpoint_path = "model_checkpoints/cp.ckpt" |
| model_checkpoint = tf.keras.callbacks.ModelCheckpoint(checkpoint_path, |
| monitor="val_acc", |
| save_best_only=True, |
| save_weights_only=True, |
| verbose=1) |
|
|
| |
| from tensorflow.keras import mixed_precision |
| mixed_precision.set_global_policy("mixed_float16") |
| mixed_precision.global_policy() |
|
|
| """ |
| Build feature extraction model |
| """ |
| from tensorflow.keras import layers |
| from tensorflow.keras.layers.experimental import preprocessing |
|
|
| |
| input_shape = (224, 224, 3) |
| base_model = tf.keras.applications.efficientnet_v2.EfficientNetV2B0(include_top=False) |
| base_model.trainable = False |
|
|
| |
| inputs = layers.Input(shape=input_shape, name="input_layer") |
| |
| |
| x = base_model(inputs, training=False) |
| x = layers.GlobalAveragePooling2D(name="global_pooling_layer")(x) |
| outputs = layers.Dense(len(class_names), activation="softmax", dtype=tf.float32, name="softmax_float32")(x) |
|
|
| model = tf.keras.Model(inputs, outputs) |
|
|
| |
| model.compile(loss="sparse_categorical_crossentropy", |
| optimizer=tf.keras.optimizers.Adam(), |
| metrics=["accuracy"]) |
|
|
| model.summary() |
|
|
| |
| for layer in model.layers: |
| print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy) |
|
|
|
|
| |
| for layer in model.layers[1].layers: |
| print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy) |
|
|
| |
|
|
| for layer in base_model.layers: |
| print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy) |
|
|
| |
| history_101_food_classes_feature_extract = model.fit(train_data, |
| epochs=10, |
| steps_per_epoch=len(train_data), |
| validation_data=test_data, |
| validation_steps=int(0.15 * len(test_data)), |
| callbacks=[create_tensorboard_callback(dir_name="training_logs", experiment_name="efficientnetb0_101_classes_all_data_feature_extract"), model_checkpoint]) |
|
|
|
|
| |
| results_feature_extract_model = model.evaluate(test_data) |
| results_feature_extract_model |
|
|
|
|
| |
| def create_model(): |
| |
| input_shape = (224, 224, 3) |
| base_model = tf.keras.applications.efficientnet.EfficientNetB0(include_top=False) |
| base_model.trainable = False |
|
|
| |
| inputs = layers.Input(shape=input_shape, name="input_layer") |
| |
| |
| x = base_model(inputs, training=False) |
| x = layers.GlobalAveragePooling2D(name="pooling_layer")(x) |
| x = layers.Dense(len(class_names))(x) |
| |
| outputs = layers.Activation("softmax", dtype=tf.float32, name="softmax_float32")(x) |
| model = tf.keras.Model(inputs, outputs) |
| |
| return model |
|
|
| |
| created_model = create_model() |
| created_model.compile(loss="sparse_categorical_crossentropy", |
| optimizer=tf.keras.optimizers.Adam(), |
| metrics=["accuracy"]) |
|
|
| |
| created_model.load_weights(checkpoint_path) |
|
|
| |
| results_created_model_with_loaded_weights = created_model.evaluate(test_data) |
|
|
| |
| import numpy as np |
| assert np.isclose(results_feature_extract_model, results_created_model_with_loaded_weights).all(), "Loaded weights results are not close to original model." |
|
|
| |
| for layer in created_model.layers[1].layers[:20]: |
| print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy) |
|
|
| |
| save_dir = "07_efficientnetb0_feature_extract_model_mixed_precision" |
| model.save(save_dir) |
|
|
| |
| loaded_saved_model = tf.keras.models.load_model(save_dir) |
|
|
| |
| loaded_saved_model = tf.keras.models.load_model(save_dir) |
|
|
|
|
| |
| for layer in loaded_saved_model.layers[1].layers[:20]: |
| print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy) |
|
|
| results_loaded_saved_model = loaded_saved_model.evaluate(test_data) |
| results_loaded_saved_model |
|
|
| |
| import numpy as np |
| assert np.isclose(results_feature_extract_model, results_loaded_saved_model).all() |
|
|
|
|
| """ |
| Optional |
| """ |
| |
|
|
| |
| |
| |
|
|
| |
| loaded_gs_model = tf.keras.models.load_model("downloaded_gs_model/07_efficientnetb0_feature_extract_model_mixed_precision") |
|
|
| |
| loaded_gs_model.summary() |
|
|
| |
| results_loaded_gs_model = loaded_gs_model.evaluate(test_data) |
| results_loaded_gs_model |
|
|
| |
| for layer in loaded_gs_model.layers: |
| layer.trainable = True |
| print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy) |
|
|
|
|
| |
| for layer in loaded_gs_model.layers[1].layers[:20]: |
| print(layer.name, layer.trainable, layer.dtype, layer.dtype_policy) |
|
|
| |
| early_stopping = tf.keras.callbacks.EarlyStopping(monitor="val_loss", |
| patience=3) |
|
|
| |
| checkpoint_path = "fine_tune_checkpoints/" |
| model_checkpoint = tf.keras.callbacks.ModelCheckpoint(checkpoint_path, |
| save_best_only=True, |
| monitor="val_loss") |
| |
| reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor="val_loss", |
| factor=0.2, |
| patience=2, |
| verbose=1, |
| min_lr=1e-7) |
|
|
| |
| loaded_gs_model.compile(loss="sparse_categorical_crossentropy", |
| optimizer=tf.keras.optimizers.Adam(0.0001), |
| metrics=["accuracy"]) |
|
|
|
|
| |
| history_101_food_classes_all_data_fine_tune = loaded_gs_model.fit(train_data, |
| epochs=100, |
| steps_per_epoch=len(train_data), |
| validation_data=test_data, |
| validation_steps=int(0.15 * len(test_data)), |
| callbacks=[create_tensorboard_callback("training_logs", "efficientb0_101_classes_all_data_fine_tuning"), |
| model_checkpoint, |
| early_stopping, |
| reduce_lr]) |
|
|
| |
| loaded_gs_model.save("07_efficientnetb0_fine_tuned_101_classes_mixed_precision") |
|
|
|
|
| """ |
| Optional |
| """ |
| |
|
|
| |
| |
| |
|
|
| |
| loaded_fine_tuned_gs_model = tf.keras.models.load_model("downloaded_fine_tuned_gs_model/07_efficientnetb0_fine_tuned_101_classes_mixed_precision") |
|
|
| |
| loaded_fine_tuned_gs_model.summary() |
|
|
| |
| results_downloaded_fine_tuned_gs_model = loaded_fine_tuned_gs_model.evaluate(test_data) |
| results_downloaded_fine_tuned_gs_model |
|
|
| """ |
| # Upload experiment results to TensorBoard (uncomment to run) |
| # !tensorboard dev upload --logdir ./training_logs \ |
| # --name "Fine-tuning EfficientNetB0 on all Food101 Data" \ |
| # --description "Training results for fine-tuning EfficientNetB0 on Food101 Data with learning rate 0.0001" \ |
| # --one_shot |
| |
| # View past TensorBoard experiments |
| # !tensorboard dev list |
| |
| |
| # Delete past TensorBoard experiments |
| # !tensorboard dev delete --experiment_id YOUR_EXPERIMENT_ID |
| |
| # Example |
| # !tensorboard dev delete --experiment_id OAE6KXizQZKQxDiqI3cnUQ |
| """ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|