获得嵌入网络的前一项功能,无法正常使用

时间:2018-09-21 12:49:26

标签: python machine-learning keras embedding keras-layer

我想嵌入一张图像,以了解网络正在寻找哪些图像,而哪些看起来对他来说却大不相同。 首先,我想在Keras中使用Tensorboard回调,但是文档对我来说还不够清楚,我找不到任何有用的示例来重现它。因此,为了确保了解我在做什么,我更愿意自己嵌入。

为此,我计划下载已经对数据进行训练的模型,删除了最后一层(最后一个辍学和密集层),并在验证图像上进行预测以获取与每个图像相关联的特征。然后,我只需要对这些特征执行PCA并根据它们的前三个主要成分值绘制图像。

但是我想我误会了一些东西,因为当我删除最后一层时,模型预测仍然是类数的大小,但是对我来说应该是最后一层的大小,即我的128情况。

下面是用于澄清的代码(我只在其中添加了似乎对回答问题有用的行,但毫不犹豫地询问更多细节)

#model creation
base_model = applications.inception_v3.InceptionV3(include_top=False, 
                                                   weights='imagenet',
                                                   pooling='avg', 
                                                   input_shape=(img_rows, img_cols, img_channel))
#Adding custom Layers
add_model = Sequential()
add_model.add(Dense(128, activation='relu',input_shape=base_model.output_shape[1:],
                    kernel_regularizer=regularizers.l2(0.001)))
add_model.add(Dropout(0.60))
add_model.add(Dense(2, activation='sigmoid'))   
# creating the final model
model = Model(inputs=base_model.input, outputs=add_model(base_model.output))

然后,我在具有两个类别的数据集上训练了模型,并加载了模型及其权重以生成特征:

model = load_model(os.path.join(ROOT_DIR,'model_1','model_cervigrams_all.h5'))
#remove the last two layers
#remove dense_2
model.layers[-1].pop()
#remove dropout_1
model.layers[-1].pop()
model.summary() # last alyer output shape is : (None, 128), so the removal worked
#predict
model.predict(np.reshape(image,[1,image.shape[0],image.shape[1],3])) #output only two values

我在哪里错了?你有什么建议吗?

1 个答案:

答案 0 :(得分:1)

使用Keras功能API添加自定义图层时的解决方案:

如果您使用Keras functional API添加自定义图层,则以下解决方案可以正常工作:

# base model creation
base_model = applications.inception_v3.InceptionV3(include_top=False, 
                                                   weights='imagenet',
                                                   pooling='avg', 
                                                   input_shape=(150, 150, 3))
# adding custom Layers
x = Dense(128, activation='relu',input_shape=base_model.output_shape[1:],
                    kernel_regularizer=regularizers.l2(0.001))(base_model.output)
x = Dropout(0.60)(x)
out = Dense(2, activation='sigmoid')(x)

# creating the final model
model = Model(inputs=base_model.input, outputs=out)
model.compile(loss='categorical_crossentropy', optimizer='adam')

这里是如何通过定义新模型来提取自定义层的激活:

# construct a new model to get the activations of custom layers
new_model = Model(model.inputs, [model.layers[-3].output,
                                 model.layers[-2].output,
                                 model.layers[-1].output])

# predict one one random input sample
inp = np.random.rand(1, 150, 150, 3)
output = new_model.predict([inp])

# verify that's what we want
print(output[0].shape)  # shape of first dense layer output, prints: (1, 128) 
print(output[1].shape)  # shape of dropout layer output, prints: (1, 128)
print(output[2].shape)  # shape of second dense layer output, prints: (1, 2)

或者,您可以定义Keras函数:

from keras import backend as K

func = K.function(inputs=model.inputs + [K.learning_phase()],
                  outputs=[model.layers[-3].output,
                           model.layers[-2].output, 
                           model.layers[-1].output])

# usage of the defined function: 
#     the inputs should be a *list* of input arrays
#     plus 1 or 0 for the train/test mode
sample_input = np.random.rand(1, 150, 150, 3)

# train mode
output = func([sample_input, 1])

# test mode
ouput = func([sample_input, 0])

请注意,you need to使用K.learning_phase(),因为模型包含BatchNormalizationDropout之类的图层,它们在测试和训练模式下的行为不同。


注意:如果使用Sequential类添加自定义图层,上述解决方案将无法正常工作。这是因为在构建{{1}时使用add_model(base_model.output) },整个model被存储为add_model的一层。您可以通过运行modelmodel.summary()进行验证。而且没有办法访问此顺序模型的中间层的输出。当然,您可以使用print(model.layers[-1])(这是辍学层):

model.layers[-1].layers[1].output

但是,由于没有提供顺序模型的原始输入,它会抱怨该图已断开:

new_model = Model(model.inputs, model.layers[-1].layers[1].output)
new_model.predict(...)

实际上,我希望顺序模型的内层(即ValueError: Graph disconnected: cannot obtain value for tensor Tensor("dense_7_input:0", shape=(?, 2048), dtype=float32) at layer "dense_7_input". The following previous layers were accessed without issue: [] )具有附加的入站和出站节点,但事实并非如此。我不知道我是否在这里丢失了某些东西,或者某种原因是Keras中的错误或不可能做到的事情。


旁注:实际上,在模型对象does not work since you need to update some of the internal attributes of the modelmodel.layers[-1].layer[1:]属性上使用pop()(尽管,仅对于顺序模型,内置{{3 }}方法已实现)。