如何训练具有不同N维标签的LSTM模型?

时间:2017-08-16 23:49:32

标签: python tensorflow keras

我正在使用keras(带有TensorFlow后端的版本2.0.6)用于简单的神经网络:

model = Sequential()
model.add(LSTM(32, return_sequences=True, input_shape=(100, 5)))
model.add(LSTM(32, return_sequences=True)) 
model.add(TimeDistributed(Dense(5)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

这只是对我的一次测试,我正在使用以下虚拟数据“训练”模型。

x_train = np.array([
    [[0,0,0,0,1], [0,0,0,1,0], [0,0,1,0,0]],
    [[1,0,0,0,0], [0,1,0,0,0], [0,0,1,0,0]],
    [[0,1,0,0,0], [0,0,1,0,0], [0,0,0,1,0]],
    [[0,0,1,0,0], [1,0,0,0,0], [1,0,0,0,0]],
    [[0,0,0,1,0], [0,0,0,0,1], [0,1,0,0,0]],
    [[0,0,0,0,1], [0,0,0,0,1], [0,0,0,0,1]]
])

y_train = np.array([
    [[0,0,0,0,1], [0,0,0,1,0], [0,0,1,0,0]],
    [[1,0,0,0,0], [0,1,0,0,0], [0,0,1,0,0]],
    [[0,1,0,0,0], [0,0,1,0,0], [0,0,0,1,0]],
    [[1,0,0,0,0], [1,0,0,0,0], [1,0,0,0,0]],
    [[1,0,0,0,0], [0,0,0,0,1], [0,1,0,0,0]],
    [[1,0,0,0,0], [0,0,0,0,1], [0,0,0,0,1]]
])

然后我做:

model.fit(x_train, y_train, batch_size=2, epochs=50, shuffle=False)

print(model.predict(x_train))

结果是:

[[[ 0.11855114  0.13603994  0.21069065  0.28492314  0.24979511]
  [ 0.03013871  0.04114409  0.16499813  0.41659597  0.34712321]
  [ 0.00194826  0.00351031  0.06993906  0.52274817  0.40185428]]

 [[ 0.17915446  0.19629011  0.21316603  0.22450975  0.18687972]
  [ 0.17935558  0.1994358   0.22070852  0.2309722   0.16952793]
  [ 0.18571526  0.20774922  0.22724937  0.23079531  0.14849086]]

 [[ 0.11163659  0.13263632  0.20109797  0.28029731  0.27433187]
  [ 0.02216373  0.03424517  0.13683401  0.38068131  0.42607573]
  [ 0.00105937  0.0023865   0.0521594   0.43946937  0.50492537]]

 [[ 0.13276921  0.15531689  0.21852671  0.25823513  0.23515201]
  [ 0.05750636  0.08210614  0.22636817  0.3303588   0.30366054]
  [ 0.01128351  0.02332032  0.210263    0.3951444   0.35998878]]

 [[ 0.15303896  0.18197381  0.21823004  0.23647803  0.21027911]
  [ 0.10842207  0.15755147  0.23791778  0.26479205  0.23131666]
  [ 0.06472684  0.12843341  0.26680911  0.28923658  0.25079405]]

 [[ 0.19560908  0.20663913  0.21954383  0.21920268  0.15900527]
  [ 0.22829761  0.22907974  0.22933882  0.20822221  0.10506159]
  [ 0.27179539  0.25587022  0.22594844  0.18308094  0.063305  ]]]

好的,它有效,但它只是一个测试,我真的不关心准确性等。我想了解我如何使用不同大小的输出。

例如:传递一个序列(numpy.array),如:

[[0,0,0,0,1], [0,0,0,1,0], [0,0,1,0,0]]

我想将4维输出作为预测:

[[..first..], [..second..], [..third..], [..four..]]

这有可能吗?尺寸可能会有所不同我会用不同的标签训练模型,这些标签可以有不同的N维度。

由于

3 个答案:

答案 0 :(得分:2)

我不认识Keras,但从实践和理论的角度来看,这绝对是可能的。

这个想法是你有一个输入序列和一个输出序列。通常,每个序列的开始和结束由一些特殊符号界定(例如,字符序列“cat”被翻译成具有开始符号“^”和结束符号“#”的“^ cat#”)。然后用另一个特殊符号填充序列,最多最大序列长度(例如“^ cat#$$$$$$”,填充符号为“$”)。

如果填充符号对应于零向量,则它对您的训练没有影响。

您的输出序列现在可以假设任何长度达到最大长度,因为实际长度是从开始到结束符号位置的长度。

换句话说,您将始终具有相同的输入和输出序列长度(即最大值),但实际长度是起始符号和结束符号之间的长度。

(显然,在输出序列中,在丢失函数中不应考虑结束符号之后的任何内容)

答案 1 :(得分:2)

这个答案是针对不同的维度,但对于不同的维度,Giuseppe的答案中的填充想法似乎是可行的方法,可能借助于提出的"Masking"在Keras文档中。

Keras的输出形状完全取决于"单位/神经元/细胞的数量"你放在最后一层,当然还有层的类型。

我可以看到您的数据与您的问题中的代码不匹配,这是不可能的,但是,假设您的代码是正确的,并暂时忘记数据。

LSTM图层中的输入形状(100,5)表示形状(None, 100, 5)的张量,这是

  • None是批量大小。您的数据的第一维保留给您拥有的数量。 (X和Y必须具有相同数量的示例)。
  • 每个示例都是sequence with 100 time steps
  • 每个时间步长为5-dimension vector

同一LSTM层中的 32个单元意味着生成的向量将从5维向量变为32维向量。使用return_sequences=True时,所有100个时间步都将出现在结果中。所以第一层的结果形状是(None, 100, 32)

  • 相同数量的示例(这将永远不会改变模型)
  • 每个示例仍然是100个步骤(因为return_sequences=True
  • 每个时间步长是32维向量(因为32个单元格)

现在第二个LSTM图层完全相同。保持100个步骤,因为它还有32个单元格,保留32维向量,所以输出也是(None, 100, 32)

最后,分布式密集层的时间也将保持100次步长(因为TimeDistributed),并再次将向量更改为5维向量(因为{{1} }),导致5 units

如您所见,您不能直接使用循环图层更改时间步数,您需要使用其他图层来更改这些尺寸。而这样做的方式完全取决于你,有无限的方法可以做到这一点。

但是在所有这些中,您需要摆脱时间步长并使用其他形状重建数据。

建议

来自我的建议(这只是一种可能性)是重塑你的结果,并应用另一个密集层来实现最终的形状。

假设您想要(None, 100, 5)这样的结果(永远不要忘记,您的数据的第一个维度是示例的数量,它可以是任何数字,但您必须将其考虑在内当你整理数据时)。我们可以通过将数据重新整形为第二维中包含4的形状来实现这一目标:

(None, 4, 5)

这将为您提供4个时间步长(因为Reshape之后的尺寸为:(None,4,125),每个步骤都是5维向量(因为Dense(5))。

使用#after the Dense layer: model.add(Reshape((4,125)) #the batch size doesn't appear here, #just make sure you have 500 elements, which is 100*5 = 4*125 model.add(TimeDistributed(Dense(5)) #this layer could also be model.add(LSTM(5,return_sequences=True)), for instance #continue to the "Activation" layer 命令查看每个图层输出的形状。

答案 2 :(得分:0)

似乎有两种方法可以对序列进行排序方法,您需要进行描述。第一个直接使用keras使用this example(下面的代码)

from keras.layers import Input, LSTM, RepeatVector
from keras.models import Model

inputs = Input(shape=(timesteps, input_dim))
encoded = LSTM(latent_dim)(inputs)

decoded = RepeatVector(timesteps)(encoded)
decoded = LSTM(input_dim, return_sequences=True)(decoded)

sequence_autoencoder = Model(inputs, decoded)
encoder = Model(inputs, encoded)

重复向量重复初始时间序列n次以匹配输出向量的时间戳数。这仍然意味着您需要在输出向量中使用固定数量的时间步长,但是,可能有一种方法可以填充时间戳比最大时间步长少的向量。

或者你可以使用基于keras构建的seq2seq模块。