- 机器学习类型
- 机器学习模型评估步骤
- 深度学习数据准备
- 特征工程
- 过拟合
- 解决机器学习问题的一般性流程
机器学习四分支
二分类、多分类以及回归问题都属于监督学习--目标是学习训练输入和对应标签之间的关系。
监督学习只是机器学习的冰山一角。机器学习主要分为4类:监督学习、非监督学习、半监督学习和强化学习。
监督学习
最常见的机器学习类型---学习输入数据和对应标签之间的映射关系。当下几乎所有的深度学习应用都属于监督学习类型,比如ocr识别,语音识别,图像分类和机器翻译等。
尽管监督学习主要由分类和回归组成,也包括一些其他变种:
- 生成序列---给定图片,生成一个概括性的标题。序列生成可以看做一系列分类问题;
- 语法树预测---将句子生成对应的句法树;
- 物体检测---给定图片,在图片中圈出物体所在的矩形框;
- 等等。
非监督学习
在没有对应标签的情况下,为了进行数据可视化、数据压缩、数据降噪或数据相关性分析对输入数据进行有趣的数据转换。数据降维和聚类是典型的非监督学习。
半监督学习
一种特殊的监督学习。半监督学习是没有手工标签的监督学习。但是学习过程中仍然有标签(还是监督学习),但是标签是由启发性算法从输入数据中生成而来。
比如,自编码器就是常见的半监督学习。
强化学习
强化学习中,agent(代理)接收关于环境的信息,然后选择可以最大化reward的动作。比如:神经网络查看网络游戏的屏幕,然后采取相应的动作--最大化得分。
当今,强化学习还处于研究阶段,还没有划时代的应用出现。
模型评估
机器学习的主要目标是提高模型的泛化能力---在新数据上的表现如何,而过拟合是机器学习中经常遇到的难题。我们只能接触到手头的数据,所以必须采用合适的评估方法衡量模型的泛化能力。
训练集、验证集和测试集
评估一个模型通常将数据分成训练集、验证集和测试集。在训练集上训练,验证集上验证模型;一旦确定模型能够应用,则在测试机上进行最后的测试。
为什么不只用两个数据集:测试集和训练集?因为模型开发过程中通常需要进行参数调整--比如网络层数目和每层神经元个数等等。使用验证集上的评估结果作为参数调整的反馈信号。超参数的调整过程也是一种学习--在超参数空间寻找合适的参数设置。基于验证集上的苹果结果训练模型,最终导致模型在验证集上过拟合--尽管最模型没有在验证集上进行训练。
导致这个现象的原因是信息泄露information leaks。每次在基于验证集表现微调模型超参数时,验证集上的信息会泄露到模型中。如果调整单个参数只做一次,只会有很少量的信息泄露到模型中,验证结果是可靠的;如果多次重复--做一次实验,在验证集上做一次验证,然后修改模型;泄露到模型中的信息会逐渐增多。
最终,训练的模型在验证集上表现非常好,因为这正是我们优化的结果。但我们最终关心的是模型在新数据上的表现如何,所以需要使用一个完全不同的、没有见过的数据集来评估模型---测试集。所以,模型直到最后才会接触到测试集。
将数据分成训练集、验证集和测试集可能看起来比较简单直观,但当数据量很小时也有其他的处理方式--留出法、K折交叉验证和打乱迭代K折验证。
简单的留出法hold-out
将数据集留出一部分作为测试集。在剩余部分数据上进行训练,在测试集上进行评估。为了避免信息泄露,不能根据测试集的表现去修改模型参数。
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折验证
将数据分成K份,每份数据量相同。每次训练在K-1份数据上,在第i份数据上进行验证。最后将K个验证结果的平均值作为最后的评估结果。
打乱迭代K折验证
当数据量很小,但又想模型评估尽可能准确,可以采用这种方法。Kaggle比赛非常有用。
多次使用K折验证,但在数据划分成K份时,先进行数据打乱。最终以多次运行K折验证的结果的平均数为准。相当于训练了P X K个模型(P是K折验证的迭代次数)----花销很大。
关键点
当选择评估方法时,需要留意:
- 数据代表性----训练集和测试集都具有数据代表性。比如:手写数字分类,如果前80%为训练集,后20%为测试集,但数据集按照类别排序,导致训练集为0~7,测试集为8~9,导致模型训练结果很差,但这种错误很常见。
- 时间维度----如果模型训练是依据过去数据预测将来(比如,天气预测),则不能随便打乱数据。
- 数据重复----如果数据集中部分数据有重复,打乱数据划分训练集和测试集会导数训练集和测试集中有部分数据重复。最终,模型在部分测试集上进行模型评估---结果虚高。确保验证集和测试集之间没有重合。
数据预处理,特征工程和特征学习
除了模型评估,在模型开发过程中,模型训练之前有一个问题必须要考虑---在将数据和标签送到模型训练之前,如何处理数据和标签?许多数据处理方式和特征工程是领域相关的,不同领域使用的技术有所区别。
数据预处理
数据预处理旨在将原始数据能更符合网络的输入格式要求。包括向量化、归一化、处理缺失值和特征抽取。
向量化
神经网络的输入和标签必须是浮点类型的张量(或者是整数类型的张量)。无论处理什么数据---声音、图片、文本,必须转换成张量形式----这一步叫数据向量化。
归一化
总体上,如果送到神经网络中的数据取值范围过大,模型的学习效果并不理想(比如说数据的取值比模型权重系数的初始值还大)。为了让模型训练更容易,数据应该满足:
- 取值范围小:通常应该在0~1之间;
- 数据同类:所有特征的取值范围相同。
处理缺失值
总体上,将缺失值以0填充(假设0并不是有意义),对于神经网络来说是可行的。然后模型会自动学习到0表示缺失值,然后会忽略0.
注意如果模型的训练数据没有缺失值,而测试集有缺失值,模型并不能学到忽略0取值。这种情况下,你应该手动生成有缺失值的训练样本:多次复制训练集,丢弃部分数据集中可能缺失的特征。
特征工程
特征工程:使用关于数据的先验知识和机器学习算法确保在数据送到模型之前对数据做变化,使最终算法工作效果更好。不能期望算法能从任意数据中学习。数据应该以有助于模型学习的方式表示。
在深度学习之前,特种工程是非常重要的,因为之前的机器学习算法没有足够大的假设空间--自己学习有用的特征。数据的表示对于算法的成功至关重要。
幸运的是,深度学习对特征工程的要求性没有那么高,因为神经网络能自动从数据中抽取有用的特征信息。但是特征工程对于深度学习仍然有帮助:
- 好的特征表示能让问题处理更加快捷、高效;
- 好的特征表示需要的数据量更小;当数据量过小时,特种工程显得格外重要。
过拟合和欠拟合
过拟合现象在每个机器学习问题中都会发生。学会避免过拟合对于掌握机器学习来说至关重要。
机器学习中的主要问题是模型优化和泛化能力之间的调和。优化---调整模型使得在训练数据上表现尽可能的好;泛化---训练模型在新数据上的表现尽可能好。我们可以调整模型获得很好的模型优化,但不能控制模型的泛化能力--只能根据模型在训练数据上的表现调整模型。
训练开始之后,优化能力和泛化能力是相互关联的:训练数据上的损失值减小,测试集上的损失也相应减小;这时候发生模型欠拟合---模型还没有学习到数据所有的知识。但是当循环多次以后,泛化能力停止提升,验证集上指标开始下降:模型发生过拟合----此时,模型开始学习数据中过于个性化的特征,但当新数据到来时会对预测产生误导作用。
为了避免模型学习训练数据中不相关、误导性的特征,最好的方法是准备更多的训练数据。训练数据越多,泛化能力越强。当数据收集困难时,调整数据的质量,对数据添加限制。如果模型能“记住”所有的数据,优化过程中强制关注更重要的数据特征上。
避免过拟合的过程叫做regularization正则化。下面介绍一些常见的正则化方法。
简化模型
避免模型过拟合最简单的方法是简化模型,减少模型的尺寸:模型中可学习的参数数目(网络数目和每层网络神经元数目)。在深度学习中,网络模型可学习参数的数目可以看做模型的容量。所以,更多的参数模型意味着有更大的记忆容量,因此能容易地学到一个类似于字典类型的映射关系---训练样本到对应标签。深度学习模型趋向于适应训练数据,但真正的挑战是模型的泛化能力,而不是适应性。
另一方面,如果网络模型被限制可记忆的容量,映射关系的学习变得困难;因此为了最小化损失函数,模型将会学习数据的压缩性表示方法。我们应该使用多参数且不欠拟合的网络模型。容量太多和容量太少之间的折中。
不幸的是并没有行之有效的规则或方法来确定模型参数的规模。必须不断在验证集上尝试寻找最佳的参数规模。确定模型规模的一般性方法:从相对简单的模型开始,逐渐增减神经元数目或增加网络层数,直到验证集上的损失值不在减小为止。
权重正则化
在复杂模型上添加约束条件,强制让权重系数取小值有助于缓和过拟合现象---权重正则化:在模型的损失函数中添加关于权重的cost函数。比如:
- L1正则化:添加权重系数的L1范数;
- L2正则化:添加权重系数的L2范数。
Keras中,通过向网络层声明参数传递权重正则化实例来进行权重正则化。如,添加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'))
Dropout层
Dropout是神经网络中最有效和最常用的正则化方法。Dropout应用于网络层,随机"扔掉"训练过程的网络层的一部分输出特征(设置为0).Dropout rate指特征设置为0的比率,通常在0.2~0.5之间。在测试过程中,没有神经元被“扔掉”;正相反,网络层的输出值需要用和Dropout rate相等数进行缩放,平衡掉与训练过程相比更多的神经元处于激活状态。(另一种平衡方法是训练过程中对输出进行和Dropout rate相同的放大,而测试过程中不做变换。)
Keras中,有Dropout网络层---对上一层的输出结果做Dropout。
model.add(layers.Dropout(0.25))
实际应用:
model = models.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'))
机器学习一般性流程
问题定义和数据获取
问题定义:
- 输入数据是什么?预测结果是什么?只有在有训练数据的情况下,才能进行预测。
- 面临的问题是什么?二分类?多分类?标量回归?向量回归等等。
上面问题回答完以后,明白当前阶段做的假设: - 数据标签可以有输入数据预测得到;
- 当前数据量足以学习到输入数据和标签之间的对应关系。
机器学习只能学习到训练数据的特征信息,只能辨别看见过的数据。使用在过去收集的数据上训练的模型预测将来数据的结果,意味着假设将来的表现行为和过去类似,但也有例外。
选择评估指标
准确率,查准率和查全率等等。评估的指标也有助于损失函数的选择。
决定评估方法
留出法、K折交叉验证、迭代K折验证。
数据准备
输出处理,处理完成送到模型进行学习。
- 数据表示为张量形式;
- 张量数值取值范围尽可能小,比如在[0,1]或[-1,1]之间;
- 如果不同特征的取值范围不同,需要进行归一化处理;
- 特征工程,特别是针对小数据集。
模型训练--好于基准模型
基准模型:随机猜。比如MNIST为0.1.
在搭建第一个模型之前需要明确:
- 最后一层激活函数:限制网络模型的输出;sigmoid,relu等;
- 损失函数:和解决问题类型相匹配;回归问题mse、二分类binary_crossentropy
- 优化配置:是用什么优化方法?学习率是多少?rmsprop对大多数问题都有效,作为默认方法。
最常见的选择:
训练一个过拟合模型
明确需要训练模型的复杂度,先开发一个过拟合模型:
- 添加网络层;
- 每层网络添加神经元数目;
- epochs变大。
监测训练集和验证集上的损失值变化以及训练集验针集准确率。当验证集上表现开始衰减时,发生过拟合。
下一阶段进行模型调整。
模型正则化和超参数微调
这个阶段耗时最长:反复尝试;训练,验证集上评估,修改模型,再次训练等等;直到模型满足要求。
- 添加Dropout;
- 不同的架构:增加、减少网络层;
- L1、L2正则化;
- 修改不同的超参数;
- 在不同的特征工程上迭代:添加新特征、减少特征等等。
每次使用验证集上的表现调整模型时,验证集的信息会泄露到模型中。重复几次是无伤大雅的;但重复次数过多,最终会导致在验证集上模型过拟合,评估结果不可信。
一旦最佳的模型参数、配置情况确定,最后在非测试集上的所有数据进行训练,最后在测试集上进行测试评估。