我使用以下formule来计算渐变
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 :(得分:0)
您的代码存在以下行的组合问题(我展示了fx_addh
的示例,fx_minush
的情况类似
fx_addh = f(x)
x[index] = x_old
您要将f(x)
的结果放入fx_addh
。但问题是你定义f(x)
的方式,它只是你lin(x)
的句柄,你直接返回参数。
在Python赋值操作中,不要复制对象,而是在目标(赋值=
左侧)和对象(赋值=
右侧)之间创建绑定。有关here的更多信息。
为了说服自己发生这种情况,您可以在设置print(fx_addh)
的行之后放置另一个x[index] = x_old
;你会看到它现在包含零值。
要解决此问题,您可以修改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
的渐变。
答案 1 :(得分:0)
因为fx_addh
和fx_minush
指向内存的相同索引。将lin
函数更改为:
def lin(x):
return x.copy()
结果:
[ 0.00101]
[ 0.00099]
[ 1.]
[ 1.]