简体   繁体   English

解释多变量函数的偏导数的Python代码

[英]Interpreting Python code for partial derivatives of multi-variable function

I'm trying to understand how the following code works to numerically approximate the partial derivative of a function of multiple variables. 我试图了解以下代码如何在数值上近似逼近多个变量的函数的偏导数。 To quote the book: 引用这本书:

When f is a function of many variables, it has multiple partial derivatives, each indicating how f changes when we make small changes in just one of the input variables. 当f是许多变量的函数时,它具有多个偏导数,每个偏导数表示当我们仅对输入变量之一进行小的更改时f的变化。 We calculate its ith partial derivative by treating it as a function of just its ith variable, holding the other variables fixed: 我们将第i个偏导数视为第i个变量的函数,并固定其他变量,从而计算出第i个偏导数:

def partial_difference_quotient(f, v, i, h):
    """compute the ith partial difference quotient of f at v"""
    w = [v_j + (h if j == i else 0) for j, v_j in enumerate(v)] # add h to just the ith element of v

    return (f(w) - f(v)) / h

def estimate_gradient(f, v, h=0.00001):
    return [partial_difference_quotient(f, v, i, h) for i, _ in enumerate(v)]

Unfortunately, the books doesn't give any example of how to use the code; 不幸的是,这些书没有提供任何有关如何使用代码的示例。 it just states that this will give you the partial derivative and then moves on. 它只是说这将给您偏导数,然后继续。

The first thing I did is to try to rewrite the code so that it is more readable for someone with my background (I'm more used to seeing C++ code), but I'm not sure if I've done it right. 我做的第一件事是尝试重写代码,以便对具有我的背景的人来说更具可读性(我更习惯于看C ++代码),但是我不确定自己是否做对了。

def partial_difference_quotient1(f, v, i, h):   # i is the variable that this function is being differentiated with respect to
    w = []
    for j, v_j in enumerate(v):
        if i == j:      # add h to just the ith element of v
            w.append(v_j + h)
        else:
            w.append(v_j)

    return (f(w) - f(v)) / h

def estimate_gradient1(f, v, h=0.00001):
    list1 = []
    for i, _ in enumerate(v):
        list1.append(partial_difference_quotient1(f, v, i, h))

    return list1

If the code is correct, then I'm still not sure how to use it. 如果代码正确,那么我仍然不确定如何使用它。 For instance, let's say I would like to find the partial derivative of f = x^2 + x*y^2 at y = 3, then I tried 例如,假设我想在y = 3时找到f = x ^ 2 + x * y ^ 2的偏导数,然后我尝试

def f1(x, y):
    return (x*x) + (x*y*y)

v = range(-10,10)
f = partial(f1, y=3)
f_x = estimate_gradient1(f, v, h=0.00001)

I can see that this wouldn't work because, for isntance, you can't multiply a list (ie v) with itself (x*x in the function f1). 我可以看到这是行不通的,因为,就本质而言,您无法将列表(即v)与其自身(函数f1中的x * x)相乘。 But it is clear from the code that v should be a list, so I've how to use the code. 但是从代码中很明显,v应该是一个列表,因此我将介绍如何使用代码。

Generally, you can work out the partial of a vector, you can do this: 通常,您可以算出向量的部分,可以这样做:

For d/dx x^2+2x+1 , the easiest way is to simply calculate the gradient for y in terms of an array of x : 对于d/dx x^2+2x+1 ,最简单的方法是根据x数组简单地计算y的梯度:

from numpy import arange, gradient

x = arange(0, 50, 0.01)  # Range

y = ((x**2) + (2*x)) + 1  # Function

ddx = gradient(y)  # Gradient

which yields the following: 结果如下: <code> f(x)</ code>及其梯度的图。

Another arbitrary example of dx/dt , d2/dy2 , and phase plot would be as follows: dx/dtd2/dy2和相位图的另一个任意示例如下:

from scipy.integrate import odeint
from numpy import arange, sin, cos, gradient


def sdot(y, t, *args):
    val = sin(t*2)+(sin(y**(t/4)))
    return val

init = 0
x = arange(0, 30, 0.01)

args = (None)

dydt = odeint(sdot, y0=init, t=x, args=(args,))
d2dy2 = gradient(dydt[:, 0])

f(x)</ code>的图,其梯度和其相位图。

For additional information of gradient , see the documentations here , and for odeint see here . 有关gradient其他信息,请参见此处的文档,而有关odeint请参见此处 Also, you may find some additional information on vectorisation (aka. array programming) useful too. 此外,您可能还会发现一些有关矢量化 (即数组编程)的附加信息。

For actual partial derivatives (ie through integration), you may also do this: 对于实际的偏导数(即通过积分),您也可以这样做:

from scipy.misc import derivative

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)

Although this would be rather more challenging for someone who is not a hardcore (Python) programmer. 尽管这对于不是铁杆(Python)程序员的人来说更具挑战性。 But if you're keen to learn it, you can find the documentations here ; 但是,如果您想学习它,可以在这里找到文档。 and learn more about wrappers and decorators in this nice tutorial from the Code Ship in here . 并从此处的Code Ship的这个不错的教程中了解有关包装器和装饰器的更多信息。

Hope this gives you an idea of how you can handle derivatives in Python. 希望这能让您对如何处理Python中的派生类有所了解。

Here is how to use it: 使用方法如下:

def f(v):
    x, y = v
    return (x*x) + (x*y*y)

x = 3
y = 3
v = [x, y]
grad = estimate_gradient1(f, v, h=0.00001)
print(grad)

This outputs: 输出:

[15.000009999965867, 18.000030000564493]

which is approximately correct. 这大概是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM