首页 > 解决方案 > 应在至少 2 个输入的列表上调用“连接”层

问题描述

我创建了一个模型,它接受一个输入层并产生两个输出层。

 model = Model(inputs=efficient_net.input, outputs=[reg_pred, class_pred])

我正在训练模型,接收结果并将 2 个模型实例保存在两个 .h5 文件中。

然后,我将 2 个模型放在一个列表中:

model_weights = []
for item in os.listdir(packages_root):
    if ".h5" in item:
        model_weights.append(item)

所以我有['model_2.h5', 'model_1.h5']

现在,我正在尝试合奏:

def ensemble(models, model_input):
    
    Models_output = [model(model_input) for model in models]
    Avg = Average()(Models_output)
    
    ensemble = Model(inputs=model_input, outputs=Avg, name='ensemble')
    ensemble.summary()
    ensemble.compile(Adam(lr=.0001), loss=loss, metrics=metrics)
    
    return ensemble

然后我这样做:

model_input = Input(shape=models[0].input_shape[1:])

这使 :<KerasTensor: shape=(None, 32, 32, 3) dtype=float32 (created by layer 'input_12')>

和:

ensemble_model = ensemble(models, model_input)

这给了我:

ValueError: A merge layer should be called on a list of inputs.

上线:Avg = Average()(Models_output)

所以,我想做:

def ensemble(models, model_input):
    
    Models_output = []
    for model in models:
        Models_output.append(model(model_input))
        
    # Concatenate the 2 output layers
    Conc = Concatenate()([Models_output[0], Models_output[1])
    Avg = Average()(Conc)
    
    ensemble = Model(inputs=model_input, outputs=Avg, name='ensemble')
    ensemble.summary()
    ensemble.compile(Adam(lr=.0001), loss=loss, metrics=metrics)
    
    return ensemble

现在给了我:

ValueError: A 连接 layer should be called on a list of at least 2 inputs

请注意,print(Models_output), 给出:

[[<KerasTensor: shape=(None, 4) dtype=float32 (created by layer 'model_1')>, <KerasTensor: shape=(None, 2) dtype=float32 (created by layer 'model_1')>],

 [<KerasTensor: shape=(None, 4) dtype=float32 (created by layer 'model_2')>, <KerasTensor: shape=(None, 2) dtype=float32 (created by layer 'model_2')>]]

标签: pythontensorflowmachine-learningkerasdeep-learning

解决方案


错误是因为您Average在列表列表而不是张量列表上调用层。这是因为您的模型产生 2 个输出 ( reg_pred, class_pred)。

您可以通过简单地构建 2 层来解决问题Average:一层用于 reg 输出,另一层用于类输出

这是一个虚拟示例,我们拟合 2 个模型以产生 2 个输出:

X = np.random.uniform(0,1, (64,28,28,1))
y = np.random.randint(0,2, 64)

def get_model():
    inp = Input((28,28,1))
    reg_pred = Dense(1)(inp)
    class_pred = Dense(2, activation='softmax')(Flatten()(inp))
    model = Model(inp, [reg_pred, class_pred])
    model.compile('adam', ['mse', 'sparse_categorical_crossentropy'])
    return model

model1 = get_model()
model1.fit(X,[X,y])
model2 = get_model()
model2.fit(X,[X,y])

您的合奏函数会产生错误:

def ensemble(models, model_input):
    
    Models_output = [model(model_input) for model in models]
    Avg = Average()(Models_output)
    
    ensemble = Model(inputs=model_input, outputs=Avg, name='ensemble')
    ensemble.compile('adam', ['mse', 'sparse_categorical_crossentropy'])
    
    return ensemble

model_input = Input((28,28,1))
models = [model1, model2]
model_ensemble = ensemble(models, model_input)

如何修复它:

def ensemble(models, model_input):
    
    output_reg = []
    output_class = []
    for model in models:
        out_reg, out_class = model(model_input)
        output_reg.append(out_reg)
        output_class.append(out_class)
    avg_reg = Average()(output_reg)
    avg_class = Average()(output_class)
    
    ensemble = Model(inputs=model_input, outputs=[avg_reg, avg_class], name='ensemble')
    ensemble.compile('adam', ['mse', 'sparse_categorical_crossentropy'])
    
    return ensemble

model_input = Input((28,28,1))
models = [model1, model2]
model_ensemble = ensemble(models, model_input)

推荐阅读