正文
Part4方法篇
上文讲了一些我关于校招同学找工作的观点。聊做参考。
也看了一些大家的反馈,其实主要的反馈点在于,很多人认为今年这个形势,你 leetcode 做不出 hard 连面试资格都没有(因为非常卷)。这里我无法向你做什么保证,因为每个公司在这方面要求确实会有所不同,但有几个点我还是愿意分享一下:
- 每个公司对 AI 算法的代码能力要求各有不同,我能提供的客观信息是,我社招面过的公司(包括但不限于字节x2、微众银行、蚂蚁金服、小红书、虾皮、爱奇艺、喜马拉雅、Roblox、私募),所遇到的所有代码问题,难度没有超过 leetcode medium 的,且有的代码没完全做出来也不影响继续下一面。
- 这个问题我和你的视角可能不一样,站在学生和求职者的视角,你看到的是今年的面试都是 medium 往上 hard 不封顶,你看到的是谁谁谁代码没做出来就没有后续了,因此你推测做不出 medium 肯定过不了面试。但实际上没有下一轮未必是代码的问题,或主要未必是代码的问题。
- 从工作实践上看,我也不认为 leetcode 代码能够对直接对工作产生什么重大增益,相对而言更好的编码习惯和对运行效率的敏感更重要一些。我相信在这点上各个业务线上的算法岗位都差不多,所以才有面试造航母入职拧螺丝的说法。基于这个认知,算法团队至少在理论上不应让 leetcode 的难度过高,并成为刷人的硬性指标。
但见仁见智,这些认识未必对,但相对于求职者的反馈,我更希望看到更多面试官的反馈,来分享你们团队对算法同学的代码能力有何种要求。
接下来务实一点,讲一下具体应该怎么准备找工作,同样有几点要写在前头:
- 事有轻重缓急,有些事情也许已经来不及做了,那你就当它是写给低年级的、还没有那么紧急的同学的;
- 如果你的时间不太多,应该捡自己还来得及做的事情,按着优先级搞,这个时候讲究二八原则:用20%的时间拿到80%的成果,不要精益求精了。
0x00:硬实力:算法基础与CS基础
开篇先打脸,尽管在上一篇中我已经讲了,八股文用处不太大,但那是对八股文和代码问题不太大同学而言的,所要指出的是,如果你的八股文水平和代码水平已经尚可,就不要花太多时间再进一步精益求精了。
现在来定义什么叫八股文尚可(其实是很优秀了):
- 常见的传统机器学习算法,如决策树、随机森林、梯度提升树、SVM、LR、PCA能够讲出其核心思想,优缺点与适用情况,能够讲出其优化目标,能够讲出这个算法为什么叫这个名字。如果你好好上了课,这点应该有一两天的集中复习就足够。
- 在至少一个细分领域了解当前技术的大体进展,SOTA 方法,思路,能对流行的方法有自己的评价,言之成理。如果你有好好做研究,不管有没有 paper,这点应该是默认具备的。
- 对广泛的深度学习话题,能够了解具有相当影响力的重要工作,能够讲出其核心 idea 和大体思路。这个“广泛的深度学习话题”既包括大的应用领域:CV、NLP或Audio,也包括近期比较热门的话题,如AI艺术创作,也包括一些理论:自监督学习、领域自适应、元学习等。这三点的优先级依次下降,最差情况,你也需要对大领域的关键工作能说出来一二三。这点比较难,因为话题广泛,难免了解过于粗浅,最佳状态是平时就很关注学界动态,牛逼的工作出来以后有好奇心能去看一眼,稍微研究一下。
- 对深度学习/机器学习的基本理论有本质层面的认识,能够从原理层面回答深度学习的各类常用组件“why”的问题。这点难在你并不知道你理解的是否正确,建议可以准备好问题列表例如“为什么正则项可以抑制过拟合”,然后去知乎搜大家的讨论,多看一些观点取其精华。
- 熟练至少一种深度学习框架,所谓熟练:
- 你对这个学习框架的设计思路基本了解,你清楚各个模块的作用和工作机理
- 你能够用这个深度学习框架实现自定义的结构,而非只是简单调用高层 API
- 你对这个深度学习框架的常见坑点很熟悉,了解大部分情况下的最佳实践
- 对常见的 CS 概念有基本了解,也就是正儿八经的八股文了,特别是:
- 对 linux 有基本了解,了解常见的命令,能够搞定一般的环境和工具配置,了解一些基本的概念,知道bashrc、根目录下的几个文件夹分别是干嘛的
- 了解 git 的一些基本概念和用法
- 了解HTTP、web服务、SQL、NoSQL、消息中间件、微服务、容器技术等等乱七八糟的概念,不用深入,基本上知道“是什么,解决什么问题,什么时候用”就可以了。
- 了解分布式的一些基本框架、工具或理论
- 知道常见算法的时空复杂度和大体思路,知道常见数据结构的概念和适用场景。
- 其他八股文:进程线程,内存,动态/静态链接库等等等,网上搜一个八股文面经看一下
- 最好能会除 Python 以外的一门静态语言,水平能够达到能看懂,能写一些不太复杂的功能。以 C++ 为例,基本上 C++ primer 模版之前的内容能大体了解,就足够了。
0x01:硬实力:代码题
继续来自我打脸,上一篇仍然讲了代码题并非那么重要,但同样,如果你从来没做过代码题,那必然也是过于离谱导致无法通过面试的。
如果你不是 ACM 选手,只是单纯为了准备招聘而练习代码,那我认为代码的程度,以 leetcode medium 为上限即可,追求过于高的代码水平边际收益不高(除非你要面试谷歌这种)
具体练习也有讲究,我认为以下面两类问题为比较重要:
- 模拟类的问题:这类问题通常都不难,也不涉及高深的算法,思路都很直接,主要练习用代码实现出来的能力
- DP 类的问题:就面试准备而言,算法上能够解决 DP 类问题就足够了,DP 可能是面试中最常见的难度稍高的问题。
以下问题无需花时间练习:
- 要借助除了栈、队列、二叉树、散列表以外的其他数据结构才能方便解决的问题
- 要借助除了排序、搜索、简单动态规划、递归以外的特殊算法才能方便解决的问题
- 脑筋急转弯类的问题
练习代码题请注意如下几点:
- 前期以熟悉为主,后期要限定时间,一般面试中的代码考察最长不会超过1h,通常是30min一个题,如果到时间没有解决,你需要练习基于已经有的部分阐述思路,讲解代码,给出没有做出来的理由
- 后期需要练习面试环节下的代码编写,面试环境下,你需要避免一声不吭写30min没做出来的情况,并且你可以向面试官寻求帮助。
- 写完代码需要看题解,了解自己代码的时空复杂度,是否还有优化的空间。通常代码题是一套一套的,面试官允许你用低效的方法实现,但一旦你实现,下来的问题就是复杂度如何,可否进一步优化。
- 基于上一条,可以练习先用蠢办法快速解决问题(i.e各种暴力),拿到基本分,然后再优化成更聪明的办法。可以避免没做出来直接0分。
0x02:硬实力:paper
没什么好说的,这不是临时抱佛脚能抱来的东西,这里只提一点:
- 对于目标岗位是大厂业务算法的同学,记住 paper 是边际效用递减的,当你已经取得不错的成果时,需要更早的思考继续投入的性价比。
- 但边际效用递减,不是说没有 paper 也能行。有没有是一个问题,什么质量是另一个问题,有多少是第三个问题,重要性依次递减。
- 对于目标岗位是纯研究岗的同学,需要在学校期间提前选定意向岗位,针对性的做 paper
0x03:硬实力:实习
如有可能,应该积极寻求大厂相似岗位的实习,如果不清楚自己要找什么工作,应积极寻求大厂的算法实习,不要太在意具体做什么。
绝对避免做无意义的实习,所谓无意义,指的是这段实习经历不能写在简历上,写上了就扣分。
找实习的面试准备与应届生面试准备大体相同,但有一点例外:
- 能够连续实习很长时间,每周能投入更多时间的实习生,能够在实习面试中获得巨大优势
这一点跟你老板的风格相关,因此这引出了对准研究生的一个建议:
- 如你的目标是工业界而非学术界,那在可能的情况下,你要找允许长时间实习、条件比较宽松的导师
- 但自带资源的业界大佬导师除外,因为你很可能会直接去他关系很好的公司
0x04:准备简历
下面是一份简历准备的注意事项,以下各项在简历上有顺序关系
- 姓名电话邮箱和微信号,如果有好的开源代码给 git 主页,有好的技术博客给博客链接,不需要告诉我你是不是党员,是否已婚。
- 教育背景给到学校和专业即可,除非你导师很牛逼(业界都知道的那种牛逼),一般也不需要告诉我你导师是谁。除非你的成绩很拿得出手,也不需要告诉我你的绩点和成绩
- 列出你拿得出手的奖项,如果没有,可以列奖学金。
- 奖项应该是专业相关的
- 如果你不是 CS 或相关专业背景的,可能需要给出与面试相关的主干课程或自学过的课程,否则不需要。你列出来的课程,不管是自学还是学校上课,都要做好被考察的准备。
- 列出你的技能点,包括编程语言能力、算法能力等
- 轻易不要用精通,精通意味着你会激发面试官的挑战欲
- 如果你确实精通,有信心面对面试官的大部分问题,大胆写精通,这将帮助你把面试话题引导到你擅长的领域
- 不要列出没有意义的证书,例如全国计算机等级考试X级,CET4成绩
- 但如果这个证书是一项有难度的、能证明你自驱的,请列出
- 如果有实习经历,展示你的实习经历
- 该实习必须是专业上的,不要写无关紧要的实习经历
- 实习经历不要写心得体会,也不要写流水账,写你所取得的最牛逼的成绩,加粗。
- 展示你的项目经历,如果没有,用 paper 经历代替,也可以用实习经历、竞赛经历代替
- 描述项目的背景,目标,意义
- 描述你在其中扮演的角色,所负责的工作
- 描述你的独特贡献,这个贡献能够展现你的聪明才智,宝贵品质,优秀素养。这一点的重要性超过你的想象,仅仅是作为一个螺丝钉参与一个项目,其中没有体现出任何个人特质,基本上等于你没有这个项目。
- 描述所取得的成果,如果没有取得预期成果,描述为什么
- 展示你的独特经历
- 开源代码或社区共建
- 公开演讲、授课
- 展示自驱的经历
- 其他具有一定影响力的经历
- 展示你的学术经历,包括 paper 和专利
- 不必按时间排,按牛逼程度降序排
- 如果上面的内容已经比较充分,这里可以按参考文献格式列出。如果觉得内容不充分,可以加一两句话描述 paper 的核心工作。
- 展示你的自评、上述模块未介绍,但你觉得值得一说的东西
简历准备的核心要义,有以下几点:
- 简明扼要,重点突出,不要让人觉得你啰啰嗦嗦婆婆妈妈
- 简历的目标是让你与众不同,一份仅仅是符合要求的简历实际上没有任何竞争力。你需要让面试官对你感兴趣,或者通过过硬的实力,或者通过特殊的经历,或者通过其他什么手段,哪怕是一个漂亮的简历模板。
- 质胜文则野。文胜质则史,文质彬彬。
0x05:面试:讲解项目
这一条是面试最重要的部分,而且不管是几面都要陈述的。之所以不放在硬实力的部分,是因为相对于“有一个不错的项目”,”讲一个不错的项目“更重要。
而”讲一个不错的项目“有时候并不需要”有一个不错的项目“作为前提。
对照你的简历,找到一个相对而言比较好的项目,所谓比较好的项目:
- 有一定的复杂度,方便扩展
- 你在其中承担了比较多的工作,且有一定难度和挑战性
列入如下内容,如果可能,准备文本:
- 具有领域特点的专业词汇及其通俗解释
- 项目的背景和价值,价值最好要关联到应用层面甚至商业化层面。
- 你参与的部分在整个项目中的作用,最忌自己的部分说的清清楚楚,跟其他部分怎么合作一脸懵逼,这是典型的没有大局观,自己把自己当螺丝钉。
- 过程中遇到的困难和解决方案,这部分需要深入挖掘整理,很多同学做事情的时候其实挺困难的,做完以后又云淡风轻觉得不过如此,感觉也没有讲的必要,这是非常不可取的。需要 review 到当时的能力和状态,完整梳理当时为什么会卡壳,都试了哪些错,为什么那些错误的方向不 work,怎么想到正确的方案的,正确的方案为什么 work。
- 从现在的角度出发,回顾项目,提出现存的问题及更优的解法或提升方案。
讲解项目要达到下面的程度:
- 对于没有领域背景,或只有比较通用的、一般的算法知识的人,能够比较轻松的理解你所讲的内容,明确你工作的价值
- 对于比较有经验的人,你能够应对他们提出的挑战
特别是第一条,有的同学把项目的重点总是放在算法细节上,这对于方向跟你一致、背景跟你相似的面试官而言是合适的,但对大部分面试官不合适。我如果连你构建的场景和问题都没有代入,基本上就不用谈对你的算法有什么看法了,更无法理解其中的精妙之处。如果我对你所说的名词没有一个基本认知,连算法都无从谈起。
算法的精妙需要大量的背景和前序知识铺垫,带着面试官进入场景,分析问题,让你的 solution 自然而然浮现,这是比较好的状态。
第二条的练习方式上一篇文章也有提,就是找比较有经验的人去挑战你,给你的解决方案提供一个 alternative 的方案,你来对面试官的方案做评价。
讲得清楚才说明理解的到位,讲不清楚,就是没理解。
0x06:面试:开放问题
开放问题实际上是 AI 算法岗位要面试的重点,由于是开放问题,反而不好做准备,所以这里是比较见功夫的。开放问题主要考察这些内容:
- 业务问题的抽象
- 可行性评估
- 沟通
所谓业务问题的抽象,指的是你能不能抓住主要矛盾,忽略次要矛盾,把一个产品经理提来的,笼统的需求转换为一个算法问题。
所谓可行性评估,指的是对于这个算法问题,你所需要的资源是否是可接受的,你所需要的前置算法是否是存在或满足需求的。
所谓沟通,就是对你所不掌握的情况,你是否会主动确认,在整个解决问题的过程中,与面试官有良性互动。
开放问题还有一个特点,就是如果你答的不错,你自己是知道的,有一种”我的思路很对头“的感觉。
我曾经遇到的一个比较好的开放问题是:某业务希望以发满减红包的形式促进用户回流,问如何设计红包的金额方案在给定预算下拉尽量多的用户回来。
大家可以试试,这个问题我也没有答案,所以不用问我了,自己思考自己评估即可。
另外一个有参考答案的开放问题见苏神的博客 “熵”不起:从熵、最大熵原理到最大熵模型(二) - 科学空间|Scientific Spaces 中提到的快餐店消费分布的估算问题,虽然这不是真实的业务问题,但也绝不是脑筋急转弯。
0x07:面试:应对挑战
挑战包括对项目的挑战,也包括一些意外情况,这里没有套路和技巧了,只有一些方法论。
- 多做铺垫:讲算法先讲思路,讲项目先讲背景。
- 合理推测:也许你不知道准确思路或定义,但你可以合理猜测一个,给出你猜测的理由并寻求验证。
- 实事求是:你永远不知道面试官的知识储备刚好在哪一点上让你踢到铁板,所以不要尝试糊弄他。也许一道没做出来的代码题不会让你挂掉,但“尝试糊弄”这种动机一定会让你挂。
- 无需争执:不要在一个点上与面试官反复拉锯
- 注意细节:细节体现真实,细节体现差异。可以主动提出具体的tricks分享给面试官,千万避免泛泛而谈。
- 坚守本心:能不能接受加班?平常有什么爱好?这种问题与其浪费心思琢磨面试官的意图,不如怎么想的怎么说,是什么样就说什么样。心态就是双向选择,也许当下你的当务之急是不管什么先拿到一个offer再说,但实际上更重要的是找到一个合适的工作。
0x08:尾声
这篇小总结乃是翻某个知乎问题的回答,看了大家哀鸿遍野的感叹,所做的一点个人的小总结。其实我并不参加今年校招,所总结的未必正确。其中有些建议,似更加适合低年级的同学,因为仓促之间难见提升。有些知易行难,因为常年养成的说话做事习惯本性难移,即使想伪装也伪装不来。
真是事到临头才准备,那所能临时补救的,可能也就是八股文和代码题了,在这上面用功倒也无可厚非。
一个算法工程师应该是什么样?我以为这个角色应该是产品中最懂算法的,码农中最懂业务的,科学家中最懂工程的,工程师里最懂理论的。这样一个处在交界地中的角色,既能够有深刻的业务洞察明晰价值,又有足够的工程能力应付落地,又有足够的科学素养调研推导,从而成为一个“擅长理解问题和解决问题”的人。解决业务问题若成为算法工程师之核心价值,那这样的人选该有什么样的素质和天分,该以什么样的题目和形式进行考核,也就不问而知了。