如何仅平均张量中的非零条目?

nur*_*ric 5 python keras tensorflow

我遇到过一种情况,其中平均值包含填充值。X给定某种形状的张量(batch_size, ..., features),可能有零填充特征来获得相同的形状。

如何对X(特征)的最终维度进行平均,但仅对非零条目进行平均?因此,我们将总和除以非零条目的数量。

输入示例:

x = [[[[1,2,3], [2,3,4], [0,0,0]],
       [[1,2,3], [2,0,4], [3,4,5]],
       [[1,2,3], [0,0,0], [0,0,0]],
       [[1,2,3], [1,2,3], [0,0,0]]],
      [[[1,2,3], [0,1,0], [0,0,0]],
       [[1,2,3], [2,3,4], [0,0,0]],                                                         
       [[1,2,3], [0,0,0], [0,0,0]],                                                         
       [[1,2,3], [1,2,3], [1,2,3]]]]
# Desired output
y = [[[1.5 2.5 3.5]
      [2.  2.  4. ]
      [1.  2.  3. ]
      [1.  2.  3. ]]
     [[0.5 1.5 1.5]
      [1.5 2.5 3.5]
      [1.  2.  3. ]
      [1.  2.  3. ]]]
Run Code Online (Sandbox Code Playgroud)

小智 3

我无意中遇到了这个问题,并注意到唯一的解决方案有点过于复杂。我将为可能在这里绊倒的人发布一个替代解决方案。在大多数情况下,不需要创建专用的 keras 层。在 TF 2.X 中可以执行以下操作:

# data prep
import tensorflow as tf
x = [[[[1, 2, 3], [2, 3, 4], [0, 0, 0]],
      [[1, 2, 3], [2, 0, 4], [3, 4, 5]],
      [[1, 2, 3], [0, 0, 0], [0, 0, 0]],
      [[1, 2, 3], [1, 2, 3], [0, 0, 0]]],
     [[[1, 2, 3], [0, 1, 0], [0, 0, 0]],
      [[1, 2, 3], [2, 3, 4], [0, 0, 0]],
      [[1, 2, 3], [0, 0, 0], [0, 0, 0]],
      [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]
x = tf.convert_to_tensor(x, dtype=tf.float32)

# solution
non_zero = tf.cast(x != 0, tf.float32)
y = tf.reduce_sum(x, axis=-2) / tf.reduce_sum(non_zero, axis=-2)
Run Code Online (Sandbox Code Playgroud)

执行的操作与当前解决方案几乎相同,只是它使用内置的 TF 函数。该数组首先沿所需轴(倒数第二个)求和,然后除以沿该轴的非零元素计数。

对于此解决方案,如果沿维度的计数为零,则该元素的结果将为 NaN。