2019年终总结

  2019年, 从研二下学期到研三上学期, 从实习到找工作到写论文投稿, 经历了很多事情. 虽然我不是一个怀旧的人, 但还是有必要在这里记录一下比较难忘的事, 作为经验, 引出接下来的2020年要做的事.
  回忆主要依据Github上的Contribution展开, 可以从下图看到, 主要有五个阶段: 一, 离校实习(2019.01.07-04.15), 这段时间主要是维护在GitLab上的公司repo, 所以Github上的Contribution是一段空白; 二, 返校做硕士课题(04.15-05.31), 做了一个用于多相流流场分割的模型, 这段主要是在维护数据和模型两个独立的repo; 三, 准备秋招(06.01-09.31), 这段时间主要在LeetCode上刷题, 零星的几个Contribution是在维护个人简历的repo; 四, 写文章(10.01-11.01), 这段时间主要在维护论文的LaTexrepo; 五, 投稿(11.01-12.26), 这段时间对硕士课题相关的课题repo有一些修补, 在等待小老板改文章的过程中浪费了很多时间.


  • 实习

  实习的计划其实酝酿了好久, 大概在2018年的暑假就有这个打算了, 但是那时知道自己还缺很多东西, 还需要再积累一段时间. 为了能尽可能多得接触一点计算机相关的知识, 在2018学年里选了几门计算机学院的课程, 一门GPU并行编程课, 一门算法课, 还有其他的几门水课. 到2018年底的时候, 这些课基本上完了, 我觉得自己的发展到瓶颈了. 在课堂上学东西太慢了, 水课占比比较多; 在实验室里也学不到什么东西, 没有什么技术文档的积累, 看似名头很大的老板懂的不多, 与学生之间也没什么指导与交流; 自学的话, 无非是一些经典书籍和Paper、开源社区文档、外网上一些质量比较高的博客和Github上比较热门的一些repo, 能接触到的都看了一遍, 但都止于学习理论, 有点像纸上谈兵, 水上浮萍.
  非科班出身的缺陷一方面在于计算机基础知识的完善程度, 另一方面也在于实验室的项目经验积累. 我曾想借实验室力学相关的方向做个算法相关的交叉课题, 两次去找小老板说想买个GPU供炼丹用, 小老板居然推推搡搡最后也没同意(到2019年底他貌似终于意识到GPU比CPU大规模集群要好使得多时, 才买入GPU). 当时我能接触到的GPU, 只有学校超算中心那儿申请到的一块K80的卡, 每个帐户下好像只有6G显存, 还有就是翻墙到Google Colab的GTX 1080, 连续使用时间超过12个小时还会自动断开. 就这种环境受限、资源受限的情况, 我觉得再这样下去就是在浪费自己的时间. 于是, 决定出去实习.
  2018年12月中旬, 在旷视招聘的微信公众号上投了简历, 经历了一面和二面, 过程比较曲折, 最终比较幸运地拿到了实习offer, 预约的入职时间是2019年01月07号. 入职前几天, 把冬天的衣服和一些书籍打包寄往了北京, 然后踏上了前往北京的高铁. 在入职前还经历了硕士开题, 但那时已经完全把课题的事放到一边了, 想的是先实习找工作, 工作的事确定之后再来忙论文和毕业的事. 有得必有舍, 想要二者兼得我感觉是比较难的, 这个时候就要看有没有舍弃的勇气了.
  入职后, 工位安排在融科四楼, 当时组里还不到40个人, 实习生的工位也都空着, 大概是正值年底, 实习生比较稀缺. 一进去安排做的是视频人脸降噪, 刚开始脑子里是稀里糊涂的, 环境怎么配, 工具怎么用, Pipeline怎么搭, 程序怎么写, 作为一个第一次到互联网工作实习的小白, 适应了好久, 不过好在也有mentor和科大师兄的帮助. 没一段时间后, 就放假过年了, 年前跟崔胖一起去付小姐吃了顿串串, 味道很不错. 当时许的2019年愿望是, 别的啥都不要求, 只求2019找工作顺利, 能拿个好offer, 现在看来, 也基本实现了. 崔胖的愿望是, 工作顺利, 天天开心, 注会考过. 现在看来, 她的注会没过怕是永远的痛了, 哈哈哈.
  再后来, 经历了和同事们一起搭Pipeline, 一起采数据, 一起开组会, 一起维护一个项目repo, 感觉还是学到了很多东西. 也让我明白了, 搞算法的, 需要时刻读Paper, 时刻保持学习状态, CVPR/ICCV/ECCV/NIPs/arXiv上新录用的文章, 外网上新上线的Blog, 跟组里项目相关的都最好拿来读一读, 万一对自己的工作有帮助呢. 而且, 这里的算法, 不单单是指神经网络算法, 还包括很多的经典CV算法, 从原理到改进到实现, 都应该清楚. 搞算法的也不能只单单懂算法, 数据采集、数据标定、数据清洗、模型训练、调参涨点、平台部署, 需要的是先做一名合格的数据工程师、后台开发工程师, 最后才是一名算法工程师. 另外, 如何写好周报、如何做好PPT也很重要, 这里不是说把自己的工作包装得很好去舔领导, 而是说把自己的工作一条条按思路捋清楚总结好, 能让别人能听懂你在做啥(能让别人明白你不是在划水), 也方便自己日后回顾和勘误. 还有一点就是一定不要重复造轮子, 在公司还没有中台的时候, 一定要学会跟同事多沟通多学习, 借点代码过来能让效率提升好多, 当然也有可能会碰到别人来借你的代码, 所以提前地, 代码注释要写好, 要不然被别人看到自己写的像屎一样的代码, 就很不好了. 最后一点, 调整作息, 晚睡晚起, 睡得晚一定也要起得晚, 要不然一整天精神就不好, 工作效率不高, 老人们常说的早睡早起, 那种作息不适合程序员.
  总结一下, 实习给我带来的, 有项目经验上的积累, 有常用开发工具的熟练, 最重要的是, 让我一个小白从”不知道自己不知道”到”知道自己不知道”, 还有很多需要学的东西.

  • 做硕士课题

  之前老板让我做可压缩湍流, 被我拒绝了. 湍流本来就很难, 大规模DNS需要的计算资源实验室根本就不够, 预想到以后老板也不会给任何指导. 写到这里突然就想起一个很搞笑的动图, 名字叫”当老板给了你一个课题方向后”.

  所以我就自己选了个课题方向, 起初是因为在JCP上看到有用神经网络做多孔介质单相流预测的, 我们实验室刚好有做多孔介质多相流的基础, 所以就顺理成章地把二者结合成了现在的课题. 网络模型用的是DeepLab v3+, 只因为图它算是个语义分割领域的SOTA, 其实用什么模型没太大区别, 本质是一个高维不确定性输入到高维输出的映射关系, 能学习到这种映射关系就是有意义的. 难的地方在于, 去哪里搞数据. 流体力学的数据, 大多需要精确数值解或者实验解, 但就这个课题而言不可能做实验, 就只能靠数值计算了. 实验室的老程序还是用FORTRAN 77写的, 算一个流场要用好几个小时, 所以我决定不破不立, 全部重写.
  万幸的是, 在Github上找到了一个用Python+CUDA写的LBM多孔介质多相流程序, 在经过一番魔改之后, 好歹是能产出数据集了, 差不多一个流场三分钟, 两万份数据开10个GPU差不多算四天. 这里要感谢的就是旷视的Brain++, 清一色的GTX 2080 Ti, 如果没去实习的话, 真不知道我这些数据该在哪里才能算出来. 有数据之后, 模型训练就很快了, 一开始碰到的问题是严重过拟合, 已经削减模型容量到24W左右, 数据经过flip增广后有4W, 但依然过拟合. 后来思考了下, 可能我这种数据形式本身就非常容易过拟合, 输入是0/1的二进制图, 网络过早地学到了0对应位置的值是0, 就没有足够的动力去学习1对应位置的值了(其实1对应的位置才是有效区域, 我们并不关心0对应的区域). 后来把学习率降得很低($1\times 10^{-5}$), 在计算图中加了$output *= input$, 相当于加了一个从头到尾的short connection, loss曲线这才收敛, 过拟合得到解决.

  其实做这个课题只用了一个月时间, 到6月初就意识到该准备秋招了, 课题也就先放到一边儿了, 文章也没有正式开始写, 在此之前只零星地写过一部分IntroductionMethodology. 既然一开始决定不读博不走科研这条路, 硕士毕业直接工作就业, 走程序员的道路, 那么在流体力学期刊上发文章这件事也就不那么重要了. 对我以后的工作也没有帮助, 只能说水一篇文章毕业就行, 对文章的要求不高.

  • 秋招

  六月份一整个月都在刷题, 一开始刷得很慢, 只刷了100多道, 还都是easy级别, 把剑指offer也看了一遍, 差不多到六月底了. 准备了一下项目经历和算法基础, 就联系旷视那边说想转正答辩. 面试安排在7月5号, 一面经历了三轮, 每轮都有笔试题, 最后一轮答得很不好. 终面安排在7月12号, 只是聊聊项目和人生就没啥了, 然后就算面试过了. 因为面试得早, 所以一直没有给录用意向书, 直到8月26号才邮件下发了录用意向书. 在这之前真是等得寝食难安, 虽然知道应该是录用了没问题, 但没收到正式的邮件之前总是觉得不安稳. 现在回想一下, 因为面试得比较早, 准备得不是很充分, 题目刷得不够多, 导致面试表现比较差. 但是早也不全是坏处, 到九月份的时候, 算法岗投递人数爆棚的迹象已经显露出来, 组里招人的标准被要求明显提升, 菜鸡可能直接就被刷了.
  想到这儿, 只能说后背一凉, 只能说自己运气稍微好一点, 实力稍微差点儿. 还记得19年年会的时候, 印奇的讲话提到了四个字: “势、命、能、运”, 势是国家和社会大势, 一个人的命运固然要靠个人的奋斗但也要考虑历史的进程, 移动互联网热潮之后是人工智能浪潮, 所以现在才会有这么多的算法岗位放出来, 命是个人在面临命运抉择时做出的选择, 是选择做一名航天工程师还是做一名程序员, 我选择了后者. 能是能力, 运是最后需要的一点点运气. 很神奇, 大家所推崇的”努力”并不在里面, 选择大于努力, 这句话是真理.
  有了offer之后, 在接下来的秋招中就比较从容了, 因为我知道大概率也是最终去旷视了. 继续刷了一些题, 投了一些大厂的岗位, 也参加了一些面试, 大厂的要求跟初创公司不同, 注重编程基本功和计算机体系的基础知识, 我在这点上吃亏不少. 说说几个大厂的面试经历. 百度, 地图算法组, 当时去的西二旗现场面试, 一面面试官出了一些很基础的编程题, 都写出来了, 最终却还是连一面都没过, 推测可能是Coding的最优时间复杂度和空间复杂度没有优化到极致, 还问了一些多进程多线程问题以及Linux操作命令. 没问我算法相关知识, 估计面试官是开发相关的, 面试完让我在旁边等了好一会儿, 最终让HR把我送走了. 出门拍了张照片, 天气真好. 阿里, 一面电话面只有十五分钟, 而且是晚上打来的, 面试官的声音听起来很疲惫. 二面也是电话面, 也是深夜打来的, 聊了一通项目后, 没问什么编程题就结束了, 我问他们哪个部门做什么的, 面试官说做强化学习相关的, 我当时就懂了, 他们是在刷KPI. 腾讯, 深圳那边打来的电话, 面试官说我笔试成绩不错, 愿不愿意来深圳之类的, 我说除北京外不考虑, 也就没有然后了. 就这样, BAT一轮游.

  算法岗确实投递人数爆棚, 竞争很激烈, 需要的是实力, 另外也要看简历所到组的方向与个人简历方向是否契合, 这个也得看运气. 经历过秋招之后回头看, 觉得还是开发岗需求最大, 大家都一窝蜂扎堆算法了, C++/JAVA开发岗就空出来了, Web/IOS/Android开发岗人就更少了. 而且算法岗这几年也存在泡沫, 供大于求, 试探性的业务铺的很开, 赚钱的没有几个, 等潮水褪去了, 一定会有一波人员优化. 如果让我再选一次的话, 我肯定就往C++/JAVA开发上转了, 其实开发的门槛一点儿也不低, 需要的基础知识比算法岗更加全面, 所需要付出的时间成本和知识成本更多. 相反算法岗对计算机知识体系的广度要求没那么严格, 才会引得那么多非科班的学生趁风口疯狂想转行.
  仔细想想, 互联网面试无非就俩, 一个项目, 一个Coding. 项目经历是靠在面试前很长一段时间内积累的, 短期内无法改变. 所以准备面试无非就是刷题. 记录一下自己的LeetCode刷题情况. 共刷259道, 其中easy110道, middle139道, hard10道, 这里面不少经典题都反复刷过, 也按照专题类型刷过(如动态规划、回溯算法), 也按高频热点刷过, 虽然比不上刷了一千多题的大佬, 但常见的高频题基本都覆盖到了. 也归纳总结过一份刷题笔记放在OneNote上(有空可以迁移到本站, tbd). 听过很多道理, 却依然过不好这一生. 无奈刷过一些题, 却也依然写不好笔试的Coding. 只能说, 这个真得看智商, 看运气, 还得看刷题的耐性. 以后肯定还得不时刷刷题, 只是不能再像以前那样用Python刷了, 碰到的大部分面试官都要求用C++写底层, 这一点我没有做好, 所以以后C++的使用要增强.

  • 写文章及投稿

  10月1号起, 就没怎么投简历和接面试了, 主要精力开始放在论文的写作上. 一开始没有太多英文写作的经验, 写得比较慢比较艰难. 到后来慢慢熟悉了基本句式, 写得就快起来了. 熬过几次夜, 最晚也就到凌晨1:30, 第二天睡到早上9:30起, 还算比较精神. 写完初稿之后, 没有立马交给老板看, 而是先给了几位师兄看, 师兄们指出了一些基本的写作错误, 提了一些结构上的意见, 然后接着我再来修改. 改了有两三版之后, 我决定正式发给老板看, 那会儿刚好是11月1日. 之后就开始了漫长的等待, 论文是小老板给改的, 当时他那儿堆了有二三篇文章要改, 所以只能排队. 大概过了两周之后小老板才把Introduction改完, 告诉我说你这个文章写法不对, 很啰嗦, 太长的句子理解起来容易有歧义, 且读起来让人没有耐心, 尽量用断句代替长句, 从句也尽量截断, 用首尾承接的It、They、And来造短句. 中文的写作可以用长句, 但是英文的写作尽量越短越好. 我照着短句的要求改完一遍之后, 小老板才正式花时间来改我的文章了.

  最难的地方在于, 小老板不懂深度学习那套理论, 所以文中很多地方都需要给他解释一遍让他懂, 然后才能改得下去, 所以就改得很慢. 而且只能在我原文的基础上, 按照我想表达的意思来重新表述一遍. 对写作内容并没有太大的改动, 基本上一开始的文章结构就没动过, 我曾一度怀疑文章内容是否还需要增删, 奈何小老板也不懂, 只能凭我自己的判断, 所以文章是啥水平我是没有底的. 小老板比较忙, 中间还掺杂着项目的事儿, 催了几次, 终于在12月11日投了出去. 投的是流体力学排名第四的SCI期刊”Computer and Fluids”, 小老板信心满满地说一定能中, 结果四天后收到主编的拒信, 还没送审直接在他那儿就给毙了. 给的理由是不符合本刊的内容范围, 没有涉及新数值算法或者流动机理的分析, 也就是说主编觉得神经网络这个东西, 没有什么显式的数学过程, 做出来的结果也不涉及到流动机理分析, 直接不予接收. 说实话, 这个结果, 我反而是很高兴的. 因为没有因为送审而耽误大量的时间, 拒了之后转投其他容易点儿的期刊也就顺理成章, 这正是我想要的.
  从师兄那儿听说实验室往年有向”Advances in Applied Mathematics and Mechanics”投稿的, 于是打算往那儿投, 只是老板不愿意挂名罢了, 这个倒无所谓. 花了两天时间修改模板、参考文献的格式和一些细节, 于12月18号发给了小老板. 但是他比较忙, 中间同主编联系也花了一段时间, 拖了好久催了几次才在12月26号正式投了出去. 这时碰上外国的圣诞及新年假期, 所以编辑部还一直没有处理. 不过既然投出去了, 就已经不着急了.
  通过写文章给我的感受是, 写英文一定要表述简单清晰. 不同于中文写作, 英文写作要的就是大白话. 另外, 因为参考了一些计算机会议上的文章, 所以写作风格有点倾向于计算机方向, 而偏离了注重建立数理过程的流体力学方向, 没有显式的数学理论推导, 写出来的文章不容易被搞流体的人所接受, 这可能也是一开始被拒稿的原因. 文章早写早投, 不过既然在一开始就早早地计划好了先工作再文章的思路, 那么现在的情况也算是在计划之中, 没有耽误太多时间.

  • 接下来的计划

  这一年, 上半年忙秋招, 下半年忙文章, 虽然过程有些波折坎坷, 但是走过来之后发现一切都如计划所愿. 如愿地转行到计算机行业, 如愿地完成论文写作并投了出去, 这一整年, 就做了这两件重要的事. 当然, 这都只是开始, 拿到offer只能说是拿到转行上车的车票, 以后的发展还有太多要学习的地方; 文章投了, 还有第二部分课题工作的完善以及毕业论文的写作, 然后等待毕业答辩. 所以在此留下2020年的计划:

  1. 硕士课题上, 在第一部份工作的基础上, 完善第二部分工作(拓展至任意时刻动态流场的预测). 可以的话, 应该尝试探索一下: Visual attention的加入, Physics informed Loss的加入, Weighted Loss in front/throat的加入, 考虑Wettability的流场数据.
  2. 硕士毕业论文的写作. 至少需要两部分的工作, 要吸取上一次投稿的经验, 在文中多加一些确定性的数学原理描述, 多一些基础知识, 多一些公式, 多一些验证对比实验. 早写早舒服.
  3. 坚持阅读CV方向的Paper, 坚持在博客上记录的习惯. ISP组的业务需求对应的算法主要有以下几块: HDR、Super resolution、Denoising、Align&Merge, 要在入职前将这几个方向的经典Paper以及最新发表的SOTA算法全部读完, 并且归纳记录. 针对传统算法, 最好能使用C++复现. CV组内的一些其他方向: Segmentation、Inpainting、GAN、Landmark也需要熟悉经典的算法. OpenCV上一些好的API文档也值得学习和复现. 模型量化与压缩, 这个迟早都会碰上, 相关领域的Paper也需要了解.
  4. C++的使用和学习. C++光看书本感觉只能纸上谈兵, 还是要在项目实操中才能学习到C++的精髓. 以前一直苦于没有合适的项目, 现在的目标是使用C++实现CV方向经典的算法. 要在入职前熟练使用C++的基本语法, 长远的目标是成为一名C++开发者, 要不然等算法浪潮褪去时, 就只能裸泳了.
  5. Be happy. 保持健康的身体, 保持愉快的心情, 这两件事是最重要的. 可以晚睡, 但也一定要晚起. 可以追求地稍微多一点, 但也一定要保持轻松愉快的心情.

「评论区」: