Python 如何在Tensorflow 2 LSTM培训中屏蔽多输出?

Python 如何在Tensorflow 2 LSTM培训中屏蔽多输出?,python,numpy,tensorflow,keras,lstm,Python,Numpy,Tensorflow,Keras,Lstm,我正在Tensorflow 2中训练一个LSTM模型来预测两个输出,流量和水温 对于某些时间步,有一个流量标签和一个温度标签 对于某些情况,只有流量标签或温度标签 对一些人来说,两者都不是 因此,当没有标签时,损失函数需要忽略温度和流量损失。我已经阅读了很多TF文档,但是我很难找到最好的方法 到目前为止我已经试过了 在编译模型时指定sample\u weight\u mode='temporal',然后在调用fit 当我这样做时,我得到一个错误,要求我传递一个2D数组。但这让我很困惑,因

我正在Tensorflow 2中训练一个LSTM模型来预测两个输出,流量和水温

  • 对于某些时间步,有一个流量标签和一个温度标签
  • 对于某些情况,只有流量标签温度标签
  • 对一些人来说,两者都不是
因此,当没有标签时,损失函数需要忽略温度和流量损失。我已经阅读了很多TF文档,但是我很难找到最好的方法

到目前为止我已经试过了

  • 在编译模型时指定
    sample\u weight\u mode='temporal'
    ,然后在调用
    fit
当我这样做时,我得到一个错误,要求我传递一个2D数组。但这让我很困惑,因为有三个维度:
n_样本
sequence_长度
,以及
n_输出

以下是我基本上要做的一些代码:

将tensorflow导入为tf
将numpy作为np导入
#建立模型
简单模型=tf.keras.models.Sequential([
tf.keras.layers.LSTM(8,返回序列=True),
tf.keras.致密层(2)
])
simple_lstm_model.compile(优化器='adam',loss='mae',
样本(重量模式=‘时间’)
n_样本=2
序号=10
n_feat=5
n_out=2
#随机输入/输出
x=np.random.randn(n_样本,序列,n_专长)
y_true=np.random.randn(n_样本,序号,n_out)
#将初始遮罩设置为所有遮罩(所有遮罩的计数相等)
掩码=np.ones([n_样本,序号,n_输出])
#设置遮罩,以便在第0个样本中,在第3-8个时间步中
#损失函数中不计算第1个变量
掩码[0,3:8,1]=0
简单的模型。拟合(x,y为真,样本重量=掩码)
错误:

ValueError: Found a sample_weight array with shape (2, 10, 2). In order to use timestep-wise sample weighting, you should
pass a 2D sample_weight array.
有什么想法吗?我不能理解
sample\u weights
做了什么,因为对我来说,只有当
sample\u weights
数组与输出具有相同的维度时,它才有意义。我可以编写一个自定义丢失函数并手动处理掩蔽,但似乎应该有一个更通用或内置的解决方案。

1<代码>样本重量 是的,你理解错了。在这种情况下,您有
2个
samples,
10个
timesteps,每个
5个
功能。您可以像这样传递
2D
张量,这样每个样本的每个时间步对总损失的贡献都不同,所有特征的权重相等(通常情况下)

那根本不是你想要的。您希望在计算后掩盖某些损失值,使其不起作用

2.海关损失 一个可能的解决方案是实现自己的损失函数,在取
平均值
总和
之前,将损失张量乘以掩码

基本上,您将
掩码
张量
以某种方式连接在一起,并将其拆分为函数以供使用。这就足够了:

def my_loss_function(y_true_mask, y_pred):
    # Recover y and mask
    y_true, mask = tf.split(y_true_mask, 2)
    # You could user reduce_sum or other combinations
    return tf.math.reduce_mean(tf.math.abs(y_true - y_pred) * mask)
现在,您的代码(不需要加权):

所以它是有效的。您也可以用其他方式堆叠这些值,但我希望您能感受到如何做到这一点

3.掩蔽输出 请注意上面介绍的几个问题。如果你有很多零并且取
mean
,你可能会得到一个非常小的损失值并抑制学习。另一方面,如果你使用
sum
,它可能会爆炸

simple_lstm_model = tf.keras.models.Sequential(
    [tf.keras.layers.LSTM(8, return_sequences=True), tf.keras.layers.Dense(2)]
)

simple_lstm_model.compile(optimizer="adam", loss=my_loss_function)

n_sample = 2
seq_len = 10
n_feat = 5
n_out = 2

x = np.random.randn(n_sample, seq_len, n_feat)
y_true = np.random.randn(n_sample, seq_len, n_out)

mask = np.ones([n_sample, seq_len, n_out])
mask[0, 3:8, 1] = 0

# Stack y and mask together
y_true_mask = np.stack([y_true, mask])

simple_lstm_model.fit(x, y_true_mask)