我正在研究一种迁移学习方法,使用keras.applications
TensorFlow Hub上的MobileNetV2和TensorFlow Hub上可用的MobileNetV2时得到了截然不同的结果。这对我来说似乎很奇怪,因为这两个版本都在此处和此处声明从同一检查点mobilenet_v2_1.0_224提取其权重。这样可以再现差异,您可以在这里找到Colab Notebook :
!pip install tensorflow-gpu==2.1.0
import tensorflow as tf
import numpy as np
import tensorflow_hub as hub
from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2
def create_model_keras():
image_input = tf.keras.Input(shape=(224, 224, 3))
out = MobileNetV2(input_shape=(224, 224, 3),
include_top=True)(image_input)
model = tf.keras.models.Model(inputs=image_input, outputs=out)
model.compile(optimizer='adam', loss=["categorical_crossentropy"])
return model
def create_model_tf():
image_input = tf.keras.Input(shape=(224, 224 ,3))
out = hub.KerasLayer("https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/4",
input_shape=(224, 224, 3))(image_input)
model = tf.keras.models.Model(inputs=image_input, outputs=out)
model.compile(optimizer='adam', loss=["categorical_crossentropy"])
return model
当我尝试预测随机批次时,结果不相等:
keras_model = create_model_keras()
tf_model = create_model_tf()
np.random.seed(42)
data = np.random.rand(32,224,224,3)
out_keras = keras_model.predict_on_batch(data)
out_tf = tf_model.predict_on_batch(data)
np.array_equal(out_keras, out_tf)
版本的输出keras.applications
总和为1,但TensorFlow Hub的版本不输出。这两个版本的形状也不同:TensorFlow Hub具有1001个标签,keras.applications
具有1000个标签。
np.sum(out_keras[0]), np.sum(out_tf[0])
版画 (1.0000001, -14.166359)
这些差异的原因是什么?我想念什么吗?
编辑18.02.2020
正如Szymon Maszke指出的那样,TFHub版本返回logits。这就是为什么我向以下添加一个Softmax层的原因create_model_tf
:out = tf.keras.layers.Softmax()(x)
arnoegw提到,TfHub版本需要将图像标准化为[0,1],而keras版本需要将图像标准化为[-1,1]。当我在测试图像上使用以下预处理时:
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
img = tf.keras.preprocessing.image.load_img("/content/panda.jpeg", target_size=(224,224))
img = tf.keras.preprocessing.image.img_to_array(img)
img = preprocess_input(img)
img = tf.io.read_file("/content/panda.jpeg")
img = tf.image.decode_jpeg(img)
img = tf.image.convert_image_dtype(img, tf.float32)
img = tf.image.resize(img, (224,224))
两者都能正确预测相同的标签,并且满足以下条件: np.allclose(out_keras, out_tf[:,1:], rtol=0.8)
编辑2 18.02.2020在我写这之前,不可能将格式互相转换。这是由错误引起的。
有一些已记录的差异:
就像Szymon所说的那样,TF Hub版本返回logits(在softmax函数将其转化为概率之前),这是一种常见的做法,因为可以从logit上以更大的数值稳定性计算出交叉熵损失。
TF Hub模型假定float32输入的范围为[0,1],tf.image.decode_jpeg(...)
后面是tf.image.convert_image_dtype(..., tf.float32)
。Keras代码使用特定于模型的范围(可能为[-1,+ 1])。
TF Hub模型在返回其所有1001输出类时更完整地反映了原始SLIM检查点。如从文档链接的ImageNetLabels.txt中所述,添加的类0是“背景”(又名“材料”)。这就是对象检测用来指示图像背景的对象,而不是任何已知类别的对象。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句