Python 如何将[2,3,4]转换为[0,0,1,1,1,2,2,2],以利用tf.math.segment_sum?

Python 如何将[2,3,4]转换为[0,0,1,1,1,2,2,2],以利用tf.math.segment_sum?,python,numpy,tensorflow,Python,Numpy,Tensorflow,假设我有一个像[2,3,4]这样的数组,我正在寻找一种在NumPy(或Tensorflow)中将其转换为[0,0,1,1,1,2,2,2]的方法,以便对大小为2+3+4的张量应用tf.math.segment_sum() 我脑子里没有优雅的想法,只有循环和列表理解。你喜欢这个工作吗 import numpy arr = numpy.array([2, 3, 4]) numpy.repeat(numpy.arange(arr.size), arr) # array([0, 0, 1, 1, 1,

假设我有一个像[2,3,4]这样的数组,我正在寻找一种在NumPy(或Tensorflow)中将其转换为[0,0,1,1,1,2,2,2]的方法,以便对大小为2+3+4的张量应用tf.math.segment_sum()


我脑子里没有优雅的想法,只有循环和列表理解。

你喜欢这个工作吗

import numpy
arr = numpy.array([2, 3, 4])
numpy.repeat(numpy.arange(arr.size), arr)
# array([0, 0, 1, 1, 1, 2, 2, 2, 2])
使用Numpy,但实际上更快(至少在示例列表中)

我会把这个答案作为另一个解决方案,但它比两者都慢

考虑到
a=[2,3,4]
这可以使用如下循环完成:

b=[]
对于范围内的i(len(a)):
对于范围(a[i])内的j:
b、 附加(范围(len(a))[i])
作为一句台词,这是一件邪恶的事情:

b=[range(len(a))[i]表示范围内的i(len(a))表示范围内的j(a[i])]

两者都以
b=[0,0,1,1,1,2,2,2]
结束,您不需要使用numpy。您只能使用列表理解:

>>> foo = [2,3,4]
>>> sum([[i]*foo[i] for i in range(len(foo))], [])
[0, 0, 1, 1, 1, 2, 2, 2, 2]
它的工作原理如下:

您可以通过将简单数组乘以常数来创建扩展数组,因此
[0]*2
==
[0,0]
。因此,对于数组中的每个索引,我们用
[i]*foo[i]
展开。换言之:

>>> [[i]*foo[i] for i in range(len(foo))]
[[0, 0], [1, 1, 1], [2, 2, 2, 2]]
然后我们使用
sum
将列表缩减为单个列表:

>>> sum([[i]*foo[i] for i in range(len(foo))], [])
[0, 0, 1, 1, 1, 2, 2, 2, 2]
因为我们是“求和”列表,而不是整数,所以我们将
[]
传递到
sum
以使空列表成为求和的起始值


(请注意,这可能比numpy慢,尽管我个人没有将其与@Patol75的答案进行比较。)

我非常喜欢@Patol75的答案,因为它很简洁。然而,目前还没有纯张量流解,所以我提供了一个可能有点复杂的解。仅供参考和娱乐

顺便说一句,我没有看到tf。在tf主机中重复这个API。请检查此选项,它添加了与
numpy.repeat
等效的
tf.repeat
支持

将tensorflow导入为tf
重复次数=tf常数([2,3,4])
值=tf.range(tf.size(repeats))#[0,1,2]
max_repeats=tf。reduce_max(repeats)#max repeat为4
平铺=tf.平铺(tf.重塑(值,[-1,1]),[1,最大重复次数]#[[0,0,0,0],[1,1,1],[2,2,2]]
掩码=tf.序列掩码(重复,最大重复)#[[1,1,0,0],[1,1,1,0],[1,1,1,0],[1,1,1]]
res=tf.boolean_掩码(平铺,掩码)#[0,0,1,1,1,2,2]

您所展示的内容可以通过标准库完成。您能否进一步解释为什么必须使用numpy或tensorflow执行此操作?循环和列表理解有什么不雅观之处?numpy在性能上更受欢迎,因为这将在非常大的阵列上执行。但我很乐意看到如何用标准库来实现这一点。这将是一个有趣的代码高尔夫!我不知道您可以将
[]
传递到
sum()
以生成列表-我喜欢它:-)我确实想知道它是否太“聪明”,在这种情况下,你应该直接使用reduce:
reduce(lambda,b:a+b,([I]*foo[I]for I in range(len(foo)))
你的比我的快得多;默认情况下,你的答案是0.848秒,我的答案是3.251秒。我相信你的答案也比Patol75的答案快得多,Patol75的答案是2.579秒。对于给定的数据,也许。我怀疑如果阵列很大,他们的速度会更快。