Python中多元函数的向量化偏导数

时间:2014-08-19 20:27:36

标签: python numpy vector scipy derivative

this thread中,alko用数字方式计算多元函数的偏导数,发现了一个非凡的答案。

我现在有一个关于增强此函数以接受输入值数组的后续问题。我有一些代码,我循环遍历一大堆n维点,计算每个变量的偏导数,这在计算上非常昂贵。

使用np.vectorize对相关函数进行矢量化很容易,但它会导致partial_derivative包装器出现问题:

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]。当它传递给函数wraps时,这似乎会受到损害。它最终传递给函数derivative的点是[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])

最后一行现在返回array([ 6., 6.])

1 个答案:

答案 0 :(得分:0)

我对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

此外,您可以使用numdifftools。他们似乎知道他们在做什么。这将做所有偏导数:

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]

然后用(删除'*')

替换相应的行
ret = f___(input)