赞
踩
通过前面的学习,我们知道了多维变量下的偏导数的计算方法。神经网络学习的过程是不断追求最优参数的过程,而计算偏导数和梯度就是追求最优参数的最快路径。
梯度,就是多维自变量的偏导数构成的向量集合。例如对于下面的函数:
对x0的偏导计算:
对x1的偏导计算:
那么梯度就是两个偏导数一起构成的向量:
根据前面的学习,偏导数的计算可以采用中心差分的方式计算,而就某一维自变量的计算时,其他维度的自变量视为常量:
- def numerical_gradient(f, x):
- # 微小变化量
- h = 1e-4 # 0.0001
-
- # 生成等维度的数组
- grad = np.zeros_like(x) # 生成和x形状相同的数组
-
- for idx in range(x.size):
- # 当前维度的自变量的值
- tmp_val = x[idx]
-
- # f(x+h)的计算
- x[idx] = tmp_val + h
- fxh1 = f(x)
-
- # f(x-h)的计算
- x[idx] = tmp_val - h
- fxh2 = f(x)
-
- # 差分计算
- grad[idx] = (fxh1 - fxh2) / (2*h)
-
- x[idx] = tmp_val # 还原值
-
- return grad
那么计算函数在某些位置的偏导、梯度就很方便了:
- def function_2(x):
- return x[0]**2 + x[1]**2
- >>> numerical_gradient(function_2, np.array([3.0, 4.0]))
- array([ 6., 8.])A
- >>> numerical_gradient(function_2, np.array([0.0, 2.0]))
- array([ 0., 4.])
- >>> numerical_gradient(function_2, np.array([3.0, 0.0]))
- array([ 6., 0.])
我们看到函数在不同的位置,他们的偏导数各不相同,那么这些偏导数和梯度有什么含义呢?
如果按照负梯度作为向量绘制到图像中的时候,我们得到上面的图像。我们发现,箭头都指向函数最小值的位置,就像我们三维图像一样,他们都指向凹槽的底部:
实际上,负梯度所指向的方向,就是函数在该位置减小幅度最大的方向。
既然负梯度指向的是函数在该位置减小幅度最大的方向,我们就可以利用这一特性,慢慢的调整参数,使之达到最优(达到代价函数的最低点)。
也就是说,每次我们计算该位置的梯度,然后在此处向梯度下降的位置移动一个小单位,这样我们一步步地接近目标。
这里的η是学习率,觉得我们每一步迈进的大小。学习率不宜过大,否则容易来回跳,找不到最优的值;学习率也不宜过小,否则学习速度太慢,效率低。
(一般动态调整学习率,前面的步骤使用较大的学习率,速度快,后面的步骤使用较小的学习率,速度慢但是可以避免越过最优值。)
我们先来实现梯度下降过程中的位置更新:
- def gradient_descent(f, init_x, lr=0.01, step_num=100):
- x = init_x
- # 开始迭代更新
- for i in range(step_num):
- # 计算梯度
- grad = numerical_gradient(f, x)
- # 移动位置
- x -= lr * grad
-
- return x
我们尝试计算一下最小值:
- >>> def function_2(x):
- ... return x[0]**2 + x[1]**2 ...
- >>> init_x = np.array([-3.0, 4.0])
- >>> gradient_descent(function_2, init_x=init_x, lr=0.1, step_num=100)
- array([ -6.11110793e-10, 8.14814391e-10])
我们发现得到的结果非常接近(0,0)这说明真的找到了函数的最低点
而实际上,自变量也真的是沿着负梯度的方向一步步地移动到最低处。
在学习过程中的梯度就是代价函数与权重矩阵的偏导向量。
权重更新
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。