我也需要这个答案,通过你问题底部的链接找到了所需信息。
简而言之,按照链接中的回答操作,但是如果你不想使用嵌入层,则“简单地”省略它。强烈建议阅读和理解
链接的答案,因为它详细介绍了此过程,并且在
遮蔽文档中有更多信息,但是这里是一个修改后的版本,它在序列输入上使用了遮蔽层来替换“sequence_length”:
import numpy as np
import tensorflow as tf
pad_value = 0.37
test_input = np.array(
[[[1., 1. ],
[2, 2. ],
[1., 1. ],
[pad_value, pad_value],
[pad_value, pad_value]],
[[pad_value, pad_value],
[1., 1. ],
[2, 2. ],
[1., 1. ],
[pad_value, pad_value]]])
mask = tf.keras.layers.Masking(mask_value=pad_value)
rnn = tf.keras.layers.GRU(
1,
return_sequences=True,
activation=None,
recurrent_activation=None,
kernel_initializer='ones',
recurrent_initializer='zeros',
use_bias=True,
bias_initializer='ones'
)
x = tf.keras.layers.Input(shape=test_input.shape[1:])
m0 = tf.keras.Model(inputs=x, outputs=rnn(x))
m1 = tf.keras.Model(inputs=x, outputs=mask(x))
m2 = tf.keras.Model(inputs=x, outputs=rnn(mask(x)))
print('raw inputs\n', test_input)
print('raw rnn output (no mask)\n', m0.predict(test_input).squeeze())
print('masked inputs\n', m1.predict(test_input).squeeze())
print('masked rnn output\n', m2.predict(test_input).squeeze())
输出:
raw inputs
[[[1. 1. ]
[2. 2. ]
[1. 1. ]
[0.37 0.37]
[0.37 0.37]]
[[0.37 0.37]
[1. 1. ]
[2. 2. ]
[1. 1. ]
[0.37 0.37]]]
raw rnn output (no mask)
[[ -6. -50. -156. -272.7276 -475.83362 ]
[ -1.2876 -9.862801 -69.314 -213.94202 -373.54672 ]]
masked inputs
[[[1. 1.]
[2. 2.]
[1. 1.]
[0. 0.]
[0. 0.]]
[[0. 0.]
[1. 1.]
[2. 2.]
[1. 1.]
[0. 0.]]]
masked rnn output
[[ -6. -50. -156. -156. -156.]
[ 0. -6. -50. -156. -156.]]
注意,应用掩码后,计算不会在掩码处于活动状态(即序列被填充的时间步)进行。相反,来自上一个时间步的状态被保留。
还有几点需要注意:
在链接的(以及此示例中),RNN是使用各种激活和初始化参数创建的。我认为这是为了初始化RNN以便在示例中重复使用。实际上,您可以按照自己的需求初始化RNN。
填充值可以是您指定的任何值。通常,使用零进行填充。在链接的(以及此示例中),使用0.37的值。我只能假设这是一个任意值,以显示原始和掩码RNN输出之间的差异,因为具有此示例RNN初始化的零输入值在输出中几乎没有区别,因此“一些”值(即0.37)演示了掩码的效果。
Masking 文档指出,仅当该时间步骤的所有值都包含掩码值时,才会对行/时间步骤进行掩码。例如,在上面的例子中,时间步长为
[0.37, 2]
的序列仍将使用这些值馈送到网络中,但时间步长为
[0.37, 0.37]
的序列将被跳过。
解决这个问题的另一种方法是批量训练不同长度的序列。例如,如果您有10、20和30个序列长度的混合序列长度,则可以将它们全部填充到30并进行掩码处理,或者使用所有10个序列长度进行训练,然后使用所有20个序列长度,再使用所有30个序列长度。或者,如果您有很多100个序列长度和很多3、4、5个序列长度,则可能希望将较小的序列填充到所有5个长度并使用100个和填充/掩码的5个长度进行两次训练。您可能会获得更快的训练速度,但代价是精度较低,因为您无法在不同序列长度的批次之间进行洗牌。
model.fit()
有一个固定的批量大小,对吧?如果不同长度的序列形成不同的批量大小怎么办? - ARATtrain_on_batch
)。最后一个维度 - 每个批次中每个项目的特征序列长度 - 对于RNN非常重要。每次调用fit()
都需要具有相同序列长度的批次。因此,您将把数据分成data_seq_len_1
和data_seq_len_2
,例如,并调用fit(data_seq_len_1)
和fit(data_seq_len_2)
(或者无论您如何向模型提供数据)。但是,正如您所看到的,数据不能在序列长度之间进行洗牌... - parrowdice