Pyhton入门
该书后续基本使用numpy来实现神经网络以及使用matplotlib绘制函数图像
Numpy
matplotlib
感知机(Perceptron)
感知机接受多个信号并根据内部一次多项式逻辑以及设置的阈值输出一个信号,输出信号只有0/1(根据阈值决定是否允许流通)。单层感知机的线性结构无法划分非线性空间,使用多层感知机叠加可以实现非线性的表示。单个感知机的结构如下图。
单个感知机的数学表示:
非线性空间
线性空间
神经网络
感知机与神经网络
神经网络与多层感知机有很多共同点,可以不严谨的理解为是可以自动学习权重与偏差的多层的多个感知机。其结构如下图所示,中间层又称为隐藏层(hidden layer)。
单个神经元(感知机)数学表示为
其中
需要注意到在神经网络中需要用到激活函数来实现感知机中控制输出的功能,神经元中将感知机的功能分为两步,首先计算输入信号加权后与偏置的总和,之后输入激活函数用于转换总和。
激活函数(Activation Function)
激活函数是连接神经网络与感知机的桥梁,在感知机中使用的激活函数称为阶跃函数,如果将阶跃函数换为其他曲线平滑(可导)的函数就可以进入神经网络的世界。
sigmoid函数
由于指数函数的性质,任何一个实数输入
ReLu函数
relu(Rectified Linear Unit)函数是近几年主要使用的激活函数
Tanh函数
激活函数之间的差别
输出层
机器学习大概可以将所有问题分为分类问题与回归问题。分类问题可以分为二分类与多分类,例如神奇宝贝分类与男女识别;回归问题则是预测一个具体的数值,例如股票预测。显然两类问题的输出要求是不一样的,回归问题仅仅输出一个数值,而分类问题通常输出与类别大小相同长度的数组,元素为0-1之间的概率,数组总和为1。
分类问题中常常在输出层使用softmax函数作为激活函数,softmax函数数学表示为
计算机中的数值运算问题
主要是计算机中浮点数表示的问题,浮点数有上溢区和下溢区之分,当浮点数的阶码大于最大阶码时,称为上溢,此时机器停止运算,进行溢出中断处理;如果阶码小于最小的阶码时,称为下溢, 此时溢出的数值非常小,直接强制将浮点数的尾数置为0,可以继续执行运算。
一些术语
向前传播(forward propagation)
神经网络向前推理的过程(predict)
正则化(normalization)
将输入映射到一个范围的转化
预处理(pre-processing)
数据在输入网络前的处理
识别精度(accuracy)
准确率=精度=accuracy、精确率=precision、召回率=recall
批(batch)
一次训练的输入样本个数
神经网络的学习
学习是指从训练数据中自动获取最优权重参数的过程,为了使神经网络能进行学习,将导入损失函数这一指标。而学习的目的就是以该损失函数为基准,找出能使它的值达到最小的权重参数。为了找出尽可能小的损失函数的值,绍利用了函数斜率的梯度法。
可以从图上看出,深度学习的方法取代了人工特征工程,实现了端到端(end-to-end)的解决方案。
训练数据和测试数据
机器学习中一般将数据分为训练数据集与测试数据集,首先在训练时,使用训练数据集进行学习,更新参数使网络能够拟合训练数据,之后用测试数据集测试模型的的泛化能力,是否能在未知的数据上预测出符合预期的结果。训练数据有时候也被称为监督数据,当模型在训练数据集上取得良好的结果,却在测试数据上表现不佳时,可能是出现了过拟合,所谓的过拟合(over fitting)指的是模型对于一个数据集过度拟合,但是无法处理其他数据集的情况。
损失函数
损失函数用于表示神经网络性能的恶劣程度,即当前的神经网络对监督数据在多大程度上不拟合,在多大程度上不一致,学习的目标即是找到一组参数使损失函数降到最低。这个损失函数可以使用任意函数,但一般用均方误差和交叉熵误差等。
之所以引入损失函数是由于识别精度本身无法通过求导(导数几乎都是0)来确定精度变化的趋势,因此无法通过小幅度的更改参数来提升精确度。
均方误差
交叉熵误差
mini-batch学习
通常在使用训练数据进行学习的时候,同时会输入许多条数据,则计算损失函数时也需要对这些数据进行计算。也就是说,如果训练数据有100个的话,我们就要把这100个损失函数的总和作为学习的指标。
以交叉熵误差为例,可以写成下面的式子
假设数据有
数值微分
损失函数与精确度相关,以此来衡量神经网络的优劣程度,学习的目标转为追求损失函数(凹函数)的最小值点,如果损失函数可导,则某一点的导数就表示某个极小范围的变化量,通过观察变化趋势来进行小范围更新参数,逐渐使导数趋近于零,得到最小值。
导数的数学定义,详见高等数学
由于网络中输入变量众多,因此在实际中往往是要对参数求偏导数,且由于神经网络中层与层复合的关系,也需要进行复合函数求导。
梯度
包含对应位置变量偏导数的向量。
函数的极小值、最小值以及被称为鞍点(saddlepoint)的地方,梯度为0。极小值是局部最小值,也就是限定在某个范围内的最小值。鞍点是从某个方向上看是极大值,从另一个方向上看则是极小值的点。虽然梯度法是要寻找梯度为0的地方,但是那个地方不一定就是最小值(也有可能是极小值或者鞍点)。此外,当函数很复杂且呈扁平状时,学习可能会进入一个(几乎)平坦的地区,陷入被称为“学习高原”的无法前进的停滞期。
梯度的方向并不一定指向最小值,但沿着它的方向能够最大限度地减小函数的值。因此,在寻找函数的最小值(或者尽可能小的值)的位置的任务中,要以梯度的信息为线索,决定前进的方向。
梯度法的数学表示
在神经网络中表示梯度
机器学习算法的实现
神经网络的学习分成下面4个步骤
- mini-batch
从训练数据中随机选出一部分数据,这部分数据称为mini-batch。我们的目标是减小mini-batch的损失函数的值。
- 计算梯度
为了减小mini-batch的损失函数的值,需要求出各个权重参数的梯度。梯度表示损失函数的值减小最多的方向。
- 更新参数
将权重参数沿梯度方向进行微小更新。
- 重复
重复以上步骤直到损失函数小于某个阈值
这个方法通过梯度下降法更新参数,不过因为这里使用的数据是随机选择的mini batch数据,所以又称为随机梯度下降法(stochastic gradient descent)
误差反向传播
计算图
计算图将计算过程用图形表示出来,引入计算图可以分解复杂运算。这里的图指的是有向无环图(DAG),我们在数据结构中曾经学习过有向无环图来描述数学表达式。
计算图一个优点就在于前面所说的局部计算。无论全局是多么复杂的计算,都可以通过局部计算使各个节点致力于简单的计算,从而简化问题。另一个优点是,利用计算图可以将中间的计算结果全部保存起来(比如,计算进行到2个苹果时的金额是200日元、加上消费税之前的金额650日元等)。但是只有这些理由可能还无法令人信服。实际上,使用计算图最大的原因是,可以通过反向传播高效计算导数。
链式求导与反向传播
神经网络中神经元之间的传递可以理解为一种复合的关系,复合函数求导需要用到链式求导法则(具体见高等数学)。与反向传播结合,我们可以从后面的梯度往前推前面各个参数所对应的梯度。
仍然和求导有关,基于函数的四则运算求导的规则,对于加法节点与乘法节点进行不同的反向传播计算规则。
反向传播实现
与学习相关的技巧
- 寻找最优权重参数的最优化方法
- 权重参数的初始值
- 超参数(Hyperparameter)的设定方法
- 权值衰减(Weight Decay)、Dropout等正则化方法(应对过拟合)
- Batch Normalization
参数更新
神经网络的学习的目的是找到使损失函数的值尽可能小的参数,寻找最优参数的问题,解决这个问题的过程称为最优化(optimization)。
随机梯度下降法(SGD)
这里把需要更新的权重参数记为
使用参数的梯度,沿梯度方向更新参数,并重复这个步骤多次,从而逐渐靠近最优参数,这个过程称为随机梯度下降法。
SGD的缺点是,如果函数的形状非均向(anisotropic),比如呈延伸状,搜索的路径就会非常低效。因此,我们需要比单纯朝梯度方向前进的SGD更聪明的方法。SGD低效的根本原因是,梯度的方向并没有指向最小值的方向。
Momentum
式(6.3)中有
会发现
AdaGrad
AdaGrad会记录过去所有梯度的平方和。因此,学习越深入,更新的幅度就越小。实际上,如果无止境地学习,更新量就会变为0,完全不再更新。为了改善这个问题,可以使用RMSProp [7]方法。RMSProp方法并不是将过去所有的梯度一视同仁地相加,而是逐渐地遗忘过去的梯度,在做加法运算时将新梯度的信息更多地反映出来。这种操作从专业上讲,称为“指数移动平均”,呈指数函数式地减小过去的梯度的尺度。
Adam
融合了Momentum和AdaGrad的方法。通过组合前面两个方法的优点,有望实现参数空间的高效搜索。此外,进行超参数的“偏置校正”也是Adam的特征。
使用哪种
很多研究中至今仍在使用SGD。Momentum和AdaGrad也是值得一试的方法。最近,很多研究人员和技术人员都喜欢用Adam。
权重的初始值
权重初始值不能设为0,将会导致无法学习,反向传播时梯度都将为0。
激活函数数值分布
sigmoid
标准差为1的高斯分布
初始权重为使用标准差为1的高斯分布产生的随机数情况下,各层激活值分布。各层的激活值呈偏向0和1的分布。
这里使用的sigmoid函数是S型函数,随着输出不断地靠近0(或者靠近1),它的导数的值逐渐接近0。因此,偏向0和1的数据分布会造成反向传播中梯度的值不断变小,最后消失。这个问题称为梯度消失(gradient vanishing)。层次加深的深度学习中,梯度消失的问题可能会更加严重。
标准差为0.01的高斯分布
这次呈集中在0.5附近的分布。因为不像刚才的例子那样偏向0和1,所以不会发生梯度消失的问题。但是,激活值的分布有所偏向,说明在表现力上会有很大问题。为什么这么说呢?因为如果有多个神经元都输出几乎相同的值,那它们就没有存在的意义了。比如,如果100个神经元都输出几乎相同的值,那么也可以由1个神经元来表达基本相同的事情。因此,激活值在分布上有所偏向会出现“表现力受限”的问题。
各层的激活值的分布都要求有适当的广度。为什么呢?因为通过在各层间传递多样性的数据,神经网络可以进行高效的学习。反过来,如果传递的是有所偏向的数据,就会出现梯度消失或者“表现力受限”的问题,导致学习可能无法顺利进行。
Xavier初始值
Xavier初始值下的数值分布,如果前一层的节点数为
图6-13的分布中,后面的层的分布呈稍微歪斜的形状。如果用tanh函数(双曲线函数)代替sigmoid函数,这个稍微歪斜的问题就能得到改善。实际上,使用tanh函数后,会呈漂亮的吊钟型分布。tanh函数和sigmoid函数同是S型曲线函数,但tanh函数是关于原点(0,0)对称的S型曲线,而sigmoid函数是关于(x,y)=(0,0.5)对称的S型曲线。众所周知,用作激活函数的函数最好具有关于原点对称的性质。
ReLu
Xavier初始值是以激活函数是线性函数为前提而推导出来的。因为sigmoid函数和tanh函数左右对称,且中央附近可以视作线性函数,所以适合使用Xavier初始值。但当激活函数使用ReLU时,一般推荐使用ReLU专用的初始值,也就是Kaiming He等人推荐的初始值,也称为“He初始值”[10]。当前一层的节点数为n时,He初始值使用标准差为
Batch Normalization
如果设定了合适的权重初始值,则各层的激活值分布会有适当的广度,从而可以顺利地进行学习。那么,为了使各层拥有适当的广度,“强制性”地调整激活值的分布会怎样呢?实际上,Batch Normalization方法就是基于这个想法而产生的。
Batch Norm,顾名思义,以进行学习时的mini-batch为单位,按mini-batch进行正规化。具体而言,就是进行使数据分布的均值为0、方差为1的正规化。
这里对mini-batch的
接着,Batch Norm层会对正规化后的数据进行缩放和平移的变换,用数学式可以如下表示。
γ和β是参数。一开始γ=1,β=0,然后再通过学习调整到合适的值。
Batch Norm的优点
- 可以使学习快速进行(可以增大学习率)
- 不那么依赖初始值(对于初始值不用那么神经质)
- 抑制过拟合(降低Dropout等的必要性)
Batch Norm评估
正则化
过拟合
过拟合指的是只能拟合训练数据,但不能很好地拟合不包含在训练数据中的其他数据的状态。机器学习的目标是提高泛化能力,即便是没有包含在训练数据里的未观测数据,也希望模型可以进行正确的识别。
发生过拟合的原因,主要有以下两个:
- 模型拥有大量参数、表现力强。
- 训练数据少。
权值衰减
权值衰减是一直以来经常被使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。很多过拟合原本就是因为权重参数取值过大才发生的。
神经网络的学习目的是减小损失函数的值。这时,例如为损失函数加上权重的平方范数(L2范数)。这样一来,就可以抑制权重变大。用符号表示的话,如果将权重记为
L2范数
L2范数相当于各个元素的平方和。用数学式表示的话,假设有权重
Dropout
如果网络的模型变得很复杂,只用权值衰减就难以应对了。在这种情况下,我们经常会使用Dropout[14]方法。
Dropout是一种在学习的过程中随机删除神经元的方法。训练时,随机选出隐藏层的神经元,然后将其删除。被删除的神经元不再进行信号的传递,如图6-22所示。训练时,每传递一次数据,就会随机选择要删除的神经元。然后,测试时,虽然会传递所有的神经元信号,但是对于各个神经元的输出,要乘上训练时的删除比例后再输出。
卷积神经网络(Convolutional Neural Network,CNN)
CNN被用于图像识别、语音识别等各种场合,在图像识别的比赛中,基于深度学习的方法几乎都以CNN为基础。CNN中新出现了卷积层(Convolution层)和池化层(Pooling层)。
与全连接层对比
在全连接层中,相邻层的神经元全部连接在一起,输出的数量可以任意决定。在输入是图片时,我们将图片进行Flatten,使输入从3维数据拉平为1维数据,变为一维的向量,这一操作破坏了图片重要的空间信息,且由于现代图片分辨率较高,全连接的神经网络结构将带来极大的计算复杂度。
而卷积层可以保持形状不变。当输入数据是图像时,卷积层会以3维数据的形式接收输入数据,并同样以3维数据的形式输出至下一层。因此,在CNN中,可以(有可能)正确理解图像等具有形状的数据。
另外,CNN中,有时将卷积层的输入输出数据称为特征图(feature map)。其中,卷积层的输入数据称为输入特征图(input feature map), 输 出数据称为输出特征图(output feature map)。
卷积
卷积运算
卷积层进行的处理就是卷积运算。卷积运算相当于图像处理中的“滤波器运算”。
对于输入数据,卷积运算以一定间隔滑动滤波器的窗口并应用。这里所说的窗口是指图7-4中灰色的3×3的部分。如图7-4所示,将各个位置上滤波器的元素和输入的对应元素相乘,然后再求和(有时将这个计算称为乘积累加运算)。然后,将这个结果保存到输出的对应位置。将这个过程在所有位置都进行一遍,就可以得到卷积运算的输出。
在全连接的神经网络中,除了权重参数,还存在偏置。CNN中,滤波器的参数就对应之前的权重。并且,CNN中也存在偏置。图7-3的卷积运算的例子一直展示到了应用滤波器的阶段。包含偏置的卷积运算的处理流如图7-5所示。
如图7-5所示,向应用了滤波器的数据加上了偏置。偏置通常只有1个(1×1)(本例中,相对于应用了滤波器的4个数据,偏置只有1个),这个值会被加到应用了滤波器的所有元素上。
填充
在进行卷积层的处理之前,有时要向输入数据的周围填入固定的数据(比如0等),这称为填充(padding),是卷积运算中经常会用到的处理。比如,在图7-6的例子中,对大小为(4,4)的输入数据应用了幅度为1的填充。“幅度为1的填充”是指用幅度为1像素的0填充周围。
使用填充主要是为了调整输出的大小。比如,对大小为(4,4)的输入数据应用(3,3)的滤波器时,输出大小变为(2,2),相当于输出大小比输入大小缩小了2个元素。这在反复进行多次卷积运算的深度网络中会成为问题。为什么呢?因为如果每次进行卷积运算都会缩小空间,那么在某个时刻输出大小就有可能变为1,导致无法再应用卷积运算。为了避免出现这样的情况,就要使用填充。在刚才的例子中,将填充的幅度设为1,那么相对于输入大小(4,4),输出大小也保持为原来的(4,4)。因此,卷积运算就可以在保持空间大小不变的情况下将数据传给下一层。
步幅
应用滤波器的位置间隔称为步幅(stride)。增大步幅后,输出大小会变小。而增大填充后,输出大小会变大。
三维数据卷积运算
通道方向上有多个特征图时,会按通道进行输入数据和滤波器的卷积运算,并将结果相加,从而得到输出。
将数据和滤波器结合长方体的方块来考虑,3维数据的卷积运算会很容易理解。方块是如图7-10所示的3维长方体。把3维数据表示为多维数组时,书写顺序为(channel, height, width)。比如,通道数为C、高度为H、长度为W的数据的形状可以写成(C,H,W)。滤波器也一样,要按(channel, height,width)的顺序书写。比如,通道数为C、滤波器高度为FH(Filter Height)、长度为FW(Filter Width)时,可以写成(C,FH,FW)。
图7-11中,通过应用FN个滤波器,输出特征图也生成了FN个。如果将这FN个特征图汇集在一起,就得到了形状为(FN,OH,OW)的方块。将这个方块传给下一层,就是CNN的处理流。
如图7-11所示,关于卷积运算的滤波器,也必须考虑滤波器的数量。因此,作为4维数据,滤波器的权重数据要按(output_channel,input_channel,height,width)的顺序书写。比如,通道数为3、大小为5×5的滤波器有20个时,可以写成(20,3,5,5)。
卷积运算中(和全连接层一样)存在偏置。在图7-11的例子中,如果进一步追加偏置的加法运算处理,则结果如下面的图7-12所示。
图7-12中,每个通道只有一个偏置。这里,偏置的形状是(FN,1,1),滤波器的输出结果的形状是(FN,OH,OW)。这两个方块相加时,要对滤波器的输出结果(FN,OH,OW)按通道加上相同的偏置值。另外,不同形状的方块相加时,可以基于NumPy的广播功能轻松实现(1.5.5节 )。
池化层
池化是缩小高、长方向上的空间的运算。比如,如图7-14所示,进行将2×2的区域集约成1个元素的处理,缩小空间大小。主要目的是减少计算复杂度,当然也会丢失一些信息(现在很多网络结构选择不使用池化层)。池化层没有要学习的参数,通道数不发生变化,对微小的位置变化具有鲁棒性(健壮)。
Comments | NOTHING