使用预训练的Inceptionv3提取瓶颈特征 - Keras'之间的差异。实现和Native Tensorflow实现

时间:2017-11-07 19:41:54

标签: python tensorflow keras

(长篇道歉)

所有

我想使用预训练的Inceptionv3模型的瓶颈功能来预测输入图像的分类。在训练模型和预测分类之前,我尝试了3种不同的方法来提取瓶颈特征。

我的3种方法产生了不同的瓶颈特征(不仅仅是数值,甚至大小也不同)。

  1. 方法1和2的瓶颈特征:(输入图像数量)x 3 x 3 x 2048

    我的瓶颈大小来自方法3 :(输入图像的数量)x 2048

    为什么基于Keras的Inceptionv3模型和原生Tensorflow模型之间的大小不同?我的猜测是,当我在Keras中说include_top = False时,我没有提取' pool_3 / _reshape:0'层。它是否正确?如果是,我该如何提取' pool_3 / _reshape:0' Keras的一层?如果我的猜测不正确,我错过了什么?

  2. 我比较了方法1和方法2中的瓶颈特征值,它们有显着差异。我想我给它输入了相同的输入图像,因为我在将其作为脚本的输入读取之前调整了图像并重新调整了图像。我在方法1中没有选择ImageDataGenerator,根据该函数的文档,所有默认值都不会改变我的输入图像。我已将shuffle设置为false,因此我假设predict_generator和predict是以相同的顺序读取图像。我错过了什么?

  3. 请注意:

    我的输入图像是RGB格式(因此通道数= 3),我将它们全部调整为150x150。我使用inceptionv3.py中的preprocess_input函数来预处理我的所有图像。

    def preprocess_input(image):
        image /= 255.
        image -= 0.5
        image *= 2.
        return image
    

    方法1:使用带有tensorflow作为后端的Keras,用于读取我的数据的ImageDataGenerator和用于计算瓶颈功能的model.predict_generator

    我按照了example(部分使用预先训练过的网络的瓶颈功能:一分钟内准确度达到90%)来自Keras'博客。我没有列出那里列出的VGG模型,而是使用了Inceptionv3。以下是我使用的代码片段

    (代码未在此处显示,但我在下面的代码之前所做的):读取所有输入图像,调整大小为150x150x3,根据上面提到的preprocessing_input函数重新缩放,保存调整大小和重新缩放的图像

    train_datagen = ImageDataGenerator() 
    train_generator = train_datagen.flow_from_directory(my_input_dir, target_size=(150,150),shuffle=False, batch_size=16)
    
    # get bottleneck features
    # use pre-trained model and exclude top layer - which is used for classification
    pretrained_model = InceptionV3(include_top=False, weights='imagenet', input_shape=(150,150,3))
    bottleneck_features_train_v1 = pretrained_model.predict_generator(train_generator,len(train_generator.filenames)//16)
    

    方法2:使用带有tensorflow作为后端的Keras,我自己的reader和model.predict来计算瓶颈功能

    这种方法与早期方法之间的区别仅在于我使用自己的阅读器来读取输入图像。 (这里没有显示代码,但是我在下面的代码之前做了什么):读取所有输入图像,调整大小为150x150x3,根据上面提到的preprocessing_input函数重新缩放,保存调整大小和重新缩放的图像

    # inputImages is a numpy array of size <number of input images x 150 x 150 x 3>
    inputImages = readAllJPEGsInFolderAndMergeAsRGB(my_input_dir)
    
    # get bottleneck features
    # use pre-trained model and exclude top layer - which is used for classification
    pretrained_model = InceptionV3(include_top=False, weights='imagenet', input_shape=(img_width, img_height, 3))
    bottleneck_features_train_v2 = pretrained_model.predict(trainData.images,batch_size=16)
    

    方法3:使用张量流(NO KERAS)计算瓶颈特征

    我跟着retrain.py提取输入图像的瓶颈功能。请注意,该脚本的权重可以从(http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz

    获得

    如该示例中所述,我使用了bottleneck_tensor_name =&#39; pool_3 / _reshape:0&#39;作为提取和计算瓶颈功能的层。与前两种方法类似,我使用调整大小和重新缩放的图像作为脚本的输入,我将此功能列表称为瓶颈_features_train_v3

    非常感谢

2 个答案:

答案 0 :(得分:4)

1到2之间的不同结果

由于您没有显示您的代码,我(可能错误地)提出问题是您在声明preprocess_input时可能没有使用ImageDataGenerator

from keras.applications.inception_v3 import preprocess_input

train_datagen = ImageDataGenerator(preprocessing_function=preprocess_input) 

但请确保您保存的图像文件的范围为0到255.(位深24)。

1到3之间的不同形状

在这种情况下,有三种可能的模型类型:

  • include_top = True - &gt;这将返回类
  • include_top = False(仅限) - &gt;这意味着在pooling = None(没有最终的汇集层)
  • include_top = False, pooling='avg'='max' - &gt;有一个汇集层

因此,没有显式pooling=something的声明模型在keras中没有最终的池化层。然后输出仍然具有空间维度。

只需在最后添加池即可解决这个问题。其中之一:

pretrained_model = InceptionV3(include_top=False, pooling = 'avg', weights='imagenet', input_shape=(img_width, img_height, 3))
pretrained_model = InceptionV3(include_top=False, pooling = 'max', weights='imagenet', input_shape=(img_width, img_height, 3))

不确定tgz文件中的哪个模型正在使用。

作为替代方案,您还可以从Tensorflow模型中获取另一个图层,即'pool_3'之前的图层。

答案 1 :(得分:2)

您可以在此处查看inceptionv3的Keras实现: https://github.com/keras-team/keras/blob/master/keras/applications/inception_v3.py

所以,默认参数是:

def InceptionV3(include_top=True,
                weights='imagenet',
                input_tensor=None,
                input_shape=None,
                pooling=None,
                classes=1000):

请注意,pooling的默认值为None,然后在构建模型时,代码为:

if include_top:
    # Classification block
    x = GlobalAveragePooling2D(name='avg_pool')(x)
    x = Dense(classes, activation='softmax', name='predictions')(x)
else:
    if pooling == 'avg':
        x = GlobalAveragePooling2D()(x)
    elif pooling == 'max':
        x = GlobalMaxPooling2D()(x)

# Ensure that the model takes into account
# any potential predecessors of `input_tensor`.
if input_tensor is not None:
    inputs = get_source_inputs(input_tensor)
else:
    inputs = img_input
# Create model.
model = Model(inputs, x, name='inception_v3')

因此,如果您没有指定池,则在没有任何池的情况下提取瓶颈功能,您需要指定是否要在这些功能之上获得平均池或最大池。