I am attempting to migrate an existing Efficientnet model from keras.applications to the respective hub. However, I see vastly different behaviors in training and final performance, and thus I am trying to find the root cause.
Even with the correct preprocessing ([0-255] for keras.applications, [0-1] for tf hub), and having checked that the weights are exactly the same between the loaded feature extractors, I get different results.
However, as shown below, the keras.applications approach actually does a Rescaling(1/255.0), followed by a Normalization() layer before passing the inputs to the rest of the layers, where tf hub (as far as I understand) only receives the already rescaled outputs, so I am wondering if there might be a discrepancy due to different ways of normalizations.
import collections
import tensorflow as tf
import tensorflow_hub as tfh
img2 = tf.io.read_file("tests/test2.jpg")
img2 = tf.image.decode_jpeg(img2)
img2 = tf.image.convert_image_dtype(img2, tf.float32)
img2 = tf.image.resize(img2, (224, 224))
print(img2.numpy().min(), img2.numpy().max(), img2.numpy().mean())
# 0.0 1.0 0.14994633
img2 = tf.expand_dims(img2, axis=0)
model = tf.keras.applications.efficientnet.EfficientNetB0(include_top=False, input_shape=(224, 224, 3), pooling="avg")
model.trainable = False
# Note: each Keras Application expects a specific kind of input preprocessing.
# For EfficientNet, input preprocessing is included as part of the model (as a Rescaling layer),
# and thus tf.keras.applications.efficientnet.preprocess_input is actually a pass-through function.
# EfficientNet models expect their inputs to be float tensors of pixels with values in the [0-255] range.
print(model(img2 * 255.0, training=False))
# [[-0.1674832 0.06747124 -0.00998851 ... -0.09722453 -0.05333998
# -0.09630407]], shape=(1, 1280), dtype=float32)
inp = tf.keras.layers.Input(shape=(224, 224, 3))
layer = tfh.KerasLayer("https://tfhub.dev/tensorflow/efficientnet/b0/feature-vector/1", trainable=False)(inp)
model_hub = tf.keras.models.Model(inputs=inp, outputs=layer)
print(model_hub(img2, training=False))
# tf.Tensor(
# [[-0.1534781 -0.00044355 0.02527641 ... 0.03095446 -0.07474983
# -0.12997748]], shape=(1, 1280), dtype=float32)
weights = collections.defaultdict(lambda: collections.defaultdict(dict))
for w in model.non_trainable_weights:
m = w.numpy().mean()
weights[tuple(w.shape)][m][f"{w.name}_KERAS"] = w.numpy()
for w in model_hub.non_trainable_weights:
m = w.numpy().mean()
weights[tuple(w.shape)][m][f"{w.name}_HUB"] = w.numpy()
for s, data in weights.items():
for mn, data2 in data.items():
n = len(data2)
has_hub = any("HUB" in name for name in data2.keys())
has_keras = any("KERAS" in name for name in data2.keys())
if n % 2 != 0 or not has_hub or not has_keras:
print(s, mn, data2)
# (3,) 0.449 {'normalization/mean:0_KERAS': array([0.485, 0.456, 0.406], dtype=float32)}
# (3,) 0.226 {'normalization/variance:0_KERAS': array([0.229, 0.224, 0.225], dtype=float32)}
# () 0.0 {'normalization/count:0_KERAS': 0}
I am attempting to migrate an existing Efficientnet model from keras.applications to the respective hub. However, I see vastly different behaviors in training and final performance, and thus I am trying to find the root cause.
Even with the correct preprocessing ([0-255] for keras.applications, [0-1] for tf hub), and having checked that the weights are exactly the same between the loaded feature extractors, I get different results.
However, as shown below, the keras.applications approach actually does a Rescaling(1/255.0), followed by a Normalization() layer before passing the inputs to the rest of the layers, where tf hub (as far as I understand) only receives the already rescaled outputs, so I am wondering if there might be a discrepancy due to different ways of normalizations.