简体   繁体   English

Keras 功能 api 多输入:传递给 model 的输入列表是冗余的

[英]Keras functional api multiple input: The list of inputs passed to the model is redundant

I have a huge networt ( keras-bert ) which works fine for classification.我有一个巨大的网络( keras-bert ),可以很好地进行分类。 Since my data has two different columns, I'd like to fine-tune a BERT model for each column and connect them in the final layer.由于我的数据有两个不同的列,我想为每一列微调一个 BERT model 并将它们连接到最后一层。 But I get the following error:但我收到以下错误:

---> 20 model = keras.models.Model(inputs=[inputs1, inputs2], outputs=outputs) ---> 20 model = keras.models.Model(输入=[输入1,输入2],输出=输出)

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/network.py in _validate_graph_inputs_and_outputs(self) /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/network.py 在 _validate_graph_inputs_and_outputs(self)

1620 """Validates the inputs and outputs of a Graph Network.""" 1620 """验证图网络的输入和输出。"""

1621 # Check for redundancy in inputs. 1621 # 检查输入中的冗余。

-> 1622 if len(set(self.inputs)).= len(self:inputs): -> 1622 如果 len(set(self.inputs)).= len(self:inputs):

1623 raise ValueError('The list of inputs passed to the model ' 1623 raise ValueError('传递给 model 的输入列表'

1624 'is redundant. 1624'是多余的。 ' '

TypeError: unhashable type: 'list'类型错误:不可散列类型:“列表”

In my code I have two bert models, model1 and model2 .在我的代码中,我有两个 bert 模型, model1model2 With just one model it worked fine.只需一个 model 就可以正常工作。 The only things I added were that 2 models instead of one are loaded from checkpoint and the second input-layer and the concatenation of dense1 and dense2:我唯一添加的是从检查点和第二个输入层以及dense1和dense2的串联加载了2个模型而不是一个:

#load_trained_model_from_checkpoint is defined here:
# https://github.com/CyberZHG/keras-bert/blob/master/keras_bert/loader.py
model1 = load_trained_model_from_checkpoint(
    config_path,
    checkpoint_path,
    training=True,
    trainable=True,
    seq_len=SEQ_LEN,
    )
model2 = load_trained_model_from_checkpoint(
    config_path,
    checkpoint_path,
    training=True,
    trainable=True,
    seq_len=SEQ_LEN,
)

inputs1 = model1.inputs[:2] #model 1 for titles
inputs2 = model2.inputs[:2] #model 2 for texts
dense1 = model1.get_layer('NSP-Dense').output
dense2 = model2.get_layer('NSP-Dense').output
outputs = keras.layers.Dense(len(test_title_y[0]), activation='sigmoid')(keras.layers.concatenate([dense1, dense2]))


model = keras.models.Model(inputs=[inputs1, inputs2], outputs=outputs)

What am I overseeing?我在监督什么? Do I somehow have to wrap the input?我是否必须以某种方式包装输入?

Edit: I suspect that the problem has something to do with my input being a list of lists: the inputs1 and inputs2 look like that:编辑:我怀疑问题与我的输入是列表列表有关:输入 1 和输入 2 看起来像这样:

[<tf.Tensor 'Input-Token:0' shape=(?, 256) dtype=float32>, <tf.Tensor 'Input-Segment:0' shape=(?, 256) dtype=float32>]
[<tf.Tensor 'Input-Token_1:0' shape=(?, 256) dtype=float32>, <tf.Tensor 'Input-Segment_1:0' shape=(?, 256) dtype=float32>]

Can I somehow reshape or concatenate my input to overcome this error?我可以以某种方式重塑或连接我的输入来克服这个错误吗?

Edit:编辑:

The summaries of model1 looks like that, model2 looks the same but with LAYER_2 for each layer name: model1 的摘要看起来像这样,model2 看起来相同,但每个层名称都有 LAYER_2:

Layer (type) Output Shape Param # Connected to层(类型)Output Shape Param # Connected to


Input-Token (InputLayer) (None, 256) 0输入令牌(InputLayer)(无,256)0


Input-Segment (InputLayer) (None, 256) 0输入段(InputLayer)(无,256)0


Embedding-Token (TokenEmbedding [(None, 256, 768), ( 23440896 Input-Token[0][0] Embedding-Token (TokenEmbedding [(None, 256, 768), ( 23440896 Input-Token[0][0]


Embedding-Segment (Embedding) (None, 256, 768) 1536 Input-Segment[0][0] Embedding-Segment (嵌入) (None, 256, 768) 1536 Input-Segment[0][0]


... (lots of layers in between) ...(中间有很多层)


NSP-Dense (Dense) (None, 768) 590592 Extract[0][0] NSP-密集(密集)(无,768)590592 提取物[0][0]

It looks like there is an internal check which looks for equal length inputs to a model.看起来有一个内部检查来查找 model 的等长输入。 In this case both inputs are [batchSize, 256] .在这种情况下,两个输入都是[batchSize, 256] One thing that you can do is try packing the two inputs into one with three dimensions (ie [batchSize, inputs, 256] ).您可以做的一件事是尝试将两个输入打包成一个具有三个维度的输入(即[batchSize, inputs, 256] )。 You would need to handle some slicing in the model to make sure you are passing the correct input to the layers.您需要在 model 中处理一些切片,以确保将正确的输入传递给层。

Here is an example:这是一个例子:

#load_trained_model_from_checkpoint is defined here:
# https://github.com/CyberZHG/keras-bert/blob/master/keras_bert/loader.py

model1 = load_trained_model_from_checkpoint(
    config_path,
    checkpoint_path,
    training=True,
    trainable=True,
    seq_len=SEQ_LEN,
    )
model2 = load_trained_model_from_checkpoint(
    config_path,
    checkpoint_path,
    training=True,
    trainable=True,
    seq_len=SEQ_LEN,
)

inputs1 = model1.inputs[:2] #model 1 for titles
inputs2 = model2.inputs[:2] #model 2 for texts
# concatenate the inputs into one tensor
concatInputs = keras.backend.concatenate([inputs1, inputs2],axis=0)

dense1 = model1.get_layer('NSP-Dense').output
dense2 = model2.get_layer('NSP-Dense').output

def getModel():
    inputs=keras.layers.Input([2,256])
    # slice inputs into individual tensors
    in1 = keras.layers.Lambda(lambda x: tf.slice(inputs,[0,0],[1,inputs.get_shape()[1]])
    in2 = keras.layers.Lambda(lambda x: tf.slice(inputs,[1,0],[2,inputs.get_shape()[1]])
    d1 = dense1(in1)
    d2 = dense2(in2)
    outputs = keras.layers.Dense(len(test_title_y[0]), activation='sigmoid')(keras.layers.concatenate([d1, d2]))

    return inputs,outputs

ins,outs = getModel()

model = keras.models.Model(inputs=[ins], outputs=[outs])

I didn't get a chance to test so the syntax may not be exact but the idea should work.我没有机会测试,所以语法可能不准确,但这个想法应该可行。

This may sound a little copy+paste, but I think you solved your own question when you noticed the inputs are lists of lists.这听起来可能有点复制+粘贴,但我认为当您注意到输入是列表列表时,您解决了自己的问题。

Instead of using [inputs1, inputs2] , use inputs1 + inputs2 .不要使用[inputs1, inputs2] ,而是使用inputs1 + inputs2

Test if they are lists with isinstance(inputs1, list) .测试它们是否是带有isinstance(inputs1, list)

The error means that somewhere, the function is trying to use a list as a hash argument instead.该错误意味着 function 在某处尝试使用列表作为 hash 参数。 ie using a list as a key in a dictionary.即使用列表作为字典中的键。

The Model(inputs=[input1,input2]) cannot take in a list. Model(inputs=[input1,input2]) 不能接受列表。

Try using尝试使用

np.reshape

On input1 and input2 first.首先在 input1 和 input2 上。 Additionally, cast the lists to tuples.此外,将列表转换为元组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM