当每个批次中的观察值具有不同数量的缺失值时使用 Keras 掩蔽层
Using Keras Masking Layer when observations in each batch have different numbers of missing values
我正在使用 Keras 为具有不同长度的序列构建 RNN。我用值 -99 填充了每个序列的缺失值(我没有使用 0,因为这在我的数据集中是一个有意义的值)。模型定义如下:
model = keras.models.Sequential([
keras.layers.Masking(mask_value=-99, input_shape=(n_lags, n_input_vars)),
keras.layers.LSTM(64, return_sequences=True),
keras.layers.LSTM(16),
keras.layers.Dense(3)
])
model.compile(loss="mse", optimizer="adam")
history = model.fit(X_train, y_train, epochs=50, validation_data=(X_val, y_val), batch_size=100)
训练集已被分成 100 个观察值的块。每个批次可能包含不同长度的观察(序列),例如:
序列 1: [0, 1, 3], [-99, -99, -99], [-99, -99, -99]
序列 2: [1, 5, 9], [6, 7, 10], [-99, -99, -99]
.....
序列 100:[8、7、4]、[-99、-99、-99]、[-99、-99、-99]
Keras Masking 层是否允许这种情况,即批处理中的观察结果的序列长度不同?或者我是否需要为每个观察构建具有相同缺失输入值的批次?
我相信 LSTM 可以识别序列中的哪些时间点应该被忽略,因为它理解掩蔽层提供的信息,而且每个序列(在批次中)可以有不同数量的有效时间点,就像你的例子。此处提供更多信息:https://www.tensorflow.org/guide/keras/masking_and_padding。希望对您有所帮助。
@ad2004 只是部分正确,因为 return_sequence = True 的 LSTM 可以正确传播掩码,但是,第二个 LSTM 层(默认 return_sequence = False)将丢失掩码.所以掩码实际上永远不会传播到输出层,因此损失仍将包括填充数据(但当然,掩码层将 -99 变为 0,只是损失仍将包括填充值的部分)。为了验证这一点,我们可以简单地打印出每一层的 input_mask 和 output_mask,如果是 None 则表示没有遮罩。
for i, l in enumerate(model.layers):
print(f'layer {i}: {l}')
print(f'has input mask: {l.input_mask}')
print(f'has output mask: {l.output_mask}')
layer 0: <tensorflow.python.keras.layers.core.Masking object at 0x6675b2f98>
has input mask: None
has output mask: Tensor("masking_7/Identity_1:0", shape=(None, 30), dtype=bool)
layer 1: <tensorflow.python.keras.layers.recurrent_v2.LSTM object at 0x66537f278>
has input mask: Tensor("masking_7/Identity_1:0", shape=(None, 30), dtype=bool)
has output mask: Tensor("masking_7/Identity_1:0", shape=(None, 30), dtype=bool)
layer 2: <tensorflow.python.keras.layers.recurrent_v2.LSTM object at 0x6676b4588>
has input mask: Tensor("masking_7/Identity_1:0", shape=(None, 30), dtype=bool)
has output mask: None
layer 3: <tensorflow.python.keras.layers.core.Dense object at 0x6676b6240>
has input mask: None
has output mask: None
我正在使用 Keras 为具有不同长度的序列构建 RNN。我用值 -99 填充了每个序列的缺失值(我没有使用 0,因为这在我的数据集中是一个有意义的值)。模型定义如下:
model = keras.models.Sequential([
keras.layers.Masking(mask_value=-99, input_shape=(n_lags, n_input_vars)),
keras.layers.LSTM(64, return_sequences=True),
keras.layers.LSTM(16),
keras.layers.Dense(3)
])
model.compile(loss="mse", optimizer="adam")
history = model.fit(X_train, y_train, epochs=50, validation_data=(X_val, y_val), batch_size=100)
训练集已被分成 100 个观察值的块。每个批次可能包含不同长度的观察(序列),例如:
序列 1: [0, 1, 3], [-99, -99, -99], [-99, -99, -99]
序列 2: [1, 5, 9], [6, 7, 10], [-99, -99, -99]
.....
序列 100:[8、7、4]、[-99、-99、-99]、[-99、-99、-99]
Keras Masking 层是否允许这种情况,即批处理中的观察结果的序列长度不同?或者我是否需要为每个观察构建具有相同缺失输入值的批次?
我相信 LSTM 可以识别序列中的哪些时间点应该被忽略,因为它理解掩蔽层提供的信息,而且每个序列(在批次中)可以有不同数量的有效时间点,就像你的例子。此处提供更多信息:https://www.tensorflow.org/guide/keras/masking_and_padding。希望对您有所帮助。
@ad2004 只是部分正确,因为 return_sequence = True 的 LSTM 可以正确传播掩码,但是,第二个 LSTM 层(默认 return_sequence = False)将丢失掩码.所以掩码实际上永远不会传播到输出层,因此损失仍将包括填充数据(但当然,掩码层将 -99 变为 0,只是损失仍将包括填充值的部分)。为了验证这一点,我们可以简单地打印出每一层的 input_mask 和 output_mask,如果是 None 则表示没有遮罩。
for i, l in enumerate(model.layers):
print(f'layer {i}: {l}')
print(f'has input mask: {l.input_mask}')
print(f'has output mask: {l.output_mask}')
layer 0: <tensorflow.python.keras.layers.core.Masking object at 0x6675b2f98>
has input mask: None
has output mask: Tensor("masking_7/Identity_1:0", shape=(None, 30), dtype=bool)
layer 1: <tensorflow.python.keras.layers.recurrent_v2.LSTM object at 0x66537f278>
has input mask: Tensor("masking_7/Identity_1:0", shape=(None, 30), dtype=bool)
has output mask: Tensor("masking_7/Identity_1:0", shape=(None, 30), dtype=bool)
layer 2: <tensorflow.python.keras.layers.recurrent_v2.LSTM object at 0x6676b4588>
has input mask: Tensor("masking_7/Identity_1:0", shape=(None, 30), dtype=bool)
has output mask: None
layer 3: <tensorflow.python.keras.layers.core.Dense object at 0x6676b6240>
has input mask: None
has output mask: None