神经网络 dnn,神经网络的梯度
本文用目录梯度法的概念梯度法编程实现了神经网络的梯度汇总
梯度法的概念
机器学习的主要任务是在学习过程中寻找最优参数。同样,神经网络在学习时必须找到最优参数(权重和偏差)。这里的最优参数是指损失函数取最小值时的参数。但总的来说,损失函数非常复杂,参数空间巨大,我们不知道它能在哪里得到最小值。巧妙地利用梯度求函数的最小值(或最小可能值)的方法就是梯度法。
这里需要注意的是,梯度表示每个点的函数值下降最多的方向。所以不能保证梯度指示的方向就是函数的最小值或者是真正应该前进的方向。其实在复杂函数中,梯度表示的方向基本上不是函数值最小的地方。
函数的最小值和称为鞍点的地方的梯度为0。最小值是局部最小值,即限定在一定范围内的最小值。鞍点是在一个方向上最大而在另一个方向上最小的点。梯度法虽然是求梯度为0的地方,但那个地方不一定是最小值(也可能是最小值或鞍点)。此外,当函数复杂而平坦时,学习可能会进入一个(几乎)平坦的区域,陷入一个称为学习平台期的停滞期。
虽然梯度的方向不一定指向最小值,但是函数值可以沿着它的方向最小化。因此,在寻找函数的最小值(或最小可能值)的位置的任务中,需要以梯度的信息为线索来决定前进的方向。
这时,梯度法就派上用场了。在梯度法中,函数值从当前位置沿梯度方向前进一定距离,然后在新的位置重新计算梯度,然后沿新的梯度方向前进,以此类推。这样,梯度法就是沿着梯度方向不断前进,使函数值逐渐减小的过程。梯度法是机器学习,尤其是神经网络学习中解决优化问题的常用方法。
现在,我们以两个变量为例,尝试用数学公式表示梯度法:
公式中的代表更新量,在神经网络的学习中称为学习率。学习率决定了您应该学习多少,以及您应该在一项研究中更新参数到什么程度。这个公式是更新一次的公式,这个步骤会重复。也就是说,每一步都按照这个公式更新变量值,通过重复这一步,逐渐减少函数值。虽然这里只展示了有两个变量时的更新过程,但即使变量个数增加,也可以用类似的公式(每个变量的偏导数)进行更新。
学习率需要预先确定为某个值,比如0.01或者0.001。一般来说,这个值太大或太小都达不到“好位置”。在神经网络的学习中,我们通常会改变学习率的值,并确认学习是否正确进行。
梯度法编程实现接下来,我们用Python实现梯度下降法:
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其中,参数f是要优化的函数,init _ x是初始值,lr是学习率,step _ num是梯度法的重复次数。numeric _ gradient(f,x)会求出函数的梯度,用梯度乘以学习率来更新。step_num指定重复的次数。用这个函数求函数的最小值,顺利的话还可以求函数的最小值。
这里有一个例子可以帮助你理解:
用梯度法求f(x0+x1)=x02+x12的最小值
使用Python编程:
定义函数_2(x):返回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)# Run Result Array([-6.11110793 e-10,8.14814391e-10])这里将初始值设为(-3.0,4.0),开始用梯度法求最小值。最终结果是(-6.1e-10,8.1e-10),非常接近(0,0)。实际上真正的最小值是(0,0),所以我们基本上是用梯度法得到正确的结果。如果用图形来表示梯度法的更新过程,如下图所示:
可以发现原点是最低的地方,函数值在一点点向它靠近。
如前所述,学习率过大或过小,都无法取得好的效果。让我们看另一个例子:
#学习率过高的例子:LR=10.0init _ x=np.array ([-3.0,4.0]) Gradient _ Descent(function _ 2,init _ x=init _ x,LR=10.0,step _ num=100) #运行结果数组([-2.50) -1.29524862e 12])#学习率过低的例子:LR=1e-10init _ x=np.array ([-3.0,4.0])Gradient 3.999992])实验结果表明,如果学习率过大,会发散到一个非常大的值; 另一方面,如果学习率太小,就会以很少更新而告终。也就是说,设定一个合适的学习率是一个非常重要的问题。
像学习率这样的参数被称为超参数。该参数不同于神经网络的参数(权重和偏差)。相对于神经网络的权值参数由训练数据和学习算法自动获得,而学习率等超参数则由人工设定。一般来说,超参数需要尝试几个值,才能找到一个可以让学习顺利进行的设置。
神经网络的梯度神经网络的学习也需要梯度。这里的梯度是指损失函数相对于权重参数的梯度。比如有一个神经网络,只有一个权重W,形状为23,损失函数用l表示,这时梯度可以用dL/dW表示。如果用数学方法表示,如下所示:
dL/dW的元素由每个元素相对于w的偏导数组成。例如,第一行和第一列中的元素dL/dW11表示当W11稍微改变时,损失函数L将改变多少。
下面,我们以一个简单的神经网络为例,实现梯度的代码。这里构建了一个名为simpleNet的类:
导入numpy为NP类simpleet:def _ _ init _ _(self):Self . w=NP . random . randn(2,3) # Initialize def predict (self,x): return np.dot (x,Self。w) def损失(self,x,t): z=self。predict(x)y=softmax(z)loss=cross_entropy_error(y,t) returnloss这里用到前面提到的soft max、cross _ entropy _ error和numerical_gradient方法。SimpleNet类只有一个实例变量,即形状为23的权重参数。它有两种方法,一种是predict(x)进行预测,另一种是loss(x,t)求损失函数值。这里,参数x接收输入数据,t接收正确的解锁。现在尝试使用这个简单网络:
Net=simpleNet() print(net。W) # weight参数[[0.47355232 0.9977393 0.8468094],[0.8557411 0.03563661 0.69422093]]]x=NP . array([0.6,0.9])p=net . predict(x)print(p)[1.05414809 0.63071653 1.1328077如前所述,我们使用numerical_gradient(f,x)来寻找梯度:
女(女):返回净损失(x,t).dw=numerical _ gradient (f,net . w)print(dw)[[0.21924763 0.14356247-0.36281009][0.32887144 0因此,这里,参数x取为net。w,并定义一个新的用于计算损失函数的函数f,然后将新定义的函数传递给numerical_gradient(f,x)。
numerical_gradient(f,net的结果。w)是dW,一个形状为23的二维数组。例如,查看dW的内容,您会发现dL/dw中的dL/dW11的值约为0.2,这意味着如果w11增加h,损失函数值将增加0.2h。dL/dw23的相应值约为0.5,这意味着如果w23增加h,损失函数值将减少0.5h。因此,从减少损失函数值的角度来看,W23应正向更新,w11应在至于更新程度,w23贡献大于w11。
在找到神经网络的梯度之后,我们只需要根据梯度方法更新权重参数。
总结沿梯度方向不断前进使函数值逐渐减小的过程就是梯度法。梯度法是解决机器学习中最优化问题的一种常用方法。特别是在神经网络学习中,虽然梯度方向不一定指向最小值,但是使函数值沿其方向最小,并设定合适的学习率,是一个非常重要的问题。超参数是手动设置的。与神经网络参数不同,可以尝试多个值,使学习顺利进行。