如何在TensorFlow中使用指定掩码对张量轴进行平均值处理

3
例如:
我有一个输入张量tensor(input),形状为(?,10)dtype=float32,第一个维度表示batch_size
还有一个掩码张量tensor(mask),形状为(?,10)mask[sample_number][True,True,False,...],表示掩码。
还有一个标签张量(avg_label),形状为(?,),表示每个样本掩码位置的正确平均值。
我想训练模型,但找不到一个好的方法来获得输出。 tf.reduce_...函数(例如tf.reduce_mean)似乎不支持关于掩码的参数。
我尝试了tf.boolean_mask,但它会将输出形状压缩成只有一个维度,抛弃了sample_number维度,因此无法区分样本。
我考虑使用tf.where,例如:
masked=tf.where(mask,input,tf.zeros(tf.shape(input)))
avg_out=tf.reduce_mean(masked,axis=1)
loss=tf.pow(avg_out-avg_label,2)

但是上面的代码肯定不起作用,因为将 False 设置为 0 会改变平均值。如果使用 np.nan,则始终会得到 nan。 我想知道在执行 reduce 操作时是否存在表示缺失的值。
我该如何做到这一点?

你的问题不够清楚。你有一个形状为(?, 10)的输入张量,一个形状为(?, 10)的掩码张量,你想要计算输入张量中那些mask=True的值的平均值,是这样吗? - layog
是的,这是意思。 - locys
3个回答

11
你可以使用tf.ragged.boolean_mask来保持维度。
tf.reduce_mean(tf.ragged.boolean_mask(x, mask=mask), axis=1)

5
您可以使用tf.boolean_mask
In [17]: tensor = tf.constant([[1, 2], [3, 4], [5, 6]])
In [18]: mask = np.array([[True, False], [False, True], [True, False]])
In [19]: masked = tf.boolean_mask(tensor, mask)
In [20]: masked.eval()
Out[20]: array([1, 4, 5], dtype=int32)
In [21]: tf.reduce_mean(masked).eval()
Out[21]: 3

对于虚假的掩码值,您可以使用tf.logical_not来切换掩码。


4
你可以通过计算掩码中非零条目的数量来编写自己的平均函数。
为什么不只是这样?
import tensorflow as tf
import numpy as np

B, H, W, C = 5, 224, 224, 3

data = np.random.randn(B, H, W, C).astype(np.float32)
mask = np.random.randint(2, size=(B, H, W, C)).astype(np.float32)

expected = (data * mask).sum(axis=(1, 2, 3), keepdims=True)
expected = expected / mask.sum(axis=(1, 2, 3), keepdims=True)

data_op = tf.convert_to_tensor(data)
mask_op = tf.convert_to_tensor(mask)

actual_op = tf.reduce_sum(tf.multiply(data, mask), axis=[1, 2, 3], keepdims=True) / tf.reduce_sum(mask, axis=[1, 2, 3], keepdims=True)

with tf.Session() as sess:
    actual = sess.run(actual_op)

np.testing.assert_allclose(actual, expected)

1
如果这不是讽刺的话,请随意接受它。否则,请相应地修改您的问题,以便您真正获得所需的信息。 - Patwie
我可以建议在填充上下文中使用tf.math.divide_no_nan。序列的结束部分可能在你要减少的维度上具有所有零值的掩码。 - generic_user

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接