计算梯度使用时出错 python
error in calculating gradient use 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?
你的代码的问题出在下面的行组合上(我展示了fx_addh
的例子,fx_minush
的情况类似
fx_addh = f(x)
x[index] = x_old
您正在将 f(x)
的结果放入 fx_addh
。但问题是您定义 f(x)
的方式只是 lin(x)
的句柄,您是在直接 return 参数。
在Python中,赋值操作不复制对象,而是在目标(在赋值=
的左侧)和对象(在赋值的右侧[=]之间创建绑定19=]).关于此的更多信息 here.
为了让自己相信这正在发生,您可以在设置 x[index] = x_old
的行之后放置另一个 print(fx_addh)
;你会看到它现在包含值零。
要解决此问题,您可以将 lin(x)
函数修改为 return 作为参数传入的对象的副本:
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)
哪个 returns:
[ 0.00101]
[ 0.00099]
[ 1.]
[ 1.]
如您所料,表示 1
的梯度。
因为fx_addh
和fx_minush
指向内存的同一个索引。将 lin
函数更改为:
def lin(x):
return x.copy()
结果:
[ 0.00101]
[ 0.00099]
[ 1.]
[ 1.]
我用下面的公式计算梯度
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?
你的代码的问题出在下面的行组合上(我展示了fx_addh
的例子,fx_minush
的情况类似
fx_addh = f(x)
x[index] = x_old
您正在将 f(x)
的结果放入 fx_addh
。但问题是您定义 f(x)
的方式只是 lin(x)
的句柄,您是在直接 return 参数。
在Python中,赋值操作不复制对象,而是在目标(在赋值=
的左侧)和对象(在赋值的右侧[=]之间创建绑定19=]).关于此的更多信息 here.
为了让自己相信这正在发生,您可以在设置 x[index] = x_old
的行之后放置另一个 print(fx_addh)
;你会看到它现在包含值零。
要解决此问题,您可以将 lin(x)
函数修改为 return 作为参数传入的对象的副本:
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)
哪个 returns:
[ 0.00101]
[ 0.00099]
[ 1.]
[ 1.]
如您所料,表示 1
的梯度。
因为fx_addh
和fx_minush
指向内存的同一个索引。将 lin
函数更改为:
def lin(x):
return x.copy()
结果:
[ 0.00101]
[ 0.00099]
[ 1.]
[ 1.]