来自 Algorithmia 的布道师 Stephanie Kim 在西雅图 PyData 大会上呈现了关于数据工程师如何从开发者社区借鉴经验来提升数据科学技能的演讲。在这篇文章里,她把演讲内容通过文字的形式再次呈现给读者,并进行了归纳总结。内容分为五个部分:
- 10x 开发者的历史渊源
- 项目设计
- 代码设计
- 用好工具
- 学会部署代码
相应的演讲视频可以在YouTube 上找到,或者查看英文原文 Becoming a 10x Data Scientist 。
10x 开发者是指那些能够产生 10 倍于普通开发者效能的开发者。他们在相同的时间内可以写出更多的代码,而且这些代码质量很高,bug 很少。他们测试自己的代码,辅导初级开发者,自己写文档,而且还懂得很多代码之外的知识。
1968 年,H. Sackman、W. J. Erikson 和 E. E. Grant 做过一个叫作“编程效率差异性”的探索性实验。实验发现,程序员在完成编码任务上所花的时间存在很大的差异。
参与实验的程序员平均拥有 7 年的编程经验,在极端情况下,他们之间的差异比达到了 20 比 1。
虽然实验中也存在“作弊”成分,比如有的程序员使用了低级的编程语言而有的则使用了高级的编程语言,但越来越多的研究也都得出了类似的结论。
关于是否存在 10x 开发者的争论一直没有停息,不过不管怎样,这篇文章主要是想告诉大家如何从高效率的开发者那里借鉴经验,让自己成为卓有成效的数据科学家。
了解业务
不管你从事的是哪个领域的工作——教育、生物技术、金融行业——你都起码应该对所在领域的业务有所了解。
在数据分析的背后,你需要知道是什么在推动着业务的发展,需要了解业务的目标是什么。
举个例子,如果你要优化小吃售卖车的位置,就需要对人流、竞争者、目标区域内发生的事件和天气都有很好的了解。你要明白为什么要优化位置,这么做可能是为了增加当前售卖车的售货量,也有可能是因为要增加新的售卖车。
你今天可能是一个搜索网站的数据科学家,而明天可能会跑去金融公司,但不管到了哪里,你都需要了解业务,让你的数据分析为利益相关者带来好处。
你还需要了解业务流程,比如谁应该对最终结果负责、在你完成你的工作后谁来接手后续的部分、时间表是怎么安排的。
最后,你要知道利益相关者是谁,并向那些不懂技术的利益相关者说明现实的期望是什么。把自己当成是一个老师,教会那些不懂技术的利益相关者,告诉他们为什么达成目标需要更多的时间和资源。
在了解了利益相关者的目标并在技术和时间方面达成一致之后,你无疑会成为公司更有价值的无形资产。
了解数据
了解业务固然重要,而了解数据的重要性也是有过之而无不及。你需要知道数据是如何以及何时被抽取出来的、是谁在负责质量管控、数据之间可能存在的差异(如数据提供者发生变化或数据抽取方式发生变化)、数据可能丢失掉哪些信息,以及可以通过增加哪些数据源来提高数据模型的准确性。
这个需要与团队展开沟通。你可以大胆地问他们在做什么,也告诉他们你在做什么,避免大家做了重复性的工作,也让他们对你想要访问的数据有个清晰的了解。这样可以为你节省很多时间。
为什么说在进行项目设计时多费点心能够让你成为 10x 数据科学家?
- 你只需要完成必要的工作,这样就可以更快地完成项目。
- 澄清用户的真实需求和假想需求,让它们达成一致,你就会成为这方面的专家。
- 加深你自己对问题的理解,这样就不会犯下大错。
代码设计
在设计代码时有很多最佳实践可供参考,其中有几个比较突出的技巧可以让你的效率提升若干倍。
在我的一次大学写作课上,我第一次听说条理清晰(clearness)比灵巧(cleverness)更加重要。人们很容易就陷入自作聪明的陷阱,使用最新颖的词汇表达自己的想法,但如果把这种习惯带到了编程里,不仅可能给自己造成迷惑,也会给别人带来麻烦。
在上面的例子里,第一行代码使用了简短的 sortBy 方法,它确实很简短,但很难让人想明白下划线代表的是什么意思。很多人在匿名函数的参数上也使用了这种方式,初级开发者(或者你很久没有看过自己写的代码)很难猜出这些代码是干什么用的。
第二行代码使用了一个参数名,还写出了赋值的过程,这样我们起码可以知道它要将序列 x 按照倒序来排列。
代码可读性越好就越容易调试,于是第三行代码就给出了具体的参数名,表明了它的含义。
在进行调试或添加新功能时,你的大脑需要不断回顾那些短代码代表的是什么意思,这样会占用你更多的时间。虽然代码看起来很简短,可以少敲几次键盘,但从长远来看,其实是得不偿失的。
Phil Karlton 曾经说过:“计算机科学领域有两大难题——如何让缓存失效和如何命名事物”。
在这里我们不讲缓存,所以就让我们来讲讲命名的重要性。以上述的第一行代码为例:
.sortBy(x => -x._2)
使用单个字母来命名一个序列并不会为我们提供任何有用的信息,如果你的数据是从某处的 API、数据库或 Spark 的数据流里抽取出来的,那么你就需要运行这行代码才能知道 x 代表的是什么。
再来看看第三行代码:
.sortBy(clothesCount => -clothesCount._2)
我们甚至不需要运行代码就可以知道我们正在对什么进行排序。
不过,有时候使用 x 作为变量名也是很有必要的。例如,x 经常被用在机器学习的软件包里,x 表示被观测的数据,而 y 表示被预测的变量。在这种情况下,应该首选“x”和“y”作为字段名。
不过,在数据科学领域之外,你应该更多地遵循编程语言本身的约定。如果你使用的是 Python,那么就应该通过查阅 PEP 文档来了解 Python 的最佳实践。
良好的命名风格和清晰的代码逻辑让重构和调试都变得更加简单和快速。凭借这两个代码设计原则,你离成为 10x 数据科学家又近了一步。
保持代码风格一致性也很重要。为了保持代码风格一致,你要始终如一,比如不要在同一个脚本里混杂驼峰式命名方式和蛇形命名方式,这样只会让代码变得难以阅读。另外要注意,不要使用多种方式来完成同一种任务。例如,你要在代码的多个地方给字典去重,为了表现你的创新,你使用了一种很不一样的方式,只是因为你在 Stack Overflow 上看到有人这么做,但其实完全没有必要这样。你要做的应该是在你的整个代码里使用一种清晰而不取巧的方式。再次强调,保持一致性是为了避免让你自己和他人感到困惑,也是为了让调试变得更简单。
刚才我们说过,在代码的多个地方给字典去重应该要怎么做?我们可以使用函数,这样就不需要写重复的代码。即使写函数不是为了重用代码,把代码包装成函数也算是一个最佳实践。函数体应该保持紧凑,每个函数只做一件事情,这样它们更有可能被重用。
如果不使用函数,就会出现很多全局变量,进而导致命名冲突,让代码变得难以测试,而且会出现很多重复代码。
如果把代码包装成函数,就很容易进行单元测试。
不仅要保持函数紧凑,让每个函数只做一件事情,而且要对函数进行抽象,这样才能重用它们,让开发速度得到 2 倍的提升。
虽然人们不是很经常使用代码桩(stub),但它对于代码设计来说其实是很重要的。简单地说,代码桩就是模拟用的类和函数,它们提供输入、输出,描绘了代码的框架结构。在写真正的代码之前使用代码桩有助于你展开思考,避免写出怪异的意面式代码。在写代码之前你会注意到哪些地方可能出现重复代码,并考虑使用更合适的数据结构。
接下来要讲讲注释和文档。要让你的同事喜欢你并让自己成为更高效的数据科学家,你就应该在代码里加入简洁的注释。不仅要写明代码的用处,还要指出输入和输出是什么。
在大部分编程语言里,可以通过一些工具包将 docstring 转成文档,这真是太酷了。比如,Python 里有一个叫作 Sphinx 的工具包就可以将 docstring 转成详尽的文档。
在写代码的时候你当然知道这些代码是干什么用的,但过了一段时间之后,当你要调试代码或往里面添加新功能的时候,不管是你自己还是别人都会因为这些详尽的注释而感激你。
不管你使用的是哪一门编程语言,都要进行异常处理,并为自己和他人留下有用的错误信息。上面的代码将 API 的错误信息传给了 stop 函数。
如果输入数据不是 API 所期望的,它就会抛出一个错误消息。你可以在代码里传一个消息给 stop 函数:
stop(paste0(“Make sure all your inputs are strings: ”, e))
上面的例子来自 Hitchhikers 的 Python 指南,并使用了 Python 测试框架 Pytest。
编写单元测试对于开发者来说是一件很平常的事情,但在数据科学领域就不是这样的。你一般会使用交叉验证、混淆矩阵等方式来验证模型,但你有对抽取数据的方式进行过测试吗?你有对清理数据和转换数据的方式进行过测试吗?这些地方都是对垃圾数据进行拦截的关键关卡。测试代码不仅意味着可以移除 bug,当你的高质量代码进入到生产环境,其他人会看在眼里,你会成为他们眼中的明星。
使用版本控制系统对于成为一个 10x 数据科学家来说也是至关重要的。你可以保存多种版本的模型,还可以很轻松地进行跨团队合作,你的代码保存在代码仓库里,如果电脑被偷或者硬盘损坏,代码仍然是安全的。
有一个叫作 Data Version Control 的数据版本控制系统,它专注于数据科学工作流,现在还处在 beta 测试阶段。它是基于 Git 构建的,因此可以通过建立数据依赖图在多个团队间共享项目。你的数据与模型是单独保存的,就像其他版本控制系统一样,支持回滚到之前的任意一个保存点。
10x 开发者知道如何选择合适的工具,知道如何使用软件工具包来节省时间,知道如何通过更换编程语言来提升性能,或调用已有的 API 而不是自己从头开始开发相同的功能。
假设你要基于 Twitter 或其他社交媒体数据展开文本倾向性分析,可以自己给数据打标签然后自己训练模型,也可以使用别人预先训练过的模型。不重复发明轮子是最好不过的了。选择合适的工具,即使那些工具不是你自己开发的。
我们都会通过 Crob 作业运行 Bash 脚本来自动生成报告,但当你在调试别人生成的报告时,却不知道它是从哪里开始运行的,于是你开始意识到我们应该使用更好的工具。我们可以使用 Puppet、Chef、Ansible 或其他任何一个流行的自动化工具,这样可以加快调试速度。
有时候,不一定会有团队帮你部署模型,所以你需要自己知道怎么部署模型。
有很多厂商提供了模型部署服务,有些很简单,有些比较复杂。如果你想知道更多相关细节,可以参考我们的其他演讲内容,如“ intro to deploying your model ”和“ deploying and scaling your deep learning model ”。
一旦知道如何部署模型,你就可以很容易地与团队成员分享你的数据模型,或者把模型部署到生产环境,把它们分享给成千上万的用户。你会因此成为一个 10x 的数据科学家,因为你知道如何有效地改进模型来满足用户需求。只要用户开心了,业务所有者也会开心。
接下来再总结一下如何成为一个 10x 的数据科学家。
- 模式匹配。借鉴他人经验来解决当前的问题。
- 学会解释你的代码。可以利用白板,可以进行代码审查,甚至是结对编程。
- 学会放弃和重新来过。如果有更好的解决方案,不要害怕从新来过。
- 利用 GitHub 创建自己的 Gists 仓库。
最后,每一个 10x 开发者都是调试高手,他们调试代码的时间通常是写代码时间的 10 倍。要成为一个调试高手,需要做好异常处理,利用 IDE 的调试器,在代码逻辑当中寻找错误,查看发生错误的软件包源代码,确保传入的参数是正确的。
即使你只是从这篇文章里学到了其中几点,它们也能帮助你在成为 10x 数据科学家的道路上走得更远。
感谢蔡芳芳对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论