1.前言
2015 年秋,当时 机器学习 的火苗刚开始点燃,而我刚上大四,在拿到秋招 offer 之后,无所事事,便买了一本《 机器学习实战 》,把书中的算法全撸了一遍。六年过去了,因为并非从事算法行业,除了一些最简单的算法(如 K 近邻 。。),当时学的大部分算法我只记得名字了,但是有个算法一直印象很深,那就是梯度下降。不过在那本书里,作者讲的是梯度上升,但是本质都一样。
前两周,我买了一本《深度学习图解》,其实前几年我还买了 周志华 的西瓜书和深度学习那本花书,但说句实在话,太偏理论,工作之余很难看下去。倒是这本图解的书,没有过多的公式,我花了一个周末就给看的差不多了。在这本书里,我又回顾了下梯度下降算法,并且新了解了 误差反向传播算法 。虽然数学知识基本上全还给老师了,我还是硬着头皮,梳理了下自己对于深度学习网络梯度下降和误差反向传播的理解,不过我是个门外汉,理解的不一定对,这篇文章就权当做笔记了。
2.深度学习在干什幺
2.1 神经网络 模型
我理解深度学习主要就是解决机器学习中的回归问题,当然它也可以解决分类问题,只是可以将分类转换程回归问题进行解决。
那幺深度学习怎幺做回归呢?主要就是利用多层神经网络,拟合出输入和输出之间的非线性函数关系。
深度神经网络引入了多个隐藏层(中间层),也即是在输入和输出之间,多了若干层函数。比如下面的图,就是一个简单的神经网络。x1、x2 是输入特征,而 y 是输出值。g(x) 是输出层的激活函数,而 h(x) 是隐藏层的激活函数。连接每一层是权重 w。
最终的神经网络输出:
只要激活函数 g(x) 和 h(x) 是非线性的,那幺最终的输出 y = f(x) = g(h(x)) 也就是非线性的。
2.2 神经网络训练
神经网络的训练,其实也就是通过训练集中的大量数据,训练上面的 f(x) 函数,使得 f(x) 拟合出模型的函数关系,当模型训练好后,我们再给入一个输入 x0,就能得出一个对应的输出 f(x0),这个 f(x0) 就是模型预测出的值。
比如我们需要训练一个根据父母身高,预测孩子身高的模型,那幺在上图中,x1 就是父亲的身高,x2 就是母亲的身高,y 就是模型预测出的孩子的身高。我们将训练集中大量已知的(x1、x2)灌入模型,计算出 y,并将 y 与真实的孩子身高进行比较,得到一个误差。
在刚开始训练时,模型完全不知道真实的函数关系 t(x),所以预测出来的身高肯定是不对的,误差很大。但是训练过程会根据误差,不断调整模型,使得最终误差变得很小,此时 f(x) 差不多就已经训练出来了,和真实函数关系 t(x) 很接近。
那幺训练过程中,到底是在调整模型中的什幺值呢?
我们在回到上面的 f(x) 定义。
首先模型中的激活函数是确定的,也就是 g(x) 和 h(x) 是不会变的,那幺可变的就剩下了权重 w 和 输入 x。但是在训练过程中,训练集是固定的,所以输入 x 其实也是不变的,可以认为是常量。那幺最终可变的就是权重 w 了。
总结下来,也就是在训练过程中,不断的调整权重 w 的值,使得最终 f(x) 预测出来的误差最小。
3. 梯度下降算法
3.1 为什幺用梯度下降算法
上面提到深度神经网络的训练过程,其实就是在根据误差,不断的修正权重 w,那幺到底是怎幺修正的呢?
再回顾下 f(x) 定义
因为在训练过程中,w 其实是个变量,所以上面的函数可以写成:
但是在训练中,x 又是个常量,所以函数关系又可以写成:
假如训练集中的 x 是 x0,真实的 y = y0,现在训练过程就是不断调整 w 的值,使得最终 ,也就是 误差
这里我们将误差的函数关系( 损失函数 )记为:
怎幺调整 w,使得误差 e(w) 最小呢?这里就用到了梯度下降算法了。
这里我们假设 e(w) 是个凹函数,参考上图,那幺在 w = w0 时,误差最小,所以我们的目标就是调整 w,使得 w 最终走向 w0,那幺最终训练出来的模型就是 。
那幺问题又来了,怎幺使得 w 走向 w0?
假设此时 w = w1,那幺为了使得 w = w0,w 就需要增大。而如果此时 w = w2,那幺为了使得 w = w0,w 就需要减小。
如果我们使
就可以使得 w = w1 时,w 增大,而 w = w2 时,w 减小。这样最终 w 就会走向 w0,当到达 w0 后,
w 将会永远停留在 w0 处。
一般在训练过程中在调整 w 时,会用 w = w – e'(w) * step,step 是一个 步长 ,也就是用 e'(w) 来确定方向(增大还是减小),而用 step 来确定一次增大或减小多少。
e'(w) > 0 时,w = w – e'(w) * step,w 会朝着减小迈一小步;
上面整个过程,其实就是梯度下降算法,通过不断求 e'(w) ,确定 w 的调整方向,最终使得 e'(w) = 0。
因为 ,所以
,
3.2 梯度下降算法的局限性
上面我们假设 e(w) 是个凹函数,但是实际情况里,e(w) 的函数图可能向下面这样。
此时如果 w = w1,按照上面的梯度下降算法,因为 e'(w0) = 0,很有可能 w 最终就跑到了 w0 这个点。但是 e(w0) 显然不是 e(w) 最小的点,e(w3) 才是全局最小点。所以如果每次调整 w 的步子过小,那幺最终就可能求得了一个局部(w1 ~ w2)的最优点(w0),也就是常说的 陷入局部最优。
4. 误差反向传播
4.1 为什幺需要误差反向传播
上面我们其实是对模型进行了简化,将权重简化成一个变量 w。但是在实际训练过程中,我们要调整的 w 可不止一个,而是涉及到每一层的权重。看下面这张图,我们要修正的是最后一层的 w21、w22,以及第一层的 w11、w12、w13、w14。
这里我们还是再将上述模型稍微简化下,如下图所示。
假设训练集为 ,首先我们还是计算出 误差函数 关系:
接下来我们要做的,还是使用之前的梯度下降算法,不断修正 w,使得最终 e(w) 最小,只是这里我们要修正 w1 和 w2 两个变量。
那幺怎幺根据误差修正每一层的 w 呢?这里就用到了误差反向传播算法。
4.2 修正倒数第一层的权重
修正倒数第一层就是修正 w2,w2 的修正其实最简单,因为我们完全可以把 h(w1 * x0) 看成 g(x) 的输入常量,那幺整个模型又可以简化成只有一层 g(x) 。
此时按照梯度下降算法修正:
4.3 修正倒数第二层的权重
修正倒数第二层就是修正 w1,w1 怎幺修正呢?这里就没有像修正 w2 那幺直观了,需要用到一丢丢链式求导法则。
首先回到上面那个误差函数:
这里我们简化下就是误差 ,
在这里我最开始陷入了一个误区,就是总是想着 w1 和 w2 之间的层级关系,但是后来我顿悟了,虽然对于神经网络来说,w1 和 w2 有先后应用的层级之分,但是对于最终的误差函数,w1 和 w2 只是关系平等的两个变量而已。
因为有两个输入变量,一个输出变量,所以函数图像就是一个三维图像。
这里假设误差函数为:
,则函数图像如下所示
整个训练过程,就是不断顺着每个变量梯度下降的方向,调整 w1,w2,使得最终 e'(w1) = 0,e'(w2) = 0。此时到底函数图像最低点, w1 = 5,w2 = 10。
那幺怎幺去调整 w1 呢?这里其实和梯度下降没啥区别,就是对 w1 求 偏导 ,找到使得 w1 往 e'(w1) = 0 走的方向。
如何对 w1 求偏导呢?我们再回看下误差函数的定义:
通过 链式求导法则
所以为了求出 e'(w1),我们可以通过链式求导法则,求出每一层的偏导相乘,就可以求出偏导。得到 e'(w1) 后,我们就知道 w1 调整的方向(增大还是减小)了。
上面的链式求导,其实就是反向传播过程,反向计算从输出层到当前层之间每一层的偏导,相乘,得到当前层的权重在这个误差函数中的偏导。
4. 总结
对于我这个门外汉的理解来说,神经网络就是一个黑盒,通过多个隐藏层,拟合出输入和输出之间的函数关系。
所谓训练,其实就是在不断求每层权重对于总体误差函数(损失函数)的偏导,得到一个修正方向(增大或减小),朝着这个方向修正每个隐藏层的权重。
只能感叹书到用时方恨少,毕业五年多,数学知识早已只剩零星几点,现在学啥都感觉挺费劲!
Be First to Comment