交叉熵函数

常用的代价函数往往选用二次代价函数,此时代价函数对参数的梯度的大小对学习的速度影响很大。倘若初始网络输出值与预期值相差很大,可能会出现初始阶段学习很慢的现象。以单独的神经元为例,初始网络输出值与预期值相差很大时的训练过程如下:
image.png
image.png
二次代价函数为:
Chapter3 改进神经网络的学习方法 - 图4
对应的偏导数:
Chapter3 改进神经网络的学习方法 - 图5
神经元通过改变权重和偏置,并以⼀个代价函数的偏导数(∂C/∂w 和 ∂C/∂b)决定的速度学习。(见梯度下降)所以,「学习缓慢」实际上就是说这些偏导数很⼩。
偏导数小的原因正在于偏导数的形式,当Chapter3 改进神经网络的学习方法 - 图6接近1或0时,sigmoid函数的斜率很小,在前一项也很小的情况下,得到的偏导数就很小,神经元的学习也变得缓慢。


为了解决这个问题,研究者使用了交叉熵函数,其具体形式如下:
Chapter3 改进神经网络的学习方法 - 图7
该代价函数满足代价函数的基本要求:

  1. 非负性
  2. 如果对于所有的训练输⼊ x,神经元实际的输出接近⽬标值,那么代价函数值将接近 0(需要假设⽬标输出 y 都是 0 或 1。这通常是解决分类问题的情况,但可以证明对于非分类问题(如回归),当输出等于预期输出Chapter3 改进神经网络的学习方法 - 图8时,代价函数值最小,为二元熵Chapter3 改进神经网络的学习方法 - 图9

对一个多输入的神经元应用该交叉熵代价函数:
image.png
此时,考察其对权重和偏置的偏导数:
Chapter3 改进神经网络的学习方法 - 图11
由于,对sigmoid函数有Chapter3 改进神经网络的学习方法 - 图12,偏导数变为:
Chapter3 改进神经网络的学习方法 - 图13
同理,此时对偏置的偏导数:
Chapter3 改进神经网络的学习方法 - 图14
显然,此时偏导数不再与斜率相关,避免了之前二次代价函数中由于Chapter3 改进神经网络的学习方法 - 图15过小学习缓慢的问题,且交叉熵函数符合人脑的纠错机制,即:当输出误差越大时学习速度越快
image.png
将单个神经元的情况推广到深度神经网络,定义交叉熵如下:
Chapter3 改进神经网络的学习方法 - 图17
实际上,如果在输出神经元是 S 型神经元时,交叉熵⼀般都是更好的选择。由于初始化⽹络的权重和偏置时通常使⽤某种随机⽅法,可能会出现某些训练输⼊误差相当明显 —— ⽐如说,⽬标输出是 1,⽽实际值是 0,或者完全反过来的情况。但如果输出神经元为线性神经元,⼆次代价函数不会导致学习速度下降的问题。


一些补充Tips:

关于不同代价函数学习速率的选择: 实际上,根据不同的代价函数,不能够直接套⽤同样的学习速率。

关于优化效果的证明: 交叉熵代价函数给了我们和⼆次代价相⽐类似的或者更好的结果。然⽽,这些结果并没有能够明确地证明交叉熵是更好的选择。原因在于作者花费了少许努⼒在选择诸如学习速率,⼩批量数据⼤⼩等等这样的超参数上。为了让这些提升更具说服⼒,需要进⾏对超参数进⾏深度的优化。然⽽,这些结果仍然是令⼈⿎舞的,巩固了我们早先关于交叉熵优于⼆次代价的理论论断。 这只是本章后⾯的内容和整本书剩余内容中的更为⼀般的模式的⼀部分。我们将给出⼀个新的技术,然后进⾏尝试,随后获得“提升的”结果。当然,看到这些进步是很好的。但是这些提升的解释⼀般来说都困难重重。它们只有在我们进⾏了⼤量⼯作来优化所有其他的超参数时,才确实具有说服⼒。⼯作量很⼤,需要⼤量的计算能⼒,我们通常也不会进⾏这样彻底的调研。 相反,我采⽤上⾯进⾏的那些不正式的测试来达成⽬标。然⽽你要记住这样的测试仍然缺乏权威的证明,需要注意那些使得论断失效的迹象。

代码实现

  1. class CrossEntropyCost(object):
  2. @staticmethod
  3. def fn(a, y):
  4. return np.sum(np.nan_to_num(-y*np.log(a)-(1-y)*np.log(1-a))) # np.log对无效值会输出nan,np.nan_to_num用于转化nan和inf为数值
  5. @staticmethod
  6. def delta(z, a, y):
  7. return (a-y) # 没有使用到z,写入是为了使得形式与二次函数相同
  8. class QuadraticCost(object):
  9. @staticmethod
  10. def fn(a, y):
  11. return 0.5*np.linalg.norm(a-y)**2 # np.linalg.norm()计算二范数即各分量平方和开根号
  12. @staticmethod
  13. def delta(z, a, y):
  14. return (a-y) * sigmoid_prime(z) # sigmoid_prime()计算导数

交叉熵是什么?从何而来?

直观来看,交叉熵解决了二次代价函数中残留的Chapter3 改进神经网络的学习方法 - 图18项,使得学习速度与斜率不再有关联,且误差越大学习速率越快。因此,我们希望得到的偏导数应满足:
Chapter3 改进神经网络的学习方法 - 图19
为了得到该偏导数,进行正向推导:
Chapter3 改进神经网络的学习方法 - 图20
该式子应满足之前的条件,所以可以得到
Chapter3 改进神经网络的学习方法 - 图21
对其积分,得到代价函数的表达式:
Chapter3 改进神经网络的学习方法 - 图22
这是单个样本的代价,求和后就可以得到之前的交叉熵函数。
以上,我们得到了交叉熵形式的推导思路。从直观意义来看,交叉熵本义其实是信息论中不确定性的一种度量,特别地,我们的神经元想要计算函数 x → y = y(x)。但是,它⽤函数 x → a = a(x) 进⾏了替换。假设我们将 a 想象成我们神经元估计为 y = 1 的概率, ⽽ 1 − a 则是 y = 0 的概率。那么交叉熵衡量我们学习到 y 的正确值的平均起来的不确定性。如果输出我们期望的结果,不确定性就会⼩⼀点;反之,不确定性就⼤⼀些。

另⼀个可能会影响学习速度的因素就是在⽅程Chapter3 改进神经网络的学习方法 - 图23中的 Chapter3 改进神经网络的学习方法 - 图24 项。由于此项,当输⼊ Chapter3 改进神经网络的学习方法 - 图25 接近 0 时, 对应的权重 Chapter3 改进神经网络的学习方法 - 图26 会学习得相当缓慢。解释为何不可以通过改变代价函数来消除 Chapter3 改进神经网络的学习方法 - 图27 项的影响。

柔性最大值(softmax)

解决学习缓慢问题的另一途径,即:为神经网络定义一种新的输出层。类似S型神经元,其激活函数形式为:
Chapter3 改进神经网络的学习方法 - 图28
很显然,该层所有输出值为正,其和为1,增加任一神经元加权输入会导致其他神经元输出下降总和相同的大小。其输出可以看作是一个概率分布,这将方便我们将其应用于需要将输出激活值解释为概率的场景。
Chapter3 改进神经网络的学习方法 - 图29
柔性最大值神经元层具有两个性质:

  • 单调性:增加单个加权输入会提到对应输出激活值并降低其他所有输出激活值
  • 非局部性:任何特定的输出激活值依赖于所有的带权输入

并且,可以证明得到此时带权输入的形式为Chapter3 改进神经网络的学习方法 - 图30


柔性最大值输出层往往与最大似然代价函数结合使用,可以解决学习缓慢的问题:
Chapter3 改进神经网络的学习方法 - 图31
对MNIST问题,就可以解释为当网络效果好,其认为图象为对应数字的概率很大接近1,这个时候代价函数值就会接近0,说明该函数是满足代价函数的基本要求的。
此时,考察代价函数的偏导数(证明相较之前复杂些):
Chapter3 改进神经网络的学习方法 - 图32
其偏导数值与交叉熵代价函数与S型输出层的组合完全一致,达到了解决学习缓慢问题的效果。事实上,⼀个具有对数似然代价的柔性最⼤值输出层与⼀个具有交叉熵代价的 S 型输出层⾮常相似。

交叉熵代价函数本质与似然代价函数本质是一样的 交叉熵函数针对二分类问题,表示到两种类别的不确定性整体度量(y+1-y=1,a+1-a=1);似然代价函数针对多分类问题,表示到各类别的不确定性整体度量(Σyk=1, Σak=1)。 参考资料

作为⼀种更加通⽤的视⻆,柔性最⼤值加上对数似然的组合更加适⽤于那些需要将输出激活值解释为概率的场景,比如:相比sigmoid,softmax更适合解决多分类问题,其在诸如 MNIST 这种有着不重叠的分类问题上效果很好。


柔性最大值的来源是基于一般化的最大化函数:
Chapter3 改进神经网络的学习方法 - 图33
其中Chapter3 改进神经网络的学习方法 - 图34是正的常量。Chapter3 改进神经网络的学习方法 - 图35对应标准的柔性最⼤值函数。如果我们使⽤不同的Chapter3 改进神经网络的学习方法 - 图36得到不同的函数,其本质上和原来的柔性最⼤值函数是很相似的。假设我们允许Chapter3 改进神经网络的学习方法 - 图37⾜够⼤,Chapter3 改进神经网络的学习方法 - 图38,那么输出激活值的极限值就会趋近1,权重和偏置的变化率将非常大(求导后偏导数多乘了一个Chapter3 改进神经网络的学习方法 - 图39),Chapter3 改进神经网络的学习方法 - 图40时变化率相对较小,适合神经网络的学习,因此,对应的函数可以看作是⼀个最⼤化函数的柔和版本。

相关证明(计算偏导数)

根据i与j的关系分为两种情况对softmax函数求偏导:
Chapter3 改进神经网络的学习方法 - 图41时,
Chapter3 改进神经网络的学习方法 - 图42
Chapter3 改进神经网络的学习方法 - 图43时,
Chapter3 改进神经网络的学习方法 - 图44
进一步计算代价函数的偏导:
Chapter3 改进神经网络的学习方法 - 图45
Chapter3 改进神经网络的学习方法 - 图46
Chapter3 改进神经网络的学习方法 - 图47

过度拟合和规范化

过拟合

过度拟合(Overfitting):模型在训练集上表现很好,但对新数据预测时效果不好。
对于拥有⼤量⾃由参数的模型,⾜够的⾃由度使得它可以描述⼏乎所有给定⼤⼩的数据集,⽽不需要真正洞察现象的本质,这使得模型很可能出现对已有的数据表现的很好,但是对新的数据很难泛化的现象。这将导致训练得到的模型无法应用于新的数据。

如何检测模型是否产生过拟合?

跟踪测试数据集合上的准确率随训练变化的情况,在训练集上训练模型的过程中,当模型在测试集上的准确率不再上升,而训练集上的准确率依然上升(代价函数值还在下降)时,往往代表模型存在过拟合现象。
image.pngimage.png
image.pngimage.png
实际训练中,很少使用测试集来检测是否存在过拟合问题,常常将数据集划分为三个部分:训练集(training data)、交叉验证集(validation data)测试集(testing data)
其中,训练集用于训练模型,验证集用于调整和优化模型的超参数、检测过拟合现象,测试集用于检验模型性能,即模型的泛化误差。
image.png
形象上来说,训练集就像是学生的课本,学生根据课本里的内容来掌握知识,验证集就像是作业,通过作业可以知道不同学生学习情况、进步的速度快慢,而最终的测试集就像是考试,考的题是平常都没有见过,考察学生举一反三的能力。

为什么需要设置多余的验证集(validation data)? 为了优化模型的超参数,我们需要一个训练算法观测不到的数据集样本来进行调试,倘若直接使用测试集来作为调节模型超参数的依据,由于测试集参与了模型的调整,可能最终我们就会得到过度拟合于测试集(testing data)的超参数,使得模型无法泛化到其他数据集合上。因此,测试样本不能以任何形式参与到模型选择中,包括设定超参数。 因此,研究人员设定了专门用于调试超参数的验证集(validation data),可以把验证集看成是⼀种特殊的训练数据集,它能够帮助我们学习好的超参数。这种寻找好的超参数的⽅法有时被称为 hold out ⽅法,因为验证集(validation data)是从训练集(training data)中留出的⼀部分。

如何防止模型过拟合?

⼀般来说,最好的降低过度拟合的⽅式之⼀就是增加训练样本容量。有了⾜够的训练数据,就算是⼀个规模⾮常⼤的⽹络也不⼤容易过度拟合。然而训练数据往往是稀缺资源,增加训练样本容量不是⼀种太切实际的选择。
另一种可行的方法是降低⽹络的规模。然⽽,⼤的⽹络拥有⽐⼩⽹络更强的潜⼒,这样做可能会浪费这部分潜力。
此外,还有一种能够有效缓解过拟合的方法——规范化。

规范化(Regularization)

规范化是一种在尽管只有⼀个固定的⽹络和固定的训练集下仍能缓解过拟合的方法。
最常用的规范化方法是L2规范化(或称权重衰减)。L2 规范化的想法是增加⼀个额外的项到代价函数上,这个项叫做规范化项
Chapter3 改进神经网络的学习方法 - 图53
Chapter3 改进神经网络的学习方法 - 图54为原始代价函数,加入的规范化项等于所有权重的和乘以一个调节因子,Chapter3 改进神经网络的学习方法 - 图55规范化常数,规范化项⾥⾯并不包含偏置。
直觉地看,规范化的效果是让⽹络倾向于学习⼩⼀点的权重,⼤权重只在能够使得原始代价函数有比较大的下降时才被允许。规范化可以当做⼀种寻找⼩的权重和最⼩化原始的代价函数之间的折中,两部分的相对重要性由Chapter3 改进神经网络的学习方法 - 图56来控制:Chapter3 改进神经网络的学习方法 - 图57越⼩,越偏向于最⼩化原始代价函数,反之则倾向于⼩的权重。
此时代价函数对权重的偏导数会发生变化,偏置偏导不变:
Chapter3 改进神经网络的学习方法 - 图58
相应的学习规则也发生变化:
Chapter3 改进神经网络的学习方法 - 图59
和原始梯度下降的区别在于权重的重新调整(乘上因子Chapter3 改进神经网络的学习方法 - 图60),因此也称作权重衰减。权重并不会因此不断趋近于0,当原始梯度下降时,权重实际可能会变大。
随机梯度下降类似,只要把Chapter3 改进神经网络的学习方法 - 图61改成Chapter3 改进神经网络的学习方法 - 图62就可以。
规范化能够减轻过度拟合,提⾼分类准确率。除此之外。实践表明,在使⽤不同的(随机)权重初始化进⾏多次 MNIST ⽹络训练的时候,⽆规范化的⽹络会偶尔陷入局部最优,这导致不同的运⾏结果相差很⼤。
对⽐看来,规范化⽹络的输出效果相对稳定。从经验上看,如果代价函数是⽆规范化的,那么权重向量的⻓度可能会增⻓,随着时间的推移,这会导致权重向量变得⾮常⼤。当⻓度很⼤的时候,梯度下降仅仅引起权重在那个⽅向发⽣微⼩的变化,使得权重向量陷入局部最优。

规范化参数的选择要依据训练样本量来进行,样本量大时,分母大,规范化参数设置的应该大一些才能起到衰减的作用。

代码实现
    # 代价函数的修改
    def total_cost(self, data, lmbda, convert=False):
        cost = 0.0
        for x, y in data:
            a = self.feedforward(x)
            if convert: y = vectorized_result(y)
            cost += self.cost.fn(a, y)/len(data)
            cost += 0.5*(lmbda/len(data))*sum(np.linalg.norm(w)**2 for w in self.weights) # 多添加了规范化(正则化)项
        return cost

    # 更新规则的修改
     def update_mini_batch(self, mini_batch, eta, lmbda, n):
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        for x, y in mini_batch:
            delta_nabla_b, delta_nabla_w = self.backprop(x, y)
            nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
            nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
        self.weights = [(1-eta*(lmbda/n))*w-(eta/len(mini_batch))*nw for w, nw in zip(self.weights, nabla_w)]  # 修改了更新规则 
        self.biases = [b-(eta/len(mini_batch))*nb for b, nb in zip(self.biases, nabla_b)]

规范化为什么可以避免过拟合

通常的说法是:⼩的权重在某种程度上,意味着更低的复杂性,也就对数据给出了⼀种更简单却更强⼤的解释,因此应该优先选择。
image.pngimage.pngimage.png
举例而言,针对左侧的样本点,有右侧通过多项式拟合和线性拟合两种可能,二者都能取得不错的拟合效果,而多项式拟合几乎没有误差。
两种可能的情况:

  1. 9 阶多项式实际 上是完全描述了真实情况的模型,最终它能够很好地泛化;
  2. 正确的模型是 y = 2x,但是存 在着由于测量误差导致的额外的噪声,使得模型不能够准确拟合。

我们无法确认哪个模型是正确的模型,泛化能力更好的模型,但科学家往往认为简单的模型更能反映存在的潜在真理,因为规律简单是出于偶然的可能性较小。从这个⻆度看,多项式模型仅仅是学习到了局部噪声的影响效果。所以尽管对于这些特定的数据点表现得很好,但模型最终会在未知数据上的泛化上出现问题,所以噪声线性模型具有更强⼤的预测能⼒。

奥卡姆剃刀原则 一种常用的、自然科学研究中最基本的原则,主张选择与经验观察一致的最简单假设,即:若有多个假设与观察一致,则选最简单的那个。

在神经网络中,更⼩的权重意味着⽹络不会因为随便改变了⼀个输⼊⽽改变太⼤,这让规范化⽹络学习局部噪声的影响更加困难。⼤权重的⽹络可能会因为输⼊的微⼩改变⽽产⽣⽐较⼤的⾏为改变。简⾔之,规范化⽹络受限于根据训练数据中常⻅的模式来构造相对简单的模型,⽽能够抵抗训练数据中噪声特性的影响。
但奥卡姆剃刀并非唯一可能的原则,有时复杂的模型反而是更好的。对模型真正的测试不是简单性,⽽是它在新场景中对新活动的预测能⼒。规范化能帮助模型泛化的更好,但是并不会带来原理上理解的指导,我们无法确定如何泛化是更好的。

「没有免费的午餐」定理(NFL) 该定理证明了对于所有机器学习问题,算法A更好和算法B更好的概率是一样的。更一般地说,对于所有机器学习问题,任何一种算法(包括瞎猜)的期望效果都是一样的。

自规范化效应 拥有 100 个隐藏元的⽹络会有接近 80,000 个参数。我们的训练集仅仅有 50,000 幅图像。这好像是⽤⼀个 80,000 阶的多项式来拟合 50,000 个数据点。我们的⽹络肯定会过度拟合得很严重。但是,这样的⽹络实际上却泛化得很好。为什么?这⼀点并没有很好地理解。这⾥有个猜想:梯度下降学习的动态有⼀种⾃规范化的效应。

规范化为什么没有限制偏置

我们通常不会对偏置进⾏规范化。有⼀个⼤的偏置并不会像⼤的权重那样会让神经元对输⼊太过敏感,我们不需要对⼤的偏置所带来的学习训练数据的噪声太过担⼼。同时,允许⼤的偏置能够让⽹络更加灵活,⼤的偏置让神经元更加容易饱和。

规范化的其他技术

L1规范化

在未规范化的代价函数上加上⼀个权重绝对值的和:
Chapter3 改进神经网络的学习方法 - 图66
其更新规则与L2有些许差异:
Chapter3 改进神经网络的学习方法 - 图67
L2和L1规范化都缩小了权重,不同的是:

  • L1减少的是一个常量,L2减少的是权重的固定比例
  • 因此,当Chapter3 改进神经网络的学习方法 - 图68很大时,L2缩小的更多;当Chapter3 改进神经网络的学习方法 - 图69很小时,L1缩小的更多
  • L1使权重稀疏,L2使权重平滑,一句话总结就是:L1会趋向于产生少量的特征,而其他的特征都是0,而L2会选择更多的特征,这些特征都会接近于0
  • 实践中L2正则化通常优于L1正则化

    由于绝对值函数在0处不可导,因此可令Chapter3 改进神经网络的学习方法 - 图70,在0处不使用L1正则化(使用非规范化的梯度下降)。

弃权(Dropout)

  • 相对激进
  • 不依赖于对代价函数修改
  • 改变网络本身

其具体操作流程如下,假设我们要训练一个神经网络:
Chapter3 改进神经网络的学习方法 - 图71Chapter3 改进神经网络的学习方法 - 图72

输入是x输出是y,正常的流程是:我们首先把x通过网络前向传播,然后把误差反向传播以决定如何更新参数让网络进行学习。使用Dropout之后,过程如下:

  1. 随机(临时)删掉网络中一半的隐藏神经元,输入输出神经元保持不变(右图中虚线为部分临时被删除的神经元)
  2. 把输入x通过修改后的网络前向传播,然后把得到的损失结果通过修改的网络反向传播。一小批训练样本(batch)执行完这个过程后,在没有被删除的神经元上按照随机梯度下降法更新对应的参数(w,b)。
  3. 继续重复这一过程:
  • 恢复被删掉的神经元(此时被删除的神经元保持原样,而没有被删除的神经元已经有所更新)
  • 从隐藏层神经元中随机选择一个一半大小的子集临时删除掉(备份被删除神经元的参数)。
  • 对一小批训练样本,先前向传播然后反向传播损失并根据随机梯度下降法更新参数(w,b) (没有被删除的那一部分参数得到更新,删除的神经元参数保持被删除前的结果)。
  1. 不断重复这一过程,得到一个权重和偏置的集合

    Notes: 代码层面实现删除网络中一定数量的隐藏神经元,其实就是让某个神经元以概率p停止工作,即让它的激活函数值以概率p变为0。比如我们某一层网络神经元的个数为1000个,其激活函数输出值为y1、y2、y3、……、y1000,我们dropout比率选择0.4,那么这一层神经元经过dropout后,1000个神经元中会有大约400个的值被置为0。 经过上面屏蔽掉某些神经元,使其激活值为0以后,我们还需要对向量y1……y1000进行缩放(rescale),也就是乘以1/(1-p)。如果在训练的时候,经过置0后,没有对y1……y1000进行以上的缩放(rescale),那么在测试的时候,就需要对权重进行缩放,预测模型的时候,每一个神经单元的权重参数要乘以概率1-p。


为什么Dropout可以起到避免过拟合的作用?

  • 取平均的作用:标准的模型(没有Dropout)中,用相同的训练数据去训练不同的神经网络得到不同的结果,此时我们可以采用取均值或者多数取胜的投票策略决定最终结果。这种「综合起来取平均」的策略通常可以有效防止过拟合问题。Dropout不同的隐藏神经元就类似在训练不同的网络,随机删掉一半隐藏神经元导致网络结构不同,整个Dropout过程就相当于对很多个不同的神经网络取平均。而不同的网络产生不同的过拟合,一些互为“反向”的拟合相互抵消就可以达到整体上减少过拟合。
  • 减少神经元之间复杂的共适应关系: 因为两个神经元不一定每次都在一个Dropout网络中出现,这样权值的更新不再依赖于有固定关系的隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况 ,迫使网络去学习更加鲁棒的特征。换句话说,假如我们的神经网络是在做出某种预测,它不应该对一些特定的线索片段太过敏感,即使丢失特定的线索,它也应该可以从众多其它线索中学习一些共同的特征。从这个角度看Dropout类似L1,L2正则,减少权重使得网络对丢失特定神经元连接的鲁棒性提高。

    人为扩展训练数据

    获取更多的训练样本进行训练往往能得到更好的性能,但实践中数据的获取往往比较困难,因此可以采用人工扩展训练数据的方法来扩大样本容量。这种方法往往基于现实经验进行。比如,对于MNIST数据集提供的手写数字图片,可以进行小幅度的旋转、扭曲来产生新的样本,或者手动增加背景噪声来扩展数据。
    image.png

    数据规模和分类准确率的一些笔记: 更多的训练数据可以弥补不同机器学习算法之间的差距。同时,在不同的数据集合上,不同机器学习算法的效果会有区别,算法A可能在这个训练集合上好于B,但它在另一个训练集合上可能会比B差很多。

    image.png 因此,在标准(基准)数据集上表现得好依旧仅仅是在特定数据集上的性能表现,需要同时寻找更好的算法和更好的训练数据,而不是盲目在标准数据集上提升性能。

权重初始化

初始方法

根据独立高斯随机变量选择权重和偏置,均值为1,标准差为0。

缺陷

输入Chapter3 改进神经网络的学习方法 - 图75各分量相互独立,服从Chapter3 改进神经网络的学习方法 - 图76正态分布,此时Chapter3 改进神经网络的学习方法 - 图77服从一个标准差很大的正态分布,是一个非常宽的正态分布。此时Chapter3 改进神经网络的学习方法 - 图78有很大概率远大于1,Chapter3 改进神经网络的学习方法 - 图79接近1或0,神经元接近饱和,调整权重将带来代价函数值非常微小的改变,使得网络学习得很慢。

image.png
尽管之前调整代价函数的方法能够避免这个问题,但其仅仅针对输出神经元的饱和,对隐藏神经元的饱和并没有效果。

改进方法——Chapter3 改进神经网络的学习方法 - 图81 权重

使⽤均值为 0 标准差为Chapter3 改进神经网络的学习方法 - 图82 权重的⾼斯随机分布初始化权重(由于偏置只有一项对整体分布影响小,因而不必作过多修改,继续使⽤均值为 0 标准差为 1 的⾼斯分布来对偏置进⾏初始化)
假设有1000个输入,500个为0,500个为1,由于偏置Chapter3 改进神经网络的学习方法 - 图83,此时Chapter3 改进神经网络的学习方法 - 图84,即其标准差为Chapter3 改进神经网络的学习方法 - 图85的一个较窄的高斯分布:
image.png
这样的⼀个神经元更不可能饱和,因此,该方法降低了遇到学习速度下降问题的概率。


验证改进后的效果

比较隐藏输入层分别为30和100情况下,初始权重是否经过以上调整的结果:
image.pngimage.png
基于这些实验,可以发现提升的权重初始化仅仅会加快训练,不会改变⽹络的最终性能。然⽽,在后面的学习中,会看到⼀些例⼦⾥使⽤ Chapter3 改进神经网络的学习方法 - 图89 权重初始化的⻓期运⾏的结果要显著更优。因此,使⽤ Chapter3 改进神经网络的学习方法 - 图90 权重不仅仅能够带来训练速度的加快,有时候在最终性能上也有很大的提升。

代码实现
# 改进方法,区别在于添加了'/np.sqrt(x)'
def default_weight_initializer(self):
        self.biases = [np.random.randn(y, 1) for y in self.sizes[1:]]
        self.weights = [np.random.randn(y, x)/np.sqrt(x)
                        for x, y in zip(self.sizes[:-1], self.sizes[1:])]
# 原始方法
def large_weight_initializer(self):
        self.biases = [np.random.randn(y, 1) for y in self.sizes[1:]]
        self.weights = [np.random.randn(y, x)
                        for x, y in zip(self.sizes[:-1], self.sizes[1:])]

超参数的选择

宽泛策略(Broad Strategy)

简化问题和架构,从较为简单的结构进行测试,来寻找好的超参数。由于问题规模等的简化,模型训练速度会快很多,可以进行更多的测试。

具体超参数设置

主要给出了一些超参数选择的启发式规则,但并不局限于这里列举的这些。
超参数的选择有很多方法和策略,可以参考以下的论⽂:

  • Yoshua Bengio 在 2012 年的论⽂Practical recommendations for gradient-based training of deep architectures中给出了⼀些实践上关于训练神经⽹络⽤到的反向传播和梯度下降的技术的推荐策略,其中还包含如何进⾏系统化的超参数搜索。
  • 1998 年的 Yann LeCun、Léon Bottou、Genevieve Orr 和 Klaus-Robert Müller 所著的Efficient BackProp
  • 这些论⽂收集在 2012年的Neural Networks: Tricks of the Trade中,这本书介绍了很多训练神经⽹络的常⽤技巧。

    学习速率

    使用不同的学习速率,得到的代价函数下降过程主要呈现以下两种状态:

  • 训练一开始很快进入震荡/增加

  • 训练一开始就进入下降,而后逐渐收敛,最终进入小幅度震荡

image.png
如该图,Chapter3 改进神经网络的学习方法 - 图92时,步长很大,代价自始至终震荡的非常明显;Chapter3 改进神经网络的学习方法 - 图93时,代价一直保持下降至最后,但这样的学习速率会使训练过程很漫长;相对而言Chapter3 改进神经网络的学习方法 - 图94时,初始几步下降,很快进入小幅度震荡,即后期该步长使得函数很容易跨过「谷底」,更好的方法是在后期使用更小的步长,比如Chapter3 改进神经网络的学习方法 - 图95,这种方法被称为可变学习速率
因此,在选择合适的学习速率的问题上,为了兼顾训练速度和训练效果,可以考虑利用试错法找到介于震荡和下降之间的阈值。最终取的值不会取阈值,而往往会取比阈值稍小的值,因为往往训练的回合会较长,后期该学习速率就会偏大。可以考虑取阈值的⼀半,这样的选择能够允许你训练更多的回合,且不会减慢学习的速度。

为什么学习速率这一超参数的选择没有使用验证集? 其他超参数倾向于提升最终测试集上的分类准确率,如:mini-batch的大小、网络层数、隐藏元个数,往往使用验证集计算分类准确率来寻找好的规范化超参数。相比之下,学习速率仅仅偶然影响最终的分类准确率。学习速率主要的⽬的是控制梯度下降的步⻓,监控训练代价是最好的检测步⻓过⼤的⽅法。 作者提到,没有使用验证集仅仅是一种个人选择。

迭代期数——提前终止

基本思路

在每个回合后都计算验证集上的分类准确率,待分类准确率不再提升,就终止它。

具体实现

分类准确率不再上升并不指前后两次不再上升,这样的判断准则会使该策略过于激进,因为常常出现迭代需要经历「平台期」的情况,即上升一定幅度后需要经历一段时间代价基本不变的阶段。
可以针对这种情况设置一种新的判断规则——分类准确率在10/20/…回合内没有提升时终止,这种方法也衍生出了新的一个超参数,但该参数并不难选择,考虑从10回合(一般而言不错的初始值)开始尝试,逐步加大回合数,寻找好的提前终止策略。

可变学习速率

基本思路

前期学习速率较大,便于快速下降,后期逐渐减小,防止震荡,慢慢收敛于局部最小值

具体实现

⼀种⾃然的观点是使⽤提前终⽌的想法。保持学习速率为⼀个常量直到验证准确率开始变差,然后按照某个量下降学习速率,⽐如说按 10 或者 2。重复此过程若⼲次,直到学习速率是初始值的 1/1024(或者 1/1000)时终⽌。

规范化参数

开始时不包含规范化(Chapter3 改进神经网络的学习方法 - 图96),确定Chapter3 改进神经网络的学习方法 - 图97的值。使⽤确定出来的Chapter3 改进神经网络的学习方法 - 图98,使⽤验证数据来选择好的Chapter3 改进神经网络的学习方法 - 图99。从尝试Chapter3 改进神经网络的学习方法 - 图100开始,然后根据验证集上的性能按照因⼦ 10 增加或减少其值。⼀旦找到⼀个好的量级,就可以改进Chapter3 改进神经网络的学习方法 - 图101的值。这⾥搞定后,返回再重新优化Chapter3 改进神经网络的学习方法 - 图102

小批量数据大小(size of mini-batch)

优化思路——大好还是小好?

对于小批量数据大小,只需寻找确保代价函数保持下降的⾜够精确的估计,因此尽管在线学习设置的batch size为1,和实际梯度会有很大误差,但并不妨碍梯度的下降。
为了寻找合适的小批量数据大小,可以这样考虑,在前一章提到,使用矩阵并行运算mini-batch中所有样本的梯度比之于循环计算样本梯度可以加快运算速度,节省运算时间。此时,在线学习就类似于循环(尽管实际是存在差异的,因为使用的权重不同,在线学习使用的权重是累加的,循环计算使用的权重则是一致的),因此,适当提高小批量数据大小是能够提升训练速度的。
综上,选择最好的⼩批量数据⼤⼩也是⼀种折衷。太⼩,不能利用矩阵库的并行计算提高运算速度。太⼤,则不能够⾜够频繁地更新权重。

具体实现

⼩批量数据⼤⼩其实是相对独⽴的⼀个超参数(⽹络整体架构外的参数),其并不需要优化其他参数来寻找更优的⼩批量数据⼤⼩。因此,可以使⽤某些可以接受的值(不需要是最优的)作为其他参数的选择,然后在不同⼩批量数据⼤⼩上进行试验,像上⾯那样调整 Chapter3 改进神经网络的学习方法 - 图103——画出验证准确率的值随时间(⾮回合)变化的图,选择能够得到最快性能提升的⼤⼩。

自动化技术

之前的方法都需要人工手动调整来寻找好的超参数,但现实中,有很大部分超参数都已经使用自动化过程来确定和优化。运用最广的技术是网格搜索(grid search),该方法可以系统化地对超参数的参数空间的⽹格进⾏搜索,具体参见Random search for hyper-parameter optimization,作者为 James Bergstra 和 Yoshua Bengio (2012)。
此外还有使用贝叶斯观点的自动优化,详见Practical Bayesian optimization of machine learning algorithms,作者为 Jasper Snoek,Hugo Larochelle和Ryan Adams。

其他技术

随机梯度下降的变化形式

Hessian技术

Hessian技术其实就是优化中的牛顿法,相比梯度下降法下降的更快。

优化里一般每次下降取最优步长(最优学习速率),但神经网络学习为了提高效率中一般使用固定学习率

权重更新方程:
Chapter3 改进神经网络的学习方法 - 图104
Hessian技术比标准梯度下降速度要快,但由于Hessian矩阵很难计算,因此实践中很少使用。

基于momentum的梯度下降

Hessian优化的特点在于它还考虑了梯度如何变化的信息,momentum方法就基于这个直觉对标准梯度下降进行了改进,基于物理学的启发,引入了速度的概念。

momentum本义即冲量,反映了力对时间的积累效应。同样的,momentum梯度下降中Chapter3 改进神经网络的学习方法 - 图105是通过梯度对Chapter3 改进神经网络的学习方法 - 图106产生作用的积累而得到的。梯度影响速度(相当于一个力,施加了一个加速度,改变了速度),速度积攒了历史梯度,然后间接控制了Chapter3 改进神经网络的学习方法 - 图107的变化率。

权重更新方程:
Chapter3 改进神经网络的学习方法 - 图108
其中,Chapter3 改进神经网络的学习方法 - 图109是用于控制阻碍或摩擦力大小的超参数。Chapter3 改进神经网络的学习方法 - 图110代表摩檫力的大小,可以使用hold out来选择适合的值。
当梯度方向变化较大(夹角呈钝角),Chapter3 改进神经网络的学习方法 - 图111就会被相互抵消,使得下降变慢;当梯度方向变化不大时,Chapter3 改进神经网络的学习方法 - 图112被放大,相当于加大现梯度,加快了下降速度。同时,由于前后两次梯度的叠加,可以减轻左右振荡,更快到达谷底。

Chapter3 改进神经网络的学习方法 - 图113,相当于摩擦力为负值,训练过程将永远无法收敛;当Chapter3 改进神经网络的学习方法 - 图114,先前的梯度影响过大(摩擦力过大),可能会使球反向运动,减缓下降速度。

其他优化代价函数的方法

  • 共轭梯度下降
  • BFGS
  • Nesterov的加速下降技术

    人工神经元的其他模型

    tanh神经元

    实际仅仅是S型函数的按比例变化版本,基于双曲正切函数:
    Chapter3 改进神经网络的学习方法 - 图115
    Chapter3 改进神经网络的学习方法 - 图116
    其函数图象为:
    image.png
    由于Chapter3 改进神经网络的学习方法 - 图118神经元输出的值域为Chapter3 改进神经网络的学习方法 - 图119,需要对最终的输出进行正规化(标准化)。

    某种对tanh神经元优于S型神经元的启发性解释: 由于权重的梯度为Chapter3 改进神经网络的学习方法 - 图120,而S型神经元输出值Chapter3 改进神经网络的学习方法 - 图121均为正值,因此,这会导致连接在同一个神经元的所有权重变化的方向都是一致的(取决于Chapter3 改进神经网络的学习方法 - 图122)。而tanh神经元的激活值能够在正负之间保持平衡,使得权重的更新不会出现系统化单方向的偏置。

修正线性神经元(ReLU)

其函数形式:
Chapter3 改进神经网络的学习方法 - 图123
对应函数图象:
image.png
ReLU和Sigmoid以及tanh都能够用于计算任何函数,使用反向传播算法和随机梯度下降进行训练。
ReLU目前广泛使用于计算机视觉领域,它有两个优点:

  • 不会像sigmoid一样出现饱和的问题(导数是不变的)
  • 当带全输入为负数时,梯度完全消失,神经元也会完全停止学习。