切片每个项目,除了每第n个

4

在TensorFlow中,使用切片符号[::n]可以选择每个第n个项目。

但是如何执行相反的操作?我想选择除了每个第n个之外的所有项目。

例如:

a = [1, 2, 3, 4, 5, 6, 7, 8]

a[2::3] 的结果是 [3, 6]

现在我想要相反的结果:[1, 2, 4, 5, 7, 8]

上面的数组只是一个例子。解决方案应该适用于 tensorflow 中维度为 [batch, width, height, channels] 的更大矩阵。选择仅在通道上完成。此外,我的矩阵包含非唯一的实值。我也无法将其重新调整为两个维度([batch, channels])以下。


1
正如答案所示,您可以构建一个列表(或布尔掩码)来保留项目。所得到的选择将是原始数据的副本。它不会是一个“视图”(这是::n会产生的)。 - hpaulj
3个回答

7

一种方法是通过测试区间索引来创建布尔索引:

import numpy as np
start, step = 2, 3
a[np.arange(len(a)) % step != start]
# array([1, 2, 4, 5, 7, 8])

您可以使用 tf.boolean_mask 在tensorflow中实现类似的功能:

import tensorflow as tf

a = tf.constant([1, 2, 3, 4, 5, 6, 7, 8])

start, step = 2, 3
mask = ~tf.equal(tf.range(a.shape[-1]) % step, start)

tf.boolean_mask(a, mask).eval()
# array([1, 2, 4, 5, 7, 8], dtype=int32)

如果 a 是一个 ND 张量,你可以使用 boolean_mask 来指定轴;例如对于 4D 张量 [batch, width, height, channels],要选择第四个轴,即 channels,你可以设置 axis=3:

mask = ~tf.equal(tf.range(a.shape[-1]) % step, start)
tf.boolean_mask(a, mask, axis=3)

tf.boolean_mask 的唯一问题是,最后一个维度是未知的( None )。我使用了 tensor.set_shape(...) 来解决这个问题(需要从我拥有的信息计算出新的形状)。 - Spenhouet

1
您可以使用np.delete()方法:
>>> np.delete(a, a[1::3])
array([1, 2, 4, 5, 7, 8])

请记住,此操作不会修改原始数组:

返回一个删除了沿轴的子数组的新数组。对于一维数组,这将返回arr[obj]未返回的条目。


抱歉,我的问题表述不够清晰。我只是在寻找tensorflow内部的解决方案。 - Spenhouet

1

对于一维的int类型数组,直接使用numpy.setdiff1d()即可。

In [16]: arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])

In [17]: np.setdiff1d(arr, arr[2::3])
Out[17]: array([1, 2, 4, 5, 7, 8])

对应的 TensorFlow 等效方法是 tf.setdiff1d()

为了处理n维数组(即张量),您可以首先将它们重塑为1D数组,使用setdiff1d进行选择,然后再将结果重塑回n维。


我无法将其重塑为两个维度以下(因为批处理)。我至少会有[批次,通道]作为维度。但更重要的是,我的矩阵包含实数值。tf.setdiff1d对此无效。 - Spenhouet

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