神经网络
都知道到神经网络这一章就开始变得异常重要了。
首先需要知道,神经网络只是个概念或者抽象模型,它的定义就不多说了。重点是算法,因为神经网络需要算法来实现,而整个算法的实现过程才是真正的神经网络模型,和决策树类似,这类模型不是一个简单的公式,而是由很多个数学公式和技巧组成。
其基本知识,主要是偏导数,激活函数以及激活函数求导。偏导数和激活函数求导就是大学微积分的部分,稍微回忆回忆会有印象,而激活函数网上有讲它的意义和作用。但是我个人理解起来还是蛮费劲,所以自己总结出来,对神经网络模型来说,它的作用其实就是把连续的输入数据(即0.1,0.2等等)都输入一个函数,然后输出的只会是离散的值(如是和否),并且它会把所有的数据都挤压到(0,1)这个范围里方便计算,这个函数就是激活函数。
感知机方面书上的内容很少,所以我没有深究,可以参看这里。
这里主要记录误差逆传播算法或BP算法的过程,网络上BP算法的文章很多,但很多不该省略的地方省略了,且多数都是互相转载,能用于理解的例子也是极其少,所以这里依然以西瓜为例子来描述BP算法的过程,当然因为这个过程真的蛮复杂,需要重复计算很多东西,因此以能明白这个过程为主就行了。
- 首先是数据集
下面是数据集的表格形式。
编号 | 色泽 | 根蒂 | 好瓜 |
---|---|---|---|
1 | 青绿 | 蜷缩 | 是 |
2 | 乌黑 | 蜷缩 | 是 |
3 | 乌黑 | 蜷缩 | 是 |
4 | 青绿 | 蜷缩 | 是 |
5 | 浅白 | 蜷缩 | 是 |
6 | 青绿 | 稍蜷 | 是 |
7 | 乌黑 | 稍蜷 | 是 |
8 | 乌黑 | 稍蜷 | 是 |
但是表格形式的数据并不能作为bp算法的输入。所以需要对其进行转换,形式如下:
设
色泽:
青绿 = 0,乌黑 = 1,浅白 = 2
根蒂:
蜷缩 = 0,稍蜷 = 1,硬挺 = 2
那么色泽的节点和根蒂的节点的数据集分别为:
node1色泽=[0,1,1,0,2,0,1,1] 和 node2根蒂=[0,0,0,0,0,1,1,1]
这里需要说明的是,输入节点及其个数是如何确定的?数据集的属性的个数就是输入节点的个数,上面这个例子的数据集只有色泽和根蒂两个属性,因此输入节点只有色泽和根蒂两个,但属性只能决定个数,其真实的值实际还是如上node色泽和node2根蒂的数据。
- 接下来就开始画图了
目前已知,输入节点的个数是两个,上面已解释过了;而输出节点也是两个,因为输出的节点数是由分类的个数决定的,这个例子的分类为是和否。而隐藏层,为了方便计算,我们假设有三个节点,实际情况隐藏层的节点数通常会有很多。
如上就是我们构建的神经网络模型的说明图,其中每根线上都一个w,它就是所谓的权重。它的作用可以与前面讲过的代价联系起来,主要代表这个属性的输入的重要性。当然现在是在赋初值,可以随机赋值,因为后面在逆传播的时候会动态调整这些参数,当这些参数为最优的时候,这个模型就算是做好了,可以进入预测阶段。
那么这里假设
w1-12 = [0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65]
b1-2= [0.35, 0.65]
这里的b是指的隐藏层和输出层的偏移,用于增加灵活性,它的值也是随机值。
-
接下来,就是正式的训练过程。首先是前向传播,即从输入到输出的数据流向。这个过程基本就是公式计算:
h1 = w1 * node1 + w4 * node2 + b1 = 0.1 * 0 + 0.25 * 0 + 0.35 = 0.35
h2 = w2 * node1 + w5 * node2 + b1 = 0.35
h3 = w3 * node1 + w6 * node2 + b1 = 0.35
需要注意node1和node2的值都为0,是因为我们这里在拿数据集进行训练,因为是第一轮所以从node1色泽里面拿到第一个值为0放到这个node1这个节点作为它的值,同样从node2根蒂拿到第一个值为0放到node2这个节点作为它的值,然后就可以计算。那么后面的值何时会用到呢?答案是第二轮开始就会分别拿第二个值。
这里计算的是三个隐藏层的值,其计算方式值得注意,它是以隐藏层节点为准进行权重相乘的。
然后通过激活函数对结果进行处理:
hi1 = 1 / (1 + e^(-0.35)) = 0.58
hi2 = 0.58
hi3 = 0.58
这三个变量被作为输入用于o1和o2的计算过程中,o1和o2的计算与前面计算隐藏层一样:
o1 = w7 * hi1 + w8 * hi2+ w9 * hi3 + b2 = 1.433
o2 = w10 * hi1 + w11 * hi2+ w12 * hi3 + b2 = 1.694
然后再通过激活函数对结果进行处理:
oi1 = 1 / (1 + e^(-1.433)) = 0.8
oi2 = 0.845
最后计算平方和误差:
E = ((1 - 0.8)^2) / 2 + ((0 - 0.845)^2) / 2 = 0.377一般使用1代表分类结果是,0代表分类结果否。 平方和的计算就是使用真实结果与计算结果的差别来判断是否需要进行逆传播来校正权重。 而具体误差应该小于多少是没有定论的,场景不同这个判断依据就不同,一般是小于0.1 。
- 因为上面计算出的误差太大,因此需要进行逆传播调整所有的w的值。
而这需要一个公式即:
那么现在要反向计算w7到w12的值,那么其公式如下:
Etotal是指上面的误差E,w5替换成w7,而这里的目标就是要求得E关于w7的偏导,它由三个偏导相乘而得。
公式右边第一部分是指的E关于oi1的偏导,那么因为E = ((target1 -output1)^2) / 2 + ((target2 -output2)^2) / 2, 其中target1为1(是),target2为0(否),而output1和output2分别为o1和o2。所以先进行求偏导,再进行带入o1和o2的值进行计算可得第一部分为0.2 。
公式右边第二部分是指的oi1关于o1的偏导,因为oi1 = 1 / (1 + e^(-o1)),所以直接对该式求偏导,可得
∂ o i 1 ∂ o 1 = e − o 1 ( 1 + e − o 1 ) 2 \frac{\partial oi1}{\partial o1} = {e^{-o1}\over (1 + e ^ {-o1})^2} ∂o1∂oi1=(1+e−o1)2e−o1
转换下可得:
∂ o i 1 ∂ o 1 = 1 1 + e − o 1 − 1 ( 1 + e − o 1 ) 2 \frac{\partial oi1}{\partial o1} = {1 \over 1 + e ^ {-o1}} - {1 \over (1 + e ^ {-o1})^2} ∂o1∂oi1=1+e−o11−(1+e−o1)21
最后可得:
∂ o i 1 ∂ o 1 = 1 1 + e − o 1 ∗ ( 1 − 1 1 + e − o 1 ) = o i 1 ∗ ( 1 − o i 1 ) \frac{\partial oi1}{\partial o1} = {1 \over 1 + e ^ {-o1}} * (1 - {1 \over 1 + e ^ {-o1}}) = oi1 * (1 - oi1) ∂o1∂oi1=1+e−o11∗(1−1+e−o11)=oi1∗(1−oi1)
现在因为oi1为0.8,所以带入可得第二部分为0.16 。
公式右边第二部分是指的o1关于w7的偏导,而上面写过o1 = w7 * hi1 + w8 * hi2+ w9 * hi3 + b2,对该式求偏导,可得第三部分为0.58。
最后三者相乘可得E关于w7的结果0.018。然后又需要依赖另一个公式:
Δ w = − n ∗ ∂ E k ∂ w \Delta w = - n * {\frac{\partial E_k}{\partial w}} Δw=−n∗∂w∂Ek
该公式基于梯度下降策略,以目标的负梯度方向对参数进行调整,所以该式在这里可以替换为:
w 新 = w 旧 − n ∗ ∂ E k ∂ w w_新 = w_旧 - n * {\frac{\partial E_k}{\partial w}} w新=w旧−n∗∂w∂Ek
这里的w旧是指的w7上一个值,即我们的初始值,现在需要求得它的新值;n代表学习率,然后就可以得到最新的w7 = 0.4 - 0.018 = 0.382 。
到这里就是w7的值的求得,接下来一样的方式需要求得从1到12的w值,到那时,第一轮就算是结束。接下来是第二轮,上面说过,从数据集里分别拿数组里第二的两个值作为node1和node2的值进行训练,做法还是一样,这里就不赘述。
通过上面的推导可以总结下来,bp算法的流程就是不断的来回训练数据,以调整所有的参数为目的,直到错误率非常小为止。本文有参考文章。
累计BP算法与标准BP算法的区别:都是BP算法,上面的例子就是标准BP算法,标准的做法上面也说了,每轮从node色泽和node2根蒂各取一个值,这样就需要来回很多次的调整w参数;而累计的做法在前向传播与标准是一样的,只不过,它会把所有的数据都先做一遍前向传播,然后得到非常多的E,最后取一根最优的E及其输出值,然后再做反向传播一次,调整好参数。需要注意的是两者都会做很多轮的训练,标准的算法在数据都迭代完了之后依然会继续重复做很多次,直到参数最优;累积一次把所有数据都训练了,但它同样会继续把这些数据重复做很多次,直到参数最优。