登 录
注 册
< 人工智能
深度学习
机器学习
大模型
深度学习介绍
现状和未来
数学基础
通用工作流程
Keras简介
过拟合与欠拟合
卷积神经网络
热门推荐>>>
中台架构
中台建设与架构
Hadoop
源码分析-NN启动(三)
HBase
HBased对接Hive
Linux
Nginx高可用
Python
数据导出工具
Flink
3分钟搭建Flink SQL测试环境
Kafka
Kafka对接Flume
数据结构与算法
选择合适的算法
MySQL
数据备份恢复
计算机系统
信号量同步线程
Hive
Hive调优参数大全
其他框架
Azkaban Flow1.0与2.0
ClickHouse
表引擎-其他类型
技术成长
最好的职业建议
精选书单
技术成长书单—机器学习
技术资讯
数据在线:计算将成为公共服务
开发工具
IntelliJ IDEA 20年发展回顾(二)
系统工具
Mac命令行工具
虚拟化
内存虚拟化概述
云原生
云原生构建现代化应用
云服务
一文搞懂公有云、私有云...
Java
Spring Boot依赖注入与Runners
Go
Go函数与方法
SQL
SQL模板
安全常识
一文读懂SSO
当前位置:
首页
>>
深度学习
>>
过拟合与欠拟合
过拟合与欠拟合
2020-07-04 17:26:36 星期六 阅读:6378
机器学习的根本问题是优化和泛化之间的对立。`优化(optimization)`是指调节模型以在训练数据上得到最佳性能(即机器学习中的学习),而`泛化(generalization)`是指训练好的模型在前所未见的数据上的性能好坏。机器学习的目的当然是得到良好的泛化,但你无法控制泛化, 只能基于训练数据调节模型。 训练开始时,优化和泛化是相关的:训练数据上的损失越小,测试数据上的损失也越小。这时的模型是欠拟合(underfit)的,即仍有改进的空间,网络还没有对训练数据中所有相关模 式建模。但在训练数据上迭代一定次数之后,泛化不再提高,验证指标先是不变,然后开始变差, 即模型开始过拟合。这时模型开始学习仅和训练数据有关的模式,但这种模式对新数据来说是 错误的或无关紧要的。 为了防止模型从训练数据中学到错误或无关紧要的模式,`最优解决方法是获取更多的训练数据`。模型的训练数据越多,泛化能力自然也越好。如果无法获取更多数据,次优解决方法是`调节模型允许存储的信息量`,或对模型允许存储的信息加以约束。如果一个网络只能记住几个模式,那么优化过程会迫使模型集中学习最重要的模式,这样更可能得到良好的泛化。 这种降低过拟合的方法叫做正则化,我们先介绍几种最常见的正则化方法,然后将其应用于实践中。 ####减小网络大小 防止过拟合的最简单的方法就是减小模型大小,即减少模型中可学习参数的个数(这由层数和每层的单元个数决定)。**`在深度学习中,模型中可学习参数的个数通常被称为模型的容量 (capacity)`**。直观上来看,参数更多的模型拥有更大的记忆容量(memorization capacity),因此能够在训练样本和目标之间轻松地学会完美的字典式映射,这种映射没有任何泛化能力。例如,拥有 500 000 个二进制参数的模型,能够轻松学会 MNIST 训练集中所有数字对应的类别——我们只需让 50 000 个数字每个都对应 10 个二进制参数。但这种模型对于新数字样本的分类毫无用处。 始终牢记:`深度学习模型通常都很擅长拟合训练数据,但真正的挑战在于泛化,而不是拟合。` 与此相反,如果网络的记忆资源有限,则无法轻松学会这种映射。因此,为了让损失最小化, 网络必须学会对目标具有很强预测能力的压缩表示,这也正是我们感兴趣的数据表示。同时请 记住,你使用的模型应该具有足够多的参数,以防欠拟合,即模型应避免记忆资源不足。在容 量过大与容量不足之间要找到一个折中。 不幸的是,没有一个魔法公式能够确定最佳层数或每层的最佳大小。你必须评估一系列不同的网络架构(当然是在验证集上评估,而不是在测试集上),以便为数据找到最佳的模型大小,要找到合适的模型大小,一般的工作流程是`开始时选择相对较少的层和参数,然后逐渐加层的大小或增加新层,直到这种增加对验证损失的影响很小。` 我们在电影评论分类的网络上试一下,原始网络结构如下 ``` from keras import models from keras import layers model = models.Sequential() model.add(layers.Dense(16, activation="relu", input_shape=(10000,))) model.add(layers.Dense(16, activation="relu")) model.add(layers.Dense(1, activation="sigmoid")) ``` 现在我们尝试用下面的这个更小的网络来替换 ``` from keras import models from keras import layers model = models.Sequential() model.add(layers.Dense(4, activation="relu", input_shape=(10000,))) model.add(layers.Dense(4, activation="relu")) model.add(layers.Dense(1, activation="sigmoid")) ``` `更小的网络开始过拟合的时间要晚于更大的网络。而且过拟合之后,它的性能变差的速度也更慢` `网络的容量越大,它拟合训练数据(即得到很小的训练损失)的速度就越快,但也更容易过拟合。` ####添加权重正则化 你可能知道奥卡姆剃刀(Occam’s razor)原理:如果一件事情有两种解释,那么最可能正 确的解释就是最简单的那个,即假设更少的那个。这个原理也适用于神经网络学到的模型:给定一些训练数据和一种网络架构,很多组权重值(即很多模型)都可以解释这些数据。简单模 型比复杂模型更不容易过拟合。 这里的简单模型(simple model)是指参数值分布的熵更小的模型(或参数更少的模型,比 如上一节的例子)。因此,`一种常见的降低过拟合的方法就是强制让模型权重只能取较小的值`,从而限制模型的复杂度,这使得权重值的分布更加规则(regular)。这种方法叫作`权重正则化(weight regularization)`,其实现方法是向网络损失函数中添加与较大权重值相关的成本(cost)。 这个成本有两种形式。 - L1 正则化(L1 regularization):添加的成本与权重系数的绝对值[权重的 L1 范数(norm)] 成正比。 L2 正则化(L2 regularization):添加的成本与权重系数的平方(权重的 L2 范数)成正比。 神经网络的 L2 正则化也叫权重衰减(weight decay)。 不要被不同的名称搞混,权重衰减 与 L2 正则化在数学上是完全相同的。 在 Keras 中,添加权重正则化的方法是向层传递权重正则化项实例(weight regularizer instance)作为关键字参数。下列代码将向电影评论分类网络中添加 L2 权重正则化。 ``` from keras import regularizers model = models.Sequential() model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001), activation="relu", input_shape=(10000,))) model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001), activation="relu")) model.add(layers.Dense(1, activation="sigmoid")) ``` l2(0.001)的意思是该层权重矩阵的每个系数都会使网络总损失增加0.001 * weight_ coefficient_value。注意,由于这个惩罚项只在训练时添加,所以这个网络的训练损失会比测试损失大很多。 ####增加dropout正则化 dropout 是神经网络最有效也最常用的正则化方法之一,它是由多伦多大学的 Geoffrey Hinton 和他的学生开发的。`对某一层使用 dropout,就是在训练过程中随机将该层的一些输出特征舍弃(设置为 0)`。假设在训练过程中,某一层对给定输入样本的返回值应该是向量 [0.2, 0.5, 1.3, 0.8, 1.1]。使用 dropout 后,这个向量会有几个随机的元素变成 0,比如 [0, 0.5, 1.3, 0, 1.1]。dropout 比率(dropout rate)是被设为 0 的特征所占的比例,通常在 0.2~0.5 范围内。测试时没有单元被舍弃,而该层的输出值需要按 dropout 比率缩小,因为这时比训练时 有更多的单元被激活,需要加以平衡。 假设有一个包含某层输出的 Numpy 矩阵layer_output,其形状为(batch_size, features)。训练时,我们随机将矩阵中一部分值设为 0。 ``` # 随机生成指定size的0、1整数 layer_out *= np.random.randint(0, high=2, size=layer_output.shape) ``` 测试时,我们将输出按 dropout 比率缩小。这里我们乘以 0.5(因为前面舍弃了一半的单元)。 `layer_output *= 0.5` 注意, 为了实现这个过程,还可以让两个运算都在训练时进行。而测试时输出保持不变,这通常也是实践中的实现方式。 ``` layer_output *= np.random.randint(0, high=2, size=layer.output.shape) layer_output /= 0.5 #等比例方法 ``` 这一方法可能看起来有些奇怪和随意。它为什么能够降低过拟合? Hinton 说他的灵感之一来自于银行的防欺诈机制。用他自己的话来说:“我去银行办理业务。柜员不停地换人,于是我问其中一人这是为什么。他说他不知道,但他们经常换来换去。我猜想,银行工作人员要想成功欺诈银行,他们之间要互相合作才行。这让我意识到,`在每个样本中随机删除不同的部分神经元,可以阻止它们的阴谋,因此可以降低过拟合`。其核心思想是在层的输出值中引入噪声, 打破不显著的偶然模式(Hinton 称之为阴谋)。如果没有噪声的话,网络将会记住这些偶然模式。 在 Keras 中,你可以通过 Dropout 层向网络中引入 dropout,dropout 将被应用于前面一层 的输出。 我们向IMDB网络中添加两个Dropout层,来看一下它们降低过拟合的效果 ``` model = model.Sequential() model.add(layers.Dense(16, activation="relu", input_shape=(10000,))) model.add(layers.Dropout(0.5)) model.add(layers.Dense(16, activation="relu")) model.add(layers.Dropout(0.5)) model.add(layers.Dense(1, activation="sigmoid")) ``` ####总结 防止神经网络过拟合的常用方法包括: - 获取等多的训练数据 减小网络容量 添加权重正则化 添加dropout