为什么 Keras 中 VGG16 中的输入预处理不是 1/255.0

数据挖掘 喀拉斯 预言 预处理 迁移学习 vgg16
2021-10-10 20:36:21

我只是想像这样使用预训练的 vgg16 在 Keras 中进行预测。

from scipy import ndimage
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input

im = scipy.misc.imread("cat_dog/validation/cats/cat.1362.jpg").astype(np.float32)
im = scipy.misc.imresize(im, (224, 224)).astype(np.float32)

#im /= 255.0
#im = im - np.mean(im, axis=2, keepdims=True)

im = np.expand_dims(im, axis=0)
im = preprocess_input(im)

out = vgg16_model.predict(im)
np.argmax(out)

似乎 im /= 255.0 给出了非常糟糕的预测。我评论了它,它开始做出很好的预测。我还添加了 preprocess_input(...) 但这似乎不会影响我所做的少数随机试验的预测。

问题是,根据这个伟大的博客:

https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

在“使用预训练网络的瓶颈特征:一分钟内达到 90% 的准确率”下,预训练的 VGG16 处于迁移学习环境中。如果你看一下这个gist,你会看到这行代码:

def save_bottlebeck_features():
    datagen = ImageDataGenerator(rescale=1. / 255)
    etc.

在缓存最后一个卷积层的特征期间,输入的预处理似乎是 1/255.0。这有点令人费解。我还进一步查找了 preprocess_input(...) 在我拥有的代码中是如何定义的,并找到了“tf”:

x /= 127.5
x -= 1.

你可以在这里查看

2个回答

Keras 上可用的预训练权重通过preprocess_input()函数中定义的预处理步骤进行训练,该函数可用于每个网络架构(VGG16、InceptionV3 等)。

例如

from keras.applications.vgg16 import preprocess_input

如果你使用 keras 自带的权重进行微调,那么你应该preprocess_input()对网络使用相应的函数。它可以不同于论文中提到的原始预处理步骤。

from keras.applications.vgg16 import VGG16
model = VGG16(weights='imagenet', include_top=False)

如果您想坚持原始的预处理步骤,您可以找到使用原始预处理步骤训练的预训练权重,而不是使用 Keras 附带的权重。

也许在写博客文章的时候,权重是用不同的预处理步骤训练的。

查看此 github问题以了解更多信息。

我对此有了新的思考。我认为在迁移学习(预训练)的上下文中使用不同但合理的预处理(例如 1/255。),而不是最初用于训练 VGG16 的预处理可能是可以的。只要最顶层的 conv-conv-...pool 表示对您的新任务有用,并且它凭经验验证了 F. Chollet 在他的博客中所做的一切。