📚简单神经网络
type
status
date
slug
summary
tags
category
icon
password
当输入为标量
对于一个最简单的神经网络而言,它的一个神经元通常长这个样子:

假设我们有a1, a2, ... , an共n个输入,对于每个输入都给定一个权重w1, w2, ... , wn,再给定一个偏置b,将权重和输入相乘,加上偏置,就得到了一个神经元SUM,SUM的表达式为:SUM = w1 * x1 + w2 * x2 + ... + wn * xn + b,在这里由于各个项都是标量,得到的结果SUM也是一个标量。得到了SUM这个输出神经元后,我们通常会在后面加一个激活函数(上图中的f),增强其拟合数据的能力。通过相乘和相加的运算,并通过激活函数后,我们得到了最终的结果t(上图中最后的小圆圈)。
上图仅仅是一个神经元,在神经网络的不同层中,往往有不止一个神经元,所以在学习神经网络的过程中,我们往往会看到如下图所示的神经网络的示意图:

在这张图所表示的神经网络中,有一个输入层(input layer),三个隐层(hidden layer 1-3),最后是一个输出层(output layer),下面一一进行分析(在这步及其以后的分析中,我都会忽略偏置b,因为偏置对于形状的变化没有影响):
在input layer层,也就是输入层,我们先还是假设输入是简单的标量,即:a1, a2, ... , an,这时候我们看到input layer后的hidden layer 1层,就远远不止一个神经元了。第一步的分析中我们知道,每个输入都对应一组权重:w1, w2, ... , wn,有了这组权重之后,我们才能计算得到一个神经元的值,那么对于hidden layer 1中9个神经元的情况,我们自然也需要9组不同的权重,每组权重分别和输入计算得到一个神经元,每组权重都是独立的。分析完了hidden layer 1 之后,其余的两个隐层和最后的输出层也是同样的处理,比如要计算得到hidden layer 2,我们可以把hidden layer 1的每个神经元看成输入;要计算得到output layer,把hidden layer 3中的每个神经元看成输入。
补充一些小细节:
1.一般神经网络的示意图中,都是跟上图一样,只画一个圆圈表示神经元,但是不画激活函数,但其实激活函数已经包含在这个小圆圈里面了,便于理解,可以将神经元的这个小圆圈从中间切一刀,前半部分的状态是输入的各个量乘以权重,加上偏置得到的未经过激活函数之前的状态,然后把中间的这条竖线看成是激活函数,那么右半边的这个半圆就是代表通过激活函数之后的神经元了。
2.若神经网络要完成一个分类任务,输出层output layer通常使用softmax作为激活函数,想实现n分类,把输出层的神经元数量也设计为n即可,各个层的神经元的数量都是可以自己设计的。
当输入为向量
但是我们在用一些深度学习的框架完成一些任务的时候,往往会发现输入的形式往往不是一个数(标量),通常情况下都是一个多维的向量,这时候的情况要略微复杂一些,看下面这张神经网络的图:

在这张图中,只画了两层的网络:N-1层,N层,N-1层可以是输入层,也可以是任意的一个隐层,在前面中我们提到,隐层的神经元在计算得到下一层的网络时,可以看成输入。所以无论N-1层是输入层还是隐层,都可以看成输入层,图中N-1层有n个神经元(图中只标了8个,但是讨论中我们认为这一层的神经元数量是n,而第N层的神经元数量是k),那么我们可以认为对应n个标量的输入,观察这个式子,有了前面的讲解,这个式子应该非常容易理解:

这个式子的结果就是如图中箭头所示的神经元,下标的0是代表这个神经元在当前层中,它是第一个神经元,上标的(1)代表层的标号(N-1层中神经元的标号是0,那么N层就是1,以此类推),继续观察式子中的权重参数,w有两个下标,第一个下标都是0,代表它们都是第一组权重(也就是得到下一层第一个神经元的一组w),后面的下标是0-n,就是对应n个神经元的输入。那么对应的,要是我们想要计算得到第N层第二个神经元,那么这组w就应该为...,这样的w共有n组,n取决于第N层到底有多少个神经元。
那么此时思考两个问题,1.怎么表示这个n组w?2.怎么表示权重w和输入的相乘呢?答案是矩阵相乘的形式:

首先为了避免混淆,再次说明下图中符号的含义:N-1层有n个输入神经元,第N层有k个神经元,也就是说:要通过运算,做一个形状变化,由N个神经元的层,变为k个神经元的层。
图中可以看到,我们把输入变为列向量的形式,形状为[n,1];把k组权重w变成了矩阵的形式,形状为[k,n]。由矩阵乘法的定义可知,前面矩阵的列,后面矩阵(列向量也是矩阵)的行相同,可以进行乘法运算,可以得到一个[k,1]的矩阵,恰好代表了第N层的k个神经元。最后仔细思考一下矩阵乘法的运算过程,这跟我们前面讨论的标量的情况是一模一样的。
考虑batch_size
以上,我们理解了标量的输入形式和向量的输入形式。但往往我们用数据的时候,会有一个维度叫做batch_size。换而言之,我们的输入往往不止一个数据,在把数据喂给神经网络时,通常情况下我们都有一个batch_size,也就是同时把一批数据作为输入。我们还是在上图矩阵相乘的图中考虑此时跟之前一个样本时候的差异。
1.之前一个样本的时候,输入是列向量的形式,此时样本数量变多,那么这个时候在列这个维度上,自然不然是1了,此时的输入应该是一个矩阵,其形状是[n,batch_size],即行不变,每一列代表一个样本的所有特征输入。
2.权重矩阵w不变,形状仍然是[k,n],样本量的变化并不会影响权重矩阵的形状。此时进行矩阵乘法发现,[k,n]*[n,batch_size]得到的结果为[k,batch_size],k代表计算得到结果的这一层的神经元数量。在过程中我们可以发现,无论通过几次矩阵运算,batch_size这个维度始终不会变化,因为权重矩阵都是针对一个样本的,样本间是“互相独立”的,但是权重矩阵是公用的。用深度学习框架设计网络结构时,也不会考虑batch_size这一维。
总结以及易混淆的要点梳理
以下是之前我在学习deep learning的一些困惑,可能看一遍会有所帮助:
1.上面几张神经网络的示意图,也包括我们在网上看到的所有神经网络的结构,都仅仅是“针对一个样本”的,也就是说,我们设计网络结构的时候,不会去考虑样本的数量,也就是说,不会去考虑batch_size这个维度,这一点相信在使用深度学习框架设计网络结构的时候,都会深有体会。
2.为什么要一次向网络中输入多个样本呢?因为这样才能发挥GPU并行计算的优势,GPU能够加速神经网络的收敛,其实现原理的底层就在于它能够加速张量(向量)的运算。GPU跟CPU相比,运算能力远远没有CPU那么强,但是GPU有很多小的运算核心,对于一些简单的运算任务,它能挥发“人多力量大”的优势,而CPU虽然运算能力很强,但是没有那么多的核心。就好比做极为简单的加减乘除数学题,100个小学生和一个博士都能做,但是两者数量存在差异,使得小学生做相同的题反而比博士快得多。恰巧神经网络能够充分发挥并行计算的优势(神经网络本质就是矩阵向量间的运算),所以GPU在深度学习中至关重要。
3.既然GPU能够对多个样本进行并行计算,为什么不一次性将所有样本输入呢?当数据量过大的时候,输入矩阵的维度也跟着膨胀,一次喂给神经网络的样本过多,会超过GPU的负载能力。因此batch_size的设计要合理,不能过大也不能过小。
4.考虑下batch_size这个维度,理一下神经网络的优化过程:对于一个样本,输入层的n个神经元就是其特征的维度,比如我们要进行房价的预测任务,房价高低有多个影响因素,比如地理位置,平方数等。也就是有多个特征,这些特征都需要转化成可以量化的数据进行表示。一个房价样本通过隐层到输出层,输入通过层与层之间一系列的权重得到了最终的输出,跟这个样本的目标值(比如该预测任务中,目标值就是房价)计算损失(分类和回归有不同的损失函数),最后反向传播,更新权重参数w,这就是一个完整的过程。当然一个样本肯定不能把w更新的很完美,那么所有数据中的样本都通过神经网络一遍,自然神经网络就能找出输入数据共性的规律,然后将这些规律反映在权重参数w中。还是那房价预测的例子直观感受下:房价高低必然是受地理位置,平方数等因素影响的,其中每个因素影响有大有小,将房价样本通过神经网络,假设就学习到了:房价=平方数0.8+地理位置0.2,0.8和0.2就是在大量样本中学习到的,也就是模型的参数,有了这些参数后,后续就能根据特征进行最终房价的预测。
5.各种优化算法(梯度下降BGD,随机梯度下降SGD等)是怎么体现的呢?在4中,我们说的是一个样本,但是实际中一次有batch_size个样本,事实上在进行反向传播更新参数的时候,我们通常也不是每次就根据一个样本来更新参数的,而是有着更多样化的选择。比如梯度下降算法(BGD):每次迭代都需要把所有样本都送入,这样的好处是每次迭代都顾及了全部的样本,做的是全局最优化,但是有可能达到局部最优。随机梯度下降(SGD):从样本中随机抽出一个,训练后按梯度更新一次,然后再抽取一个,再更新一次(看到一个样本就更新一次,类似4中的方法),优点在于在样本量极其大的情况下,可能不用训练完所有的样本就可以获得一个损失值在可接受范围之内的模型。缺点在于单个样本的训练可能会带来很多噪声,使得SGD并不是每次迭代都向着整体最优化方向,因此在刚开始训练时可能收敛得很快,但是训练一段时间后就会变得很慢。当然还有小批量梯度下降等:选取一个小批次的样本计算损失,然后进行参数更新,是大多数情况下一个较为常用,也是较为优秀的优化算法的选择。
6.怎么理解将数据按照batch_size分成好几个批次,还要设计各种SGD/BGD等优化算法,这两者不是矛盾了吗?首先,梯度下降的各种算法是在batch_size的基础上的,也就是说。即使你使用的是BGD,顾及所有样本进行梯度更新,这个所有样本也只是当前的batch_size的大小,并不是所有数据。当然如果batch_size比较小,直接兼顾所有样本用BGD也可以,但实际上我们用其他的优化算法用的比较多,很少用BGD。所以batch_size和各种优化算法并不矛盾。
上一篇
机器学习
下一篇
卷积神经网络CNN
Loading...