深度学习 数学公式

1、得分函数:

2、SVM损失函数:

3、加入正则化惩罚项的SVM损失函数:

其中,为正则化惩罚项。

4、L2正则化:

那么,加入正则化惩罚项的SVM损失函数

 

5、交叉熵损失(cross-entropy loss)函数:

其中,被称作softmax函数。

其输入值是一个向量,向量中元素为任意实数的评分值;输出是一个向量,其中每个元素值在0到1之间,且所有元素之和为1。

6、SVM损失函数输出的是一个值,softmax损失函数输出的是一个概率。

7、梯度函数:

深度学习中所说的学习率即是梯度下降的步长。

8、单层的神经网络:

双层的神经网络:

其中,W1、W2、W3为权重参数,max为激活函数。

单层的神经网络相当于线性分类。

简单的神经网络模型可参考:http://cs.stanford.edu/people/karpathy/convnetjs/demo/classify2d.html

9、有下列激活函数:

Sigmoid函数、tanh(x)函数、ReLu函数(即函数max(0,x))。

一.损失函数

回顾之前讲过的线性回归模型,我们为了要学习参数使得得到的直线更好的拟合数据,我们使用了一个函数
这里写图片描述

这个函数就是比较模型得到的结果和“真实值”之间的“差距”,来判断这个模型是不是好。因为模型越好,差距越小,就越能够反应真实值。这个是能够很容易理解的。
但是上面的解释毕竟太过于“通俗”,而且事实上面还存在很多的损失函数的类型供我们使用,你甚至能够定义自己的损失函数类型。所以下面的篇幅就来讲讲一些常用的损失函数。

Ⅰ.0-1损失函数(0-1 loss function)

这里写图片描述

这个函数比较好理解。要是我们模型得到值和“真实值(标签值)”不一样,损失为1.要是一样的话,没有损失,自然为0.
这个函数的优点就是简单,非常的简单。但是缺点也非常的明显,就是无法度量损失的“严重程度”,无论有多不一样,都得到1的损失,很显然不利于后面的学习。
用途:
我暂时没有发现哪个机器学习算法用了0-1损失函数,有的话给个提示。

Ⅱ.平方损失函数(quadratic loss function)

我们也常常把这个方法称为最小二乘法(Ordinary least Squares)
这里写图片描述

这个函数就是我们之前一直使用的函数啦,非常非常的常见,还记得我们为什么会选择平方损失函数吗?不记得了参见第三节对于线性回归的回顾。机器学习笔记四:线性回归回顾与logistic回归 
我们给直线模型加上了一个服从高斯分布的“噪声”项,使得整个模型都服从高斯分布,然后用极大似然估计推导出来最小二乘式。不记得的话回去回顾一下。
最小二乘的基本原则是:最优拟合直线应该是使各点到回归直线的距离和最小的直线,即平方和最小。这是一开始讲线性回归的时候就说过的。这是很直观的理解。
总结一下:假如我们有m个输入(实例),
那么平方损失的一般形式(某个样本)为:
这里写图片描述
但是样本数量到m个的话,这么多样本的平方损失为:
这里写图片描述

Ⅲ.对数损失函数(logarithmic loss function)

这里写图片描述
上面的形式就是对数损失函数的形式啦。
这里只说两点,因为以后还会经常见到。
第一点就是对数损失函数非常常用。比如后面我们会看到的logistic回归,没错,又是这货。还有softmax回归等等,还要再来讲这个损失函数。
第二点就是对于这个公式的理解。这个公式的意思是在样本x在分类为y的情况下,我们需要让概率p(y|x)达到最大值。要是这个说法很难懂的话,就换个方式,就是利用目前已知的样本分布,找到最有可能导致这种分布的参数值。更通俗的说,就是什么样的参数才能够使我们观测到目前这组数据的概率最大。
要是现在还是不理解,后面会再讲,知道这种形式就行了。
前面加了一个负号是因为log函数是单调递增的,在前面加上负号之后,最大化p(y|x)就等价于最小化L。

Ⅳ.指数损失函数(exp-loss)

这里写图片描述
指数损失函数的形式的adaboost部分会用的很多。在后面的Adaboost部分会详细讲使用方式。

二.风险函数

上面说到了损失函数,通俗来说,损失函数就是度量模型得到某个样本的值和本该有的“真实值”之间的“接近程度”,值越“接近”,说明模型的效果更能够体现样本的“规律”。这里应该很好理解。而风险函数,可以认为是平均意义下的损失。有两个概念,一个是经验风险,还有一个是机构风险。

Ⅰ.经验风险(Empirical Risk)

给定一个数据集,模型f(x)关于训练集的平均损失被称为经验风险,或者叫做经验损失。
这里写图片描述
其中N是样本数量。
这个公式的用意很明显,就是模型关于训练集的平均损失(每个样本的损失加起来,然后平均一下)。在实际中用的时候,我们也就很自然的这么用了。
同样,这里还有一个理论,就是经验风险最小的模型是最优的模型,即经验风险最小化(ERM)。
在之前,这个理论我们也是直接拿来用了,因为这个理论很符合人的直观理解。因为在训练集上面的经验风险最小,也就是平均损失越小,意味着模型得到结果和“真实值”尽可能接近,表明模型越好。
经验风险最小化可以总结为:
这里写图片描述

Ⅱ.结构风险(Structural Risk)

当样本容量不大的时候,经验风险最小化模型容易产生“过拟合”的问题。为了“减缓”过拟合问题,就提出了结构风险最小(SRM)的理论。
结构风险的定义也很简单,就是在经验风险上加上一个正则化项(regularizer)或者叫做罚项(penalty term),即
这里写图片描述

结构风险最小化就是认为,结构风险最小的模型是最优的模型。即
这里写图片描述

 

本课程笔记是基于今年斯坦福大学Feifei Li, Andrej Karpathy & Justin Johnson联合开设的Convolutional Neural Networks for Visual Recognition课程的学习笔记。目前课程还在更新中,此学习笔记也会尽量根据课程的进度来更新。

今天终于可以开始讲神经网络啦~~

1.一个简单的介绍

我们先把那些关于人脑、神经什么的东西抛到一边,来简单地理解下神经网络。在linear classification那一章,我们是通过计算输入图片属于不同类别的score来判断它到底属于哪个类的,即s=Wx,其中W是参数矩阵,x是由输入图像的所有pixel组成的一个特征列向量。比如以CIFAR-10为例的话x就是[3072*1]的列向量,W是[10*3072]的矩阵,因此输出是10个类别得分。
那么在神经网络中,计算score的方法有所不同:s=W2max(0,W1x)。其中W1也是一个参数矩阵,他可以把原始图像特征x转变成比如说100维的中间层向量特征 (则此时W1应为[100*3072]维)。函数max(0,~)是一个非线性函数,对矩阵中小于0的元素置零而保留大于0的元素值不变。这个非线性函数我们有多种选择(后面会讲),不过这一个是比较常用的,简单地通过0阈值来激活元素值。最后,W2则应该是一个[10*100]的矩阵,这样我们最后还是得到了10个类别得分。其中W1W2就是通过之前所说的随机梯度下降法学习到的,其中用到反向传播算法来计算每一步更新的梯度哦(不了解这部分内容要去戳一下我前面的课程笔记了啊)。注意非线性函数部分(也称为激活函数),是神经网络中很重要的一个部分,但是即使我们把非线性函数部分去掉,把W1x直接和W2相乘我们也可以得到10个类别得分,但是这样就少了一些扰动(wiggle),影响泛化性能等。
同样的,3层的神经网络会长这个样子:s=W3max(0,W2max(0,W1x)),就是这么简单!其中W1W2W3都是学习得到的参数。中间层特征向量的维度是hyperparameter,我们在后面会讲怎么设置他们。
接下来让我们再用人脑神经元之类的东西来解释上面所说的神经网络吧。

2. 建模神经元

神经网络这一领域最早来源于对生物神经系统的建模,而后慢慢演变成一种工程的方法,并且在机器学习中取得了很好的效果。我们这边只简短地介绍和我们相关的生物学系统的知识。

2.1 神经元的激活和连接

人脑中基本的计算单元叫做神经元(neuron).人的神经系统中大约包含860亿个这样的神经元,并且他们之间通过大约10^14~10^15这么多的突触(synapses)连接。下图就显示了一个神经元和它抽象出的数学模型。每个神经元会从它们的树突(dendrites)获得输入信号,然后再将输出信号传给它唯一的轴突(axon)。轴突再通过突触和其他神经元的树突相连。
在神经元的数学模型中,轴突所携带的信号(例如:x0)通过突触进行传递,由于突触的强弱不一,假设我们以w0表示,那么我们传到下一个神经元的树突处的信号就变成了w0x0。其中突触强弱(参数w)是可学的,它控制了一个神经元对另一个神经元影响的大小和方向(正负)。然后树突接收到信号后传递到神经元内部(cell body),与其他树突传递过来的信号一起进行加和,如果这个和的值大于某一个固定的阈值的话,神经元就会被激活,然后传递冲激信号给树突。在数学模型中我们假设传递冲激信号的时间长短并不重要,只有神经元被激活的频率用于传递信息。我们将是否激活神经元的函数称为激活函数(activation function f),它代表了轴突接收到冲激信号的频率。以前我们比较常用的一个激活信号是sigmoid function σ,因为它接收一个实值的信号(即上面所说的加和的值)然后将它压缩到0-1的范围内。我们在后面会介绍更多的激活函数。
这里写图片描述
关于上述传播过程(前向传播),代码如下:

<code class="language-python hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Neuron</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(object)</span>:</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># ... </span> <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">forward</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(inputs)</span>:</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""" assume inputs and weights are 1-D numpy arrays and bias is a number """</span> cell_body_sum = np.sum(inputs * self.weights) + self.bias firing_rate = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span> / (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span> + math.exp(-cell_body_sum)) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># sigmoid activation function</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> firing_rate</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

2.2 一个神经元就是一个线性分类器

神经元的上述前向传播过程从形式上看着很熟悉。我们之前在线性分类器中看到,分类器具有判断score好坏的能力,在神经元中也是一样,我们通过激活与否来得到神经元的输出,再通过一个恰当的损失函数就能将一个神经元转化成线性分类器了。
Binary Softmax classifier. 比如说,我们可以把σ(iwixi+b)看成是某类的概率P(yi=1|xi;w),那么另一类的概率则是P(yi=0|xi;w)=1P(yi=1|xi;w),因为对于二值分类器而言两类的概率相加应为1。然后我们再通过在线性分类器那一章见过的交叉熵loss对score的好坏进行量化,这就是一个二值softmax分类器了(也叫逻辑回归)。因为sigmoid function会把只限定于0-1之间,分类器可以通过判断上述概率是否大于0.5来进行分类。
Binary SVM classifier. 我们还可以选择边界最大化的hinge loss来衡量神经元输出的好坏,那么此时就变成了一个二值SVM分类器了。
Regularization.不管是在SoftmaxLoss还是在SVM中,loss的正则项regularization loss在生物学角度上都可以理解成是渐进遗忘(gradual forgetting),因为它的作用在于使得所有突触的权重w在权重更新的过程中都趋向于0。

2.3 几种常见的激活函数

这里写图片描述
Sigmoid. Sigmoid 非线性激活函数的形式是σ(x)=1/(1+ex),其图形如上图左所示。之前我们说过,sigmoid函数输入一个实值的数,然后将其压缩到0~1的范围内。特别地,大的负数被映射成0,大的正数被映射成1。sigmoid function在历史上流行过一段时间因为它能够很好的表达“激活”的意思,未激活就是0,完全饱和的激活则是1。而现在sigmoid已经不怎么常用了,主要是因为它有两个缺点:

  • Sigmoids saturate and kill gradients. Sigmoid容易饱和,并且当输入非常大或者非常小的时候,神经元的梯度就接近于0了,从图中可以看出梯度的趋势。这就使得我们在反向传播算法中反向传播接近于0的梯度,导致最终权重基本没什么更新,我们就无法递归地学习到输入数据了。另外,你需要尤其注意参数的初始值来尽量避免saturation的情况。如果你的初始值很大的话,大部分神经元可能都会处在saturation的状态而把gradient kill掉,这会导致网络变的很难学习。
  • Sigmoid outputs are not zero-centered. Sigmoid 的输出不是0均值的,这是我们不希望的,因为这会导致后层的神经元的输入是非0均值的信号,这会对梯度产生影响:假设后层神经元的输入都为正(e.g. x>0 elementwise in f=wTx+b),那么对w求局部梯度则都为正,这样在反向传播的过程中w要么都往正方向更新,要么都往负方向更新,导致有一种捆绑的效果,使得收敛缓慢。
    当然了,如果你是按batch去训练,那么每个batch可能得到不同的符号(正或负),那么相加一下这个问题还是可以缓解。因此,非0均值这个问题虽然会产生一些不好的影响,不过跟上面提到的 kill gradients 问题相比还是要好很多的。

Tanh. Tanh和Sigmoid是有异曲同工之妙的,它的图形如上图右所示,不同的是它把实值得输入压缩到-1~1的范围,因此它基本是0均值的,也就解决了上述Sigmoid缺点中的第二个,所以实际中tanh会比sigmoid更常用。但是它还是存在梯度饱和的问题。Tanh是sigmoid的变形:tanh(x)=2σ(2x)1

这里写图片描述
ReLU. 近年来,ReLU 变的越来越受欢迎。它的数学表达式是: f(x)=max(0,x)。很显然,从上图左可以看出,输入信号
<0时,输出为0,>0时,输出等于输入。ReLU的优缺点如下:

  • 优点1:Krizhevsky et al. 发现使用 ReLU 得到的SGD的收敛速度会比 sigmoid/tanh 快很多(如上图右)。有人说这是因为它是linear,而且梯度不会饱和
  • 优点2:相比于 sigmoid/tanh需要计算指数等,计算复杂度高,ReLU 只需要一个阈值就可以得到激活值。
  • 缺点1: ReLU在训练的时候很”脆弱”,一不小心有可能导致神经元”坏死”。举个例子:由于ReLU在x<0时梯度为0,这样就导致负的梯度在这个ReLU被置零,而且这个神经元有可能再也不会被任何数据激活。如果这个情况发生了,那么这个神经元之后的梯度就永远是0了,也就是ReLU神经元坏死了,不再对任何数据有所响应。实际操作中,如果你的learning rate 很大,那么很有可能你网络中的40%的神经元都坏死了。 当然,如果你设置了一个合适的较小的learning rate,这个问题发生的情况其实也不会太频繁。

Leaky ReLU. Leaky ReLUs 就是用来解决ReLU坏死的问题的。和ReLU不同,当x<0时,它的值不再是0,而是一个较小斜率(如0.01等)的函数。也就是说f(x)=1(x<0)(ax)+1(x>=0)(x),其中a是一个很小的常数。这样,既修正了数据分布,又保留了一些负轴的值,使得负轴信息不会全部丢失。关于Leaky ReLU 的效果,众说纷纭,没有清晰的定论。有些人做了实验发现 Leaky ReLU 表现的很好;有些实验则证明并不是这样。
– PReLU. 对于 Leaky ReLU 中的a,通常都是通过先验知识人工赋值的。然而可以观察到,损失函数对a的导数我们是可以求得的,可不可以将它作为一个参数进行训练呢? Kaiming He 2015的论文《Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification》指出,不仅可以训练,而且效果更好。原文说使用了Parametric ReLU后,最终效果比不用提高了1.03%.
-Randomized Leaky ReLU. Randomized Leaky ReLU 是 leaky ReLU 的random 版本, 其核心思想就是,在训练过程中,a是从一个高斯分布中随机出来的,然后再在测试过程中进行修正。
这里写图片描述

Maxout. Maxout的形式是f(x)=max(w_1^Tx+b_1,w_2^Tx+b_2),它最早出现在ICML2013上,作者Goodfellow将maxout和dropout结合后,号称在MNIST, CIFAR-10, CIFAR-100, SVHN这4个数据上都取得了start-of-art的识别率。可以看出ReLU 和 Leaky ReLU 都是Maxout的一个变形,所以Maxout 具有 ReLU 的优点(如:计算简单,不会 saturation),同时又没有 ReLU 的一些缺点 (如:容易饱和)。不过呢Maxout相当于把每个神经元的参数都double了,造成参数增多。
Maxout的拟合能力非常强,它可以拟合任意的的凸函数。作者从数学的角度上也证明了这个结论,即只需2个maxout节点就可以拟合任意的凸函数了(相减),前提是”隐含层”节点的个数可以任意多。
这里写图片描述

How to choose a activation function? 怎么选择激活函数呢?
我觉得这种问题不可能有定论的吧,只能说是个人建议。
如果你使用 ReLU,那么一定要小心设置 learning rate,而且要注意不要让你的网络出现很多坏死的 神经元,如果这个问题不好解决,那么可以试试 Leaky ReLU、PReLU 或者 Maxout.
友情提醒:最好不要用 sigmoid,你可以试试 tanh,不过可以预期它的效果会比不上 ReLU 和 Maxout.
还有,通常来说,很少会把各种激活函数串起来在一个网络中使用的。

3. 神经网络结构

3.1 逐层构建

神经网络是神经元构成的图(此图是指graph,而不是指image)。神经网络是神经元互相连接构成的一个非循环的图,也就是说一些神经元的输出会作为其他神经元的输入,另外环路是不允许的因为这会使得神经网络的前向传播陷入无止尽的循环中。当然,神经元之间的排列是有规律的,通常情况下被构建成层层连接的形式,每一层中又有多个神经元。比如说常见的一种层叫做全连接层(fully-connected layer),表示的是相邻两层之间的神经元两两连接,同层的神经元则互不连接。下图是两个全连接的例子:
这里写图片描述
命名习惯。注意我们平时说N层神经网络,是不把输入层计算在内的。也就是说一个单层神经网络表示的是输入层接输出层,没有隐含层的网络结构。所以有时候你可能会注意到逻辑回归或SVM被看成是单层神经网络,或者叫人工神经网络(Artificial Neural Networks,ANN)或多层感知机(Multi-Layer Perceptrons,MLP)。还有许多人并不喜欢“神经网络”这个称呼,容易联想成生物学的神经元什么的,所以倾向于把neurons称为units。
输出层。和神经网络其他的层不同,最后的输出层通常情况下没有activation function,这是因为最后一层的输出通常用来表示类别的score(特别是分类),score嘛通常是实值的数。
神经网络的大小。衡量某个神经网络有多大,通常有两种方法,1是神经元的数目,2是参数的数目,相比之下第二种更常用。比如说以上图为例:
– 上图左的网络共包含(4+2=6)个神经元(不包括输入层),参数则有[3*4]+[4*2]=20个weights还有[4+2=6]个bias,也就是总共26个可学习的参数。
– 上图右的网络共包含(4+4+1=9)个神经元,参数则有[3*4]+[4*4]+[4*1]=12+16+4=32个weights还有[4+4+1=9]个bias,也就是总共41个可学习的参数。
实际上,现在所有的卷积网络通常都包含亿级的参数,并且由10-20层网络组成(因此说是deep learning)。

3.2 例子:前向传播的计算

在神经网路中,矩阵运算是非常常用和有效的。神经网络之所以被构建成层层连接的形式,一个重要的原因就是通过矩阵运算可以很方便快捷地计算不同层的输入输出。比如以上图3层的神经网络为例,输入就是一个[3*1]维的向量,每一层的所有权重也同样是矩阵形式,例如第一个隐层的weights W1就是一个[4*3]维的矩阵,同时该层所有units的bias b1维度则是[4*1]。也就是说每个神经元的weights在W1中都是一列,那么简单的矩阵乘法np.dot(W1,x)就可以计算出这一层所有神经元的激活值。同样的,W2是[4*4]维的矩阵,存储着第二个隐含层的所有连接参数,W3则是输出层的weights,是[1*4]维的矩阵。那么这整个3层神经网络的前向传播过程就是3个简单的矩阵乘法,然后再接激活函数:

<code class="language-python hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># forward-pass of a 3-layer neural network:</span> f = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">lambda</span> x: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span>/(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span> + np.exp(-x)) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># activation function (use sigmoid)</span> x = np.random.randn(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># random input vector of three numbers (3x1)</span> h1 = f(np.dot(W1, x) + b1) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># calculate first hidden layer activations (4x1)</span> h2 = f(np.dot(W2, h1) + b2) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># calculate second hidden layer activations (4x1)</span> out = np.dot(W3, h2) + b3 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># output neuron (1x1)</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

在上述代码中,W1W2,W3,b1,b2,b3是网络的可学习参数。注意最后一层输出层是不用加激活函数的。其实,输入数据x也可以不是一个列向量,而是包含整个训练数据batch的一个矩阵,矩阵中的每一列还是代表一个训练数据样本。这样所有的样本就可以同时进行计算了,非常高效。

The forward pass of a fully-connected layer corresponds to one matrix multiplication followed by a bias offset and an activation function.

3.3 神经网络对数据的表达力

我们常常会把包含全连接层的神经网络看成是一系列由网络参数构成的函数的组合。那么问题来了,这些函数的组合对数据的表达力怎么样?是不是任何函数都能通过神经网络进行建模?
有人证明过包含一层隐含层的神经网络是一个万能逼近器(见Michael Nielsen的证明),也就是说它可以估计任何连续的f(x)。那么既然两层的神经网络就可以估计任何函数了,为什么我们还需要更多的层,需要Go deeper?这是因为虽然两层神经网络从数学上来看是能逼近任何连续函数,但是从实际来看,更深的网络通常都比两层网络效果好,也就是说这是一种经验论,虽然它们从数学上来看对数据的表达力是一样的。
顺便说一下,在实际中3层的神经网络通常比2层的效果更好,但是4,5,6层却不一定能提升更多,这和卷积网络有着鲜明的对比,在卷积网络中通常深度是一个好的识别系统的非常关键的因素。有人说这是因为图像本身就是一个分层的结构(比如人脸是由眼睛构成的,眼睛由由边缘构成等),因此分多层来学习数据能够使网络获得更加语义化的理解。当然了,这整个领域还在不断的研究中,下面是一些可参考的读物:

3.4 如何设置神经网络的层数和神经元数

面对一个实际问题,我们到底该使用什么样的网络呢?我们是应该用没有隐含层的呢,还是1个,2个隐含层呢?每一层所包含的神经元数目又该怎么设置?
首先我们需要注意到当我们增加层数和神经元数目的时候,神经网络的性能也会有所提升。因为神经元可以协同作用表达出不同的函数来对数据进行表示。比如说假设我们在二维空间中有一个二值的分类问题,我们可以训练3个不同的神经网络,每个神经网络都包含一个隐含层,但是隐含层中包含的神经元数目不一样,我们来看一下分类器的分类效果:
这里写图片描述
在上图中,我们看到包含更多神经元的神经网络能够表达更加复杂的函数。但是这既好又不好,好是因为可以对更复杂的数据进行分类,不好是因为它容易对训练数据过拟合(overfitting)。比如说隐层包含20个神经元的那个图,它虽然把所有的数据都分对了但是把整个平面分成了红绿相间、相互脱节的小区域,看上去很不平滑;而3个神经元的图,它能够从大方向上去分类数据,而把一些被绿色点包围的红色点看成是异常值、噪声(outliers)。实际中这能够使得模型在测试数据上有更好的泛化能力。
基于上述讨论,貌似当数据不太复杂的时候,我们可以选用小一点的神经网络来预防overfitting?不不不,这是不对滴,我们可以选择其他更好的方法来避免过拟合(比如L2正则化,dropout,增加噪声等,我们后面再讨论)。实际中用这些方法避免过拟合比减少神经元的个数要更好。比如说我们可以看看不同的正则强度是如何控制20个隐含神经元的过拟合的:
这里写图片描述
总的来说就是你不能因为害怕过拟合就使用小一点的神经网络,相反如果你的计算机性能允许,你应该用大的神经网络,丙炔通过一些正则的方法来控制overfitting.

4. 总结

在这章中,我们介绍了如下内容:
– 我们粗略地介绍了生物的神经元。
– 我们讨论了几种实际使用的激活函数,其中ReLU是最常用的选择
– 我们介绍了神经网络,其中神经元是通过全连接层来组织的,全连接层中相邻层的神经元两两连接,同一层的神经元互相不连接
– 我们发现这种层级的结构使得神经网络只要进行矩阵乘法和激活函数就可以计算了
– 我们发现神经网络是万能逼急器,但是我们也说了这种特性并不能表示我们不需要go deeper。
– 我们讨论了大型的神经网络总是会比小型神经网络效果要好,但是这也导致它们有可能会过拟合,因此我们需要选用恰当的正则方法来弥补这一缺点,在后面我们会见到更多形式的正则(如dropout等)。

 

Loss Function 是定义在单个样本上的,算的是一个样本的误差。

Cost Function 是定义在整个训练集上的,是所有样本误差的平均,也就是损失函数的平均。

Object Function(目标函数 )定义为:Cost Function + 正则化项。

 

 

召回率

 

权重参数

 

激活函数

 

梯度下降

 

鲁棒性

鲁棒是Robust的音译,也就是健壮和强壮的意思。它是在异常和危险情况下系统生存的关键。比如说,计算机软件在输入错误、磁盘故障、网络过载或有意攻击情况下,能否不死机、不崩溃,就是该软件的鲁棒性。所谓“鲁棒性”,是指控制系统在一定(结构,大小)的参数摄动下,维持其它某些性能的特性。根据对性能的不同定义,可分为稳定鲁棒性和性能鲁棒性。以闭环系统的鲁棒性作为目标设计得到的固定控制器称为鲁棒控制器

 

似然

最大似然法(Maximum Likelihood,ML)也称为最大概似估计,也叫极大似然估计,是一种具有理论性的点估计法,此方法的基本思想是:当从模型总体随机抽取n组样本观测值后,最合理的参数估计量应该使得从模型中抽取该n组样本观测值的概率最大,而不是像最小二乘估计法旨在得到使得模型能最好地拟合样本数据的参数估计量。

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *