机器学习这东西,在学术界产出颇多,但在工业界,却很少落地。究其原因,是理念落地不够彻底,很多从业者和相关上下游不理解所致。这次就这这个机会,梳理下一个机器学习,从立项到落地再到结束,他的完整生命周期该是什么样子的。这里参考了《Hands-On Machine Learning with Scikit-Learn and Tensorflow》,值得一提的是这本书写的很不错,和《集体智慧编程》有一拼,建议阅读英文原著或东南大学出的影印版。

机器学习项目的生命周期

  1. 问题定义
  • 定义问题,并关注大局
  1. 数据处理

    • 获取数据
    • 探索性的数据分析
    • 清洗数据,为接下来的模型做准备
  2. 模型方案

    • 探索不同的模型并挑选合适的模型
    • 对模型进行微调,并集成为更好的模型
    • 解决方案呈现
  3. 部署维护

    • 部署、监控并维护系统

定义问题,从大局出发

  1. 和业务团队一起定义问题目标
  2. 我们的解决方案将会如何发挥作用
  3. 现在的解决方案是什么样的(如果有)
  4. 你将如何定义这个问题(有监督、无监督,在线还是离线)
  5. 结果该如何衡量
  6. 衡量方法是否和商业目标一致
  7. 要达成这一目标,至少的表现该是什么样子的
  8. 类似的问题是什么?有无可复用的经验与工具
  9. 我们有专家知识吗
  10. 你将如何着手解决这个问题
  11. 列出你或者别人目前所作的努力
  12. 如果可能,对假说进行验证

获取数据

建议:尽量自动化以更容易地方式获取最新的数据

  1. 列出你所需的数据以及体量
  2. 找寻并记录下获取数据的方式
  3. 检查数据将占据多少空间
  4. 检查是否有法律风险,如有必要请获得许可
  5. 获取许可
  6. 创建工作空间,确保存储足够大
  7. 获取数据
  8. 转换数据的格式以便能够方便操作(不需要改变数据本身)
  9. 确保敏感信息被删除或保护加密(匿名)
  10. 检查数据的大小和类型(时间序列、采样、地理信息等)
  11. 划分测试集,把他放一边,并且不再去动他(防止数据泄露)

探索数据

建议:在该阶段尽量获取领域专家的意见

  1. 创建数据的副本以便做数据探索(如果数据量太大,做降采样处理)
  2. 创建 Jupyter notebook 以便保存探索记录
  3. 研究每个属性及其特征
    • 名称
    • 类型(类别,整型/浮点,有无上下界,文本,结构化等)
    • 缺失值
    • 噪声数据(随机数,异常值,四舍五入的误差)
    • 对本任务可能有用的数据
    • 分布类型(高斯分布,均匀分布,指数分布)
  4. 对于有监督问题:确定目标对象
  5. 可视化数据
  6. 研究变量间的相关性
  7. 研究你将如何着手解决此问题
  8. 确认比较有希望的解决方案
  9. 确认有用的外部数据
  10. 将以上信息存档记录下来

准备数据

建议:

  • 在数据的副本上操作(保持原始数据不被影响)
  • 将你所作的数据变换写成函数,有以下5个原因
    • 便于在本项目的新数据上复用
    • 便于在别的项目中复用
    • 快速清洗和准备测试集
    • 在立项后,能够及时对数据进行处理
    • 让数据变换过程也能作为超参数的一份子,进行调参
  1. 数据清洗
    • 调整或移除异常值(可选)
    • 填补缺失值(0,平均数、中位数),或者简单的去掉缺失的样本或特征
  2. 特征选择(可选)
    • 去掉对本任务无用的信息
  3. 特征工程,适度
    • 连续数值离散化
    • 特征分解(分类特征、时间特征等)
    • 特征变换(log(x),sqrt(x),x^2等)
    • 特征组合
  4. 特征尺度变换:标准化或归一化

挑选合适的模型

建议:

  • 如果数据很大,做降采样,以便能够在合理时间内尝试多个模型(不过要注意,这样的操作对于复杂模型不太友好,比如神经网络和随机森林)
  • 再一次的,尽量自动化以上流程
  1. 训练很多模型,快且原始地使用模型参数,训练尽可能多的模型(线性模型、朴素贝叶斯、SVM、随机森林、神经网络等等)
  2. 测量并评估他们的表现
    • 对于每个模型,使用 N-fold 交叉验证,计算表现的均值与方差
  3. 分析每个模型上最为显著的特征
  4. 分析模型所犯的错误类型
    • 如果是人类,会采用什么样的方法避免犯错?
  5. 快速地做一波特征选择和特征工程
  6. 前面步骤重复一两次
  7. 列出表现最好的3-5个模型,最好他们的错误情况不同以便集成

微调系统

建议:

  • 随着微调的进行,你将会使用尽可能多的数据
  • 总是使你的操作自动化
  1. 使用交叉验证进行超参数的微调
    • 将你的数据变换也变成超参数的一部分,特别是当你对数据不熟悉的时候(比如:我应该用0还是中位数填补缺失值,还是仅仅去掉那个样本?)
    • 除非超参数非常少,使用随机搜索而不是网格搜索。如果训练耗时非常久,你可能会想用贝叶斯优化方法。(比如使用高斯过程)
  2. 采用集成方法。集成最优的方案,往往表现会超过单独模型方案。
  3. 一旦你对自己的模型很有信心,那就在测试集上验证其泛化误差。

方案呈现

  1. 记下你所做的努力,文档化
  2. 起草一份漂亮的展示稿
    • 确保先强调大局
  3. 解释为何你的方案达到了商业目标
  4. 不要忘记展现整个过程中你认为的有趣部分
    • 讲述什么有效、以及什么没起作用
    • 列出你的前提条件,并说明边界
  5. 通过可视乎,确保你的关键发现易于理解和传播;或是利用容易记住的表达

部署

  1. 准备将你的解决方案接入生产环境(接入生产环境的数据,写单元测试等)
  2. 写监控代码以监测系统的表现,当系统宕机时发出警告
    • 要意识到,随着数据的更新,模型的效果也会衰减
    • 可能需要人工检测数据的表现
    • 同样监控输入数据(例如:失灵的传感器会传回随机的数据,而其他的传感器的输出会是一个稳定值)这对于在线学习系统尤为重要
  3. 当模型达到一定偏差时,重新在新数据上训练(尽可能自动化)

以上,我们从立项、数据准备、模型准备到模型的部署,全面梳理的真实项目中的机器学习模型生命周期。在真实的工业场景中,我们所作的可能有些许差别,但都差不多。例如:我们会对问题定义、会对数据进行探索、会给需求方呈现我们的解决方案、会监控我们的模型表现。

在梳理过程中我也发现自身团队的不足:对大背景商业目标的认识不到位、很多时候是拿着锤子(模型)去找钉子(场景)、方案呈现上理工科思维偏重、系统迭代不足。除此之外,还有些细节不是很规范。简单来说就是有些跑马圈地、急功近利的感觉。业务向较重,算法模型潜力并未完全释放,在团队内推行以上规范非常有必要。

不知道看本文的读者,你们的团队会有这样的情况吗?欢迎就此在评论区发表你的看法。喜欢本文的读者,别忘了点赞、喜欢、加关注哦,你的鼓励,将是我写作分享的动力(^_^)