第四章 机器学习基础
本章重点:处理机器学习问题的通用工作流程:
- 定义问题与要训练的数据。 收集这些数据,有需要的话用标签来标注数据。
- 选择衡量问题成功的指标。 你要在验证数据上监控哪些指标?
- 确定评估方法:留出验证? K 折验证?你应该将哪一部分数据用于验证?
- 开发第一个比基准更好的模型,即一个具有统计功效的模型。
- 开发过拟合的模型。
- 基于模型在验证数据上的性能来进行模型正则化与调节超参数。
4.1 机器学习的四个分支
4.1.1 监督学习
监督学习是目前最常见的机器学习类型。给定一组样本(通常由人工标注),它可以学会将输入数据映射到已知目标[也叫 标 注 ( a n n o t a t i o n ) \color{red}标注(annotation) 标注(annotation)]。
监督学习主要包括分类和回归,更多的奇特变体,主要包括如下几种:
- 序列生成(sequence generation)。给定一张图像,预测描述图像的文字。序列生成有时可以被重新表示为一系列分类问题,比如反复预测序列中的单词或标记。
- 语法树预测(syntax tree prediction)。给定一个句子,预测其分解生成的语法树。
- 目标检测(object detection)。给定一张图像,在图中特定目标的周围画一个边界框。这个问题也可以表示为分类问题(给定多个候选边界框,对每个框内的目标进行分类)或分类与回归联合问题(用向量回归来预测边界框的坐标)。
- 图像分割(image segmentation)。给定一张图像,在特定物体上画一个像素级的掩模(mask)。
4.1.2 无监督学习
- 无监督学习是指在没有目标的情况下寻找输入数据的有趣变换,其目的在于数据可视化、数据压缩、数据去噪或更好地理解数据中的相关性。
- 为了更好地了解数据集,是解决监督学习问题之前的一个必要步骤。降维(dimensionality reduction)和聚类(clustering)都是众所周知的无监督学习方法。
4.1.3 自监督学习
- 自监督学习是 没 有 人 工 标 注 的 标 签 的 监 督 学 习 \color{red}没有人工标注的标签的监督学习 没有人工标注的标签的监督学习。标签仍然存在(因为总要有什么东西来监督学习过程),但它们是从输入数据中生成的,通常是使用 启 发 式 算 法 生 成 \color{red}启发式算法生成 启发式算法生成的。
- 常见的自监督学习
- 自编码器(autoencoder),其生成的目标就是未经修改的输入。
- 时序监督学习(temporally supervised learning),给定视频中过去的帧来预测下一帧,或者给定文本中前面的词来预测下一个词。
- 监督学习、自监督学习和无监督学习之间的区别有时很模糊,这三个类别更像是没有明确界限的连续体。
分类和回归术语表:
- 样 本 ( s a m p l e ) 或 输 入 ( i n p u t ) \color{red}样本(sample)或输入(input) 样本(sample)或输入(input):进入模型的数据点。
- 预 测 ( p r e d i c t i o n ) 或 输 出 ( o u t p u t ) \color{red}预测(prediction)或输出(output) 预测(prediction)或输出(output):从模型出来的结果。
- 目 标 ( t a r g e t ) \color{red}目标(target) 目标(target):真实值。对于外部数据源,理想情况下,模型应该能够预测出目标。
- 预 测 误 差 ( p r e d i c t i o n e r r o r ) 或 损 失 值 ( l o s s v a l u e ) \color{red}预测误差(prediction error)或损失值(loss value) 预测误差(predictionerror)或损失值(lossvalue):模型预测与目标之间的距离。
- 类 别 ( c l a s s ) \color{red}类别(class) 类别(class):分类问题中供选择的一组标签。例如,对猫狗图像进行分类时,“狗”和“猫”就是两个类别。
- 标 签 ( l a b e l ) \color{red}标签(label) 标签(label):分类问题中类别标注的具体例子。比如,如果 1234 号图像被标注为包含类别“狗”,那么“狗”就是 1234 号图像的标签。
- 真 值 ( g r o u n d − t r u t h ) 或 标 注 ( a n n o t a t i o n ) \color{red}真值(ground-truth)或标注(annotation) 真值(ground−truth)或标注(annotation):数据集的所有目标,通常由人工收集。
- 二 分 类 ( b i n a r y c l a s s i f i c a t i o n ) \color{red} 二分类(binary classification) 二分类(binaryclassification):一种分类任务,每个输入样本都应被划分到两个互斥的类别中。
- 多 分 类 ( m u l t i c l a s s c l a s s i f i c a t i o n ) \color{red}多分类(multiclass classification) 多分类(multiclassclassification):一种分类任务,每个输入样本都应被划分到两个以上的类别中,比如手写数字分类。
- 多 标 签 分 类 ( m u l t i l a b e l c l a s s i f i c a t i o n ) \color{red}多标签分类(multilabel classification) 多标签分类(multilabelclassification):一种分类任务,每个输入样本都可以分配多个标签。举个例子,如果一幅图像里可能既有猫又有狗,那么应该同时标注“猫”标签和“狗”标签。每幅图像的标签个数通常是可变的。
- 标 量 回 归 ( s c a l a r r e g r e s s i o n ) \color{red}标量回归(scalar regression) 标量回归(scalarregression):目标是连续标量值的任务。预测房价就是一个很好的例子,不同的目标价格形成一个连续的空间。
- 向 量 回 归 ( v e c t o r r e g r e s s i o n ) \color{red}向量回归(vector regression) 向量回归(vectorregression):目标是一组连续值(比如一个连续向量)的任务。如果对多个值(比如图像边界框的坐标)进行回归,那就是向量回归。
- 小 批 量 ( m i n i − b a t c h ) 或 批 量 ( b a t c h ) \color{red}小批量(mini-batch)或批量(batch) 小批量(mini−batch)或批量(batch):模型同时处理的一小部分样本(样本数通常为 8~128)。样本数通常取 2 的幂,这样便于 GPU 上的内存分配。训练时,小批量用来为模型权重计算一次梯度下降更新。
4.2 评估机器学习模型
本小节主要是:1)数据划分为训练集、验证集和测试集。2)如何衡量泛化能力。
4.2.1 训练集、验证集和测试集
- 评估模型的重点是将数据划分为三个集合:
训
练
集
、
验
证
集
和
测
试
集
\color{red}训练集、验证集和测试集
训练集、验证集和测试集。
- 在 训 练 数 据 上 训 练 模 型 \color{red}训练数据上训练模型 训练数据上训练模型,这个过程本质上是学习:在某个参数空间中寻找良好的模型配置。
- 在 验 证 数 据 上 评 估 模 型 \color{red}验证数据上评估模型 验证数据上评估模型,验证是否过拟合,要防止信息泄露(information leak)。
- 找到最佳参数,在 测 试 数 据 上 最 后 测 试 一 次 \color{red}测试数据上最后测试一次 测试数据上最后测试一次。
- 三种经典的评估方法:
-
简单的留出验证
缺点:如果可用的数据很少,那么可能验证集和测试集包含的样本就太少,从而无法在统计学上代表数据。
num_validation_samples = 10000 #通常需要打乱数据 np.random.shuffle(data) #定义验证集 validation_data = data[:num_validation_samples] data = data[num_validation_samples:] #定义训练集 training_data = data[:] model = get_model() #在训练数据上训练模型,并在验证数据上评估模型 model.train(training_data) validation_score = model.evaluate(validation_data) # 现在你可以调节模型、重新训练、评估,然后再次调节…… # 一旦调节好超参数,通常就在所有非测试数据上从头开始训练最终模型 model = get_model() model.train(np.concatenate([training_data, validation_data])) test_score = model.evaluate(test_data)
-
K 折验证
- K 折验证(K-fold validation) 将数据划分为大小相同的 K K K个分区。对于每个分区 i i i ,在剩余的 K − 1 K-1 K−1个分区上训练模型,然后在分区 i i i上评估模型。最终分数等于 K K K个分数的平均值。
- 应用场景:对于不同的训练集 - 测试集划分,如果
模
型
性
能
的
变
化
很
大
\color{red}模型性能的变化很大
模型性能的变化很大,那么这种方法很有用。
k = 4 num_validation_samples = len(data) // k np.random.shuffle(data) validation_scores = [] for fold in range(k): # 选择验证数据分区 validation_data = data[num_validation_samples * fold: num_validation_samples * (fold + 1)] #使用剩余数据作为训练数据。注意,+ 运算符是列表合并,不是求和 training_data = data[:num_validation_samples * fold] + data[num_validation_samples * (fold + 1):] # 创建一个全新的模型实例(未训练) model = get_model() model.train(training_data) validation_score = model.evaluate(validation_data) validation_scores.append(validation_score) # 最终验证分数:K 折验证分数的平均值 validation_score = np.average(validation_scores) # 在所有非测试数据上训练最终模型 model = get_model() model.train(data) test_score = model.evaluate(test_data)
-
带有打乱数据的重复 K 折验证(iterated K-fold validation with shuffling)
- 如果可用的数据相对较少,而你又需要尽可能精确地评估模型,那么可以选择此方法。
- 具体做法是多次使用 K K K折验证,在每次将数据划分为 K K K个分区之前都先将数据打乱。最终分数是每次 K K K折验证分数的平均值。
- 这种方法一共要训练和评估 P × K \color{red}P×K P×K个模型( P P P是重复次数), 计 算 代 价 很 大 \color{red}计算代价很大 计算代价很大。
-
4.2.2 评估模型的注意事项
- 数据代表性(data representativeness)。在将数据划分为训练集和测试集之前,通常应该 随 机 打 乱 \color{red}随机打乱 随机打乱数据。
- 时间箭头(the arrow of time)。如果想要根据过去预测未来,那么在划分数据前你不应该随机打乱数据,因为这么做会造成时间泄露(temporal leak)。应该始终确保测试集中所有数据的时间都晚于训练集数据。
- 数据冗余(redundancy in your data)。 如果数据中的某些数据点出现了两次,那么打乱数据并划分成训练集和验证集会导致训练集和验证集之间的数据冗余。 一 定 要 确 保 训 练 集 和 验 证 集 之 间 没 有 交 集 \color{red}一定要确保训练集和验证集之间没有交集 一定要确保训练集和验证集之间没有交集。
4.3 数据预处理、特征工程和特征学习
4.3.1 神经网络的数据预处理
数据预处理的目的是使原始数据更适于用神经网络处理,包括 向 量 化 \color{red}向量化 向量化、 标 准 化 \color{red}标准化 标准化、 处 理 缺 失 值 \color{red}处理缺失值 处理缺失值和 特 征 提 取 \color{red}特征提取 特征提取。
-
向 量 化 \color{red}向量化 向量化
神经网络的所有输入和目标都必须是浮点数张量。无论处理什么数据,都必须首先将其转换为张量,这一步叫作 数 据 向 量 化 ( d a t a v e c t o r i z a t i o n ) \color{red}数据向量化(data\;vectorization) 数据向量化(datavectorization)。 -
标 准 化 \color{red}标准化 标准化
输入数据应该具有以下特征。- 取值较小:大部分值都应该在 0~1 范围内。
- 同质性(homogenous):所有特征的取值都应该在大致相同的范围内。
- 将每个特征分别标准化,使其均值为 0。
- 将每个特征分别标准化,使其标准差为 1。
这对于 Numpy 数组很容易实现。
# 假设 x 是一个形状为 (samples,features) 的二维矩阵 x -= x.mean(axis=0) x /= x.std(axis=0)
-
处 理 缺 失 值 \color{red}处理缺失值 处理缺失值
一般来说,对于神经网络,将缺失值设置为 0 是安全的,只要 0 不 是 一 个 有 意 义 的 值 \color{red}0 不是一个有意义的值 0不是一个有意义的值。网络能够从数据中学到 0 意味着缺失数据,并且会忽略这个值。注意:如果 测 试 数 据 中 可 能 有 缺 失 值 \color{red}测试数据中可能有缺失值 测试数据中可能有缺失值,而网络是在没有缺失值的数据上训练的,那么网络不可能学会忽略缺失值。在这种情况下,你应该 人 为 生 成 一 些 有 缺 失 项 的 训 练 样 本 \color{red}人为生成一些有缺失项的训练样本 人为生成一些有缺失项的训练样本:多次复制一些训练样本,然后删除测试数据中可能缺失的某些特征。
4.3.2 特征工程
- 定义:特征工程(feature engineering)是指将数据输入模型之前,利用你自己关于数据和机器学习算法(这里指神经网络)的知识对数据进行硬编码的变换(不是模型学到的),以改善模型的效果。
- 本质:用 更 简 单 的 方 式 \color{red}更简单的方式 更简单的方式表述问题,从而使问题变得更容易。它通常需要深入理解问题。
- 作用:
- 良好的特征仍然可以让你 用 更 少 的 资 源 更 优 雅 地 解 决 问 题 \color{red}用更少的资源更优雅地解决问题 用更少的资源更优雅地解决问题。
- 良好的特征可以让你 用 更 少 的 数 据 解 决 问 题 \color{red}用更少的数据解决问题 用更少的数据解决问题。
4.4 过拟合与欠拟合
- 机器学习的根本问题是
优
化
\color{red}优化
优化和
泛
化
\color{red}泛化
泛化之间的对立。
- 优化(optimization)是指调节模型以在训练数据上得到最佳性能(即机器学习中的学习)。
- 泛化(generalization)是指训练好的模型在前所未见的数据上的性能好坏。
- 防止过拟合
最
优
解
决
方
法
是
获
取
更
多
的
训
练
数
据
\color{red}最优解决方法是获取更多的训练数据
最优解决方法是获取更多的训练数据。此最优的方法调节模型允许存储的信息量,或
对
模
型
允
许
存
储
的
信
息
加
以
约
束
\color{red}对模型允许存储的信息加以约束
对模型允许存储的信息加以约束。有:减小网络大小、添加权重正则化和添加 dropout 正则化等方法。
- 获取更多的训练数据
- 减小网络容量
- 添加权重正则化
- 添加 dropout
4.4.1 减小网络大小
- 在深度学习中,模型中可学习参数的个数通常被称为 模 型 的 容 量 ( c a p a c i t y ) \color{red}模型的容量(capacity) 模型的容量(capacity),参数更多的模型拥有更大的记忆容量(memorization capacity)。
- 深度学习模型通常都很擅长拟合训练数据,但 真 正 的 挑 战 在 于 泛 化 \color{red}真正的挑战在于泛化 真正的挑战在于泛化,而不是拟合。
- 因此要在 容 量 过 大 \color{red}容量过大 容量过大与 容 量 不 足 \color{red}容量不足 容量不足之间要找到一个折中。
- 一般的工作流程是:
- 开始时选择相对较少的层和参数;
- 然后逐渐增加层的大小或增加新层;
- 直到这种增加对验证损失的影响变得很小。
4.4.2 添加权重正则化
-
奥卡姆剃刀(Occam’s razor)原理:如果一件事情有两种解释,那么最可能正确的解释就是最简单的那个,即假设更少的那个。即: 简 单 模 型 比 复 杂 模 型 更 不 容 易 过 拟 合 \color{red}简单模型比复杂模型更不容易过拟合 简单模型比复杂模型更不容易过拟合。
-
简 单 模 型 ( s i m p l e m o d e l ) 是 指 参 数 值 分 布 的 熵 更 小 的 模 型 \color{red}简单模型(simple model)是指参数值分布的熵更小的模型 简单模型(simplemodel)是指参数值分布的熵更小的模型。
-
强制让模型权重只能取较小的值,从而限制模型的复杂度,这使得权重值的分布更加规则(regular)。这种方法叫作权重正则化(weight regularization)。正则化分为:
- L 1 正 则 化 ( L 1 r e g u l a r i z a t i o n ) \color{red}L1 正则化(L1 regularization) L1正则化(L1regularization):添加的成本与权重系数的 绝 对 值 \color{red}绝对值 绝对值[权重的 L1 范数(norm)]成正比。
- L 2 正 则 化 ( L 2 r e g u l a r i z a t i o n ) \color{red}L2 正则化(L2 regularization) L2正则化(L2regularization):添加的成本与权重系数的 平 方 \color{red}平方 平方(权重的 L2 范数)成正比。神经网络的 L2 正则化也叫权重衰减(weight decay)。
-
在 Keras 中,添加权重正则化的方法是向层传递权重正则化项实例(weight regularizer instance)作为关键字参数。
from keras import regularizers model = models.Sequential() # 添加L2正则化 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'))
from keras import regularizers regularizers.l1(0.001)#L1 正则化 regularizers.l1_l2(l1=0.001, l2=0.001)#同时做 L1 和 L2 正则化
4.4.3 添加 dropout 正则化
- 对某一层使用 dropout,就是在训练过程中随机将该层的一些输出特征舍弃(设置为 0)。
- dropout 比率(dropout rate)是被设为 0 的特征所占的比例,通常在 0.2~0.5范围内。
- 方法:
- 训练时,我们随机将矩阵中一部分值设为 0,测试时dropout。
#训练时,舍弃 50%的输出单元 layer_output *= np.random.randint(0, high=2, size=layer_output.shape) #测试时,我们将输出按 dropout 比率缩小。这里我们乘以 0.5. layer_output *= 0.5
- 训练时就dropout
#训练时 layer_output *= np.random.randint(0, high=2, size=layer_output.shape) layer_output /= 0.5 #注意,是成比例放大而不是成比例缩小
- 训练时,我们随机将矩阵中一部分值设为 0,测试时dropout。
4.5 机器学习的通用工作流程
4.5.1 定义问题,收集数据集
- 明确了输入、输出以及所使用的数据。
- 假设输出是可以根据输入进行预测的。
- 假设可用数据包含足够多的信息,足以学习输入和输出之间的关系。
- 一定要是
非
平
稳
问
题
(
n
o
n
s
t
a
t
i
o
n
a
r
y
p
r
o
b
l
e
m
)
\color{red}非平稳问题(nonstationary\;problem)
非平稳问题(nonstationaryproblem)。
4.5.2 选择衡量成功的指标
- 损失函数的选择,即模型要优化什么。
- 问题分类:
- 对于
平
衡
分
类
问
题
\color{red}平衡分类问题
平衡分类问题(每个类别的可能性相同),精度和接收者操作特征曲线下面积(area under the receiver operating characteristic curve,
R
O
C
、
A
U
C
\color{red}ROC、AUC
ROC、AUC)是常用的指标。
广泛使用的分类指标 ROC AUC 就不能被直接优化。因此在分类任务中,常见的做法是优化 ROC AUC 的替代指标,比如 交 叉 熵 \color{red}交叉熵 交叉熵。 交 叉 熵 越 小 , R O C A U C 越 大 \color{red}交叉熵越小,ROC AUC 越大 交叉熵越小,ROCAUC越大。
- 对于 类 别 不 平 衡 的 问 题 \color{red}类别不平衡的问题 类别不平衡的问题,可以使用 准 确 率 和 召 回 率 \color{red}准确率和召回率 准确率和召回率。
- 对于
排
序
问
题
或
多
标
签
分
类
\color{red}排序问题或多标签分类
排序问题或多标签分类,你可以使用
平
均
准
确
率
均
值
\color{red}平均准确率均值
平均准确率均值(mean average precision)。
要想了解各种机器学习的成功衡量指标以及这些指标与不同问题域的关系,你可以浏览 Kaggle 网站上的数据科学竞赛。
- 对于
平
衡
分
类
问
题
\color{red}平衡分类问题
平衡分类问题(每个类别的可能性相同),精度和接收者操作特征曲线下面积(area under the receiver operating characteristic curve,
R
O
C
、
A
U
C
\color{red}ROC、AUC
ROC、AUC)是常用的指标。
4.5.3 确定评估方法
- 留出验证集。数据量很大时可以采用这种方法。
- K 折交叉验证。如果留出验证的样本量太少,无法保证可靠性,那么应该选择这种方法。
- 重复的 K 折验证。如果可用的数据很少,同时模型评估又需要非常准确,那么应该使用这种方法。
只需选择三者之一。大多数情况下,第一种方法足以满足要求。
4.5.4 准备数据
将数据格式化:
- 将数据格式化为张量。
- 特征工程。
- 数据标准化,将张量的取值缩放为较小的值,比如在 [-1, 1] 区间或 [0, 1] 区间。
4.5.5 开发比基准更好的模型
-
统
计
功
效
(
s
t
a
t
i
s
t
i
c
a
l
p
o
w
e
r
)
\color{red}统计功效(statistical\;power)
统计功效(statisticalpower),即开发一个小型模型,它能够打败纯
随
机
的
基
准
(
d
u
m
b
b
a
s
e
l
i
n
e
)
\color{red}随机的基准(dumb\;baseline)
随机的基准(dumbbaseline)。
例如:在 MNIST 数字分类的例子中,任何精度大于 0.1 的模型都可以说具有统计功效。
- 选择三个关键参数来构建第一个工作模型:
- 最后一层的激活。它对网络输出进行有效的限制。
- 损失函数。它应该匹配你要解决的问题的类型。
- 优化配置。你要使用哪种优化器?学习率是多少?大多数情况下,使用 rmsprop 及其默认的学习率是稳妥的。
4.5.6 扩大模型规模:开发过拟合的模型
开发一个 过 拟 合 的 模 型 \color{red}过拟合的模型 过拟合的模型:
- 添加更多的层。
- 让每一层变得更大。
- 训练更多的轮次。
要始终监控 训 练 损 失 \color{red}训练损失 训练损失和 验 证 损 失 \color{red}验证损失 验证损失,以及你所关心的指标的训练值和验证值。如果你发现模型在验证数据上的性能开始下降,那么就出现了过拟合。
4.5.7 模型正则化与调节超参数
- 过 程 \color{red}过程 过程:不断地调节模型、训练、在验证数据上评估(这里不是测试数据)、再次调节模型,然后重复这一过程,直到模型达到最佳性能。
-
可
选
方
法
\color{red}可选方法
可选方法:
- 添加 dropout。
- 尝试不同的架构:增加或减少层数。
- 添加 L1 和 / 或 L2 正则化。
- 尝试不同的超参数(比如每层的单元个数或优化器的学习率),以找到最佳配置。
- (可选)反复做特征工程:添加新特征或删除没有信息量的特征。
- 每次使用验证过程的反馈来调节模型,都会将有关验证过程的
信
息
泄
露
\color{red}信息泄露
信息泄露到模型中。
- 如果只重复几次,那么无关紧要;
- 但如果系统性地迭代许多次,最终会导致模型对验证过程过拟合(即使模型并没有直接在验证数据上训练)。这会降低验证过程的可靠性。
- 一旦开发出令人满意的模型配置,你就可以在 所 有 可 用 数 据 ( 训 练 数 据 + 验 证 数 据 ) \color{red}所有可用数据(训练数据 + 验证数据) 所有可用数据(训练数据+验证数据)上训练 最 终 的 生 产 模 型 \color{red}最终的生产模型 最终的生产模型,然后在测试集上最后评估一次。
- 如果测试集上的性能比验证集上差很多, 需 要 换 用 更 加 可 靠 的 评 估 方 法 \color{red}需要换用更加可靠的评估方法 需要换用更加可靠的评估方法,比如重复的 K 折验证。