数据驱动
神经网络的特征是可以从数据中学习,即可以由数据自动决定权重参数的值。
人工学习、机器学习、深度学习的区别:
人工学习:数据——>人想到的算法——>答案
机器学习:数据——>人想到的特征量(SIIFT、HOG等)——>机器学习(SVM、KNN等)——>答案
深度学习:数据——>神经网络(深度学习)——>答案
训练数据和测试数据
在机器学习中一般将需要用到的数据分为训练数据和测试数据,之所以这么分,是为了追求模型的泛化能力。
训练数据也称为监督数据。泛化能力是指处理未被观察过的数据(不包含在训练数据中的数据)的能力。获得泛化能力是机器学习的最终目标。
损失函数
神经网络以某个指标为线索寻找最优权重参数,这个指标在神经网络中称为损失函数。
损失函数表示神经网络性能的恶劣程度,即指当前的神经网络对监督数据在多大程度上不拟合,在多大程度上不一致。
均方误差
yk表示神经网络的输出,tk表示监督数据,k表示数据的维度
python代码
交叉熵误差
og表示以e为底数的自然对数(loge)o,yk表示神经网络的输出,tk表示正确解标签
tk中只有正确解标签的索引为1,其他均为0(one-hot表示)
python代码
mini-batch学习
机器学习使用训练数据进行学习,针对训练数据计算损失函数的值,来找出使该值尽可能小的参数,即计算损失函数时必须将所有的训练数据作为对象。
上述两种损失函数的python代码实现考虑的是针对单个数据的损失函数,要想在神经网络中实际使用起来,就要求计算所有的训练数据损失函数的总和。
当数据量较大时,如果以全部数据作为计算损失函数的对象是很耗费时间的,因此在神经网络的学习中,一般从全部数据中选取一部分,作为全部数据的近似,这种学习方式称为mini-batch学习。
one-hot表示(指仅正确解标签为1,其余为0的数据结构)
(支持one-hot表示)交叉熵误差的python代码
(非one-hot表示)交叉熵误差的python代码
梯度法
在了解梯度法前,需要先了解一下,为什么要设定损失函数?
在神经网络的学习时,不能将识别精度作为指标。因为如果以识别精度作为指标时,参数的导数在绝大多数地方都会变成0.
阶跃函数就想“竹筒敲石”,只在某个瞬间产生变化。而sigmoid函数不仅y的输出时连续变化的,曲线的斜率(导数)也是连续变化的,因此得益于sigmoid函数导数在任何地方都不为0的性质,使得神经网络的学习得以正常进行。
在高等数学课上我们知道,导数就是某个瞬间的变化量。
数值微分的python代码:
由于计算机缺陷导数无法真正意义上被计算,因此上述代码中引入的微小值h变量取值0.0001,避免过小导致的舍入误差,然后通过中心差分法继续减小误差,这一过程的代码改进过程在《深度学习入门基于Python的理论与实现 斋藤康毅》书中p95-96有详细介绍。
单变量的导数和多变量的偏导数,都是求某个地方的斜率,不过偏导数需要将多个变量中的其中一个定位目标变量,将其他变量固定为某个值,定义新的函数,对新定义的函数应用数值微分的函数得到偏导数。
对于一个多变量的函数,若想计算所有变量的偏导数,一般这种由全部变量的偏导数汇总而成的向量称为梯度。
梯度的python代码:
梯度有一个重要的性质,那就是梯度会指向各点处的函数值降低的方向。梯度指示的方向时各点处的函数值减少最多的方向。
在高等数学中,方向导数=cos(∂) * 梯度(∂是方向导数的方向与梯度方向的夹角)。因此,所有的下降方向中,梯度方向下降最多。
机器学习的主要任务是在学习中寻找最优参数,神经网络也必须在学习时找到最优参数(权重和偏置)。最优参数即损失函数取最小值时的参数。
一般而言,损失函数很复杂,参数空间相当庞大,我们不知道它在何处能取得最小值。而通过巧妙地使用梯度来寻找函数最小值(或者尽可能小的值)的方法就是梯度法。
当函数很复杂且呈扁平状时,学习可能会进入一个(几乎)平坦的地区,陷入被称为“学习高原”的无法前进的停滞期。
在梯度法中,函数的取值从当前位置沿着梯度方向前进一定距离,然后在新的地方重新求梯度,再沿着新梯度方向前进,如此反复,不断地沿梯度方向前进。即通过不断地沿着梯度方向前进,逐渐减小函数值的过程。
Π表示更新量,在神经网络的学习中,被称为学习率。学习率决定在一次学习中,应该学习多少,以及在多大程度上更新参数。
梯度下降法的python代码:
学习率过大或者过小都无法得到好的结果。
像学习率这样的参数一般称为超参数。这是一种和神经网络的参数(权重和偏置)性质不同的参数。相对于神经网络的权重参数是通过训练数据和学习算法自动获得的,学习率这样的超参数则是人工设定的。
一般的,神经网络数据量庞大,我们一般使用随机选择的mini-batch数据进行梯度下降,所有该算法又称随机梯度下降法(SGD)。
SGD完整代码:
神经网络的学习顺序
前提
神经网络存在合适的权重和偏置,调整权重和偏置以便拟合训练数据的过程称为学习。
步骤1(mini-batch)
从训练数据中随机选出部分数据,这部分数据称为mini-batch。我们的目标是减小mini-batch的损失函数的值。
步骤2(计算梯度)
为了减小mini-batch的损失函数的值,需要求出各个权重参数的梯度。梯度表示损失函数的值减小最多的方向。
步骤3(更新参数)
将权重参数沿梯度方向进行微小更新。
步骤4(重复)
重复步骤1、步骤2、步骤3。
2层神经网络的实现
下面,来实现一个手写数字识别的神经网络,以2层神经网络为对象(隐藏层为1层的网络),使用MNIST数据集进行学习。
代码的实现参考斯坦福大学CS231n课程提供的python源代码
完整代码:
mini-batch的改造和对测试数据的评价
通过上述2层神经网络TwoLayerNet为对象,使用MNIST数据集,从训练数据随机选择一部分数据使用梯度法更新参数,即mini-batch学习。
此外,神经网络的学习中,必须确认是否能够正确识别训练数据以外的其他数据,即确认是否会发生过拟合。神经网络学习的最初目标是掌握泛化能力,因此要评价神经网络的泛化能力,就必须使用不包含在训练数据中的数据。
对于mini-batch的学习,一般做法是事先将所有训练数据随机打乱,然后按指定的批次大小,按序生成mini-batch。这样每个mini-batch均有一个索引号,比如比例可以是0,1,2,…,99,然后用索引号可以遍历所有的mini-batch。遍历一次所有数据,就称为一个epoch。 一个epoch表示学习中所有训练数据均被使用过一次时的更新次数。
过拟合是指,对于手写数字识别,虽然训练数据中的数字图像能被正确辨别,但是不在训练数据中的数字图像却无法被识别的现象。