1.过拟合和欠拟合
过拟合是指在验证数据上模型的准确性将达到峰值,然后停滞或开始下降。
过度拟合训练数据。学习如何应对过度拟合非常重要。尽管通常可以在训练集上达到高精度,但是我们真正想要的是开发能够很好地推广到测试集(或之前未见的数据)的模型。
如下图:
欠拟合是指模型仍有改进空间,如果模型不够强大,模型过于规范化,或者仅仅是没有经过足够长时间的训练。
而在机器学习过程中经常面对和需要解决的是过拟合问题。
2.如何处理过拟合
2.1处理过拟合的理论:
- 正则化
- 提前停止(Early stopping)
- 获取更多的训练集
- 选用合适的模型
2.2 TensorFlow中的方法
为了防止过度拟合,最好的解决方案是使用更完整的训练数据。数据集应涵盖模型应处理的所有输入范围。仅当涉及新的有趣案例时,其他数据才有用。
经过更完整数据训练的模型自然会更好地推广。当这不再可能时,下一个最佳解决方案是使用正则化之类的技术。这些因素限制了模型可以存储的信息的数量和类型。如果网络只能存储少量模式,那么优化过程将迫使它专注于最突出的模式,这些模式具有更好的泛化性。
但是在现实生活中通常无法将所有的数据都收集起来做为训练集,这样的话模型就没有了预测的意义。所以本文着重介绍一下正则化的技术:
from IPython import display
from matplotlib import pyplot as plt
import numpy as np
import pathlib
import shutil
import tempfile
pathlib
--- 面向对象的文件系统路径
该模块提供表示文件系统路径的类,其语义适用于不同的操作系统。路径类被分为提供纯计算操作而没有 I/O 的 纯路径,以及从纯路径继承而来但提供 I/O 操作的 具体路径。
shutil
--- 高阶文件操作
shutil
模块提供了一系列对文件和文件集合的高阶操作。 特别是提供了一些支持文件拷贝和删除的函数。
temfile --- 临时文件操作
临时文件来存储数据,但不需要同其他程序共享,那么用TemporaryFile函数创建临时文件是最好的选择。其他的应用程序是无法找到或打开这个文件的,因为它并没有引用文件系统表。用这个函数创建的临时文件,关闭后会自动删除。
补充知识点——是否采用批处理的方式
缩短了时间但是并不明显,我们采用一个大的数据集:
深度学习模型往往擅长拟合训练数据,但真正的挑战是泛化,而不是拟合。即需要的是在测试集上的准确率。
防止过度拟合的最简单方法是从小模型开始:具有少量可学习参数(由层数和每层单位数确定)的模型。在深度学习中,模型中可学习参数的数量通常称为模型的“容量”。
直观地讲,具有更多参数的模型将具有更多的“记忆能力”,因此将能够轻松学习训练样本与其目标之间的完美的字典式映射,但是过于记住训练的样本的能力反而丧失了良好的泛化能力。
为了找到合适的模型大小,最好从相对较少的图层和参数开始,然后开始增加图层的大小或添加新的图层,直到看到验证损失的收益递减为止。
训练程序
如果在训练过程中逐渐降低学习率,许多模型的训练效果会更好。
逐渐增加模型的复杂度,先从简单的模型开始。
第一个模型是3072-500-64-10的神经网络
第二个模型是3072-1000-256-10的神经网络;
我们发现准确率反而下降了。
简化网络3072-1000-128-10:(上面是tanh函数,下面是sigmoid)
继续简化3072-800-96:
添加权重正则化
# 2.构建模型
model = keras.Sequential([
keras.layers.Flatten(input_shape=(32, 32, 3)), # Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。
keras.layers.Dense(1024, activation='sigmoid', kernel_regularizer=regularizers.l2(0.001)),
keras.layers.Dense(512, activation='sigmoid', kernel_regularizer=regularizers.l2(0.001)),
keras.layers.Dense(128, activation='sigmoid', kernel_regularizer=regularizers.l2(0.001)),
keras.layers.Dense(10)
])
通过L2参数进行正则化:
L2正则化,其中增加的成本与权重系数的值的平方成正比(即与权重的平方的“ L2范数”平方成正比)。 L2正则化在神经网络中也称为权重衰减。 不要让其他名称感到困惑:权重衰减在数学上与L2正则化完全相同。
虽然从整体上看准确率是在上升,loss在下降,但是发生了剧烈的抖动,仍然存在问题。
添加dropout
# 2.构建模型
model = keras.Sequential([
keras.layers.Flatten(input_shape=(32, 32, 3)), # Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。
keras.layers.Dense(1000, activation='sigmoid'),
keras.layers.Dropout(0.5),
keras.layers.Dense(256, activation='sigmoid'),
keras.layers.Dropout(0.5),
keras.layers.Dense(32, activation='sigmoid'),
keras.layers.Dropout(0.5),
keras.layers.Dense(10)
])
Dropout是Hinton和他在多伦多大学的学生开发的最有效,最常用的神经网络正则化技术之一。
“dropout rate”是被清零的特征的一部分。通常设置在0.2到0.5之间。在测试时,不会丢失任何单元,而是将图层的输出值按等于丢失率的比例缩小,以平衡比训练时活动的单元更多的事实。
相比于l2正则化,dropout处理的曲线更圆滑,而且效果更好一些。
但是出现了一个“反常”的情况就是模型在验证集上的表现竟然比在训练集上要好一些。
关键就是丢弃的特征都是训练集上特有的正好在验证集上没有导致在验证集上的表现比在训练集上更好一些。
两种方法混合
# 2.构建模型
model = keras.Sequential([
keras.layers.Flatten(input_shape=(32, 32, 3)), # Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。
keras.layers.Dense(1000, activation='sigmoid', kernel_regularizer=regularizers.l2(0.001)),
keras.layers.Dropout(0.5),
keras.layers.Dense(256, activation='sigmoid', kernel_regularizer=regularizers.l2(0.001)),
keras.layers.Dropout(0.5),
keras.layers.Dense(10)
])
效果非常不好,按理说不会这样,于是改编模型架构。
设置为3072-512-128-10