我想嵌入一张图像,以了解网络正在寻找哪些图像,而哪些看起来对他来说却大不相同。 首先,我想在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
我在哪里错了?你有什么建议吗?
答案 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()
,因为模型包含BatchNormalization
和Dropout
之类的图层,它们在测试和训练模式下的行为不同。
注意:如果使用Sequential
类添加自定义图层,上述解决方案将无法正常工作。这是因为在构建{{1}时使用add_model(base_model.output)
},整个model
被存储为add_model
的一层。您可以通过运行model
或model.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 model的model.layers[-1].layer[1:]
属性上使用pop()
(尽管,仅对于顺序模型,内置{{3 }}方法已实现)。