如何将带有 boolean_mask 的蒙版应用于最后一个维度

how to apply mask with boolean_mask to the last dimensions

我正在尝试将三角形遮罩应用于张量的最后两个维度。

我正在做这样的事情:

a, b, c, d = 2, 2, 2, 2
tensor = tf.random.uniform((a, b, c, d))

lower_triangular = tf.linalg.band_part(tf.reshape(tf.ones((c, d)), shape=(1, 1, c, d)), -1, 0)

tf.boolean_mask(tensor, lower_triangular == 0)

最后一条指令失败,出现以下异常

/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/dispatch.py in wrapper(*args, **kwargs)
    199     """Call target, and fall back on dispatchers if there is a TypeError."""
    200     try:
--> 201       return target(*args, **kwargs)
    202     except (TypeError, ValueError):
    203       # Note: convert_to_eager_tensor currently raises a ValueError, not a

/usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/array_ops.py in boolean_mask_v2(tensor, mask, axis, name)
   1824   ```
   1825   """
-> 1826   return boolean_mask(tensor, mask, name, axis)
   1827 
   1828 

/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/dispatch.py in wrapper(*args, **kwargs)
    199     """Call target, and fall back on dispatchers if there is a TypeError."""
    200     try:
--> 201       return target(*args, **kwargs)
    202     except (TypeError, ValueError):
    203       # Note: convert_to_eager_tensor currently raises a ValueError, not a

/usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/array_ops.py in boolean_mask(tensor, mask, name, axis)
   1744     if axis_value is not None:
   1745       axis = axis_value
-> 1746       shape_tensor[axis:axis + ndims_mask].assert_is_compatible_with(shape_mask)
   1747 
   1748     leading_size = gen_math_ops.prod(shape(tensor)[axis:axis + ndims_mask], [0])

/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/tensor_shape.py in assert_is_compatible_with(self, other)
   1132     """
   1133     if not self.is_compatible_with(other):
-> 1134       raise ValueError("Shapes %s and %s are incompatible" % (self, other))
   1135 
   1136   def most_specific_compatible_shape(self, other):

ValueError: Shapes (2, 2, 2, 2) and (1, 1, 2, 2) are incompatible

如果我创建一个与我的张量形状完全相同的蒙版,我会得到一个奇怪的结果:

a, b, c, d = 2, 2, 2, 2
tensor = tf.random.uniform((a, b, c, d))

lower_triangular = tf.linalg.band_part(tf.ones((a, b, c, d)), -1, 0)

result = tf.boolean_mask(tensor, lower_triangular == 0)
result.shape

结果有一个形状 TensorShape([4]) 不确定这是在做什么。

正确的敷面膜方法是怎样的?

The result has a shape TensorShape([4]) not sure what is this doing.

你有一个像这样的张量:

   [[[[0.7786709 , 0.67790854],
     [0.72038054, 0.8475332 ]],

    [[0.945917  , 0.496732  ],
     [0.05510616, 0.44530773]]],


   [[[0.05596864, 0.59605396],
     [0.5459013 , 0.80567217]],

    [[0.1393286 , 0.74939907],
     [0.1695472 , 0.55127   ]]]]

还有这样的面具:

  [[[[False,  True],
     [False, False]],

    [[False,  True],
     [False, False]]],


   [[[False,  True],
     [False, False]],

    [[False,  True],
     [False, False]]]]

所以,你最终得到这样的结果:

[0.67790854, 0.496732  , 0.59605396, 0.74939907]

我们可以看到掩码“过滤”掉了掩码为假的所有值并使结果变平。

因此,如果掩码中 True 个值的总数为 n,并且您匹配了张量和掩码的尺寸,那么您最终会得到形状为 [n] 的张量。

我不清楚您对蒙版操作的期望结果是什么,但是,如果扁平化让您感到惊讶,那么听起来您可能只是想要这样的结果?:

  [[[[0.        , 0.67790854],
     [0.        , 0.        ]],

    [[0.        , 0.496732  ],
     [0.        , 0.        ]]],


   [[[0.        , 0.59605396],
     [0.        , 0.        ]],

    [[0.        , 0.74939907],
     [0.        , 0.        ]]]]

你可以通过乘以掩码得到它(当然,我们需要先投射它)。

也许是这样的:

tf.cast(lower_triangular == 0, tf.float32) * tensor

W.R.T原报错信息:

如果要应用与张量具有相同秩的掩码,则所有维度都需要相等。而您 可以 应用维数较少的掩码(我怀疑您正试图这样做)。

例如:

tf.boolean_mask(tensor, lower_triangular[0,0] == 0)

给出:

[[[0.945917  , 0.496732  ],
  [0.05510616, 0.44530773]]]

我们还可以控制 axis 掩码适用于哪个对象。所以,例如:

tf.boolean_mask(tensor, lower_triangular[0,0] == 0, axis=2)

returns:

[[[0.67790854],
  [0.496732  ]],

  [[0.59605396],
  [0.74939907]]]

蒙版应用于第 2 个轴(而不是默认第 0 个轴)

tf.boolean_mask(
    tensor, mask, axis=None, name='boolean_mask'
)

Numpy 等价于张量[mask]。

# 1-D example
tensor = [0, 1, 2, 3]
mask = np.array([True, False, True, False])
boolean_mask(tensor, mask)  # [0, 2]

一般来说,0 < dim(mask) = K <= dim(tensor),mask的形状必须匹配张量形状的前K维。然后我们有: boolean_mask(tensor, mask)[i, j1,...,jd] = tensor[i1,...,iK,j1,...,jd] 其中 (i1,...,iK) 是掩码的第 i 个 True 条目(row-major 顺序)。该轴可以与 mask 一起使用以指示要屏蔽的轴。在这种情况下,axis + dim(mask) <= dim(tensor) 和掩码的形状必须匹配张量形状的第一个轴 + dim(mask) 维度。

For more information.