【问题标题】:Keras multi-output data reshape for LSTM model用于 LSTM 模型的 Keras 多输出数据重塑
【发布时间】:2019-07-26 23:15:54
【问题描述】:

我有一个包含多个输出的 Keras LSTM 模型。 模型定义如下:

outputs=[]

main_input = Input(shape= (seq_length,feature_cnt), name='main_input')
lstm = LSTM(32,return_sequences=True)(main_input)
for _ in range((output_branches)): #output_branches is the number of output branches of the model
    prediction = LSTM(8,return_sequences=False)(lstm)
    out = Dense(1)(prediction)
    outputs.append(out)

model = Model(inputs=main_input, outputs=outputs)
model.compile(optimizer='rmsprop',loss='mse')    

我在重塑输出数据时遇到了问题。 重塑输出数据的代码是:

y=y.reshape((len(y),output_branches,1))

我收到以下错误:

ValueError: 检查模型目标时出错:Numpy 数组列表 您传递给模型的大小不是模型预期的大小。 预计会看到 5 个数组,但得到了以下 1 个列表 数组:[数组([[[0.29670931], [0.16652206], [0.25114482], [0.36952324], [0.09429612]],

   [[0.16652206],
    [0.25114482],
    [0.36952324],
    [0.09429612],...

如何正确重塑输出数据?

【问题讨论】:

    标签: python keras lstm


    【解决方案1】:

    这取决于y 最初的结构。这里我假设y是批量每个序列的单值标签。

    当有多个输入/输出时,model.fit() 期望给出相应的输入/输出列表。 np.split(y, output_branches, axis=-1) 在以下完全可重现的示例中正是这样做的 - 对于每个批次,将单个输出列表拆分为单独的输出列表,其中每个输出(在这种情况下)是 1 元素列表:

    import tensorflow as tf
    import numpy as np
    
    tf.enable_eager_execution()
    
    batch_size = 100
    seq_length = 10
    feature_cnt = 5
    output_branches = 3
    
    # Say we've got:
    # - 100-element batch
    # - of 10-element sequences
    # - where each element of a sequence is a vector describing 5 features.
    X = np.random.random_sample([batch_size, seq_length, feature_cnt])
    
    # Every sequence of a batch is labelled with `output_branches` labels.
    y = np.random.random_sample([batch_size, output_branches])
    # Here y.shape() == (100, 3)
    
    # Here we split the last axis of y (output_branches) into `output_branches` separate lists.
    y = np.split(y, output_branches, axis=-1)
    # Here y is not a numpy matrix anymore, but a list of matrices.
    # E.g. y[0].shape() == (100, 1); y[1].shape() == (100, 1) etc...
    
    outputs = []
    
    main_input = tf.keras.layers.Input(shape=(seq_length, feature_cnt), name='main_input')
    lstm = tf.keras.layers.LSTM(32, return_sequences=True)(main_input)
    for _ in range(output_branches):
        prediction = tf.keras.layers.LSTM(8, return_sequences=False)(lstm)
        out = tf.keras.layers.Dense(1)(prediction)
        outputs.append(out)
    
    model = tf.keras.models.Model(inputs=main_input, outputs=outputs)
    model.compile(optimizer='rmsprop', loss='mse')
    
    model.fit(X, y)
    

    您可能需要使用坐标轴,因为您没有指定数据的具体外观。

    编辑: 由于作者正在从官方来源寻找答案,因此提到了here(虽然没有明确,它只提到数据集应该产生什么,因此 - model.fit() 期望什么样的输入结构):

    当使用 Dataset 对象调用 fit 时,它应该产生像 ([title_data, body_data, tags_data], [priority_targets, dept_targets]) 这样的列表元组或像 ({'title': title_data, 'body': body_data, 'tags': tags_data}, {'priority': priority_targets, 'department': dept_targets}) 这样的字典元组。

    【讨论】:

      【解决方案2】:

      由于您的输出数量等于output_branches,因此您的输出数据必须是具有相同数量数组的list

      基本上,如果输出数据在您的reshape 建议的中间维度:

      y = [ y[:,i] for i in range(output_branches)]   
      

      【讨论】: