1.2 深度学习与神经网络基础
深度学习这个词语很时髦,这里通俗地解释一下它的概念。
深度学习就是使用神经网络来进行学习,将一种表示(Representation)转换为另外一种表示,那么神经网络是什么呢?简单来说神经网络就是一个函数,但它可以非常简单,如y=x+3;也可以非常复杂,复杂到难以用数学公式进行解析表达,一般来讲,神经网络会包含两个主要部分:线性变换函数和非线性变换函数。
1.2.1 函数的简单表达
简单说函数就是将输入通过一些操作或变换变为输出,简记为y=f(x),就可以说x经过函数f的作用变成了y。很多人就学过以下函数,这些函数通常做的就是将一个数字(标量,scalar)映射(变成)为另外一个数字(标量),当然可能存在一一对应,一多对应和多一对应这些情况,此处只讨论一一对应,即一个x只能映射为一个y,如下所示:
1.2.2 函数的矩阵表达
如果输入的是多个数字组成的向量(vector)呢,比如一个点在二维平面空间的坐标(x,y),然后输出是一个标量,比如高度z。假设可以用一个简单的线性函数来表示,即:z=a×x+b×y+c,这样便表示了整个操作过程。但输入通常会被当作一个变量,此时应该怎么表示这个式子呢?此时便引出了以下矩阵和向量的操作:将[a, b]视为矩阵A,将[x, y]视为向量X,然后进行矩阵与向量的乘法操作,其实就是行的元素与列的元素对应相乘然后相加。如果输入的维度更高,那么只需要增加输入X向量中的元素个数即可,同时对应增加线性变换矩阵A中每行的元素个数。如果输出多个值怎么办呢?其实只需要将线性变换矩阵A的行数增加即可,有多少个值A中就有多少行,此时输出也可以使用矩阵Z表示,如下所示:
1.2.3 神经网络的线性变换
函数的矩阵操作也可称为线性变换,它是神经网络中最基础的操作之一。神经网络中的线性变换只是将变换矩阵A和输入X的维度变得更大了而已。对于图像来说,X已经是成百上千级别的矩阵变量了,但原理还是一样:对应相乘然后做连加操作。
比如对于一个2×2灰度图片,可以想象将所有的元素拉伸为一维数组(当然这样做会失去图像的空间特性),然后进行线性变换,可用以下式子表示,此处省略常数项:
这样操作之后就得到一个输出,输出包括两个数字,即可理解为2维输出。现实情况中输出会有更多的维度。另外值得一提的是,此处每一行的参数个数与图片的高和宽的乘积一样,其本质就是卷积操作。
1.2.4 神经网络的非线性变换
神经网络使用线性变换可以做非常多的线性操作,但这个世界还有非常多的非线性映射,比如二次函数x2,此时就需要通过非线性变换来解决此类问题。
过去非常多的学者为之努力过,并提出了使用激活函数来进行非线性变换。目前常用的激活函数及对应的导数如图1-3所示,可以看到其是否有梯度消失或爆炸、饱和等性质,如想直观了解更多的激活函数可参见相关网站(2)。
1.2.5 深层神经网络
前文讲解了神经网络的两个最重要的基本组成单元,即线性变换和非线性变换,使用它们的组合既可以模拟线性变换又可以模拟非线性变换。但世界上有无数函数(线性+非线性),那么怎么去模拟更多的函数呢?答案就是Deep。
所谓Deep,其实质就是不断地叠加这种线性和非线性操作,每次操作如果被称为一个网络层,那么叠加很多次这些操作,就形成了所谓的深层网络结构,如图1-4所示。
图1-3 常见激活函数
图1-4 神经网络示意图
假如将线性操作记为WX+b,激活函数(非线性)操作记为δ(x),那么线性操作后跟激活函数的结果就是,如果后面再跟一个线性操作和激活函数,则输出为。这样通过不断地循环操作,就达到模拟复杂函数的目的。注意每一层的参数W和b的具体内容一般是不一样的。
神经网络通过修改神经元的个数(影响每层W和b的参数数量)和网络的层数可以模拟非常多复杂的函数,甚至可以说是可以模拟世界上任意的函数(前提是神经元和网络层数也是无限的)。
1.2.6 神经网络的学习过程
理解了神经网络的组成后,便面临着如何确定这些参数(每层参数矩阵W和b的具体数值)的问题。
深度学习在很大程度上是学习历史经验,那么要确定神经网络的参数,就需要大量的历史数据来进行训练。
这个过程可形象地理解为学生进行题海战术:给学生很多以前考试出现过的考题,让学生做,做完后与标准答案对照,然后学生根据对错情况进行查漏补缺再学习。通过不断地重复这个过程,学生就能学习很多知识,能做到举一反三,真正考试的时候也能取得好成绩。这些知识就对应着神经网络里的各种参数,神经网络学到这些参数后,就可以对类似的输入进行变换,从而得到“正确的答案”。
这些历史数据就组成了所谓的数据集(dataset),一个数据集包含很多条数据(sample或data point),每条数据一般包含问题及答案。对于图像分类来说:问题就是原始图像,答案就是对应的类别。有了这些数据后,神经网络每次做题给出答案就和标准答案进行对比,然后可以得到一个错误指标,其计算可使用loss=loss_fun(output,true_value)来计算。得到loss后,便对其求微分,即loss相对于神经网络中各个参数的变化情况,然后使用参数更新算法对参数进行更新(如随机梯度下降法),这就是知识更新的过程。
通过不断地训练,神经网络就会不断地更新参数,学习新知识,从而达到从历史数据中学到经验教训的目的。
学生学习得好不好,还得经受模拟考试和真正考试的检验,这同样适用于神经网络,所以需要用神经网络在另外一部分它没见过的数据上进行测试,看神经网络是否能够举一反三。在这个过程中会使用训练集上的错误率和测试集上的错误率作对比,来观察学习的效果。这就会出现以下三种情况。
(1)理想情况:两个数据集上的loss变化趋势一样,或差距越来越少,同时降低。
(2)欠拟合:在训练集上loss就非常大,随着时间的推移,甚至越来越大。
(3)过拟合:训练集上loss越来越小,而测试集上loss越来越大,即两者间出现了很大的鸿沟。
如图1-5所示,一般训练过程都会经历欠拟合、理想和过拟合中的一种或几种情况。
图1-5 损失函数值变化
(1)欠拟合:学生最开始学得差,题海战术中的题都不会做,更别提模拟考试了。
(2)理想情况:学生在题海战术表现优秀,同样模拟考试也优秀。
(3)过拟合:学生在题海战术中表现非常优秀,但考试表现很差,出现所谓的背题现象,遇到新题不能举一反三,没有学到真功夫。
神经网络举一反三的这种能力通常被叫作模型(即这个训练好的神经网络)的泛化能力。所以训练神经网络的目标就是训练集上要优秀,测试集上的泛化能力也要好。