前面的训练过程我们已经了解的差不多了,但是我们所用到的模型还是一个线性模型,这一小节就让我们正经开始神经网络的搭建,研究怎么把之前的线性模型替换成神经网络来解决我们的问题。
为了更好的理解神经网络,这里我们把假设的关系改成一个二次函数,接下来的事情就是研究怎么用神经网络来找到其中的参数,模拟这个二次函数。
image.png
人工神经网络
要学习写代码,我们先来学一些概念知识。看看神经网络模型和我们前面用的线性模型有什么区别。大家估计都已经知道了,神经网络这个词大概是受到了大脑神经系统的启发,所以被称作人工神经网络。对神经系统的生物学意义感兴趣的朋友可以在网上找一个神经系统公开课学一下。
神经网络是现在深度学习的核心,神经网络就是一种能够通过简单函数的组合来表示复杂函数的数学实体。
通过上面的描述我们可以大概知道,神经网络中的每一个神经元都是一个简单函数,那么它是怎么去组合的呢?我们来看一下书中的原图。一个神经元内部的构造如下,中间是一个线性变换,就像我们之前的代码中模拟的wx+b这种就属于一个线性变换,但是线性变换大家都看到了,是一条直线,因此这里在线性变换的外面加了一层非线性变换,这个称作激活函数,使得输出成了一个非线性的结果。
image.png
横线下面的部分给出了一些真实的例子,假设我们已经习得w和b这两个参数值(考虑我们之前学的模型学习方案),这时候把样本放进去,在线性变换上得到的结果再经过激活函数,得到了一个新的结果,如我们在这个实例中使用的是tanh激活函数,可以看到,在x为负无穷的时候输出趋近于-1,在x为正无穷的时候输出趋近于1。而在(-1,1)区间的时候结果近似于wx+b的线性结果。
多层神经网络
看完上一个小例子,我们先不纠结里面概念的细节,一个个来解决。让我们不妨先深入看一下,什么是多层神经网络。看过图你大概就明白了,一个多层神经网络也是由我们前面提到的神经元构成。在同一层中,多个神经元是并列关系,而在层与层之间,上一层的输出是下一层的输入,以此为基础将层与层串联起来,在这里说一句,通过很多的试验效果表明,深而窄的网络效果要比浅而宽的效果更好,所以在现今的深度学习中,往往会堆砌很深的层。
image.png
关于这个图需要注意的一点是,这个图上把线性单元和激活函数分开画了两个小圆点,在很多现在流行的深度网络表示图形上,可能不会像这样分开画,如果刚开始看可能会有点困惑。
损失函数
有人说误差函数和损失函数是两个东西,不过大部分认为误差函数就是我们之前说的损失函数,有时候也叫代价函数。虽然理念上多多少少有点区别,但实际在计算中,我们知道损失计算就可以了。
这里为什么要单独把损失函数拿出来说呢,是因为我们前面在线性模型上计算损失的时候,所获得的误差曲线是凸的,我们很容易找到那个最小值,并通过我们的计算方法计算出那个最小值。但是在神经网络上的损失函数的曲线是非凸的,我们没办法通过一个确定的手段去获取到最小值。
激活函数
关于激活函数,我们上面已经介绍了一部分。上面我们知道了,激活函数的作用是把线性模型变成一个非线性模型,从而让神经元的各种组合可以去模拟任意形状的函数。同时,激活函数还有一个作用就是在网络的最后一层去限制输出结果的范围。
image.png
回想我们最开始手工搞得resnet分类模型,假设我们现在有一个识别狗的模型,我们给模型看一个卡车的图片,给的结果可能就是-1000,给一个狗熊的图片结果可能是-1,给一个狗的图片结果可能是100,通过激活函数的运算之后,卡车的结果可能就是-1,狗熊的结果是0.1,狗的结果是0.9,这样我们就可以很容易的设置一些范围来决定哪些可以认为是狗的图片,而不用担心有某些超出范围的事情发生。
各种激活函数
除了tanh,这里列出了几个常用的激活函数,比如sigmoid,ReLU,每一个激活函数都有不同的作用,但是目标都是为了组合出各种不同的复杂函数。
image.png
当然除了这里列的以外,还有很多其他的激活函数,这可能得需要花时间单独写一篇,或者再去网上学习一下关于各种激活函数的知识。
如果你想自己设计一个激活函数也是可以的,让我们看看激活函数有什么特性。
- 激活函数是非线性的。这是重要特性之一,非线性使得整个神经网络可以逼近任何复杂函数模型。
- 激活函数是可微的。我们要计算梯度,因此需要可微。
- 至少有一个敏感区间。就像我们看到的tanh一样,在(-1,1)区间是敏感的,而在其他区间是不敏感的,输入的增大或减小对输出结果影响不大。
强大学习能力
让我们看一下,有了激活函数之后,为什么具备强大学习能力。如下图所示,总共有9个图像。其中左上角的ABCD是原始图形,也可以认为是一个神经元,由一个线性变换+一个激活函数构成。而我们对这些神经元进行简单叠加,比如第一行最后一个使用A+B就构建出一个有波峰和波谷的图形,对于C+D,构建出了一个有大波峰的图形。在第一列最后一行,是在进行了A+B之后再进行C变换,形成了一个波峰更小,而波谷更大的图形。在最后一张图上,进行了C(A+B)+D(A+B)的变换,形成了一个有两个波谷的图形。
image.png
从最基本的图形变换到最后这个,我们只用了4个神经元。按我的理解,A、B可以看做是同一层的两个神经元,C、D可以看做是同一层的神经元,然后C、D把A、B的输出作为输入再次进行变换,就得到了最后那个神奇的图形。
到了这里就可以看到神经网络的强大学习能力,我们并不知道我们的数据所对应的模型函数是什么样的,也不需要预先去定义它,而是给出一堆最基本的线性变换和激活函数,经过我们前几节那样的迭代,找到一些权重,最后就能过模拟出一个很复杂的模型结果,是不是很神奇。
今天这篇没有写代码,纯粹是概念性叙述,下一节我们研究怎么用PyTorch构建一个神经网络来模拟我们的温度变换。