我正在将一堆Numpy计算移植到TensorFlow。在我计算的一个阶段,我使用布尔掩码从大数组中提取和展平值的子集。数组可以有许多维度,但布尔掩码仅作用于最后两个维度。在Numpy中,它看起来像这样:
mask = np.array([
[False, True , True , True ],
[True , False, True , True ],
[True , True , False, False],
[True , True , False, False]]
large_array_masked = large_array[..., mask]
我无法弄清楚如何在TensorFlow中完成相同的操作。我试过了:
tf.boolean_mask(large_array, mask, axis = -2)
这不起作用,因为tf.boolean_mask()
似乎没有采用负轴参数。
作为一个丑陋的黑客,我试图强制mask
使用以下内容广播到与large_array
相同的形状:
mask_broadcast = tf.logical_and(tf.fill(tf.shape(large_array), True), mask)
large_array_masked = tf.boolean_mask(large_array, mask_broadcast)
似乎mask_broadcast
具有我想要的形状和值,但我收到错误:
ValueError: Number of mask dimensions must be specified, even if some dimensions are None
推测会发生这种情况,因为large_array
是根据输入计算的,因此其形状不是静态的。
有什么建议吗?
答案 0 :(得分:1)
一般来说,我发现在tensorflow中你需要知名的形状。这是因为大多数操作都是矩阵乘法,矩阵是固定的形状。
如果你真的想这样做,你需要转换为稀疏张量,然后应用tf.sparse_retain
。
等同于"我通常在tensorflow中使用的是将掩码与large_array乘以False值(large_array_masked = large_array * mask
)。这保持了原始形状,因此更容易传递到密集层等...
答案 1 :(得分:1)
我想出了一个解决我的狭隘问题的黑客,所以我在这里发帖,但是我接受了@Sorin的回答,因为它可能更普遍适用。
为了解决tf.boolean_mask()
只能对初始索引起作用的事实,我只是向前滚动索引,应用掩码,然后将它们回滚。以简化形式,它看起来像这样:
indices = tf.range(tf.rank(large_array))
large_array_rolled_forward = tf.transpose(
large_array,
tf.concat([indices[-2:], indices[:-2]], axis=0))
large_array_rolled_forward_masked = tf.boolean_mask(
large_array_rolled_forward,
mask)
new_indices = tf.range(tf.rank(large_array_rolled_forward_masked))
large_array_masked = tf.transpose(
large_array_rolled_forward_masked,
tf.concat([new_indices[1:], [0]], axis=0))