6

使用 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() 中的空值带有“已连接到”)。我在文档中找不到任何解释如何解决此问题的内容。有任何想法吗?

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]                    

====================================================================================================
4

3 回答 3

5

删除图层时,您需要重新编译模型以使其生效。

所以使用

model.compile(loss=...,optimizer=..., ...)

在打印摘要之前,它应该正确集成更改。

编辑 :

您尝试做的事情实际上对于顺序模式非常复杂。这是我可以为您的 Sequential 模型提出的解决方案(如果有更好的请告诉我):

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())

hack 在于您的图层具有我无法更改的属性layer1.inputlayer1.output

一种解决方法是使用 Functionnal API 模型。这使您可以定义图层的输入和输出。

首先,您需要定义您的 pop() 函数,以便在每次弹出一个图层时正确重新链接图层,该函数来自此 github 问题

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()

可能有比这更好的解决方案,但这是我会做的。

我希望这有帮助。

于 2017-03-05T20:23:12.060 回答
0

出于某种原因,我需要在添加新层以使工作正常之前使用模型构建带有弹出层的模型。

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
于 2018-03-21T10:03:35.863 回答
0

我正在使用以下函数,它适用于我的代码:

for layer in model1.layers[:22]:
    model.add(layer)
于 2019-03-14T16:44:56.287 回答