是否可以使用NumPy(和SciPy)对元素优化进行矢量化(或以其他方式加速)?
在最抽象的意义上,我有一个函数y,它是抛物线形状的,基本上可以表示为y=x^2+b*x+z
,其中x是已知值的数组,我想找到使得y的最小值恰好为零(换句话说,我想找到一个值z,使我的抛物线只有一个零)。为此,我选择实现一种简单的二分法方法。代码如下:
import numpy as np
def find_single_root():
x = np.arange(-5, 6,0.1) # domain
z = 1 # initial guess
delta = 1 # initial step size
tol = 0.001 # tolerance
while True:
y = x**2-5*x+z
minimum = np.nanmin(y)
# update z
print(delta)
print(z)
if minimum > 0:
if delta > 0:
delta = -1*delta/2
z += delta
else:
if delta < 0:
delta = -1*delta/2
z += delta
# check if step is smaller than tolerance
if np.abs(delta) < tol:
return z
现在假设x(v,w),我想创建一个z值的二维数组,其中每个都是优化的。我现在所拥有的是(注意,新的函数定义和域如下)
def find_single_root(v, w):
x = np.arange(-5*v/w, 6*w,0.1) # domain
... # rest of the function
vs = np.arange(1,5)
ws = np.arange(1,5)
zs = np.zeros((len(vs),len(ws)))
for i, v in enumerate(vs):
for j, w in enumerate(ws):
zs[i][j] = find_single_root(v,w)
现在我只是拥有这些简单的嵌套for循环,但有没有办法我可以采用不同的方式处理它或使用NumPy矢量化加速它?
答案 0 :(得分:0)
当要执行的计算事先准确知道时,可以应用矢量化。就像“取两个数字数组,并成对地相乘”。
当计算适应给定数据时,矢量化不适用。任何类型的优化算法都是自适应的,因为在哪里寻找最小值取决于函数返回的内容。如果你有一堆函数,并且需要找到每个函数的最小值,那么你将不得不在循环中一次最小化它们。如果这个过程很慢,那是因为最小化一堆函数需要很长时间,而不是因为程序中存在for
循环。
关于你的程序,我会尝试使用一些SciPy方法进行最小化和根查找。有一个函数min_of_f(z)
可以找到参数z的给定值的最小值,可能使用minimize_scalar
。然后将min_of_f
提供给root-finding routine。这些需要多长时间可以通过它们的公差参数(xtol等)来控制。
OP编辑: 我想将此归功于正确答案,但仍然提供更多信息。
我最终使用numpy.vectorize
进行矢量化而不重构问题。虽然numpy.vectorize
并不意味着提高性能,但我的特定用例中的性能是两个更快的适度因素。对问题中的原始问题应用相同的方法导致100x100向量几乎没有加速,因此YMMV。
即使由于上述答案中给出的原因我无法从速度方面对此问题进行矢量化,但是能够在我的代码中使用普通矢量语法而不是嵌套for循环是有用的。