- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
np.apply_along_axis() 函数似乎非常慢(15 分钟后没有输出)。有没有一种快速的方法可以在长数组上执行此功能而无需并行化操作?我专门讨论的是具有数百万个元素的数组。
这是我正在尝试做的一个例子。请忽略 my_func 的简单定义,目标不是将数组乘以 55(当然无论如何都可以就地完成),而是一个说明。在实践中,my_func 稍微复杂一些,需要额外的参数,因此 a 的每个元素都被不同地修改,即不仅仅是乘以 55。
>>> def my_func(a):
... return a[0]*55
>>> a = np.ones((200000000,1))
>>> np.apply_along_axis(my_func, 1, a)
编辑:
a = np.ones((20,1))
def my_func(a, i,j):
... b = np.zeros((2,2))
... b[0,0] = a[i]
... b[1,0] = a[i]
... b[0,1] = a[i]
... b[1,1] = a[j]
... return linalg.eigh(b)
>>> my_func(a,1,1)
(array([ 0., 2.]), array([[-0.70710678, 0.70710678],
[ 0.70710678, 0.70710678]]))
最佳答案
np.apply_along_axis
不是为了速度。
没有办法将纯 Python 函数应用到 Numpy 数组的每个元素而不调用它多次,除非 AST 重写...
还好有解决办法:
矢量化
虽然这通常很难,但通常是简单的解决方案。找到某种方法以概括元素的方式来表达您的计算,这样您就可以一次处理整个矩阵。这将导致循环被提升出 Python 并进入经过高度优化的 C 和 Fortran 例程。
JITing:Numba 和 Parakeet,以及较小程度的 PyPy 和 NumPy
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)
是的,最后一个样本就是你所需要的。
关于python - numpy np.apply_along_axis 函数加速?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23849097/
如果我有一个函数 f(x),它接受一个一维数组作为参数并生成一个一维数组作为输出,我可以使用 numpy.apply_along_axis将函数应用于二维数组 X 的每一行,其行是 f 的有效参数。
我有一个返回列子集的函数,我想高效地将它应用到每一列。所以结果不再是矩阵,而是不同长度的列列表。由于大小不匹配,我未能使用 numpy apply_along_axis 来执行此操作。除了自己遍历列之
当 numpy.apply_along_axis 将一维数组作为输入时会发生什么?当我在一维数组上使用它时,我看到了一些奇怪的东西: y=array([1,2,3,4]) 第一次尝试: apply_a
我在使用 NumPy 时遇到以下问题: 代码: import numpy as np get_label = lambda x: 'SMALL' if x.sum() <= 10 else 'BIG'
我有一个 3D ndarry 对象,它包含光谱数据(即空间 xy 维度和能量维度)。我想提取并绘制线图中每个像素的光谱。目前,我正在沿我感兴趣的轴使用 np.ndenumerate 来执行此操作,但速
如何通过 numpy.apply_along_axis() 将函数应用到 NumPy 数组的元素并进行并行化,以便利用多核?这似乎是一件自然而然的事情,在对所应用函数的所有调用都是独立的常见情况下。
我正在尝试将 numpys apply_along_axis 与需要多个参数的函数一起使用。 test_array = np.arange(10) test_array2 = np.arange(10
我遇到了 numpy.apply_along_axis在一些代码中起作用。而且我不明白有关它的文档。 这是文档的示例: >>> def new_func(a): ... """Divide e
我正在将J语言代码翻译成Python,但是python的apply函数的方式对我来说似乎有点不清楚...... 我目前有一个 (3, 3, 2) 矩阵 A 和一个 (3, 3) 矩阵 B。 我想将 A
我有一些大型数据集,我想将其拟合到单指数时间衰减。 数据由在不同时间获取的多个 4D 数据集组成,因此拟合应沿着第五维运行(通过数据集)。 我当前使用的代码如下: import numpy as np
我想计算一个 mm*n 维数组的 mm 个子数组的行列式,并希望以快速/更优雅的方式执行此操作。蛮力方法有效: import numpy as n array=n.array([[[0.,1.,2.,
np.apply_along_axis() 函数似乎非常慢(15 分钟后没有输出)。有没有一种快速的方法可以在长数组上执行此功能而无需并行化操作?我专门讨论的是具有数百万个元素的数组。 这是我正在尝试
我正在尝试实现一个函数,该函数获取 numpy 二维数组中的每一行并返回特定计算的标量结果。我当前的代码如下所示: img = np.array([ [0, 5, 70, 0, 0,
我有一个通过以下算法拟合多个 x,y 数组的函数: def f(func, data, init): import scipy.optimize as opt from numpy imp
我有一个 ndarray 子类,正确实现了 __array_wrap__,np.apply_along_axis 没有返回我的子类的实例,而是 ndarrays。下面的代码复制了我的问题: impor
我想将一个函数 f 映射到一个字符串数组上。我构建了 f 的矢量化版本并将其应用于我的数组。但是数组的第一个元素被传递了两次: import numpy as np def f(string):
我不知道如何返回 dtype U3 的字符串 我想要: 将_along_axis应用于my_array 对于每一行,返回一个字符串 def my_function(x): return x[2
我对 numpy 的 numpy.apply_along_axis() 函数何时会优于简单的 Python 循环感到困惑。例如,考虑一个有很多行的矩阵,您希望计算每一行的总和: x = np.ones
我是一名优秀的程序员,十分优秀!