Python中多元函数的向量化偏导数
alko给出了一个惊人的答案,用数值计算多元函数的偏导数 我现在有一个关于增强此函数以接受输入值数组的后续问题。我有一些代码,我在一个长长的n维点列表中循环,计算每个变量的偏导数,这在计算上变得非常昂贵 使用Python中多元函数的向量化偏导数,python,numpy,vector,scipy,derivative,Python,Numpy,Vector,Scipy,Derivative,alko给出了一个惊人的答案,用数值计算多元函数的偏导数 我现在有一个关于增强此函数以接受输入值数组的后续问题。我有一些代码,我在一个长长的n维点列表中循环,计算每个变量的偏导数,这在计算上变得非常昂贵 使用np.vectorize对相关函数进行向量化非常容易,但这会导致偏导数包装器出现问题: from scipy.misc import derivative import numpy as np def foo(x, y): return(x**2 + y**3) def part
np.vectorize
对相关函数进行向量化非常容易,但这会导致偏导数
包装器出现问题:
from scipy.misc import derivative
import numpy as np
def foo(x, y):
return(x**2 + y**3)
def partial_derivative(func, var=0, point=[]):
args = point[:]
def wraps(x):
args[var] = x
return func(*args)
return derivative(wraps, point[var], dx=1e-6)
vfoo = np.vectorize(foo)
>>>foo(3,1)
>>>10
>>>vfoo([3,3], [1,1])
>>>array([10,10])
>>>partial_derivative(foo,0,[3,1])
>>>6.0
>>>partial_derivative(vfoo,0,[[3,3], [1,1]])
>>>TypeError: can only concatenate list (not "float") to list
最后一行最好返回[6.0,6.0]
。在这种情况下,提供给矢量化函数vfoo
的两个数组基本上是成对压缩的,因此([3,3],[1,1])
被转换为两个点,[3,1]
和[3,1]
。当它被传递到函数wrapps
时,它似乎被弄坏了。它最终传递给函数导数的点是[3,3]
。除此之外,还有明显的TypeError
抛出
有人有什么建议吗?有没有人需要做类似的事情
编辑
有时候,我认为在SO上发帖只是打破思维障碍的必要条件。我想我已经为任何可能感兴趣的人准备好了:
vfoo = np.vectorize(foo)
foo(3,1)
X = np.array([3,3])
Y = np.array([1,1])
vfoo(X, Y)
partial_derivative(foo,0,[3,1])
partial_derivative(vfoo,0,[X, Y])
最后一行现在返回数组([6,6.])
我对args[var]=x有一个小问题:这可能会永远更改args[var],并且所有值都已通过引用传递,无论更改多么小。所以你可能得不到你想要的确切答案。以下是一个例子:
In[67]: a = np.arange(9).reshape(3,3)
In[68]: b = a[:]
In[69]: b[0,0]=42
In[70]: a
Out[70]:
array([[42, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]])
您需要通过以下方式进行修复:
def wraps(x):
tmp = args[var]
args[var] = x
ret= func(*args)
args[var] = tmp
return ret
此外,您还可以使用。他们似乎知道自己在做什么。这将完成所有偏导数:
import numpy as np
import numdifftools as nd
def partial_function(f___,input,pos,value):
tmp = input[pos]
input[pos] = value
ret = f___(*input)
input[pos] = tmp
return ret
def partial_derivative(f,input):
ret = np.empty(len(input))
for i in range(len(input)):
fg = lambda x:partial_function(f,input,i,x)
ret[i] = nd.Derivative(fg)(input[i])
return ret
if __name__ == "__main__":
f = lambda x,y: x*x*x+y*y
input = np.array([1.0,1.0])
print ('partial_derivative of f() at: '+str(input))
print (partial_derivative(f,input))
最后:若您希望函数采用参数数组,例如:
f = lambda x: x[0]*x[0]*x[0]+x[1]*x[1]
然后将相应的行替换为(删除“*”)
请记住,np.vectorize
实际上并不比使用普通Pythonfor
循环做同样的事情快——它只是语法上的糖分。
ret = f___(input)