2016-10-28 105 views
1

我使用下面的方程式来计算梯度误差在计算梯度使用Python

gradient = [f(x+h) - f(x-h)]/2h 

和我用线性函数测试,但什么是错。 的代码是在这里:

import numpy as np 

def evla_numerical_gradient(f, x): 

    gradient = np.zeros(x.shape, dtype=np.float64) 
    delta_x = 0.00001 

    it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite']) 

    while not it.finished: 
     index = it.multi_index 
     x_old = x[index] 

     x[index] = x_old + delta_x 
     fx_addh = f(x) 
     print(fx_addh) 

     x[index] = x_old - delta_x 
     fx_minush = f(x) 
     print(fx_minush) 

     x[index] = x_old 

     print((fx_addh - fx_minush)/(2 * delta_x)) 
     gradient[index] = (fx_addh - fx_minush)/(2. * delta_x) 

     it.iternext() 

    return gradient 


def lin(x): 
    return x 

if __name__ == '__main__': 
    x = np.array([0.001]) 
    grad = evla_numerical_gradient(lin, x) 
    print(grad) 

其结果是在这里:

[ 0.00101] 
[ 0.00099] 
[ 0.] 
[ 0.] 

为什么在X坡度为0?

回答

0

与您的代码的问题是上线的以下组合(我展示的fx_addh的例子中,fx_minush的情况是类似的

fx_addh = f(x) 
x[index] = x_old 

要放置的f(x)结果为fx_addh,但问题是你定义的方式f(x),它只是你的lin(x)的一个句柄,你直接返回参数

在Python赋值操作中不要复制对象,而是在目标之间创建一个绑定(在作业=左侧)和对象(作业右侧=)。更多关于这个here

为了说服自己发生这种情况,您可以在设置x[index] = x_old的行之后放置另一个print(fx_addh);你会看到它现在包含零值。

为了解决这个问题,你可以修改你的lin(x)函数返回传递作为参数的对象的副本:

import numpy as np 
import copy 

def evla_numerical_gradient(f, x): 

    gradient = np.zeros(x.shape, dtype=np.float64) 
    delta_x = 0.00001 

    it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite']) 

    while not it.finished: 
     index = it.multi_index 
     x_old = x[index] 

     x[index] = x_old + delta_x 
     fx_addh = f(x) 
     print(fx_addh) 

     x[index] = x_old - delta_x 
     fx_minush = f(x) 
     print(fx_minush) 

     x[index] = x_old 

     print((fx_addh - fx_minush)/(2 * delta_x)) 
     gradient[index] = (fx_addh - fx_minush)/(2. * delta_x) 

     it.iternext() 

    return gradient 


def lin(x): 
    return copy.copy(x) 

if __name__ == '__main__': 
    x = np.array([0.001]) 
    grad = evla_numerical_gradient(lin, x) 
    print(grad) 

将返回:

[ 0.00101] 
[ 0.00099] 
[ 1.] 
[ 1.] 

指示1渐变为你会期待。

0

因为fx_addhfx_minush指向内存的相同索引。改变lin功能如下:

def lin(x): 
    return x.copy() 

结果:

[ 0.00101] 
[ 0.00099] 
[ 1.] 
[ 1.]