Numpy:高级索引的转置结果

2024-06-10 05:40:59 发布

您现在位置:Python中文网/ 问答频道 /正文

>>> import numpy as np
>>> X = np.arange(27).reshape(3, 3, 3)
>>> x = [0, 1]
>>> X[x, x, :]
array([[ 0,  1,  2],
       [12, 13, 14]])

我需要沿着0维求和,但在现实世界中,矩阵是巨大的,我更愿意沿着-1维求和,这是由于内存布局而更快的。因此,我希望将结果转置:

^{pr2}$

我该怎么做?我希望numpy的“高级索引”的结果被隐式地转置。在结尾用.T显式地转置它甚至更慢,而且不是一个选项。在

更新1:在现实世界中,高级索引是不可避免的,并且不能保证下标是相同的。在

>>> x = [0, 0, 1]
>>> y = [0, 1, 1]
>>> X[x, y, :]
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [12, 13, 14]])

更新2:为了澄清这不是XY problem,,实际问题是:

我有一个大矩阵X,它包含来自某种概率分布的元素x。元素的概率分布取决于元素的邻域。这个分布是未知的,所以我遵循Gibbs sampling过程来构建一个矩阵,其中包含来自这个分布的元素。简而言之,这意味着我对矩阵X做了一些初步的猜测,然后我不断迭代矩阵的元素X,用一个依赖于x相邻值的公式更新每个元素x。所以,对于矩阵的任何元素,我都需要得到它的邻居(高级索引)并对它们执行一些操作(在我的例子中是求和)。我使用line_profiler来查看代码中花费大部分时间的行是取数组相对于0而不是-1的和。因此,我想知道是否有一种方法来产生一个已经转置矩阵作为高级索引的结果。在


Tags: 内存importnumpy元素asnp世界矩阵
1条回答
网友
1楼 · 发布于 2024-06-10 05:40:59

I would like to sum it along the 0 dimension but in the real world the matrix is huge and I would prefer to be summing it along -1 dimension which is faster due to memory layout.

我不太清楚你说的是什么意思。如果底层数组是row major(默认值,即X.flags.c_contiguous == True),那么沿着0个维度求和可能会稍微快一些。简单地使用.Tnp.transpose()来转置数组本身并不会改变数组在内存中的布局方式。在

例如:

# X is row-major
print(X.flags.c_contiguous)
# True

# Y is just a transposed view of X
Y = X.T

# the indices of the elements in Y are transposed, but their layout in memory
# is the same as in X, therefore Y is column-major rather than row-major
print(Y.flags.c_contiguous)
# False

您可以从row major转换为column major,例如使用np.asfortranarray(X),但是如果不在内存中生成{}的完整副本,就无法执行此转换。除非要对X的列执行大量操作,否则几乎肯定不值得进行转换。在

如果要将求和的结果存储在列主数组中,可以使用out=kwarg来X.sum(),例如:

^{pr2}$

在您的例子中,行和列之间的差异可能非常小,但是-因为您已经在索引X中的非相邻元素,您将失去{a1}的好处,这通常会使行的求和速度稍微加快。在

例如:

X = np.random.randn(100, 100, 100)

# summing over whole rows is slightly faster than summing over whole columns
%timeit X.sum(0)
# 1000 loops, best of 3: 438 µs per loop
%timeit X.T.sum(0)
# 1000 loops, best of 3: 486 µs per loop

# however, the locality advantage disappears when you are addressing
# non-adjacent elements using fancy indexing
%timeit X[[0, 0, 1], [0, 1, 1], :].sum()
# 100000 loops, best of 3: 4.72 µs per loop
%timeit X.T[[0, 0, 1], [0, 1, 1], :].sum()
# 100000 loops, best of 3: 4.63 µs per loop

更新

@senderle在评论中提到,使用numpy v1.6.2时,他看到的计时顺序相反,即X.sum(-1)比row主数组的X.sum(0)快。这似乎与他正在使用的numpy版本有关-使用v1.6.2我可以复制他观察到的顺序,但是使用两个更新的版本(v1.8.2和1.10.0.dev-8bcb756)我观察到相反的情况(即X.sum(0)X.sum(-1)快一点)。不管怎样,我不认为改变数组的内存顺序对OP的情况有多大帮助。在

相关问题 更多 >