Keras:连接不同模型的层以创建新模型

我想做的是:
我想连接不同模型的任意层来创建一个新的Keras模型。

我目前找到的:
https://github.com/keras-team/keras/issues/4205:使用模型的call类来改变另一个模型的输入。我对这种方法的问题:

  • 只能改变模型的输入,不能改变其他层。所以如果我想在编码器的开始处切掉一些层,这是不可能的
  • 我不喜欢在获取配置文件时使用的嵌套数组结构。更希望有一个一维数组
  • 在使用model.summary()或plot_model()时,编码器只显示为“模型”。如果有的话,我认为应该将两个模型都包装起来。所以配置应该显示[model_base, model_encoder],而不是[base_input, base_conv2D, …, encoder_model]

  • 公平地说,使用这种方法:https://github.com/keras-team/keras/issues/3021,上面的点实际上是可能的,但同样,它非常不灵活。一旦我想在基础或编码器网络的顶部或底部切掉一些层,这种方法就会失败

https://github.com/keras-team/keras/issues/3465:通过使用基础模型的任何输出,向基础模型添加新层。这里存在的问题:

  1. 虽然可以使用基础模型的任何层,这意味着我可以从基础模型中切掉层,但我不能将编码器加载为Keras模型。顶层模型总是必须新创建。

我尝试过的:
我连接不同模型的任意层的方法:

  1. 清除输入层的入边节点
  2. 使用输出层的call()方法与输出层的张量
  3. 通过用新创建的张量替换之前的输出张量,清理输出张量的出边节点

起初我非常乐观,因为summary()plot_model()让我得到了我想要的结果,因此节点图应该没问题,对吗?但是在训练时我遇到了错误。虽然“目前找到的”部分中的方法训练得很好,但我使用自己的方法时遇到了错误。这是错误消息:

  File "C:\Anaconda\envs\dlpipe\lib\site-packages\tensorflow\python\framework\op_def_library.py", line 508, in apply_op    (input_name, err))ValueError: Tried to convert 'x' to a tensor and failed. Error: None values not supported.

可能是一个重要的信息,我使用TensorFlow作为后端。我能够追溯到这个错误的根源。似乎在计算梯度时出现了错误。通常,每个节点都会进行一次梯度计算,但使用我的方法时,基础网络的所有节点都是“None”。所以基本上在keras/optimizers.py中,get_updates()在计算梯度时(grad = self.get_gradients(loss, params))。

这是没有训练的代码,实现了所有三种方法:

def create_base():    in_layer = Input(shape=(32, 32, 3), name="base_input")    x = Conv2D(32, (3, 3), padding='same', activation="relu", name="base_conv2d_1")(in_layer)    x = Conv2D(32, (3, 3), padding='same', activation="relu", name="base_conv2d_2")(x)    x = MaxPooling2D(pool_size=(2, 2), name="base_maxpooling_2d_1")(x)    x = Dropout(0.25, name="base_dropout")(x)    x = Conv2D(64, (3, 3), padding='same', activation="relu", name="base_conv2d_3")(x)    x = Conv2D(64, (3, 3), padding='same', activation="relu", name="base_conv2d_4")(x)    x = MaxPooling2D(pool_size=(2, 2), name="base_maxpooling2d_2")(x)    x = Dropout(0.25, name="base_dropout_2")(x)    return Model(inputs=in_layer, outputs=x, name="base_model")def create_encoder():    in_layer = Input(shape=(8, 8, 64))    x = Flatten(name="encoder_flatten")(in_layer)    x = Dense(512, activation="relu", name="encoder_dense_1")(x)    x = Dropout(0.5, name="encoder_dropout_2")(x)    x = Dense(10, activation="softmax", name="encoder_dense_2")(x)    return Model(inputs=in_layer, outputs=x, name="encoder_model")def extend_base(input_model):    x = Flatten(name="custom_flatten")(input_model.output)    x = Dense(512, activation="relu", name="custom_dense_1")(x)    x = Dropout(0.5, name="custom_dropout_2")(x)    x = Dense(10, activation="softmax", name="custom_dense_2")(x)    return Model(inputs=input_model.input, outputs=x, name="custom_edit")def connect_layers(from_tensor, to_layer, clear_inbound_nodes=True):    try:        tmp_output = to_layer.output    except AttributeError:        raise ValueError("Connecting to shared layers is not supported!")    if clear_inbound_nodes:        to_layer.inbound_nodes = []    else:        tensor_list = to_layer.inbound_nodes[0].input_tensors        tensor_list.append(from_tensor)        from_tensor = tensor_list        to_layer.inbound_nodes = []    new_output = to_layer(from_tensor)    for out_node in to_layer.outbound_nodes:        for i, in_tensor in enumerate(out_node.input_tensors):            if in_tensor == tmp_output:                out_node.input_tensors[i] = new_outputif __name__ == "__main__":    base = create_base()    encoder = create_encoder()    #new_model_1 = Model(inputs=base.input, outputs=encoder(base.output))    #plot_model(new_model_1, to_file="plots/new_model_1.png")    new_model_2 = extend_base(base)    plot_model(new_model_2, to_file="plots/new_model_2.png")    print(new_model_2.summary())    base_layer = base.get_layer("base_dropout_2")    top_layer = encoder.get_layer("encoder_flatten")    connect_layers(base_layer.output, top_layer)    new_model_3 = Model(inputs=base.input, outputs=encoder.output)    plot_model(new_model_3, to_file="plots/new_model_3.png")    print(new_model_3.summary())

我知道这是一大段文字和大量代码。但我觉得有必要解释这里的问题。

编辑: 我刚试了theano,我认为错误信息透露了更多信息:

theano.gradient.DisconnectedInputError:  Backtrace when that variable is created:

似乎编码器模型的每一层都通过TensorVariables与编码器输入层有某种连接。


回答:

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注