简体   繁体   English

Keras 函数式 API 多输入模型

[英]Keras Functional API Multiple Input Model

I'm trying to create a multiple-input model with Functional API in Keras with this structure:我正在尝试在 Keras 中使用以下结构使用 Functional API 创建多输入模型:

多输入模型

There are three inputs: Team_1_In , Team_2_In , Home_In .共有三个输入: Team_1_InTeam_2_InHome_In Where Team_1_In and Team_2_In go through an Embedding layer, then BatchNormalization and Flatten layers.其中Team_1_InTeam_2_In通过Embedding层,然后BatchNormalizationFlatten层。 The problem is when I'm trying to add Flatten layer after BatchNormalization I get this error:问题是当我尝试在BatchNormalization之后添加Flatten层时出现此错误:

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last) <ipython-input-46-8354b255cfd1> in <module>
     15 batch_normalization_2 = BatchNormalization()(team_2_strength)
     16 
---> 17 flatten_1 = Flatten()(batch_normalization_1)
     18 flatten_2 = Flatten()(batch_normalization_2)
     19 

~/conda/lib/python3.6/site-packages/keras/engine/topology.py in
__call__(self, inputs, **kwargs)
    573                 # Raise exceptions in case the input is not compatible
    574                 # with the input_spec specified in the layer constructor.
--> 575                 self.assert_input_compatibility(inputs)
    576 
    577                 # Collect input shapes to build layer.

~/conda/lib/python3.6/site-packages/keras/engine/topology.py in assert_input_compatibility(self, inputs)
    488                                      self.name + ': expected min_ndim=' +
    489                                      str(spec.min_ndim) + ', found ndim=' +
--> 490                                      str(K.ndim(x)))
    491             # Check dtype.
    492             if spec.dtype is not None:

ValueError: Input 0 is incompatible with layer flatten_10: expected min_ndim=3, found ndim=2 

I tried to play with axis parameter of BatchNormalization layer but it didn't help.我尝试使用BatchNormalization层的轴参数,但没有帮助。 Here is my code:这是我的代码:

# create embedding layer
from keras.layers import Embedding
from keras.layers import BatchNormalization, Flatten, Dense
from numpy import unique

# Create an embedding layer
team_lookup = Embedding(input_dim=n_teams,
                        output_dim=1,
                        input_length=1,
                        name='Team-Strength')

# create model with embedding layer
from keras.layers import Input, Embedding, Flatten
from keras.models import Model

# Create an input layer for the team ID
teamid_in = Input(shape=(1,))

# Lookup the input in the team strength embedding layer
strength_lookup = team_lookup(teamid_in)

# Flatten the output
strength_lookup_flat = Flatten()(strength_lookup)

# Combine the operations into a single, re-usable model
team_strength_model = Model(teamid_in, strength_lookup_flat, name='Team-Strength-Model')



# Create an Input for each team
team_in_1 = Input(shape=(1,), name='Team-1-In')
team_in_2 = Input(shape=(1,), name='Team-2-In')

# Create an input for home vs away
home_in = Input(shape=(1,), name='Home-In')

# Lookup the team inputs in the team strength model
team_1_strength = team_strength_model(team_in_1)
team_2_strength = team_strength_model(team_in_2)

batch_normalization_1 = BatchNormalization()(team_1_strength)
batch_normalization_2 = BatchNormalization()(team_2_strength)

flatten_1 = Flatten()(batch_normalization_1)
flatten_2 = Flatten()(batch_normalization_2)

# Combine the team strengths with the home input using a Concatenate layer, then add a Dense layer
out = Concatenate()([flatten_1, flatten_2, home_in])
out = Dense(1)(out)

As shown in the error, you need a 3D tensor for Flatten layer:如错误所示,您需要Flatten层的 3D 张量:

ValueError: Input 0 is incompatible with layer flatten_10: expected min_ndim=3, found ndim=2

In the first part of the code, where you passed your input to the embedding layer, everything is fine and it compiles successfully:在代码的第一部分,您将输入传递给嵌入层,一切正常并且编译成功:

team_lookup = Embedding(input_dim=1,
                        output_dim=1,
                        input_length=1,
                        name='Team-Strength')

strength_lookup = team_lookup(teamid_in)

batch_normalization_1 = BatchNormalization()(strength_lookup)

strength_lookup_flat = Flatten()(batch_normalization_1)

team_strength_model = Model(teamid_in, strength_lookup_flat, name='Team-Strength-Model')
team_strength_model.compile(optimizer='adam', loss='categorical_crossentropy')

But in the second part the code, where you pass inputs to the team_strength_model it flatten the tensors which their shape converted to (batch, flatten) .但是在代码的第二部分中,您将输入传递给team_strength_model ,它将张量展平,它们的形状转换为(batch, flatten) When you pass this 2D tensor to BatchNormalization it throws such an exception.当您将此 2D 张量传递给BatchNormalization时,它会抛出这样的异常。

To fix the issue :要解决此问题

1) Pass the input to the Embedding layer 1)将输入传递给Embedding

2) Do BatchNormalization 2) 做BatchNormalization

3) Flatten the BatchNormalization 's output 3) 展平BatchNormalization的输出

This is a question about an exercise on Datacamp: https://campus.datacamp.com/courses/advanced-deep-learning-with-keras-in-python/multiple-inputs-3-inputs-and-beyond?ex=11这是一个关于 Datacamp 练习的问题: https ://campus.datacamp.com/courses/advanced-deep-learning-with-keras-in-python/multiple-inputs-3-inputs-and-beyond?ex= 11

I reproduce it here not to infringe upon their IP, but to explain it a little more clearly.我在这里转载不是为了侵犯他们的IP,而是为了更清楚地解释它。 One of the issues I have with sites like Datacamp (which I use heavily) is that if you don't understand what's going on, there's no real recourse, aside from posting here on SO.我对像 Datacamp 这样的网站(我经常使用它)的问题之一是,如果你不明白发生了什么,除了在 SO 上发帖之外,没有真正的追索权。

The question is not clearly phrased in Datacamp. Datacamp 中的问题没有明确表述。 The exercise introduces ensemble models;该练习介绍了集成模型; here, one model makes a prediction about the score differential between two basketball teams based on regular-season data, and another model makes a prediction about score differential based on that earlier prediction along with new data.在这里,一个模型根据常规赛数据预测两支篮球队之间的得分差异,另一个模型根据早期预测和新数据预测得分差异。

Unfortunately, in the exercise, both models are just called model , they are presented out of order, and the actual model used in the exercise is never clearly shared with the student.不幸的是,在练习中,这两个模型都只称为model ,它们的显示顺序是乱序的,而且练习中使用的实际模型从未与学生清楚地分享过。 Oops.哎呀。

Here is the first model.这是第一个模型。 Not that this differs from the OP's model, in that it uses an embedding layer , not an embedding model .并不是说这与 OP 的模型不同,因为它使用的是嵌入,而不是嵌入模型 Again, the Datacamp exercise is not clear on this, and the nature of the Embedding is changed without informing the student.同样,Datacamp 练习对此并不清楚, Embedding的性质在没有通知学生的情况下发生了变化。 It predicts a score difference between two teams based on an integer id (dumb) and which team is home or away.它根据整数 id(哑)预测两支球队之间的比分差异,以及哪支球队是主场还是客场。

# Create an Input for each team
team_in_1 = Input(shape=(1,), name='Team-1-In')
team_in_2 = Input(shape=(1,), name='Team-2-In')

# Create an input for home vs away
home_in = Input(shape=(1,), name='Home-In')

# Create an embedding layer
team_lookup = Embedding(input_dim=n_teams,
                        output_dim=1,
                        input_length=1,
                        name='Team-Strength')

team_1_strength = team_lookup(team_in_1)
team_2_strength = team_lookup(team_in_2)

batch_normalization_1 = BatchNormalization(axis=1)(team_1_strength)
batch_normalization_2 = BatchNormalization(axis=1)(team_2_strength)

# flatten batch_normalization_1
flatten_1 = Flatten()(batch_normalization_1)

# flatten batch_normalization_2
flatten_2 = Flatten()(batch_normalization_2)

out = Concatenate()([flatten_1, flatten_2, home_in])
out = Dense(1)(out)

model = Model([team_in_1, team_in_2, home_in], out)
model.compile(optimizer="adam", loss="mean_absolute_error")

This model is then fit on the regular season data:该模型然后适用于常规赛季数据:

model.fit([games_season["team_1"], games_season["team_2"], games_season["home"]],
          games_season["score_diff"],
          epochs=1,
          verbose=True,
          validation_split=0.1,
          batch_size=2048)

... and used to predict a score difference for a different data set: ...并用于预测不同数据集的得分差异:

# Predict
games_tourney['pred'] = model.predict(
    [games_tourney["team_1"], 
     games_tourney["team_2"], 
     games_tourney["home"]])

Now split this data set into train and test.现在将此数据集拆分为训练和测试。

games_tourney_train = games_tourney.loc[games_tourney["season"] < 2010]
games_tourney_test = games_tourney.loc[games_tourney["season"] >= 2010]

Here is the second model, which I've called preds_model for no specific reason:这是第二个模型,我没有具体原因将其称为preds_model

# Create an input layer with 3 columns
input_tensor = Input((3, ))

# Pass it to a Dense layer with 1 unit
output_tensor = Dense(1)(input_tensor)

# Create a model
preds_model = Model(input_tensor, output_tensor)

# Compile the model
preds_model.compile(optimizer="adam", loss="mean_absolute_error")

preds_model.fit(games_tourney_train[['home', 'seed_diff', 'pred']],
          games_tourney_train['score_diff'],
          epochs=1,
          verbose=True)

And finally, evaluate your (first) ensemble model:最后,评估您的(第一个)集成模型:

# Evaluate the model on the games_tourney_test dataset
print(preds_model.evaluate(games_tourney_test[["home", "seed_diff", "pred"]],
               games_tourney_test["score_diff"], verbose=False))

And your output:你的输出:

11.94

I suspect there is a more straightforward introduction to ensemble models out there.我怀疑那里有更直接的集成模型介绍。

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

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