尽管我们对经典理论教材能做到人手一册,如数家珍,但是在实际应用中,一方面,我们常常会疏忽掉理论,甚至是理论常识;另一方面,不考虑实际情况,首先上马复杂理论模型却几乎是我们的一种时尚。这让无数项目(也包括我做过的项目)走了不少弯路,所以在这里做个总结。
一、指标定义粗糙
这是缺乏个性化建模的意识的一个体现。
实际业务场景有特定的需求,在清晰理解需求的基础上,选用甚至自定义尽可能准确的指标。一般模型中,指标定义对模型训练的指导流程如图1所示。
图1.指标指导模型的调整
例如一个资产价值评估类项目,最初想当然地认为用户肯定是期望越准越好,所以用的指标是平均绝对百分率误差(Mean Absolute Percent Error),即每条样本评估价格与真实价格之间误差,在真实价格中所占的比例。
然而,实际使用中,尽管某些区域的MAPE很高,但用户反映体验并不好,也就是MAPE没有准确反映用户的体验。
原来,用户的需求是:每次估值只要偏差不是太大,均可接受。但是明显的偏离客观价值的结果,会被用户识别。
所以定义了一个新的指标——可用度:即MAPE在某一阈值(该阈值与用户沟通)内的测试样本的比例。这个指标非常好地反映了用户的感受,有效地改善了自测的客观性,项目优化。
在神经网络架构中,损失函数是模型调参的关键,除了准确的指标定义,还需要定义准确的损失函数。如图2所示。(而其他非神经网络模型,例如集成提升树、线性回归、逻辑回归,损失函数自定义的难度较高,不建议改动)
图2.在神经网络模型中,指标定义、损失函数共同指导模型的调整
二、唯模型论
这是缺乏个性化建模的意识的另一个体现。
很多算法工程师热衷使用机器学习模型,认为只有这样才能体现算法工程师的价值。
然而从实践上来说,应用机器学习模型至少需要三个必要条件:
-
存在可供学习的潜在模式。
虽然理论上万事万物皆有联系,即潜在模式,但关键是要“可供学习”。例如用今天的湿度预测明天的天气,这种潜在模式是可供学习的。但是用今天的湿度预测今晚足球比赛的胜负,天气与比赛胜负之间的潜在模式在有限的数据集上很难学习,即可认为是不存在。
如果不存在,则无法应用机器学习 。
-
没有可编程实现的的简单定义 。
如果我们已经熟知了某领域的规律,可以指定简单规则来实现,为何还要化简为繁,让机器学习来学习这个规律?
在图像、语音、文本等模式识别这些领域,定义规则的经验门槛非常高,完备的规则几乎不可能。这时候,适合应用机器学习,从海量数据中挖掘规则。
-
掌握关于这个模式的数据
不仅要有数据,而且必须包含该模式,这就要求数据状况达到一定的要求。
如果以上三个条件有一条不满足,则不应该使用机器学习模型。
此外,如果期望在已掌握数据上实现最高的预测可靠性,可直接在已知数据上用检索;而在未知数据上,使用机器学习模型。
三、没有baseline
baseline是指基础方法及其对应的指标,用来衡量其他改进方法的好坏。
精巧复杂的模型总是深得技术人的喜欢,然后在实践中针对特定问题应用复杂模型的同时,有必要构造一些baseline,甚至是强baseline,即在保证方法简单的同时还有相当不错的指标,以挑战复杂模型,最终方便我们权衡性能与代价,选取最合适的方法。
一般来说,简单和复杂的方法能达到同样的效果,那简单的方法更可靠。
构造方法即人工规则、或简单模型、或是该问题的常规方法。
四、测试数据的比例太少
尽管这是所有的机器学习教程上老生常谈的话题,但是工作中还是常见很多项目用非常小的测试集,例如用了2万条训练,500条测试。这是非常不合适的。测试的目的是评估模型在未知数据上的表现。如果测试比例非常少,则测试结果的随机性非常大(设想极端情况即仅用1条数据测试,指标会变得非常随机),指标的高或低很难反映模型表现。
但是我们手头的数据量又是有限的,如果分配的测试数据太多,训练数据就会太少,导致模型又没有见到足够多的数据。
所以建议:
-
如果指标是用来自评,则用30%的数据进行测试,或者至少用20%测试。
-
如果要获得最大说服力的指标,以和其他模型进行横向对比,建议用交叉验证,5折及以上。
五、缺乏对指标结果的审查
如果复杂问题却能获得很好的结果,一定要进行审查。因为大概率是存在问题的。
比如这样一个行为预测项目:即用已发生的行为序列预测下一个行为。事件池包含4000种事件,行为序列为顺序发生的5个事件。用数万条序列来训练,获得了0.8的正确率(accuracy)。
问题其实很明显:首先,这是个典型的组合问题,有4000的6次方种序列的可能(天文数字!),用数万条样本训练,几乎是沧海一粟。其次,即使不考虑行为序列里4000的5次方种组合,只考虑最终要预测的target就有4000种行为,竟然能预测出80%的正确率,几乎可以肯定是测试中存在问题。
六、忽略数据泄露
所谓数据泄露(data leakage),是指已知数据集的特征(即X)中包含了目标值(即Y)的强相关特征,而在实际评估阶段,输入数据中并不包含这些强相关特征。这将导致我们训练得很好,测试得很好,但是实际应用时,结果非常差。
例如:
-
房屋价格评估项目
在特征工程中我们把每个小区均价作为特征,将获得非常棒的训练指标、测试指标。原因是模型几乎是把本小区均价拿来用了。
但是,在实际使用时,由于用户不会输入本小区均价(要知道均价还评什么劲?),你只能去检索最近小区的均价,模型的表现将取决于最近小区的均价是否与目标小区均价接近,接近则表现很棒,否则将非常糟糕。
-
行为序列预测项目
行为序列的生成方法是:拿出一批种子用户,从他们每个人很长的行为序列里,用尺寸为6的滑动窗口,每滑动一步,生成一个样本(即5个行为预测1个行为)。这样凑齐数万条数据。然后从中随机抽出训练数据,测试数据。
问题就出在训练数据与测试数据的分割方式上。因为这种随机抽取的方式,导致一个用户的行为序列在训练数据与测试数据中均有分布,训练好的模型已经见过几乎全部测试数据里的行为序列(尽管有1位的差异)。测试数据比例非常少,甚至不到3%。获得了0.8的正确率大致是可能的。但是实际应用中的效果预期堪忧。
如有问题,欢迎评论交流。