https://leidun.pp.ua/feed/21
参考文献:feed/13


感知器模型
鳄鱼和蛇
这里有代表鳄鱼和蛇的101010个点,横坐标x1x_1x1是身长 (cm)(cm)(cm) ,纵坐标x2x_2x2是体重 (kg)(kg)(kg) 。555个黄色的点代表555种鳄鱼的数据,蓝色的点是555种蛇。
| 🐊 |
|
🐍 |
|
| 扬子鳄 |
(150,36)(150, 36)(150,36) |
赤练蛇 |
(150,1.1)(150, 1.1)(150,1.1) |
| 恒河鳄 |
(400,160)(400, 160)(400,160) |
东部菱背响尾蛇 |
(170,2.3)(170, 2.3)(170,2.3) |
| 尼罗鳄 |
(316,137.5)(316, 137.5)(316,137.5) |
眼镜王蛇 |
(359,6)(359, 6)(359,6) |
| 美洲短吻鳄 |
(340,360)(340, 360)(340,360) |
森蚺 |
(521,97.5)(521, 97.5)(521,97.5) |
| 湾鳄 |
(460,465)(460, 465)(460,465) |
网纹蟒 |
(659,59)(659, 59)(659,59) |

现在我们来画一条线w1x1+w2x2=bw_1x_1 + w_2x_2 = bw1x1+w2x2=b,把鳄鱼和蛇分开。

同样的长度,鳄鱼比蛇重多了,所以我们可以轻松画出一条线把它们分开。代表这条线的w1x1+w2x2−b=0w_1x_1 + w_2x_2 - b = 0w1x1+w2x2−b=0,就是我们需要的分割线方程。
当输入的特征是nnn维向量时,那么分割线方程∑iwixi−b=0\sum_{i} w_i x_i - b = 0∑iwixi−b=0代表的则是nnn维空间里一个(n−1)(n-1)(n−1)维的超平面,把向量分成两类。
这跟人工智能又有什么关系呢?
分类是智能的源头
刚刚这个问题的本质是二元分类,而分类,其实就是智能的源头。
我们人类智能的源头,是神经元。我们的脑子里大约有850亿个神经元,你可以把它理解成一个逻辑开关。神经元可以接受多个上游细胞传来的信号,它们有的是刺激信号,有的是抑制信号,当一个神经元接收到的信号总和达到某个阈值,它就会被激活,通过轴突向下一个神经元传递信号。所以单个神经元的输出只存在两种状态:激活和未激活。

比如这个神经元,它接收2个树突信号x1x_1x1和x2x_2x2,不同的树突重要程度也不一样,我们可以用权重w1w_1w1和w2w_2w2来表示,如果所有的树突信号的总和∑iwixi\sum_{i} w_i x_i∑iwixi大于阈值bbb,神经元就会被激活;小于bbb,神经元不激活。
单层感知器是对生物神经元的高度简化数学抽象

当输入信号f(x)=∑iwixif(\bm{x}) = \sum_{i} w_i x_if(x)=∑iwixi大于阈值bbb,神经元被激活,我们把输出的结果yyy定义为111;如果f(x)f(\bm{x})f(x)小于阈值bbb,神经元不激活,输出的yyy就是000。
请你好好地记住这样一个神经元模型:输入xix_ixi,权重wiw_iwi,判断,输出yyy。
我们后面要介绍到的看起来非常复杂的各种神经网络,都是由一个一个这样的小神经元互相连结搭建起来的,而我们只要让它开始学习就好了。

流程很简单:

现在让我们看看,这个模型是怎么把鳄鱼和蛇自动分类的。
- 输入特征:就是动物的身长x1x_1x1和体重x2x_2x2
- 识别特征:是把每个点的x1x_1x1和x2x_2x2都代入信号公式f(x)=w1x1+w2x2f(\bm{x}) = w_1 x_1 + w_2 x_2f(x)=w1x1+w2x2
- 输出结果:如果大于bbb输出结果yyy就是111,小于bbb就是000
-
判断对错
如果我们把w1w_1w1的初始值设定为−1-1−1,w2w_2w2设定为000,bbb设定为−200-200−200,我们就可以得到坐标系里每一个点的计算结果。

我们把f(x)>bf(\bm{x})>bf(x)>b的点标成黄色,f(x)<bf(\bm{x})<bf(x)<b的点标成蓝色。可以看到有一条线,这就是我们前边介绍的分割线方程f(x)−b=0f(\bm{x})-b=0f(x)−b=0。改变www或者bbb,线的位置也会改变。

但这条线不重要,线是给你看的,不是给机器看的。机器看不懂线,也不知道黄色是鳄鱼区,蓝色是蛇区,但通过对每一个点的计算,机器能知道,这6个点错了。
- 湾鳄:(460,465)(460, 465)(460,465)
- 赤练蛇:(150,1.1)(150, 1.1)(150,1.1)
- 东部菱背响尾蛇:(170,2.3)(170, 2.3)(170,2.3)
- 尼罗鳄:(316,137.5)(316, 137.5)(316,137.5)
- 美洲短吻鳄:(340,360)(340, 360)(340,360)
- 恒河鳄:(400,160)(400, 160)(400,160)
为什么?这就是让神经元开始学习的核心环节:判断对错
输出的结果是yyy,而为了能让机器判断对错,我们在训练它时需要人为设定目标结果YYY,在这个例子里边,鳄鱼的目标结果是111,蛇是000。只有输出结果和目标结果一致,分类才正确。不一致,就是错。
怎么样才能让机器把分割线的参数调对呢?在一次次迭代中,这些参数要经过怎样的调整使得分类正确率越来越高?
用ttt代表迭代次数,那么参数更新公式为:
- wi(t+1)=wi(t)+Δwiw_{i(t+1)} = w_{i(t)} + \Delta w_iwi(t+1)=wi(t)+Δwi
- b(t+1)=b(t)+Δbb_{(t+1)} = b_{(t)} + \Delta bb(t+1)=b(t)+Δb
好,最核心也最有意思的部分终于来了:Δwi\Delta w_iΔwi和Δb\Delta bΔb是怎样计算出来的呢?
我们定义误差为预期与输出的差,即Y−yY-yY−y
如果分类正确,那么误差就是000,如果分类错误,那么误差就是111或者−1-1−1
如果误差为000,则意味着分类正确,不需要调整参数们,那么Δwi\Delta w_iΔwi和Δb\Delta bΔb都为000
如果误差不为000,则意味着分类错误,参数们需要沿着误差方向调整。当对应输入的特征xix_ixi越大,则调整的幅度也应该更大。
即:
Δwi=(Y−y)⋅xi⋅η\Delta w_i = (Y-y) \cdot x_i \cdot \etaΔwi=(Y−y)⋅xi⋅η Δb=(Y−y)⋅1⋅η\Delta b = (Y-y) \cdot 1 \cdot \eta Δb=(Y−y)⋅1⋅η
其中,η\etaη是学习率 (learning rate) ,它控制着每次调整的步长——调得太大会震荡不收敛,调得太小学习速度太慢。
现在只要机器判断错误,参数们就会自动调整。随着迭代次数变多,不断调整权重wiw_iwi和偏置项bbb的值,线性函数f(x)=wTx+bf(\bm{x})=\bm{w}^\mathrm{T} \bm{x} +b f(x)=wTx+b把已知数据分成两类的正确率会越来越高。
但是现在这个感知器模型还有一个致命缺陷。 

很多数据根本没办法使用一条直线、一个平面或者超平面分开。

比如来一条身长500cm500cm500cm体重50kg50kg50kg的鳄鱼,那感知器模型调到冒烟也不会成功的。

要解决这个问题,让我们先从经典的异或问题(XOR)——把这444个点分开开始
线性变换与平移
(0,0) (1,1)和(0,1) (1,0)

你可能会想,要是这条分割线能弯一下就好了,但很可惜,弯不了。
因为分割线方程∑iwixi+b=0\sum_{i} w_i x_i + b = 0∑iwixi+b=0是一次的,在二维平面里,它就是一条直直的线。

那我们不妨试着把这个二维空间弯一下。

这时候再调整分割线方程的参数,轻松分开两类点。
加一层
感知器模型的本质是一个二元分类器,输入有222个维度就是在222维空间用一条线把向量分成两块,输入有333个维度就是在333维空间用一个面把向量分成两块。

无论在几维空间,这个分类器都太直了,处理不了数据有交叉的情况。比如你刚刚试过的(0,0)(1,1)(0,0) (1,1)(0,0)(1,1)和(0,1)(1,0)(0,1) (1,0)(0,1)(1,0)。

因为分割线方程是一次的,体现在222维空间里,就一定是一条直线。既然线弯不了,我们可以试着弯曲整个坐标系。

让我们加入两个新的神经元,把它们连接在一起。这层中间层,就是线性变换与平移:
- z1=w1x1+w2x2+b1z_1 = w_1x_1 + w_2x_2 + b_1z1=w1x1+w2x2+b1
- z2=w3x1+w4x2+b2z_2 = w_3x_1 + w_4x_2 + b_2z2=w3x1+w4x2+b2
矩阵:操作向量的工具
看到上面两行等式,以及前文提到的输入信号公式:
f(x)=∑iwixif(\bm{x}) = \sum_{i} w_i x_if(x)=∑iwixi
有没有感到熟悉?
揭晓答案!上面那个从222维到222维的线性变换和平移可以表示成这个样子:
[z1z2]⏟z=[w1w2w3w4]⏟W[x1x2]⏟x+[b1b2]⏟b \underbrace{\begin{bmatrix} z_1 \\ z_2 \end{bmatrix}}_{\bm{z}} = \underbrace{\begin{bmatrix} w_1 & w_2 \\ w_3 & w_4 \end{bmatrix}}_{\mathbf{W}} \underbrace{\begin{bmatrix} x_1 \\ x_2 \end{bmatrix}}_{\bm{x}} + \underbrace{\begin{bmatrix} b_1 \\ b_2 \end{bmatrix}}_{\bm{b}} z[z1z2]=W[w1w3w2w4]x[x1x2]+b[b1b2]
这是我们熟悉的矩阵运算,而相乘再相加的输入信号公式f(x) f(\bm{x})f(x),也可以写成向量点乘的样子:
f(x)=wTx f(\bm{x}) = \bm{w}^\mathrm{T} \bm{x} f(x)=wTx
让我们来仔细感受一下矩阵W\mathbf{W}W是怎么起作用的

把向量[21]\begin{bmatrix} 2 \\ 1 \end{bmatrix}[21]放在坐标系里的过程其实可以拆成两步:从原点出发,往[10] \begin{bmatrix} 1 \\ 0 \end{bmatrix}[10]的方向走222个单位,再往[01] \begin{bmatrix} 0 \\ 1 \end{bmatrix}[01]的方向走111个单位。也就是找到基向量,乘上系数。基向量是我们描述、刻画向量空间的基本工具。
[21]=2[10]+1[01]=[1001][21]\begin{aligned} \begin{bmatrix} 2 \\ 1 \end{bmatrix} &= 2 \begin{bmatrix} 1 \\ 0 \end{bmatrix} + 1 \begin{bmatrix} 0 \\ 1 \end{bmatrix} \\ &= \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \begin{bmatrix} 2 \\ 1 \end{bmatrix} \end{aligned}[21]=2[10]+1[01]=[1001][21]
其中,单位矩阵[1001]\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}[1001]的两列可以看成两个自然基向量[10]\begin{bmatrix} 1 \\ 0 \end{bmatrix}[10]和[01]\begin{bmatrix} 0 \\ 1 \end{bmatrix}[01]。而改变这个矩阵,就意味改变基向量,也就是改变空间。以W=[3214]\mathbf{W} = \begin{bmatrix} 3 & 2 \\ 1 & 4 \end{bmatrix}W=[3124]为例,[31]\begin{bmatrix} 3 \\ 1 \end{bmatrix}[31] [24]\begin{bmatrix} 2 \\ 4 \end{bmatrix}[24]替代了[10]\begin{bmatrix} 1 \\ 0 \end{bmatrix}[10] [01]\begin{bmatrix} 0 \\ 1 \end{bmatrix}[01]成为了新的基向量,我们来计算一下[21]\begin{bmatrix} 2 \\ 1 \end{bmatrix}[21]在进行这个线性变换之后怎么表示:

从原点出发,往[31] \begin{bmatrix} 3 \\ 1 \end{bmatrix}[31]的方向走222个单位,再往[24] \begin{bmatrix} 2 \\ 4 \end{bmatrix}[24]的方向走111个单位,结果就是[86] \begin{bmatrix} 8 \\ 6 \end{bmatrix}[86]
这就是矩阵W\mathbf{W}W的作用:通过改变基向量,来让原本平直的坐标网格发生拉伸或旋转,从而使原本的向量都移动到一个新的位置。
好,现在你试试调整矩阵W\mathbf{W}W和向量b\bm{b}b,看看能不能把(0,0)(1,1)(0,0) (1,1)(0,0)(1,1)和(0,1)(1,0)(0,1) (1,0)(0,1)(1,0)分开。

揭晓答案!其实分不开。因为不论你怎么调整,也都还是线性变换,看起来还是直直的。解决方案其实也很简单,再加一层非线性变换。

在前面,我们早就见过非线性变换了。f(x)>bf(\bm{x})>bf(x)>b输出111,f(x)<bf(\bm{x})<bf(x)<b输出000。
我们重新整理一下,就能看到阶跃函数真正的样子:
step(x)={1if x≥00if x<0\text{step}(x) = \begin{cases} 1 & \text{if } x \ge 0 \\ 0 & \text{if } x < 0 \end{cases}step(x)={10if x≥0if x<0

这也是最简单的一种激活函数。
激活函数
除了阶跃函数,在机器学习中还有三种常见的激活函数:逻辑函数(Sigmoid),线性整流函数(ReLU)和双曲正切函数(Tanh)。



现在,我们可以用一种激活函数,把刚刚经过线性变换与平移得到的向量z=[z1,z2]T\bm{z} = [z_1, z_2]^\mathrm{T}z=[z1,z2]T转化为h=[h1,h2]T\bm{h} = [h_1, h_2]^\mathrm{T}h=[h1,h2]T
我们来动手试试看,任选一种激活函数,都可以分开(0,0)(1,1)(0,0) (1,1)(0,0)(1,1)和(0,1)(1,0)(0,1) (1,0)(0,1)(1,0)。

比如我们这里加一层阶跃函数,这个坐标系看起来就不存在了,横坐标跟纵坐标都只有000和111两个值。想想看,现在应该怎样分类呢?

在这种情况下,我们可以通过之前的线性变换与平移让(0,0)(0,0)(0,0)和(1,1)(1,1)(1,1)都变换到横纵坐标都小于000的位置,且此时(0,1)(0,1)(0,1)的横坐标小于000,纵坐标大于000;(1,0)(1,0)(1,0)的横坐标大于000,纵坐标小于000

我们再应用阶跃函数:输入小于000,则输出000,输入大于000,则输出111。那么原本的(0,0)(0,0)(0,0)和(1,1)(1,1)(1,1)都变换到(0,0)(0,0)(0,0)的位置,而(0,1)(0,1)(0,1)会成为(0,1)(0,1)(0,1),同时(1,0)(1,0)(1,0)也会成为(1,0)(1,0)(1,0)

这时我们就可以调整分割线方程,轻松分开(0,0)(1,1)(0,0) (1,1)(0,0)(1,1)和(0,1)(1,0)(0,1) (1,0)(0,1)(1,0)
冷静一下,在机器学习中,一般不使用阶跃函数来作为激活函数。一个好的激活函数应该有这些好的性质:
- 连续可导
- 定义域是实数域R\mathbb{R}R
- 单调递增
我们将在后续章节梯度下降中展开这部分内容。

终于,我们手动搞定了分类异或问题,回过头来看其实也挺简单。先设定好激活函数让坐标系变形,再通过调整矩阵W\mathbf{W}W和向量b\bm{b}b的线性变换和平移分开数据,最后再调整分割线方程,完成分类。

让我们来挑战一个复杂一点的:这里有606060个点,中间303030个白点作为一组,外围303030个黑点作为另一组。你试试看,还能不能分开?
线性变换与平移:升一维

你可能已经发现了,我们很难在一个222维平面中把两个圆环分开。但解决方案也很简单,加一个维度,把222维平面变换成333维空间。在中间层(线性变换与平移)再加一个神经元,我们就能在222维输入x=[x1,x2]T\bm{x}=[x_1,x_2]^\mathrm{T}x=[x1,x2]T的基础上构建333个维度:z1,z2z_1, z_2 z1,z2和z3z_3z3。
用矩阵运算来表示这个过程就是这样:
[z1z2z3]⏟z=[w1w2w3w4w5w6]⏟W[x1x2]⏟x+[b1b2b3]⏟b \underbrace{\begin{bmatrix} z_1 \\ z_2 \\ z_3 \end{bmatrix}}_{\bm{z}} = \underbrace{\begin{bmatrix} w_1 & w_2 \\ w_3 & w_4 \\ w_5 & w_6 \end{bmatrix}}_{\mathbf{W}} \underbrace{\begin{bmatrix} x_1 \\ x_2 \end{bmatrix}}_{\bm{x}} + \underbrace{\begin{bmatrix} b_1 \\ b_2 \\ b_3 \end{bmatrix}}_{\bm{b}} zz1z2z3=Ww1w3w5w2w4w6x[x1x2]+bb1b2b3

升维把原本密集的向量在高维空间里变得稀疏,从而更好被分开。

把333维空间中的分类情况投影到222维平面,两类数据之间的分割线,就是一个圆。

原本扭曲的异或分类在投影之后,坐标系会变直,分割线会变弯。但我们都知道,在那个高维空间里真正的分割线,实际上依然是平直的。
终于,我们得到了一个新结构,在最简单的感知器模型的基础上,加多了两层神经元:线性变换与平移和激活函数。我们能否让它像分类鳄鱼和蛇一样,自动完成对(0,0)(1,1)(0,0) (1,1)(0,0)(1,1)和(0,1)(1,0)(0,1) (1,0)(0,1)(1,0)的分类呢?
先别激动,现在还不行。在让它自动学习之前,我们还需要先下个山。
梯度下降

在只有一层神经元(阶跃函数)的感知器模型中,机器只需要沿着误差方向调整参数,总可以慢慢把模型的分类正确率提高。
即:
- Δwi=(Y−y)⋅xi⋅η\Delta w_i = (Y-y) \cdot x_i \cdot \etaΔwi=(Y−y)⋅xi⋅η
- Δb=(Y−y)⋅1⋅η\Delta b = (Y-y) \cdot 1 \cdot \eta Δb=(Y−y)⋅1⋅η
但是在有了隐藏层之后(即输入 → 隐藏层 → 输出层这样的多层神经网络中),隐藏层并没有所谓的预期结果。我们不知道隐藏层应该输出什么值才能让最终结果正确,事实上这也没有唯一的正确答案。
损失函数
既然不知道隐藏层“应该”输出什么,那就看隐藏层“导致”了最终多大的误差。

我们先来量化一个模型的误差。我们定义刚刚分类(0,0)(1,1)(0,0) (1,1)(0,0)(1,1)和(0,1)(1,0)(0,1) (1,0)(0,1)(1,0)的模型的损失函数(Loss function)L=14∑i=14∣Yi−yi∣L = \frac{1}{4} \sum_{i=1}^{4} \left|Y_i - y_i \right| L=41∑i=14∣Yi−yi∣ 我们可以用它衡量这个模型的误差,而这个结果与模型中的每一个参数都相关,也就是说L=f(w1,w2,w3,w4,w5,w6,b1,b2,b3)L = f(w_1, w_2, w_3, w_4, w_5, w_6, b_1, b_2, b_3)L=f(w1,w2,w3,w4,w5,w6,b1,b2,b3)
在机器学习中,我们更常使用一种在数学和优化上具备极大优势的形式——均方误差的一半(Half MSE)。将误差平方,并在求和前乘上12\frac{1}{2}21,也就是:
L=12n∑i=1n(Yi−yi)2L = \frac{1}{2n} \sum_{i=1}^{n} (Y_i - y_i)^2L=2n1i=1∑n(Yi−yi)2
在机器学习中,损失函数是非常核心的概念。有了这个标尺,我们才能给机器设定明确的目标,让损失函数越低越好。抽象来说,其实就是“下山”。以L=f(w1,w2,w3,w4,w5,w6,b1,b2,b3)L = f(w_1, w_2, w_3, w_4, w_5, w_6, b_1, b_2, b_3)L=f(w1,w2,w3,w4,w5,w6,b1,b2,b3)为例,这999个变量和损失值LLL构成了一个101010维空间里连绵起伏的山丘,机器需要在这101010个方向爬啊爬啊爬啊……直到爬到最低点。
构建了山丘还不够,我们还需要一个算法,给机器指明方向,找到下山的路。这个算法就是梯度下降(Gradient Descent)。
梯度下降的意思很简单,拆开来看就是:找准梯度的方向,然后下降。
什么是梯度?在单变量函数里,它是导数(斜率);在多变量函数里,它是偏导数构成的向量。
你可以把梯度理解为:在当前位置,指向山坡“最陡峭、上升最快”的那个方向。
而我们的目标是下山,那就沿着梯度的反方向走,就一定是在走最陡的下坡路。
也就是说,参数们应该这样调整:
θt+1=θt−η∇θL(θt)\boldsymbol{\theta}_{t+1} = \boldsymbol{\theta}_t - \eta \nabla_{\boldsymbol{\theta}} L(\boldsymbol{\theta}_t)θt+1=θt−η∇θL(θt)
这里用θ\boldsymbol{\theta}θ表示参数们构成的向量,展开来这个公式长这样子:
[w1w2⋮b1b2⋮]t+1=[w1w2⋮b1b2⋮]t−η[∂L∂w1∂L∂w2⋮∂L∂b1∂L∂b2⋮]t\begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ b_1 \\ b_2 \\ \vdots \end{bmatrix}_{t+1} = \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ b_1 \\ b_2 \\ \vdots \end{bmatrix}_{t} - \eta \begin{bmatrix} \frac{\partial L}{\partial w_1} \\ \frac{\partial L}{\partial w_2} \\ \vdots \\ \frac{\partial L}{\partial b_1} \\ \frac{\partial L}{\partial b_2} \\ \vdots \end{bmatrix}_{t}w1w2⋮b1b2⋮t+1=w1w2⋮b1b2⋮t−η∂w1∂L∂w2∂L⋮∂b1∂L∂b2∂L⋮t
这里的η\etaη是学习率,用来控制步长。负号意味着沿梯度的反方向调整参数。
学习率设得太大容易错过“谷底”,设得太小又收敛得太慢或者容易陷进局部最优解……
只要我们能算出损失函数 LLL 对每个参数的偏导数,机器就能自动调整参数,完成学习。可是这并不是一件容易的事情。
链式法则
对于输出层直接连接的参数,算偏导数并不难。但是,对于藏在网络深处、没有直接误差信号的隐藏层,我们该怎么求最终损失 LLL 对它的偏导数呢?
这里要用到我们中学时学过的复合函数求导法则——链式法则
如果要求L=f(w1,w2,w3,w4,w5,w6,b1,b2,b3)L = f(w_1, w_2, w_3, w_4, w_5, w_6, b_1, b_2, b_3)L=f(w1,w2,w3,w4,w5,w6,b1,b2,b3)对999个变量的偏导数,我们要做些准备工作。先随便设置一下999个参数的初始值,和z1z_1z1到h1h_1h1、z2z_2z2到h2h_2h2、z3z_3z3到yyy的激活函数。

和前面的激活函数章节里不同,为了算梯度,激活函数和输出层不能使用阶跃函数,因为它的导数几乎处处为000。好的激活函数应该有这些良好性质:
- 连续可导,为了能在反向传播中把损失传播到隐藏层。
- 定义域是实数域R\mathbb{R}R,并且有好的输出范围。比如可以在靠近输入层的神经元应用线性整流函数ReLU这类输出范围较大的激活函数,远离输入层的神经元应用双曲正切函数Tanh和逻辑函数Sigmoid这类输出范围较小的激活函数。
- 单调递增,保持梯度方向一致。
想一想,用阶跃函数作为激活函数有什么局限性?
前向传播
这里我们设z1z_1z1到h1h_1h1、z2z_2z2到h2h_2h2、z3z_3z3到最终输出yyy的激活函数都为逻辑函数Sigmoid。

然后把四个点代进去算一算。

以输入x=[1,0]T\bm{x}=[1,0]^\mathrm{T}x=[1,0]T为例:
z1=w1⋅x1+w2⋅x2+b1=0.1⋅1+0.2⋅0+0.7=0.8\begin{aligned} z_1 &= w_1 \cdot x_1 + w_2 \cdot x_2 + b_1 \\ &= 0.1 \cdot 1 + 0.2 \cdot 0 + 0.7 \\ &= 0.8 \end{aligned}z1=w1⋅x1+w2⋅x2+b1=0.1⋅1+0.2⋅0+0.7=0.8 h1=σ(z1)=11+e−z1=11+e−0.8≈0.69h_1 = \sigma(z_1) = \frac{1}{1 + e^{-z_1}} = \frac{1}{1 + e^{-0.8}} \approx 0.69h1=σ(z1)=1+e−z11=1+e−0.81≈0.69 z2=w3⋅x1+w4⋅x2+b2=0.3⋅1+0.4⋅0+0.8=1.1\begin{aligned} z_2 &= w_3 \cdot x_1 + w_4 \cdot x_2 + b_2 \\ &= 0.3 \cdot 1 + 0.4 \cdot 0 + 0.8 \\ &= 1.1 \end{aligned}z2=w3⋅x1+w4⋅x2+b2=0.3⋅1+0.4⋅0+0.8=1.1 h2=σ(z2)=11+e−z2=11+e−1.1≈0.75\begin{aligned} h_2 &= \sigma(z_2) = \frac{1}{1 + e^{-z_2}} = \frac{1}{1 + e^{-1.1}} \approx 0.75 \end{aligned}h2=σ(z2)=1+e−z21=1+e−1.11≈0.75 z3=w5⋅h1+w6⋅h2+b3=0.5⋅0.69+0.6⋅0.75+0.9=0.345+0.45+0.9≈1.69\begin{aligned} z_3 &= w_5 \cdot h_1 + w_6 \cdot h_2 + b_3 \\ &= 0.5 \cdot 0.69 + 0.6 \cdot 0.75 + 0.9 \\ &= 0.345 + 0.45 + 0.9 \\ &\approx 1.69 \end{aligned}z3=w5⋅h1+w6⋅h2+b3=0.5⋅0.69+0.6⋅0.75+0.9=0.345+0.45+0.9≈1.69 y=σ(z3)=11+e−z3=11+e−1.69≈0.84\begin{aligned} y &= \sigma(z_3) = \frac{1}{1 + e^{-z_3}} = \frac{1}{1 + e^{-1.69}} \approx 0.84 \end{aligned}y=σ(z3)=1+e−z31=1+e−1.691≈0.84
输出y≈0.84y \approx 0.84y≈0.84离目标Y=1Y=1Y=1还有点距离,我们可以进一步算出损失值,在输入只有一个点的情况下L=12×1(Y−y)2=0.0120L = \frac{1}{2 \times 1} (Y - y)^2=0.0120L=2×11(Y−y)2=0.0120
我们从左往右填完了所有的空,这个过程被称为前向传播(Forward Propagation):将训练输入送入网络以获得激励响应。
反向传播
接下来我们开始反向传播(Backward Propagation,“误差反向传播”的简称,该方法对网络中所有权重计算损失函数的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数)。
直观地,就是从右边的损失值LLL来推算出左边的参数们wiw_iwi和bib_ibi要改变的值。也就是在损失函数上做梯度下降,即求LLL对999个参数的偏导数。
以b3b_3b3为例,损失函数LLL对b3b_3b3的偏导数可通过链式法则分解为:
∂L∂b3=∂L∂y⋅∂y∂z3⋅∂z3∂b3\frac{\partial L}{\partial b_3} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial z_3} \cdot \frac{\partial z_3}{\partial b_3}∂b3∂L=∂y∂L⋅∂z3∂y⋅∂b3∂z3
我们逐项计算:
-
损失对输出的偏导(均方误差损失 L=12(Y−y)2L = \frac{1}{2}(Y-y)^2L=21(Y−y)2):
∂L∂y=−(Y−y)=y−Y\frac{\partial L}{\partial y} = -(Y - y) = y - Y∂y∂L=−(Y−y)=y−Y
-
输出对加权输入的偏导(Sigmoid 逻辑函数 σ(z)=11+e−z\sigma(z) = \frac{1}{1+e^{-z}}σ(z)=1+e−z1,其导数为 σ′(z)=σ(z)(1−σ(z))\sigma'(z) = \sigma(z)(1-\sigma(z))σ′(z)=σ(z)(1−σ(z))):
∂y∂z3=σ′(z3)=y(1−y)\frac{\partial y}{\partial z_3} = \sigma'(z_3) = y(1-y)∂z3∂y=σ′(z3)=y(1−y)
-
加权输入对偏置的偏导(z3=w5h1+w6h2+b3z_3 = w_5 h_1 + w_6 h_2 + b_3z3=w5h1+w6h2+b3):
∂z3∂b3=1\frac{\partial z_3}{\partial b_3} = 1∂b3∂z3=1
因此:
∂L∂b3=(y−Y)⋅y(1−y)⋅1\boxed{\frac{\partial L}{\partial b_3} = (y - Y) \cdot y(1-y) \cdot 1}∂b3∂L=(y−Y)⋅y(1−y)⋅1
代入数值 y≈0.84y \approx 0.84y≈0.84, Y=1Y = 1Y=1:
∂L∂b3≈(0.84−1)×0.84×(1−0.84)≈−0.02\begin{aligned} \frac{\partial L}{\partial b_3} &\approx (0.84 - 1) \times 0.84 \times (1 - 0.84) \\ &\approx -0.02 \end{aligned}∂b3∂L≈(0.84−1)×0.84×(1−0.84)≈−0.02
想想看,形如Δb3=−η∂L∂b3\Delta b_3= - \eta \frac{\partial L}{\partial b_3}Δb3=−η∂b3∂L是单层感知器模型参数更新公式的推广吗?
Δwi=(Y−y)⋅xi⋅η\Delta w_i = (Y-y) \cdot x_i \cdot \etaΔwi=(Y−y)⋅xi⋅η
Δb=(Y−y)⋅1⋅η\Delta b = (Y-y) \cdot 1 \cdot \eta Δb=(Y−y)⋅1⋅η
同理,我们可以算出损失LLL剩下888个参数的偏导数,然后接着对剩下333个输入做前向传播算出损失和梯度。遍历完整个训练集444个输入之后,对算出来的444个梯度求平均,乘上−η-\eta−η,这就是这次迭代参数们需要改变的值。这样就完成了一次反向传播。
梯度比较大的时候,学习率可以适当设得大一些,坡度足够高时可以大胆跨大步下山;梯度比较小的时候,学习率应该设小一些,以防止错过谷底。
像这样,一轮前向传播遍历了整个训练集才做了一次反向传播的梯度下降叫做批量梯度下降(Batch Gradient Descent)
终于,我们这个神经网络能够自动完成对(0,0)(1,1)(0,0) (1,1)(0,0)(1,1)和(0,1)(1,0)(0,1) (1,0)(0,1)(1,0)的分类……
终点:(0,0) (1,1) 和 (0,1) (1,0)
现在,你已经掌握了机器学习的核心:
- 基本的感知器单元
- 带有目标值的训练数据
- 可以“扭曲空间”的隐藏层
- 以梯度下降为核心的更新权重的算法
把它们拼装在一起,见证人工智能的诞生吧。



暂无评论