
2.2.2 单层神经网络
我们把需要计算的层称之为“计算层”,并把拥有一个计算层的网络称之为“单层神经网络”。有一些文献会按照网络拥有的层数来命名,例如把“感知器”称为两层神经网络。所以一个感知器就可以构成一个只有一个神经单元的单层神经网络。
让我们举一个实际的例子来理解感知器,也就是一个单层神经网络(如图2-11所示)是如何工作的。电影院新上映了一部科幻片,小明同学非常感兴趣,不过他自己拿不定主意是不是要去参加,他需要考虑以下三个因素。
(1)天气,周末是不是晴天?
(2)同伴,能不能找到同学一起去?
(3)价格,电影票的价格是否可以承受?

图2-11 单层神经网络
以上这三个因素就构成了一个最基础的感知器,需要输入三个参数,分别与权重值组合,最终计算出Z值,应该就反映出小明决定去不去看电影的一个概率。
Z=a1×w1+a2×w2+a3×w3
那么,如果今天天气不错,也有同伴,但是电影票价格太贵了,小明会不会去看电影呢?接下来,就通过神经网络来帮助我们进行估计。这里最重要的就是,需要知道w1,w2,w3分别取什么样的值,这样才能进行计算以判断小明是否去看电影。
这里可以试试通过人脑去估计这种场景下,小明是否去看电影呢?答案是不知道的,因为我们不知道小明同学以前在类似情况下,会做出什么样的决定。此时我们就需要数据作为判断的依据,见表2-1。
表2-1 数据表

这张表一共有4行数据,表示小明之前出现类似情况时,最终如何做是否去看电影的决定。其中,天气一列的1和0分别表示当天的天气是晴天,还是雨天;同伴一列的1和0分别表示当天是否邀请到好朋友一起去看电影;价格一列的1和0分别表示电影票的价格是否在小明的可承受范围内,将这三列数据称为决策源。最后,去看电影一列,表示的是决策的结果,1和0分别表示当天小明最终是否去看了电影。
表2-2 决策源

如表2-2决策源所示,我们将最终去看电影的决策与之前的决策源筛选出来,可以更清晰地看出,单个条件对最终决策的影响,例如,天气几乎对最终是否去看电影没有影响,而是否有同伴,则对是否去看电影有一定影响,最后,价格是否在可承受范围内,与最后是否去看电影有很强的关联性。所以,小明最终是否去看电影,最具有影响力的应该是价格,其次是是否找到了同伴,最后才是天气是不是晴天,也就是w3>w2>w1。如果这个星期天的情况是,价格满足要求,找到了同伴,虽然天气不是晴天,小明同学也极有可能去看电影。
当然,这个分析结果是我们用人脑中千亿个神经单元经过漫长的学习训练分析得出的,如果是使用只有一个神经元的人工神经网络应该如何得出这个结论呢?和人脑一样,神经网络也需要通过训练来确定w1,w2,w3的值。训练好的参数值,也被称为神经网络的模型(model),参见图2-12神经网络模型。

图2-12 神经网络模型
神经网络通过先猜测一个权重值,代入到经验中进行检测,并通过错误反馈,不停与现有数据进行比较,进行参数调整。也就是先随机选三个数,赋值给w1,w2,w3,不停地与之前已经发生的事实对比。如果差距较大,则进行相应的调整。接下来,让我们再详细看看单个神经网络的运算过程。
第一步,数据集获取。
首先,我们将数据抽象为方便计算的形式,表格化的数据非常容易被抽象为“二维矩阵”,这里的二维矩阵和大家数学上接触的线性代数的矩阵,或者编程语言中的矩阵是一个概念。

图2-13 数据集获取
如图2-13所示,我们将小明之前做的决策源,也就是天气、同伴、价格3个因素整理为一个4行3列的矩阵,一般我们称之为4×3的矩阵,而决策则整理为一个4×1的矩阵。
第二步,神经元权重值初始化。
一开始,神经网络并不知道,是天气对小明做出决策比较重要,还是电影票价格对小明的决策更重要,所以,可以对w1,w2,w3进行随机初始化。随机时,我们也希望随机值不要太大,或者太小,这里我们将w1,w2,w3在[-1,+1]范围内取一个随机值,越靠近1,决策源的作用越大;越靠近-1,决策源的作用越小。为了便于后续计算,我们假设取到的随机值w1=-0.27,w2=0.83,w3=-0.41,也就是说,最开始未经过训练的神经网络猜测,最重要的决策源是同伴,而最不重要的决策源是价格。这似乎与我们大脑得出的结论不太相符。接下来,我们会看到神经网络经过学习,会对权重值进行调整。
第三步,结果计算(正向传播)。
神经网络学习过程中,最重要的就是要了解到结果是不是错误的。这里,我们就利用小明之前的决策进行判断,这一步我们通常会称之为神经网络的“损失函数”。不同的神经网络需要设计不同的损失函数,这里我们将损失函数定义为,在当前w1,w2,w3权重值下,和之前小明8次去电影的决策差距。
在图2-14中,使用6×3的决策源矩阵,点乘(矩阵乘)上3×1的权重值矩阵,得到4×1的预测结果矩阵。如果我们可以将其与实际决策的4×1矩阵进行对比的话,就能获得误差,这里有一个问题,实际决策的结果只有两种可能:1,小明去了;0,小明没去。我们计算出的预测结果的值是不固定的,跟进决策源的个数与权重值可能会大于1,也可能会小于0。此时,我们就可以使用激活函数Sigmoid来进行处理,将任意值约束到(0,1)范围再进行输出,参见图2-15激活函数。

图2-14 正向传播

图2-15 激活函数
经过激活处理后,预测结果被映射到一个(0,1)的区间,可以认为这是在当前权重值计算下,小明可能去看电影的概率。由于这是历史数据,小明最终是否去看电影是已经知道的,所以就可以对激活处理后的预测矩阵与实际决策矩阵进行误差计算,误差计算的方法也很简单。就是通过矩阵相减得到差值。很明显,差值越大,预测结果越差,差值越小,预测结果越好。
第四步,调整大小(梯度下降)。
通过第三步的计算,我们已经得到了一个误差结果。现在需要通过这个误差,对权重值进行调整,以期望下一次获得更小的误差。
那么我们是否可以直接使用误差矩阵去更新权重值呢?答案是否定的,或者可以称这是一个非常不好的决定。因为直接使用误差进行更新,无法反映越接近正确目标,调整参数应该越来越谨慎这一原则。例如,我想快速拿起一个水杯,那么在最开始时,手的速度应该非常快;而越靠近水杯时,手的速度应该放慢。因为手的速度太快的话,就很容易碰到水杯。
回到我们的问题,我们希望求出激活处理后的预测矩阵最终接近什么样的效果?因为希望知道小明最终会不会去看电影,那么越接近0,或者越接近1,就越能帮助我们确定结论,而概率0.5对我们帮助并不大。为了达到这个效果,我们对Sigmoid函数进行观察,会发现,越靠近中间0.5的地方,曲线越“陡峭”,越靠近1,或者0的地方,曲线越“平缓”,这正是我们希望的效果,而一个函数的曲线“陡峭”或者“平缓”,正是函数导数的作用。预测结果见图2-16。

图2-16 预测结果
有陡峭和平缓的幅度区分还不够,我们还需要一个值来确定调整的大小与步长,这里就可以利用误差矩阵了,这个值反映了距离正确的结果还有多大的差距。于是,可以使用误差矩阵中的值乘以预测矩阵求导后的值,如图2-17所示。经过一系列计算,我们得到了一个趋向调整值矩阵,而每个预测结果经过趋向调整后,都会更接近于实际决策,不过还需要通过调整矩阵对权重值进行调整。
第五步,权重调整。
最后,是进行权重调整。很直观的感受就是,我们希望6个预测结果都更接近于实际决策,但权重值只有3个,这里就需要使用计算得到的趋向调整矩阵来对权重值进行调整。

图2-17 求导值
首先,需要明白的是,趋向调整矩阵中的每个值都是3个决策因素共同的影响结果,而权重值是单个决策因素调整的值。如果我们知道了单个权重值应该如何调整,我们就知道了所有的权重应该如何调整。这里使用的方法是使用决策矩阵的转置乘以趋向调整矩阵,再以这个例子进行解释,见图2-18。

图2-18 权重调整例子
决策源矩阵原来每一行表示一次决策,列分别表示天气、同伴、电影票价格。将矩阵转置后变成,行表示天气、同伴、电影票价格,列表示决策。而矩阵点乘是使用前一矩阵的行,乘以后矩阵的列,也是权重调整矩阵的第一个数0.115,是通过决策源转置矩阵的第一行乘以趋向调整矩阵的列计算得到的,即:1×0.114+1×0.148+0×(-0.147)+1×(-0.147)计算得出的,而决策源转置的第一行代表天气因素,趋向调整矩阵代表整体应该调整的方向。这样就得到了单个天气因素应该调整的方向。依次类推,就可以知道同伴、电影票价格应该调整的方向。
从图2-19权重调整可以看到,神经网络经过第一次训练,认为电影票价格的权重应该提升,同伴的权重应该小一些,但同伴的影响因素是最大的,这与我们人脑识别的结果还是有一定差距的。不过,神经网络再经过多次训练,就会更接近人脑识别效果了。

图2-19 权重调整
第六步,多次训练。
一个单神经元单层的神经网络一次更新过程完成后,自然误差值仍然比较大,我们循环1000次对神经网络进行训练,最后,可以得到w1=-3.8,w2=0.46,w3=6.69。可以清晰地看出,小明做决策时,权重大小依次是价格、同伴和天气。如果这个周日的情况是天气不好,但是找到了同伴,电影票价格也满足了要求,通过计算,小明可能去看电影的概率z=7.15。此时,我们会产生疑惑,去看电影的概率7.15是否够大呢?此时,我们仍然可以通过Sigmoide函数来对结果进行转换,转换后的概率是99%,说明小明非常有可能去看电影。如果我们将条件转换为天气很好,同伴也找到了,但是电影票钱太贵,那么小明去看电影的概率将会是3%,这就和我们人脑的判断很接近了。可以看到,神经网络的训练就是一个不停寻找合适权重值的过程,参见图2-20。

图2-20 多次训练