Keras - 弹出并重新添加图层,但图层不会断开连接
Keras - Pop and re-add layers, but layer does not disconnect
使用 Keras (1.2.2),我正在加载一个顺序模型,其最后一层是:
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
然后,我想弹出最后一层,再添加一个全连接层,重新添加分类层。
model = load_model('model1.h5')
layer1 = model.layers.pop() # Copy activation_6 layer
layer2 = model.layers.pop() # Copy classification layer (dense_2)
model.add(Dense(512, name='dense_3'))
model.add(Activation('softmax', name='activation_7'))
model.add(layer2)
model.add(layer1)
print(model.summary())
如您所见,我的 dense_3 和 activation_7 没有连接到网络(summary() 中的空值 "Connected to")。我在说明如何解决此问题的文档中找不到任何内容。有什么想法吗?
dense_1 (Dense) (None, 512) 131584 flatten_1[0][0]
____________________________________________________________________________________________________
activation_5 (Activation) (None, 512) 0 dense_1[0][0]
____________________________________________________________________________________________________
dense_3 (Dense) (None, 512) 5632
____________________________________________________________________________________________________
activation_7 (Activation) (None, 512) 0
____________________________________________________________________________________________________
dense_2 (Dense) (None, 10) 5130 activation_5[0][0]
____________________________________________________________________________________________________
activation_6 (Activation) (None, 10) 0 dense_2[0][0]
====================================================================================================
按照下面的回答,我在打印出来之前编译了模型model.summary()
,但是由于某些原因,层没有被正确弹出,如摘要所示:最后一层的连接是错误的:
dense_1 (Dense) (None, 512) 131584 flatten_1[0][0]
____________________________________________________________________________________________________
activation_5 (Activation) (None, 512) 0 dense_1[0][0]
____________________________________________________________________________________________________
dense_3 (Dense) (None, 512) 5632 activation_6[0][0]
____________________________________________________________________________________________________
activation_7 (Activation) (None, 512) 0 dense_3[0][0]
____________________________________________________________________________________________________
dense_2 (Dense) (None, 10) 5130 activation_5[0][0]
activation_7[0][0]
____________________________________________________________________________________________________
activation_6 (Activation) (None, 10) 0 dense_2[0][0]
dense_2[1][0]
====================================================================================================
但应该是
dense_1 (Dense) (None, 512) 131584 flatten_1[0][0]
____________________________________________________________________________________________________
activation_5 (Activation) (None, 512) 0 dense_1[0][0]
____________________________________________________________________________________________________
dense_3 (Dense) (None, 512) 5632 activation_5[0][0]
____________________________________________________________________________________________________
activation_7 (Activation) (None, 512) 0 dense_3[0][0]
____________________________________________________________________________________________________
dense_2 (Dense) (None, 10) 5130
activation_7[0][0]
____________________________________________________________________________________________________
activation_6 (Activation) (None, 10) 0 dense_2[0][0]
====================================================================================================
当您删除图层时,您需要重新编译您的模型才能使其生效。
所以使用
model.compile(loss=...,optimizer=..., ...)
在打印摘要之前,它应该正确地整合更改。
编辑:
对于顺序模式,您尝试做的事情实际上非常复杂。这是我可以为您的顺序模型提出的解决方案(如果有更好的请告诉我):
model = load_model('model1.h5')
layer1 = model.layers.pop() # Copy activation_6 layer
layer2 = model.layers.pop() # Copy classification layer (dense_2)
model.add(Dense(512, name='dense_3'))
model.add(Activation('softmax', name='activation_7'))
# get layer1 config
layer1_config = layer1.get_config()
layer2_config = layer2.get_config()
# change the name of the layers otherwise it complains
layer1_config['name'] = layer1_config['name'] + '_new'
layer2_config['name'] = layer2_config['name'] + '_new'
# import the magic function
from keras.utils.layer_utils import layer_from_config
# re-add new layers from the config of the old ones
model.add(layer_from_config({'class_name':type(l2), 'config':layer2_config}))
model.add(layer_from_config({'class_name':type(l1), 'config':layer1_config}))
model.compile(...)
print(model.summary())
问题在于您的图层具有我无法更改的 layer1.input
和 layer1.output
属性。
一种解决方法是使用函数 API 模型。这允许您定义层中的内容和内容。
首先你需要定义你的 pop() 函数,以便在每次弹出时正确地重新链接图层,该函数来自 this github issue:
def pop_layer(model):
if not model.outputs:
raise Exception('Sequential model cannot be popped: model is empty.')
popped_layer = model.layers.pop()
if not model.layers:
model.outputs = []
model.inbound_nodes = []
model.outbound_nodes = []
else:
model.layers[-1].outbound_nodes = []
model.outputs = [model.layers[-1].output]
model.built = False
return popped_layer
它只是删除最后一层的每个输出链接,并将模型的输出更改为新的最后一层。现在您可以在 :
中使用它
model = load_model('model1.h5')
layer1 = model.layers.pop() # Copy activation_6 layer
layer2 = model.layers.pop() # Copy classification layer (dense_2)
# take model.outputs and feed a Dense layer
h = Dense(512,name='dense_3')(model.outputs)
h = Activation('relu', name=('activation_7')(h)
# apply
h = layer2(h)
output = layer1(h)
model = Model(input=model.input, output=output)
model.compile(...)
model.summary()
可能有比这更好的解决方案,但这是我会做的。
希望对您有所帮助。
出于某种原因,我需要在添加新层之前使用 Model 使用弹出层来构建模型。
conda list keras
# Name Version Build Channel
keras 2.1.5 py36_0 conda-forge
这是代码片段:
def pop_layer(model):
if not model.outputs:
raise Exception('Sequential model cannot be popped: model is empty.')
model.layers.pop()
if not model.layers:
model.outputs = []
model.inbound_nodes = []
model.outbound_nodes = []
else:
model.layers[-1].outbound_nodes = []
model.outputs = [model.layers[-1].output]
model.built = False
def get_model():
#Fully convolutional part of VGG16
model = VGG16(include_top=False, weights='imagenet')
#Remove last max pooling layer
pop_layer(model)
#Freeze pretrained layers
for layer in model.layers:
layer.trainable = False
model = Model(inputs=model.inputs, outputs=model.outputs)
print('len(model.layers)', len(model.layers)) #
print(model.summary()) #
x = GlobalAveragePooling2D()(model.output)
head = Dense(N_CLASS, activation='softmax')(x)
model = Model(inputs=model.inputs, outputs=head)
model.compile(optimizer=Adadelta(), loss='categorical_crossentropy', metrics=['accuracy'])
print('len(model.layers)', len(model.layers)) #
print(model.summary()) #
return model
我正在使用以下函数,它适用于我的代码:
for layer in model1.layers[:22]:
model.add(layer)
使用 Keras (1.2.2),我正在加载一个顺序模型,其最后一层是:
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
然后,我想弹出最后一层,再添加一个全连接层,重新添加分类层。
model = load_model('model1.h5')
layer1 = model.layers.pop() # Copy activation_6 layer
layer2 = model.layers.pop() # Copy classification layer (dense_2)
model.add(Dense(512, name='dense_3'))
model.add(Activation('softmax', name='activation_7'))
model.add(layer2)
model.add(layer1)
print(model.summary())
如您所见,我的 dense_3 和 activation_7 没有连接到网络(summary() 中的空值 "Connected to")。我在说明如何解决此问题的文档中找不到任何内容。有什么想法吗?
dense_1 (Dense) (None, 512) 131584 flatten_1[0][0]
____________________________________________________________________________________________________
activation_5 (Activation) (None, 512) 0 dense_1[0][0]
____________________________________________________________________________________________________
dense_3 (Dense) (None, 512) 5632
____________________________________________________________________________________________________
activation_7 (Activation) (None, 512) 0
____________________________________________________________________________________________________
dense_2 (Dense) (None, 10) 5130 activation_5[0][0]
____________________________________________________________________________________________________
activation_6 (Activation) (None, 10) 0 dense_2[0][0]
====================================================================================================
按照下面的回答,我在打印出来之前编译了模型model.summary()
,但是由于某些原因,层没有被正确弹出,如摘要所示:最后一层的连接是错误的:
dense_1 (Dense) (None, 512) 131584 flatten_1[0][0]
____________________________________________________________________________________________________
activation_5 (Activation) (None, 512) 0 dense_1[0][0]
____________________________________________________________________________________________________
dense_3 (Dense) (None, 512) 5632 activation_6[0][0]
____________________________________________________________________________________________________
activation_7 (Activation) (None, 512) 0 dense_3[0][0]
____________________________________________________________________________________________________
dense_2 (Dense) (None, 10) 5130 activation_5[0][0]
activation_7[0][0]
____________________________________________________________________________________________________
activation_6 (Activation) (None, 10) 0 dense_2[0][0]
dense_2[1][0]
====================================================================================================
但应该是
dense_1 (Dense) (None, 512) 131584 flatten_1[0][0]
____________________________________________________________________________________________________
activation_5 (Activation) (None, 512) 0 dense_1[0][0]
____________________________________________________________________________________________________
dense_3 (Dense) (None, 512) 5632 activation_5[0][0]
____________________________________________________________________________________________________
activation_7 (Activation) (None, 512) 0 dense_3[0][0]
____________________________________________________________________________________________________
dense_2 (Dense) (None, 10) 5130
activation_7[0][0]
____________________________________________________________________________________________________
activation_6 (Activation) (None, 10) 0 dense_2[0][0]
====================================================================================================
当您删除图层时,您需要重新编译您的模型才能使其生效。
所以使用
model.compile(loss=...,optimizer=..., ...)
在打印摘要之前,它应该正确地整合更改。
编辑:
对于顺序模式,您尝试做的事情实际上非常复杂。这是我可以为您的顺序模型提出的解决方案(如果有更好的请告诉我):
model = load_model('model1.h5')
layer1 = model.layers.pop() # Copy activation_6 layer
layer2 = model.layers.pop() # Copy classification layer (dense_2)
model.add(Dense(512, name='dense_3'))
model.add(Activation('softmax', name='activation_7'))
# get layer1 config
layer1_config = layer1.get_config()
layer2_config = layer2.get_config()
# change the name of the layers otherwise it complains
layer1_config['name'] = layer1_config['name'] + '_new'
layer2_config['name'] = layer2_config['name'] + '_new'
# import the magic function
from keras.utils.layer_utils import layer_from_config
# re-add new layers from the config of the old ones
model.add(layer_from_config({'class_name':type(l2), 'config':layer2_config}))
model.add(layer_from_config({'class_name':type(l1), 'config':layer1_config}))
model.compile(...)
print(model.summary())
问题在于您的图层具有我无法更改的 layer1.input
和 layer1.output
属性。
一种解决方法是使用函数 API 模型。这允许您定义层中的内容和内容。
首先你需要定义你的 pop() 函数,以便在每次弹出时正确地重新链接图层,该函数来自 this github issue:
def pop_layer(model):
if not model.outputs:
raise Exception('Sequential model cannot be popped: model is empty.')
popped_layer = model.layers.pop()
if not model.layers:
model.outputs = []
model.inbound_nodes = []
model.outbound_nodes = []
else:
model.layers[-1].outbound_nodes = []
model.outputs = [model.layers[-1].output]
model.built = False
return popped_layer
它只是删除最后一层的每个输出链接,并将模型的输出更改为新的最后一层。现在您可以在 :
中使用它model = load_model('model1.h5')
layer1 = model.layers.pop() # Copy activation_6 layer
layer2 = model.layers.pop() # Copy classification layer (dense_2)
# take model.outputs and feed a Dense layer
h = Dense(512,name='dense_3')(model.outputs)
h = Activation('relu', name=('activation_7')(h)
# apply
h = layer2(h)
output = layer1(h)
model = Model(input=model.input, output=output)
model.compile(...)
model.summary()
可能有比这更好的解决方案,但这是我会做的。
希望对您有所帮助。
出于某种原因,我需要在添加新层之前使用 Model 使用弹出层来构建模型。
conda list keras
# Name Version Build Channel
keras 2.1.5 py36_0 conda-forge
这是代码片段:
def pop_layer(model):
if not model.outputs:
raise Exception('Sequential model cannot be popped: model is empty.')
model.layers.pop()
if not model.layers:
model.outputs = []
model.inbound_nodes = []
model.outbound_nodes = []
else:
model.layers[-1].outbound_nodes = []
model.outputs = [model.layers[-1].output]
model.built = False
def get_model():
#Fully convolutional part of VGG16
model = VGG16(include_top=False, weights='imagenet')
#Remove last max pooling layer
pop_layer(model)
#Freeze pretrained layers
for layer in model.layers:
layer.trainable = False
model = Model(inputs=model.inputs, outputs=model.outputs)
print('len(model.layers)', len(model.layers)) #
print(model.summary()) #
x = GlobalAveragePooling2D()(model.output)
head = Dense(N_CLASS, activation='softmax')(x)
model = Model(inputs=model.inputs, outputs=head)
model.compile(optimizer=Adadelta(), loss='categorical_crossentropy', metrics=['accuracy'])
print('len(model.layers)', len(model.layers)) #
print(model.summary()) #
return model
我正在使用以下函数,它适用于我的代码:
for layer in model1.layers[:22]:
model.add(layer)