我正在处理时间序列,并且了解keras.layers.Masking
和keras.layers.Embedding
对于在网络中创建指示要"跳过"的时间步长的mask
值非常有用。mask
值在整个网络中传播,以供支持它的任何层使用。
Keras文档没有指定mask
值的任何进一步影响。我的期望是,在模型训练和评估中,口罩将应用于所有功能,但我看不到任何证据支持这一点。
mask
值是否影响反向传播mask
值是否影响损失函数或指标- 使用
model.compile()
中的sample_weight
参数来告诉Keras"忽略"loss函数中屏蔽的时间步长是明智还是愚蠢
我做了一些实验来回答这些问题。
这是我的示例代码:
import tensorflow as tf
import tensorflow.keras as keras
import numpy as np
# Fix the random seed for repeatable results
np.random.seed(5)
tf.random.set_seed(5)
x = np.array([[[3, 0], [1, 4], [3, 2], [4, 0], [4, 5]],
[[1, 2], [3, 1], [1, 3], [5, 1], [3, 5]]], dtype='float64')
# Choose some values to be masked out
mask = np.array([[False, False, True, True, True],
[ True, True, False, False, True]]) # True:keep. False:ignore
samples, timesteps, features_in = x.shape
features_out = 1
y_true = np.random.rand(samples, timesteps, features_out)
# y_true[~mask] = 1e6 # TEST MODIFICATION
# Apply the mask to x
mask_value = 0 # Set to any value
x[~mask] = [mask_value] * features_in
input_tensor = keras.Input(shape=(timesteps, features_in))
this_layer = input_tensor
this_layer = keras.layers.Masking(mask_value=mask_value)(this_layer)
this_layer = keras.layers.Dense(10)(this_layer)
this_layer = keras.layers.Dense(features_out)(this_layer)
model = keras.Model(input_tensor, this_layer)
model.compile(loss='mae', optimizer='adam')
model.fit(x=x, y=y_true, epochs=100, verbose=0)
y_pred = model.predict(x)
print("y_pred = ")
print(y_pred)
print("model weights = ")
print(model.get_weights()[1])
print(f"{'model.evaluate':>14s} = {model.evaluate(x, y_true, verbose=0):.5f}")
# See if the loss computed by model.evaluate() is equal to the masked loss
error = y_true - y_pred
masked_loss = np.abs(error[mask]).mean()
unmasked_loss = np.abs(error).mean()
print(f"{'masked loss':>14s} = {masked_loss:.5f}")
print(f"{'unmasked loss':>14s} = {unmasked_loss:.5f}")
哪个输出
y_pred =
[[[-0.28896046]
[-0.28896046]
[ 0.1546848 ]
[-1.1596009 ]
[ 1.5819632 ]]
[[ 0.59000516]
[-0.39362794]
[-0.28896046]
[-0.28896046]
[ 1.7996234 ]]]
model weights =
[-0.06686568 0.06484845 -0.06918766 0.06470951 0.06396528 0.06470013
0.06247645 -0.06492618 -0.06262784 -0.06445726]
model.evaluate = 0.60170
masked loss = 1.00283
unmasked loss = 0.90808
掩码和损失计算
令人惊讶的是,"mae"(平均绝对误差(损失计算并没有将屏蔽的时间步长排除在计算之外。相反,它假设这些时间步长没有损失——这是一个完美的预测。因此,每个屏蔽的时间步长实际上都减少了计算的损失
更详细地解释:上面的示例代码输入x
有10个时间步长。其中4个被掩模移除,因此保留6个有效时间步长。"平均绝对误差"损失计算将6个有效时间步长的损失相加,然后除以10,而不是除以6。这在我看来像个bug。
输出值被屏蔽
屏蔽时间步长的输出值不会影响模型训练或评估(应该如此(
这可以通过设置来轻松测试:y_true[~mask] = 1e6
模型权重、预测和损失保持完全相同。
输入值被屏蔽
屏蔽时间步长的输入值不会影响模型训练或评估(应该如此(
类似地,我可以将mask_value
从0更改为任何其他数字,得到的模型权重、预测和损失保持完全相同。
总之:
Q1:实际上是的-掩码影响损失函数,该函数通过反向传播用于更新权重
Q2:是的,但面具以一种意想不到的方式影响了损失
Q3:最初是愚蠢的-掩码应该已经应用于损失计算。然而,sample_weights
可能对纠正意外的损失计算方法有价值。。。
请注意,我使用的是Tensorflow 2.7.0。
我一直在努力解决一个相关的问题,即实现多输出模型的掩码,其中一些样本缺少不同输出的标签。这里,从数据集中构造特征、标签、sample_weights,标签和sample_weight是具有等效键的字典。每个样本的权重为0,1,表明其是否有助于相关损失的计算。
我曾希望sample_weights会对损失产生影响,就像我通过model.compile 中的weight_metrics传递损失的度量当量一样
我发现sample_weight似乎不能解决这个问题。我可以从训练度量中看出,当使用样本权重时,task_loss值与task_metric值不同。
我已经放弃了这一点,决定继续使用口罩。在你的情况下(在我的情况下(,掩蔽损失值很低,因为tensorflow认为建模的输出是完美的——我希望这意味着它看不到这些点的梯度,因此参数不会相应调整。