上一篇文章中讲到了神经网络,通俗地说,就是一堆源数据X(第一层),经过一个空间的线性变换后,再被激活函数处理这个变换,变身成为隐层(下一层),然后得到的新的数据作为这一层的输出,重复上一层的方法,又得到下一层,就像神经一个节点一个节点传播信息一样,数据一层一层地变换,到最后一层输出时,再进行分类得到结果。下面这张图更加直观,当然这个只是四层:
而像以上的过程,我们称之为正向传播。
那么,我们可能会思考,这么传播下去,如果中间存在误差,误差会不会一层一层地被放大,以至于最后一层的分类效果十分不理想呢?
换句话说,根据我们前面学习的线性回归和逻辑回归的知识,这个误差error可以由cost来表示,通过梯度下降法或者正规方程法可以得到满足要求的误差(近似认为正确)。我们可以想象,神经网络的初始参数
(类似之前线性回归中的
,只不过
是
的集合),我们不可能一开始就刚好设置得到了一个优秀的
,一开始的误差大概率是大的,所以,有木有类似梯度下降法的方法可以调整参数
呢?直至
使得整个训练模型的误差降低到一个微小范围内,我们就认为这个模型就是好的了。
所以,个人简单的理解,机器学习的训练过程,其实就是训练出一个优秀的参数
,这样,新的数据集进来,通过这些
的变换,就可以得到结果了(与真实值类似的结果)。
好的,所以不卖关子了,就如同标题所说,神经网络如何训练出优秀的参数
呢?当然是Backpropagation Algorithm(反向传播算法)。
话不多说,Let's go!
----------------我是萌萌的分割线-------------------
之前的文章中我们看到了二元分类,简单地利用逻辑回归,分类成0和1,后来又讲到如果是多分类,譬如四类分类,我们可以将四种类型这样表现:
![y^{(i)} = \left[ \begin{array}{ccc} 1 \\ 0 \\ 0\\0 \end{array} \right], \left[ \begin{array}{ccc} 0 \\ 1 \\ 0\\0 \end{array} \right], \left[ \begin{array}{ccc} 0 \\ 0 \\ 1\\0 \end{array} \right], \left[ \begin{array}{ccc} 0 \\ 0 \\ 0\\1\end{array} \right]](https://i-blog.csdnimg.cn/blog_migrate/389ce592393c26e2b7d9f4f3f646f33f.png)
如果不理解的话,可以将它看成是1,2,3,4。以此类推,如果有更多分类,那就继续扩展,简单地说,分类的标签不再是0,1,2,3,4等数字了,而是用一个向量表示。所以,我们这个时候,再定义一个变量K,
。K表示有K个输出。
所以,按照我们前面所学,我们依然要得到它的代价函数,之前是二分类,只需要计算一个y就可以了,现在因为是多分类,有K个y而且每个y都是一个向量,相当于多了一个维度K。
前面二分类时,逻辑回归的代价函数是长这个样子的:
![J(\theta)=-\frac{1}{m}[\sum_{i=1}^{m}(y^{(i)}log(h_{\theta}(x^{(i)}))+(1-y^{(i)})log(1-h_\theta(x^{(i)}))]+\frac{\lambda}{2m} \sum_{j=1}^{n}{\theta_j^2} )](https://i-blog.csdnimg.cn/blog_migrate/b0869f4cd32cfac90334a7e91b35a8e7.png)
类推到多分类:

所以,代价函数我们得到了,那么怎么可以做到更新新的
呢?之前我们用梯度下降法去实现的,在这儿,我们用的是反向传播算法。要理解反向传播,那么你肯定会想,是不是还有一个正向传播呢?
是的,上一篇文章中,我们神经网络的构建利用的就是正向传播,它实现了这么一个过程:
![\left[ \begin{array}{ccc} x_{0} \\ x_{1} \\ x_{2}\\...\\x_{n} \end{array} \right]\rightarrow \left[ \begin{array}{ccc} a_{0}^{(2)}\\a_{1} ^{(2)} \\ a_{2} ^{(2)}\\a_{3}^{(2)}\\... \end{array} \right] \rightarrow \left[ \begin{array}{ccc} a_{0}^{(3)}\\a_{1} ^{(3)} \\ a_{2} ^{(3)}\\a_{3}^{(3)}\\... \end{array} \right] \rightarrow...\rightarrow \left[ \begin{array}{ccc} h_{\Theta}(x)_{1}\\h_{\Theta}(x)_{2}\\h_{\Theta}(x)_{3}\\h_{\Theta}(x)_{4}\end{array} \right]](https://i-blog.csdnimg.cn/blog_migrate/7679a6a27831423ef9d8e774e71c081b.png)
再细致地说,用数学语言描绘是这样子的:


(
一般设为1,代表bias)

(类似
)


一层变换一层变换地往前传播,第i层的计算都是基于i-1层的输出得到的,这就是前向传播。那么反向传播呢?顾名思义,就是由后往前推,一层一层推到前面来。
或者,因为神经网络有很多层,我们在前文思考过,如果有误差,那么误差应该也会一层层地传递下来,像之前的梯度下降法,就是找到误差,然后直接调整参数。那么神经网络这么多层,反向传播,是不是意味着,也是找到每一层的误差,然后去调整这一层的参数呢?
答案是肯定的,这里我们再设定一个变量
。 代表第
层第
个节点的error偏差。
所以,我们现在反向来推下,就以上文的四层结果来:
其中 
其中 
第一层因为是输入的原数据,所以无需去计算偏差。
我们要利用这个去获得
。
,假设没有
,或者说
。
所以,我们再定义一个变量
,它是
的大写形式,这个
会用来累加以便计算出
(因为以上的过程只是一次反向传播的过程的变量,在为得到满意的结果前,我们会不断地重复正向传播,反向传播,而
就是记录每一次之后的真实误差)。我们初始化 ,然后计算出偏差:
。 ,写成向量的形式是:
。
我们重新再来整理下思路:
我们的目标是为了最小化代价函数:
,假设目前我们的数据集有m个:
。
1. 设
2. 一个for循环,t = 1 to m:
2.1 
2.2 按照前文,前向传播,依次得到
(
)
2.3 根据
,计算出 
2.4 反向传播,分别计算出
。
2.5 利用 来累积偏导数项,
3. 离开for循环,
(当
),
(当
),这其实就是利用了之前所学,使用了正则化,因为当
的时候对应的是bias,所以不需要写入惩罚项。而,其实
。
下面就可以利用梯度下降法等方法去调整
了。
至此,神经网络的流程基本完成。
此外,ng在课程中还讲了一个概念——梯度检验。 什么意思呢?就是文字表面的意思,我们算出了一个梯度,但是如何证明它是好的,所以需要去检验它。额,说得有些废话。给我的理解类似我们小时候学数学的时候,再解一个算数时,举个栗子,8*9 = 72,如何证明72是正确的,我这么来检验,8*10-8,看看结果是不是一样的。额,感觉这个例子不形象,但是小时候的我们却是学过验算方面的知识,可惜年代久远,我也一时半会儿想不起来了。
那么,梯度检验是怎么检验的呢?用的是数学的方法,如下公式:
,这个
很小。如果你学过微积分的话,会对这个有有莫名的熟悉感,没错,当
时,这不就是数学中导数的定义吗?
所以我们计算出来的和这个公式算出来的只要约等于就可以理解为正确( 在
范围内)。当然了,这种数学计算需要消耗的计算机计算资源太大,在编写程序时,检验通过后一定要及时关闭。
---------------我是萌萌的分割线---------------------
神经网络这一节学得挺费劲的,我也不知道我是否表述清楚了,感觉我还要花时间多去巩固一番,写得不好,接受广大朋友们指正批评。共勉!
378



被折叠的 条评论
为什么被折叠?



