目录
定义问题
收集标记数据
分析我们的数据
特征处理
将数据分为训练数据和评估数据
训练模型
训练参数
学习率
模型大小
迭代次数
打乱数据(Shuffling)
正则化
评估模型的准确率
二元分类(Binary Classification)
多类分类(Multiclass Classification)
回归(Regression)
提高模型的精度
模型拟合:欠拟合与过拟合
使用模型做预测
批量预测
在线预测
使用新数据重新训练
构建机器学习应用是一个迭代的过程,主要包括以下几个步骤:
机器学习的第一个步骤是要决定我们想要预测的是什么,也就是数据的标签或是目标答案。设想这样一个场景:我们生产各种各样的商品,并基于预期销量来决定每种商品要生产多少。在这个场景下,我们想要预测每种商品会被购买多少次,即预测销售量。有多种方法来定义这个问题,具体如何选择依赖于我们的使用场景或商业需求。
我们是想要预测客户对每个产品的采购量呢(此时是一个回归问题)还是想要预测哪些产品的采购量会超过10个呢(此时是一个二元分类问题)?
非常重要的是要避免把问题过度复杂化,并选择能够满足我们需求的最简单的方案。花些时间来决定预测哪个指标最有意义能够让我们免于构建那些无法回答我们问题的模型。
机器学习问题始于数据,特别是大量的我们知道答案的数据。那些我们已知道答案的数据便是标记数据。在监督学习中,算法能够利用我们提供的标记数据自己学习。
我们的数据中的每个样本都必须包括两个元素:
目标——我们想要预测的答案。我们提供标记有正确答案的数据给机器学习算法去学习,然后便可以利用训练好的模型对我们不知道答案的数据进行预测。
变量/特征——可以用来识别模式、预测答案的样本属性。
举个例子,对于邮件分类问题来说,目标是判断某封邮件是不是垃圾邮件。变量则是诸如发信人、邮件内容、邮件主题、邮件发送时间等信息。
通常来讲,数据并不总是已经标记好了,可以直接拿来用的。在处理机器学习问题时,收集和准备变量和标记常常是最重要的一个步骤。这些样本数据应该能够代表那些我们想要用模型去预测的数据。
在有了标记数据以后,我们可能还需要把它们转换成我们的算法或模型可以接受的形式。比如,可能需要把数据保存在CSV(comma-separated value)文件中。
在把标记数据输入给ML算法之前,最好能够对数据进行一些检视,以便发现问题,对数据有一些了解。必须记住的是我们的模型的预测能力完全受限于我们提供给它的数据。
在分析数据时,需要记住以下几点:
变量和目标数据的大致情况——理解变量由哪些值组成以及哪些值占主导地位是很有用的。问自己一些问题:这些数据符合我们的预期吗?是否有某一类的数据比其他类更常见?缺失的值或无效的值是否比预期的多?
变量-目标的相关性——知道每个变量与目标值之间的相关性是很有帮助的,相关性高意味着变量和目标之间存在某种关系。通常,我们想要包含高相关性的变量(因为它们的预测能力较高),而忽略掉那些低相关性的变量(因为它们可能无关紧要)。
在大致了解了我们的数据之后,可能还会想要对其做一些变换,使它们更有意义,这便是特征处理。例如,我们有一个变量是某个事件发生时的日期和时间,这个日期和时间以后肯定不会再出现,所以也就对预测目标没什么用处。但是,如果我们把这个值处理成一天里的某个时段,一周或者一个月里的某天,那这些变量就可能用来学习这个事件是否倾向于发生在某个特定的时段、日期或月份。这种特征处理能够形成更通用的数据,可以显著提升预测模型的性能。
常见的特征处理的例子:
包含更多相关的特征有助于提高预测性能。很显然,事先了解哪些特征是相关的往往是不现实的。所以,最好把所有可能的特征都包括进来,然后让模型训练算法来挑选那些强相关的特征。
ML的基本目标是基于用于训练模型的数据得到泛化到其他数据的能力。由于未来的样本的目标值是未知的,我们现在也就没办法评估我们对未来样本的预测准确性,我们需要用一些我们已知其目标值的数据来代表未来的数据。用训练数据来评估模型是没什么用的,因为这样会奖励那些“记住了”训练数据的模型,而不是那些从训练数据中进行泛化的模型。
一个常见的策略是将所有可用的标记数据分成训练集和测试集,通常训练集占70-80%,测试集占20-30%。ML系统利用训练集来训练模型以发现模式,用测试集评估训练得到的模型的预测能力。通常,我们会用在测试集上表现“最好的”模型对我们不知道目标答案的数据进行预测。
现在我们准备好向ML算法提供训练数据了。算法会从训练数据中学习将变量映射成目标值的模式,并输出一个习得了这种关系的模型。
学习算法包括一个损失函数和一种优化技术。损失是当模型给出的目标值的估计与实际目标值不一致时的惩罚。损失函数将这个惩罚量化为一个单独的值。优化技术则致力于将损失最小化。
在训练过程中,我们可以通过一些训练参数或者叫超参数来控制模型的训练效果。下面介绍几个常见的超参数。
学习率是用在随机梯度下降(SGD)算法中的一个常数,其能够影响算法收敛到最优权重的速度。学习率太大可能会导致权重无法收敛到最优解,而太小则会导致得到最优解需要很多次迭代。
大模型意味着在训练或预测时需要更多的内存来容纳模型,而模型太小的话则可能会影响模型的预测能力。
迭代次数表示在训练数据上进行多少次训练。训练次数更多会使得数据拟合得更好(学习率不能太大),但是太多也就没效果了。所以,对于小数据集来说,我们可以将迭代次数设的较大,以获得更好的拟合效果。而对于超级大的数据集而言,可能遍历一次就够了。
因为SGD算法会受到训练数据顺序的影响,所以我们需要把数据打乱。之所以把训练数据打乱能够得到更好的模型是因为它帮助SGD算法避免了那些只是对它见到的第一种类型的数据而言最优,而不是对所有数据类型最优的模型。Shuffling打乱了训练数据的顺序,使得SGD算法不会连续遇到太多同一类型的数据。如果在连续很多次的权重更新过程中只遇到一种类型的数据,算法可能无法在遇到另一种数据类型时纠正模型的权重,因为这个变动可能过大。另外,如果数据不是随机出现的,算法可能很难很快地找到对所有数据类型而言都是最优的解。
举个例子,假设我们需要训练一个模型来预测商品类型,在我们的训练集中有电影、玩具和视频游戏三种类型的商品。如果我们的数据是以商品类型排序的,那么算法将会先看到类型为电影的数据,我们的模型也将会开始学习电影的模式。然后,当我们的模型遇到类型为玩具的数据时,算法所作的每次更新都会使得模型更适合玩具类型,即使这有可能会损害其对电影类型的适配能力。这种从电影到玩具类型的突然切换会使得我们的模型不能够准确地预测产品类型。
正则化通过惩罚极端的权重值来帮助避免过拟合训练数据样本(即记住了模式,而没能进行泛化)。L1正则通过把那些原本有很小权重的特征值的权重推至0来减少特征的数量。因此,L1正则会导致一个稀疏模型,降低模型的噪声。L2正则会使得整体权重更小,当输入特征具有高相关性时能够稳定权重。
ML模型的目标是学习那些能够在未见过的数据上有很好泛化能力的模式,而不是仅仅记住在训练时遇到的数据。在我们有了一个模型后,非常有必要去检查一下我们的模型是否能够很好的处理它在训练时没有见过的数据。
在ML中有许多度量指标可以用来评估模型的预测准确率。我们需要根据ML任务来选择合适的度量指标。
基于预测值和实际值,可以将预测结果分成四组:正确的阳性预测(真阳性)、正确的阴性预测(真阴性)、错误的阳性预测(假阳性)和错误的阴性预测(假阴性)。
二元分类任务典型的度量指标包括准确率(ACC)、精确率(Precision)、召回率(Recall)、假阳性率和F1度量。每一个指标都反应了模型的不同方面。准确率(ACC)衡量的是预测正确的比例。精确率衡量的是被预测为阳性的样本中确实是阳性的比例。召回率衡量的是有多少确实是阳性的样本被预测为了阳性。F1度量则是精确率和召回率的调和平均值。不同的业务场景下,我们可能会选择这些度量中的一个特定子集。具体的信息可以看我的另一篇文章:超越准确率(Accuracy):精确率(Precision)和召回率(Recall)。
与二元分类不同的是,我们不用在做预测时选择一个阈值,预测结果就是得分最高的那个类。
在多类分类中使用的度量是与在二元分类中使用的一样的。这一部分我准备另外写一篇文章专门总结。
回归任务典型的度量指标是均方根误差(Root Mean Square Error, RMSE)和平均绝对百分比误差(Mean Absolute Percentage Error, MAPE)。这些指标测量的是预测的数值和实际的目标值(Ground Truth)之间的距离。
在实践中通常会对回归问题的残差进行检视。残差是指测试集中的一条数据中目标的实际值和预测值之间的差。残差代表的是模型未能预测出来的那部分目标值。正残差表示模型低估了目标值(即实际值大于预测值),负残差表示模型高估了目标值(即实际值小于预测值)。如果测试集残差的直方图是以钟形分布且中心在0附近,说明这个模型产生的错误是随机的,不会系统性地低估或高估某个特定范围内的目标值。如果残差呈现出的不是中心在0附近的钟形分布,说明模型的预测错误有某种结构。增加更多的变量可能会帮助模型习得当前模型没有学到的模式。
得到一个满足我们需求的ML模型通常都会经过多次迭代和实验一些改动。为了提高性能,我们需要迭代以下步骤:
理解模型拟合对于理解模型表现不好的根本原因是很重要的,它可以引导我们采取纠正措施。我们可以通过观察模型在训练集和测试集上的预测误差来判断模型是欠拟合还是过拟合。
如果模型在训练集上就表现不好说明模型是欠拟合的,这是因为模型没能学到样本的输入和目标值之间的关系。如果模型在训练集上表现良好,但是在测试集上表现不好,说明模型是过拟合的 ,这是因为模型记住了它见过的数据但没能泛化到它未见过的数据。
在训练集上的糟糕表现可能是因为模型太小了。此时通过增加模型的弹性可以提高性能。可以尝试以下方式来增加模型的弹性:
如果模型是过拟合的,那么应该降低模型的弹性。可以尝试以下方式来降低模型弹性:
在训练集和测试集上的准确率不高也可能是因为算法没有足够的数据来学习。我们可以通过以下方式提高性能:
有两种预测方式:
当我们想要一次对一组数据进行预测,然后对其中的一部分进行处理时,批量预测就很有用。举个例子,如果我们想要为某个商品的促销活动确定目标客户,我们会用模型得到所有用户的预测分数,然后根据分数进行排序后选取得分最高的前5%用户作为目标客户。
在线预测适用于低延时的,需要一条一条样本进行预测的场景。比如迅速地判断某项事务是否可能是欺诈性的事务。
为了模型能够准确的预测,预测时使用的数据必须和训练时使用的数据具有相似的分布。因为数据分布可能随着时间发生漂移,模型部署并不是一次性的事务,而是一个持续的过程。持续性的监控输入的数据并在发现数据分布与最初训练时的数据分布发生显著变化时使用新的数据重新训练模型是一种很好的做法。如果持续地监控数据分布的变化代价太大,简单一些的策略是定期地训练模型,比如每天,每周或者每月。