作者 | 栗子 (南京大学 CS硕士在读)
原文 | 文末『阅读原文』处
来源 | NewBeeNLP
今年因为疫情,很多事都发生了变化,也需要大家去"拥抱变化"。(希望有人能接住这个梗哈哈哈)
对于公司的实习或者全职招聘来说,最大的变化可能就是面试由大部分线下变成了全部线上。虽然失去了线下和面试官面对面交谈的体验,但隔着屏幕的交流,搭配上一些辅助工具可能也使得面试更加方便,孰优孰劣还是留给大家自己评判。
从春招的实习投递,到秋招的全职投递,我经历了共计6家不同的公司,大大小小27轮技术面试和6轮HR面试,有精彩也有糟糕,有成功也有失败,收获颇多,感想也颇多。
其实很早就希望能写一篇或者几篇文章来聊聊自己的春秋招和实习,做点内容上的输出,但是因为自己事实上是个懒人所以迟迟不想开动。后来想想与其让自己的碎碎念随着时间慢慢淡去,被自己忘记,被大家所不知,不如记录下来。无论是多年之后再回首现在的自己然后会心一笑,还是能给大家一点点的参考和启发,都很让人开心。
那么下面,正文开始...
"算法竞赛"里的算法,不同于被大家所熟知的"算法岗位"的算法。后者基本可以理解为机器学习、神经网络等相关的理论与应用,即设计一些模式或者策略来让机器基于海量数据的学习达到一定程度上的能力要求;而前者则更像是人类心智与自我的博弈,即提出不同的问题,然后针对这些问题,通过具体的分析来设计不同的流程和规范从而解决或一定程度上解决问题。
"算法竞赛"于招聘是我对于招聘算法题,以及算法竞赛之于招聘算法题的一些看法。因为自己接触算法竞赛的时间还算不短,所以这些观点的置信度可能相对来说高一些。
"算法岗位"于招聘是我基于面试和实习的经历,来谈一谈工作中的算法岗究竟在做什么。因为接触时间尚短,可能并不能给出专业的看法与观点,一些浅见与大家分享和交流。
"算法竞赛"于招聘
算法题是招聘中,笔试的主旨,面试的惯例,所有应聘者都无法避开的一道坎。每天我关注的一堆公众号里,都会弹出几个"xxx带你刷算法题"的广告,也足可见这些题目的重要性。
"算法竞赛"究竟能带来什么
众所周知,算法竞赛的奖牌在近些年的含金量逐年下降,从上古时代的铜牌就能得到认可,到我刚接触时起码银牌才能达到一些大公司的底线,再到现在每年都能产出海量的金牌,奖牌渐渐地代表不了能力了。竞赛圈著名的q老师曾经说过,"能力强的人到哪都不会混的差的"(大意如此)。奖牌只能代表你曾经参与过,真正的能力展现还应当是真正地在笔面试中做出题目。
我一直秉持一个观点,就是出题并不是越难越好,而应当看对应的人群以及做题的目的来做针对性的调整。我在给NJU的问题求解当助教时就总会在期末考试中控制难度,一方面是因为出题人的惯性会导致自己认为题目偏简单,另一方面也是因为受众是大部分非竞赛学生,目的也是考核而非选拔。
招聘的题目也是同理,这些题目的核心是考察你的代码能力和思维能力是否达到企业的要求,绝大部分做题的人都是未接触过算法竞赛的应聘者。作为一名算法竞赛选手,如果你觉得题目很简单,那很正常;但如果你迫切地希望能够提高笔面试题目的难度来帮助你脱颖而出,那我只能很遗憾地说你可能更应该去打比赛。
不可否认的是,随着所有人逐渐意识到算法题在招聘中的重要性,大家都开始近乎疯狂地刷题,Leetcode这类平台的崛起也正因为此。也正是因为求职者整体水平的提高,招聘算法题的难度也在逐年提升,但还远远达不到竞赛题的水准。这可能是竞赛选手有限的优势所在,即当你适应了竞赛题的难度,再回头看招聘算法题,经过简单的适应之后就是完完全全的降维打击。
绝大多数人都没怎么接触过算法竞赛,当他们看见一名竞赛选手轻松AC那些看起来很难的算法题的时候,可能会生出一种无力感,其实大可不必。原因有下:
「在企业的招聘中,算法题仅仅是一个部分,不是全部。」
当然这是对绝大部分公司来说,像Google那样面试只问算法题的公司,或者像MS那样算法题处于极端重要地位,其他知识是"Better have"的公司,终究还是少数。从我的经验看来,外企可能更看重算法题,可能是因为他们更看重思维能力,而一些工程知识他们认为可以培养之后很快上手;而国内公司虽然算法题也是重要组成部分,但其他知识同样很重要。
哪怕自己的算法题水平不如竞赛选手,但招聘是一个多维度的比较、筛选与考核。因此其他方面表现优秀,在算法题上表现不那么优秀(那肯定不能太差,毕竟会被一项否定)也无伤大雅。人很难在所有的事情上都做的极度优秀,但是在某一方面不错,其他方面不算太差,我觉得就是一个很好的表现了。
「企业招聘中算法题的目的是考核,而不是选拔。」
有别于竞赛要选出冠亚季军、出线队伍、分个金银铜牌,企业招聘中这些题目的目的更像是希望能够展现你的代码实现能力、思维能力、交流沟通能力甚至思考方式等等,让面试官对你有一个更为全面的了解。算法竞赛的内容在真正的工作中不会丝毫无用,但远远不到举足轻重的地步。可能你的经历能让你快速实现某个功能,能让你优化某个模块的时间、空间,但就像很多人说,很多时候调库就可以,我尚未见过什么需求刚好可以用某个很厉害的算法直接实现,时间空间都完爆其他实现的情况。算法竞赛能带来的思维方式会受益终生,但并不会显著产生直观的效果。
也正因为此,招聘中的算法题往往是过线就行。我觉得很多时候,只要在Leetcode这样的一些平台多刷刷题,那么你的能力就足以应付绝大部分的算法题了。只是因为面试的其他部分例如语言、网络、数据库、操作系统等等内容是大家广泛接触过的,但算法题认知可能还局限于算法与数据结构课上那些简单的内容,所以才会产生对于未知的畏惧感。真正刷了一些题之后大家就会发现,算法题也就这样。
希望竞赛选手在应聘时能够多增强其他方面的技能,仅仅是会做题其实是远远不够的。而非竞赛选手也不应当畏惧算法题,多去做准备,发扬长处、增强短板才是正确的应聘准备策略。
如何准备算法题
准备招聘算法题其实与竞赛入门有极大的相似之处,毕竟二者做的题目在本质上并没有什么不同。
「首先,应当选取一个好的练习场所,或者说是做题网站」。随着计算机行业的兴起,附加产业也越来越红火,做题网站相比也有很多,这里我就不打什么具体的广告了,就以最广为人知的Leetcode为例。
一个好的练习场所,首先需要拥有足够高质量的题目。高质量的题目定义其实很抽象,从知识点层面来说,题目应该能够覆盖到所有的知识点,对于每一个知识点来说应该有概念理解类的问题,同时也要搭配一些不同"套路"的题目,来让做题人理解这样的一个算法或者是一项工具有哪些常见的应用手段。从更为功利的应聘角度来说,企业的真题可能也是一个很好的切入点,不说能够让你了解到对应企业的出题风格(这个我个人感觉不太现实),但让你感受到不同企业之间题目的难度差异是很好的。
例如在国内企业里,根据我面试的经验,字节跳动的面试算法题会显著难于其他的一些公司,例如华为、腾讯、美团等等。而在外企里,想必大家已经知道了,Google的题目难度独一档。了解题目难度可以帮助你更好地选择目标以及训练。
「其次,要制定好目标和计划」。刷题这件事并非很短的时间能速成的,很多人羡慕竞赛选手强悍的实力,但却看不见我们多少个日日夜夜守在电脑前挠头做题的场景。提升自己的算法题实力是一个长久的事,这就更需要规范化的练习,以及最重要的坚持。
具体来说,可以先调研算法题的大概分类,例如贪心、模拟、动态规划、搜索、数据结构等等(这里只是举例,并不是全部)。然后对于每一类算法,去了解它大概的思想、典型的题目、经典的应用等等。一定要把这些都实现一遍,然后再去进行更深的探索。接下来就是大量的练习,根据自己的水平选择合适的题目去练习,既不能好高骛远一下去看太难的题导致失去信心,也不能沉迷刷水题让自己无法提高。持之以恒地练习,会让你的实现能力和思考能力都有一个质的飞跃。
「最后,一定要有探索和总结」。对于招聘的算法题来说,所牵扯到的知识点十分有限,更多地是考验你如何运用,如何在狭窄的空间内辗转腾挪。倘若真的考到了超出知识范围的内容,那就爽快而又坦诚地认命吧,这并非是技之错,仅仅是运之错而已。
对于已经学会的东西,一定要多去探索和总结。探索是为了见识到更多精彩的应用,总结是为了基于这些应用,体会到这些内容的本质。一个算法并不是会实现最简单的版本,做过最裸的题目就完事了,而是经过了千锤百炼,使用它做过了许多到题目,真切地认识到它的本质才算真正掌握。当你有一天忘了这个算法的代码怎么写,仅仅凭借自己的理解就能复现出来原算法,那才是真正掌握。
我也曾经做过Leetcode上一些有意思的题目,也曾逛过评论区,很多题解都是一知半解,甚至并不正确。试想当这道题目换了一个外衣,又有多少人能够想到它的本质,想到正确的做法。所以,对于算法的理解一定要尽可能地贴近本质,才能做到面对一个全新的题目时,对各种算法信手拈来。
"算法岗位"于招聘
说实话,这一部分的内容很难动笔。一方面是因为本身我的了解就非常浅薄,一方面是因为我觉得感想非常零碎,很难将它们串在一起去完整地归纳和总结。简单写写给大家做一些参考,欢迎讨论!
算法岗位其实是一个很复杂的概念,绝大部分是指利用机器学习等基于大数据的方法来让机器完成特定任务,还有很少的一部分是针对特定的需求来做针对性的优化,例如优化操作系统、优化数据库等等,这方面的工作因为我知之甚少,就不做介绍。后续的"算法岗位"特指机器学习等岗位。
算法岗位究竟是怎样的
首先,从工作的性质来说,算法岗位是区别于研究岗位的。研究岗位一般存在于大企业的各种实验室或者AILab之内,主要负责的就是跟进前沿的技术,然后利用企业资源去发论文。但是近年来的趋势似乎是越来越多的企业更倾向于需要AILab偏向具体的落地应用,而非单纯的科研。这也可以理解,毕竟企业是需要赚钱的,单纯的论文产出已经不够,将创新性的成果转化为收益才是企业的最终目的。算法岗位一般来说就是解决具体的问题,即前沿或较前沿技术的落地和应用。我本人更喜欢这样的工作,一方面是因为我觉得自己并不太适合纯科研,另一方面也是自己喜欢具体技术的应用而非发掘。
其次,从工作的内容来说,算法岗位会有很多的工程工作。有一句开玩笑的话是这么说的:"所有的算法工程师最后都会沦为数据库工程师"。这也是因为算法工程师需要负责从了解模型,搭建模型,到准备数据,训练模型,评估模型,到参数调整,模型部署的全部环节;并不仅仅是搭建模型使用现成的数据训练评估就可以的。这也是我实习的最大感受。其实在日常工作中,很大一部分时间都用来进行数据的准备,具体流程Pipeline的搭建等等。
最后,从工作的时间来说,算法岗位与开发岗位也有很大的不同。在我的理解里,开发岗位的工作时间更符合传统工作的时间要求,即上班开始整理需求,写代码,然后交接,然后下班(如果错了欢迎交流)。我曾经和我的mentor和mgr聊过算法岗位的时间安排,算法岗位并不是这样,更像是两条时间线的交错安排。一条时间线是程序员的时间线,你需要研究方法,编写代码去做各种各样的事情等等;另一条线则是计算资源线,这条线主要负责的就是模型训练评估等等的工作。众所周知,人需要休息,机器是不需要的,所以为了保证进度的稳定推进,算法岗位会要求计算资源不要空闲。很多时候在正常的上班时间算法工程师们也会休息,而在下班的时间大家也可能会适度地看看代码。例如白天如果模型已经在跑着,那大家可能会吃个水果玩玩手机;而晚上睡前可能会看看模型是否成功地跑起来了,来保证在睡觉的时候计算资源是有效运转的。总体来说,"算法工程师的时间安排更加地灵活和自由"。
公司的算法岗和实验室研究有什么区别
这也是我一直很想写的一个话题之一,即工业界和学术界究竟有什么不同。
相信对于很多学生来说,从学术界到工业界的转换是一种全新的体验,所以这里我想根据我在学校组里的经历以及在微软实习的经历,简单聊一聊这两个界的区别。
从目标来说,学术界的考核目标是论文。其实发论文是一个考虑了很多方面因素的事情,比如你是否有好的贡献,是否有好的效果,以及是否能得到审稿人的认可等等。一个工作可能并不能够有一些广泛或者具体的应用,但只要它具有一定的研究价值,可能就能形成一篇好的论文。工业界的考核目标是收益,相比学术界,工业界的目标更加纯粹,一个工作只要能切实地带来收入的增长,那就是好的工作。所以在工业界,大家同样会紧跟前沿,但并不会每一个新的模型都会部署到线上去,而是会评估它的效果之后,结合具体的业务做好适配再去部署。
从过程上来说,学术界很少考虑资源的问题,在很多的论文里大家都非常关注最后的效果。当然也有很多论文会附上运行的时间、资源消耗等等内容,但很少会作为主要的考量去呈现。工业界必须考虑资源的问题,任何算法当它的使用范围被扩大到海量数据时,都会牵扯到各种各样的问题,例如内存的开销、时间的限制等等,这样的一些限制在实验室研究时很难遇到,因为大家往往使用现有的数据集;而在企业落地时都是必须考虑的内容。所以在工业界,最需要做的一件事情就是trade-off,即效果和资源之间的权衡,并不是模型的效果越好就越应该使用,而是需要考虑模型轻量化的前提下选择合适的模型。
从关注内容上来说,学术界更为关注模型本身,因为评估模型使用的各种公开数据集或者benchmark,对于大家来说都是公平的。而工业界更为关注数据质量,以及数据和任务的契合程度,在工业应用中更多的是从丰富的log中抽取数据来训练模型,数据的质量就成为了关键的一环。我在微软的实习过程中在数据抽取部分就遇到过数据泄漏和数据倾斜等不同的问题,解决了这些问题之后,才能正确而有效地评估模型的表现。
从工作的体验上来说,公司则远远优于学校。这种体验上的差异不仅仅体现在资源对比上,例如公司会有充足的显卡和存储资源供大家使用,而在学校只能大家去抢占服务器上有限的几块卡;体验上的差异会更多地体现在流程中,例如准备数据的过程、训练模型的过程等等。在学校可能需要自己去服务器上操作,甚至需要为多卡并行去手动配置很多的参数;而在公司,得益于大量infra(基础架构)工程师的努力,会有很成熟的AI训练平台供你使用。高度抽象和集成的平台会让模型的部署、训练、评估、调试等等工作都变得更加轻松。
以上是个人的一些简单的体会,希望能够帮助到同学们更快更好地完成从学校到公司的转换。
尾巴
历时两天终于完成了这篇文章,也完成了很久以来就想做的一件事。希望这些内容能给大家带来帮助,也欢迎大家在知乎或者博客的评论区和我进行讨论。
推荐阅读