>>> 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
维度相加,这由于内存布局而更快。因此,我希望将结果转换为:
array([[ 0, 12],
[ 1, 13],
[ 2, 14]])
我该怎么做?我希望numpy的“高级索引”的结果是隐式转置。 1}}在结尾处明确转置它甚至更慢,不是一种选择。
Update1 :在现实世界中,高级索引是不可避免的,并且不保证下标是相同的。
.T
Update2 :为了澄清这不是XY problem,,这是实际问题:
我有一个大矩阵>>> x = [0, 0, 1]
>>> y = [0, 1, 1]
>>> X[x, y, :]
array([[ 0, 1, 2],
[ 3, 4, 5],
[12, 13, 14]])
,它包含来自某个概率分布的元素X
。元素的概率分布取决于元素的邻域。这个分布是未知的,所以我遵循Gibbs sampling过程来构建一个矩阵,该矩阵包含来自此分布的元素。简而言之,这意味着我对矩阵x
做了一些初步猜测,然后我继续迭代矩阵X
的元素,用一个取决于相邻值的公式更新每个元素X
x
。因此,对于矩阵的任何元素,我需要获取它的邻居(高级索引)并对它们执行一些操作(在我的示例中求和)。我使用x
来查看代码中占用大部分时间的行是使用与line_profiler
而不是0
相关的数组之和。因此,我想知道是否有一种方法可以通过高级索引生成已经转置的矩阵。
答案 0 :(得分:3)
我想在0维度上总结它,但在现实世界中,矩阵是巨大的,我更倾向于将它与-1维相加,这由于内存布局而更快。
我不完全确定你的意思。如果底层数组是行主要(默认值,即X.flags.c_contiguous == True
),那么它可能稍微更快,以便沿 0th 维度求和。简单地使用.T
或np.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
的完整副本,则无法执行此转换。除非您要在X
列上执行大量操作,否则几乎肯定不值得进行转换。
如果要将总和的结果存储在列主数组中,可以使用out=
kwarg到X.sum()
,例如:
result = np.empty((3, 3), order='F') # Fortran-order, i.e. column-major
X.sum(0, out=result)
在你的情况下,行与列之间的求和之间的差异可能是非常最小 - 但是 - 因为你已经要在X
索引非相邻元素,你将会已经失去了spatial locality of reference的好处,通常会在行上略微加快。
例如:
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)
比X.sum(0)
更快一行 - 主阵列。这似乎与他正在使用的numpy版本有关 - 使用v1.6.2我可以重现他观察到的顺序,但是使用两个较新的版本(v1.8.2和1.10.0.dev-8bcb756)我观察到相反的情况(即X.sum(0)
比X.sum(-1)
快一点。无论哪种方式,我都不认为更改阵列的内存顺序可能对OP的情况有很大帮助。