python numpy np_python – numpy np.apply_along_axis功能加快?

np.apply_along_axis不速度.

没有办法将纯Python函数应用于Numpy数组的每个元素,而不需要多次调用,而不是AST重写.

幸运的是有解决方案:

>矢量化

虽然这通常很困难,但通常是一个简单的解决方案.找到某种方式来表达您的计算方式,以推广这些元素,所以您可以一次在整个矩阵上工作.这将导致循环从Python中升级,并进行大量优化的C和Fortran例程.

> JITing:Numba和Parakeet,在较小程度上PyPy与NumPyPy

Numba和Parakeet都处理了Numpy数据结构中的JITing循环,所以如果你将循环内联到一个函数(这可以是一个包装函数),你可以获得大幅度的加速提升几乎免费.这取决于所使用的数据结构.

>象征评估者,如Theano和numexpr

这些允许您使用嵌入式语言来表达计算,这可能比矢量化版本更快.

> Cython和C扩展

如果所有的东西都丢失了,你可以随时手动挖掘C. Cython隐藏了很多复杂性,并且还有很多可爱的魔法,所以并不总是那么糟糕(尽管它有助于知道你在做什么).

干得好.

这是我的测试“环境”(你应该真的提供这个:P):

import itertools

import numpy

a = numpy.arange(200).reshape((200,1)) ** 2

def my_func(a, i,j):

b = numpy.zeros((2,2))

b[0,0] = a[i]

b[1,0] = a[i]

b[0,1] = a[i]

b[1,1] = a[j]

return numpy.linalg.eigh(b)

eigvals = {}

eigvecs = {}

for i, j in itertools.combinations(range(a.size), 2):

eigvals[i, j], eigvecs[i, j] = my_func(a,i,j)

现在,更容易得到所有的排列而不是组合,因为你可以这样做:

# All *permutations*, not combinations

indexes = numpy.mgrid[:a.size, :a.size]

这可能看起来很浪费,但只有两倍的排列,所以这不是一个大问题.

所以我们要使用这些索引来获取相关元素:

# Remove the extra dimension; it's not wanted here!

subs = a[:,0][indexes]

然后我们可以使我们的矩阵:

target = numpy.array([

[subs[0], subs[0]],

[subs[0], subs[1]]

])

我们需要矩阵在最后两个维度:

target.shape

#>>> (2, 2, 200, 200)

target = numpy.swapaxes(target, 0, 2)

target = numpy.swapaxes(target, 1, 3)

target.shape

#>>> (200, 200, 2, 2)

我们可以检查它是否有效:

target[10, 20]

#>>> array([[100, 100],

#>>> [100, 400]])

好极了!

所以我们只是运行numpy.linalg.eigh:

values, vectors = numpy.linalg.eigh(target)

看,它的作品!

values[10, 20]

#>>> array([ 69.72243623, 430.27756377])

eigvals[10, 20]

#>>> array([ 69.72243623, 430.27756377])

那么我想象你可能想连接这些:

numpy.concatenate([values[row, row+1:] for row in range(len(values))])

#>>> array([[ 0.00000000e+00, 1.00000000e+00],

#>>> [ 0.00000000e+00, 4.00000000e+00],

#>>> [ 0.00000000e+00, 9.00000000e+00],

#>>> ...,

#>>> [ 1.96997462e+02, 7.78160025e+04],

#>>> [ 3.93979696e+02, 7.80160203e+04],

#>>> [ 1.97997475e+02, 7.86070025e+04]])

numpy.concatenate([vectors[row, row+1:] for row in range(len(vectors))])

#>>> array([[[ 1. , 0. ],

#>>> [ 0. , 1. ]],

#>>>

#>>> [[ 1. , 0. ],

#>>> [ 0. , 1. ]],

#>>>

#>>> [[ 1. , 0. ],

#>>> [ 0. , 1. ]],

#>>>

#>>> ...,

#>>> [[-0.70890372, 0.70530527],

#>>> [ 0.70530527, 0.70890372]],

#>>>

#>>> [[-0.71070503, 0.70349013],

#>>> [ 0.70349013, 0.71070503]],

#>>>

#>>> [[-0.70889463, 0.7053144 ],

#>>> [ 0.7053144 , 0.70889463]]])

也可以在numpy.mgrid之后做这个连接循环将工作量减半:

# All *permutations*, not combinations

indexes = numpy.mgrid[:a.size, :a.size]

# Convert to all *combinations* and reduce the dimensionality

indexes = numpy.concatenate([indexes[:, row, row+1:] for row in range(indexes.shape[1])], axis=1)

# Remove the extra dimension; it's not wanted here!

subs = a[:,0][indexes]

target = numpy.array([

[subs[0], subs[0]],

[subs[0], subs[1]]

])

target = numpy.rollaxis(target, 2)

values, vectors = numpy.linalg.eigh(target)

是的,最后一个样本是你需要的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值