通过 for 循环使用函数式 API 创建 Keras 输入层?



假设我需要动态生成特定于用户的keras模型。每个用户可以有可变数量的分类输入,但是一旦你知道分类输入的数量,手动构建模型就很容易了。

我想编写一个函数,给定每个分类变量的基数列表将返回适当的模型。我对这个问题的第一次尝试产生了以下解决方案,但执行这样的字符串似乎不对。

from keras.layers import Dense,Embedding,Input,Flatten,Add
from keras.models import Model
def build_model(input_cardinalities,num_outputs):
layers = []
inputs = []
for i,cardinality in enumerate(input_cardinalities):
exec("input{0} = Input(shape=[1], name='input{0}')".format(i))
exec("embedding{0} =  Embedding({1}, 20, name='embedding{0}')(input{0})".format(i,cardinality))
exec("vec{0} = Flatten(name='flatten{0}')(embedding{0})".format(i))
exec("layers.append(vec{0})".format(i))
exec("inputs.append(input{0})".format(i))
context_layer = Add(layers)
dense1 = Dense(50, name='Dense1',activation='relu')(context_layer)
dense2 = Dense(num_outputs, name='Output', activation='softmax')(dense1)
model = Model(inputs,dense2)
model.compile('sgd','categorical_crossentropy')
return model

我只是觉得执行这样的字符串不舒服,但这是我能想到的做我想做的事的唯一方法。我只是觉得应该有更好的方法。

实际上根本不需要使用exec,您一次构建一个输入/嵌入,然后将它们存储到列表中。这是正确的方法,不需要exec

def build_model(input_cardinalities,num_outputs):
layers = []
inputs = []
for i,cardinality in enumerate(input_cardinalities):
input = Input(shape=[1], name='input{0}'.format(i))
embedding =  Embedding(cardinality, 20, name='embedding{0}'.format(i))
vec = Flatten(name='flatten{0}'.format(i))(embedding)
layers.append(vec)
inputs.append(input)
context_layer = Add()(layers)
dense1 = Dense(50, name='Dense1',activation='relu')(context_layer)
dense2 = Dense(num_outputs, name='Output', activation='softmax')(dense1)
model = Model(inputs,dense2)
model.compile('sgd','categorical_crossentropy')
return model

另请注意,我更正了Add()(layers)呼叫。

我遇到了类似的问题,我想使用 for 循环实例化多个输入层。首先,我尝试重现上述内容,并仅完成上述答案以全面性(并打印模型摘要(。

from keras.layers import Dense,Embedding,Input,Flatten,Add
from keras.models import Model
from tensorflow.keras.utils import plot_model
def build_model(input_cardinalities,num_outputs):
layers = []
inputs = []
for i,cardinality in enumerate(input_cardinalities):
input = Input(shape=[1], name='input{0}'.format(i))
embedding =  Embedding(cardinality, 20, name='embedding{0}'.format(i))(input)
vec = Flatten(name='flatten{0}'.format(i))(embedding)
layers.append(vec)
inputs.append(input)
context_layer = Add(name='context')(layers)
dense1 = Dense(50, name='Dense1',activation='relu')(context_layer)
dense2 = Dense(num_outputs, name='Output', activation='softmax')(dense1)
model = Model(inputs,dense2)
model.compile('sgd','categorical_crossentropy')
return model

然后像

input_cardinalities = [1,2,3]
num_outputs = 6
model = build_model(input_cardinalities, num_outputs)
model.summary()
plot_model(model, 'model.png', show_shapes=True)

输出如下所示

Model: "model_14"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input0 (InputLayer)             [(None, 1)]          0                                            
__________________________________________________________________________________________________
input1 (InputLayer)             [(None, 1)]          0                                            
__________________________________________________________________________________________________
input2 (InputLayer)             [(None, 1)]          0                                            
__________________________________________________________________________________________________
embedding0 (Embedding)          (None, 1, 20)        20          input0[0][0]                     
__________________________________________________________________________________________________
embedding1 (Embedding)          (None, 1, 20)        40          input1[0][0]                     
__________________________________________________________________________________________________
embedding2 (Embedding)          (None, 1, 20)        60          input2[0][0]                     
__________________________________________________________________________________________________
flatten0 (Flatten)              (None, 20)           0           embedding0[0][0]                 
__________________________________________________________________________________________________
flatten1 (Flatten)              (None, 20)           0           embedding1[0][0]                 
__________________________________________________________________________________________________
flatten2 (Flatten)              (None, 20)           0           embedding2[0][0]                 
__________________________________________________________________________________________________
context (Add)                   (None, 20)           0           flatten0[0][0]                   
flatten1[0][0]                   
flatten2[0][0]                   
__________________________________________________________________________________________________
Dense1 (Dense)                  (None, 50)           1050        context[0][0]                    
__________________________________________________________________________________________________
Output (Dense)                  (None, 6)            306         Dense1[0][0]                     
==================================================================================================
Total params: 1,476
Trainable params: 1,476
Non-trainable params: 0
__________________________________________________________________________________________________

为了获得更好的可视化效果,请参阅 此模型的 plot_model(( 返回

末尾缺少一个(input)

embedding =  Embedding(cardinality, 20, name='embedding{0}'.format(i))(input)

最新更新