机器学习现状与问题

2012年,数据科学击败生命科学,成为”21世界最性感的职业“。2016年,AlphaGo 战胜人类顶尖围棋手,深度学习、人工智能一度占领新闻头版头条,并引起一股机器学习新热潮。

这一效应,一直持续到今年:在2019这一年,高考志愿填报金融遇冷,计算机一跃成为抢手专业,在各大工科院校中,有取代传统电气、机械之势;各学院的研究生院,纷纷开始往人工智能、深度学习上贴近。

这从一个侧面,反应了民众对于计算机、人工智能、机器学习的就业预期。但是,随着原来越多的从业者涌入,项目落地越来越多,机器学习这一领域的问题也开始暴露,亟需解决。

机器学习中的常见问题

机器学习的问题,由其特性所致。众所周知,机器学习的发展,离不开大数据技术。海量数据的收集、存储,让算法有了更强大的生命力。通过对大量数据的挖掘、学习,机器学习能够猜你所想,提升购物网站的转化率;能够识别障碍,让自动驾驶成为可能;能够识别风险,扩大业务同时减轻坏账。

由此,针对模型和数据的关系,大致可以分为三类问题。第一种:数据量不足,模型过拟合。算法学习的过程就犹如考前刷题,过拟合相当于只刷一套题,这样的后果就是上一套不同的卷子,算法就懵逼了。第二种:数据量充足,模型欠拟合。欠拟合的算法就像是心思不在学习上的孩子,报再多的补习班,结果也不会太好。最后一种:数据不稳定。算法前期可能很好的学到精髓,但是随着数据的变化,时间的流逝,模型很可能将变得不可预测。

测试驱动开发的解决之道

机器学习的实现方式还是通过软件工程、代码实现,既然是代码,那就存在应对范式。这里,就不得不提 Test Driven Development(测试驱动开发),简称 TDD。TDD 是一种很朴实的想法,在编码开始前,评估需要交付的功能点并写测试用例,一开始的时候测试会失败,接着编写代码修复测试,最后测试通过,修复代码。这里的方式,通俗来讲就是:目标导向,先成事,再迭代。

测试驱动有一个明显的好处就是,能够加快产品发布速度。以往的项目,需求讨论会占据很大时间,讨论完之后,开发方案一旦定下来,后续变更就很难。而现实却是需求常常变更,这往往会导致产品发布的延期。而在机器学习上,测试驱动好处更多体现在保证模型质量上。具体来讲,常通过以下办法:

  • 交叉验证 通过交叉验证来验证拟合效果
  • 运行速度测试 根据奥卡姆剃刀原则:”如无必要,勿增实体“;简单模型胜过复杂模型
  • 衔接测试 对数据的输入输入进行检测,以防止数据异常波动对模型影响
  • 指标追踪 监控关键指标,不断追踪模型的性能,防止失效模型继续运行

机器学习的债务危机

测试驱动开发一定程度上能减轻机器学习中的问题,但是它只是一种表象。测试通过了,不代表算法模型就没有问题了。魔鬼藏在细节中。机器学习目前仍存在一些技术债务,仍需按特定原则对代码修复,迭代演进。

什么是技术债务

技术债务是一个比方,类比的金融领域的债务。一般指为了加快软件开发速度,折中妥协,选择易于实现的方式,结果是短期加速了软件开发,但长期来讲,开发负担累计,发布逐渐停滞。债务不都是有害的。在业务扩张,市场抢占时期,适当的债务有助于公司扩张。但是若一直不管不顾,最后只能花更大的成本去维护它,直至无法维护。

机器学习中的技术债务

机器学习项目中同样存在债务危机,Google 还就此写了篇文章 《Machine Learning: The High interest Credit Card of Technical Debt》。总结起来有三种:一、边界模糊,数据之间彼此依赖关联。二、没有系统级别代码分离,胶水代码处理一切。三、机器学习系统随着外部世界的改变而彻底改变。

偿还债务

代码重构,就犹如对你的资产进行一次清点盘算:清除不良资产、偿还债务、进行资产上的重新配置。重构能够有效减缓技术债务带来的负面影响。

面向对象的 SOLID 原则

SOLID 原则由罗伯特·C·马丁提出,是五项原则–单一职责、开闭原则、替换原则、接口隔离、依赖倒置的缩写,是面向对象设计与开发的五个基本原则。通过这五项原则,写出来的程序可读性、可扩展性都大大提高,软件维护和系统扩展变得更加容易。

  • SRP 单一职责原则:一片代码只做一件事,及一块代码只实现某一特定功能,尽量减少逻辑的交叉堆叠。
  • OCP 开闭原则:对象对于扩展开放,对于修改关闭。即保持最小单元,写完后不去修改它,而是通过扩展或者配置的方式补充功能。
  • LSP 替换原则:任何的子类应该轻松由同一对象树的其它对象替代。
  • ISP 接口隔离原则:不同的接口做不同的事,软件开发没有银弹,接口也是。解耦能解决掉开发过程中“牵一发而动全身”的情况。
  • DIP 依赖倒置原则:抽象来自于细节、来自于底层,开发依赖抽象。

机器学习与 SOLID 原则

将 SOLID 原则应用于机器学习,会发现:机器学习与 SOLID 原则相互交织。诸如机器学习中的降维,是在减少耦合;胶水代码、数据依赖又与 SOLID 原则相抵触。

  • 单一职责
    • 机器学习中的数据相互依赖,更有利用 GBDT 生成特征,这一情况与单一职责冲突。所幸可通过降维、正则化的手段减轻影响。
    • 数据获取、数据处理、特征工程、模型训练、模型预测、数据监控,各模块无系统级代码分离,胶水代码处理一切。开发时应小心谨慎。
  • 开闭原则
    • 代码上可以做到开闭,但机器学习会作用于真实世界,引起的反馈将传导至模型内部。如模型预测出一批”潜在犯罪“,于是加大警力盯住这些人,最后发现他们的犯罪率果然高于常人。但他们就真的比别人更”坏“吗?这里有一个”预测、实施、证实“的偏差存在,算法无形中放大了偏见。
  • 替换原则
    • 机器学习的模型效果常由强特征决定,且特征众多。应用尽可能少的特征和数据,取得稳定结果。
  • 接口隔离
    • 模型的数据上游,可能会多个部门共用,数据源的人为变化,可能会导致模型的突然失效。因而需要对数据输入进行监控。
  • 依赖倒置
    • 测试代码、中间数据大量堆积,各个部分相互依赖。应定时对遗留代码和中间数据进行清理。

总结

机器学习、人工智能在经历这几年的爆发之后,出现了很多病症。测试驱动开发、SOLID 原则重构能够有效的缓解病症,还系统健康。如果你的项目已经落地,用 SOLID原则进行一次检查;如果项目还未实施,不妨尝试下测试驱动开发。系统更好的可读性、可维护性,不仅是程序员的责任,更是评判机器学习从业者的一把尺子。

不知道读者朋友对此怎么看,欢迎就此在评论区发表你的看法。喜欢本文的读者,别忘了点赞、喜欢、加关注哦,你的鼓励,将是我写作分享的动力💪

参考

  • wikipedia SOLID 原则
  • 《Python 机器学习实战– 测试驱动的开发方法》
  • 《高效程序员的45个习惯–敏捷开发修炼之道》

关于作者

谷粒,华中科技大学毕业,某游戏公司从事数据挖掘工作,常与机器学习、数据系统打交道。