算法工程师的深度经验总结!

2023-09-27 09:26:30 浏览数 (1)

作者丨机智的叉烧@知乎(已授权)

来源丨https://zhuanlan.zhihu.com/p/453800419

编辑丨极市平台

导读

作者对自己的成长和思路进行了总结,总共分了三个角度:模型策略、工作思路以及个人成长来总结自己在算法岗位三年的心得体会。

目录:

  • 模型策略篇。讨论算法方案的思考。
  • 工作思路篇。工作思维,结果导向。
  • 个人成长篇。如何让自己更好地解决更多问题。

模型策略篇

  • 从模型套用到方案设计:模型的套用和调参是不能解决所有问题的。
  • 从单一指标到综合效果:优化不能只盯着一成不变的指标。
  • 从实现本身到可拓展性:开拓思路,思考战胜更多问题的方法。

预警,有些东西可能比较扎心,说的是我自己的经历,大家有则改之无则加勉。

从模型套用到方案设计

这次给大家介绍的是自己在解决特定算法问题下的模型和策略思路上的经验。在我刚学习机器学习的时候(大概是16、17年的时候吧),踌躇满志,自以为拿到一把屠龙宝刀,自然是想霍霍一下,找到一个问题,开始张罗准备数据,然后就开始整分类了,本以为效果非常好结果不行,手足无措的我开始了效果调优(当时写的还是py2):

代码语言:javascript复制
X_train, X_test, y_train, y_test = train_test_split(textVectorList, YUse, test_size=0.33, random_state=10)
maxDepthArrary=[10,20,30,40,50,80,100]
nEstimatorsArrary=[10,50,100,300,500]
learningRateArrary=[0.2,0.4,0.6,0.8,1,1.2,1.4,1.6,1.8,2.0]
paraResult=[]
startAllTime = datetime.datetime.now()
for maxDepth in maxDepthArrary:
    for nEstimators in nEstimatorsArrary:
        for learningRate in learningRateArrary:
            startTime = datetime.datetime.now()
            print 'maxDepth:' str(maxDepth) ',nEstimators:' str(nEstimators) ',learningRate:' str(learningRate)
            clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=maxDepth),
                                     algorithm="SAMME",
                                     n_estimators=nEstimators, learning_rate=learningRate)
            clf.fit(X_train, y_train)

            score=clf.score(X_test,y_test)
            print '计算精度:' str(score)

            paraResultItem={}
            paraResultItem['maxDepth']=maxDepth
            paraResultItem['nEstimators']=nEstimators
            paraResultItem['learningRate']=learningRate
            paraResultItem['score']=score
            paraResult.append(paraResultItem)
            endTime = datetime.datetime.now()
            print endTime - startTime

print paraResult
endAllTime = datetime.datetime.now()
print endAllTime - startAllTime
print '程序真的结束了'
print '程序结束'

没错,还是手动调参,非常暴力。

运气好,找到一个比较不错的调参结果,但问题是,后续可不是每次都这么好运了。

这件事之后一直在反思一个点,就是这种调参到底是否健康合理,于是逐步走的方向是,挖掘问题、解决问题的道路,从而逐步摆脱“调参师”、“调包侠”的流程,这里我要感谢很多工作中的导师,出于隐私的原因我这里就不说名字了,懂得大家都懂。

那么正确的方式是什么呢,最简单的就是让自己的思路从使用特定方法来解决问题转移到为了解决问题设计特定方案,这点能让自己从模型本身跳出,把模型当做是自己解决问题的工具(这个在哲学上应该叫工具主义,不说对不对,至少这个思想更符合日常工作的需求),而不是我要去用这个模型。

举个例子,收到一个需求,要做文本分类,那我就要去了解问题,例如看数据、看文档,充分了解数据后设计解决方案,来尽可能又好又快地解决问题,我们的目标就很明确,是一个特定的文本分类问题,深度学习也好,规则词典也罢,我们要解决问题。

于是这里会引申出一个比较关键的能力:自己手里到底有多少方法。首先,方法不多,只知道上面的模型的话,是很难支持你为问题设计方案的,因为设计方案是一个选择的过程,没有足够的方法知识支撑,何来选择。其次,这个阶段我们了解问题的核心是找方法,我们了解问题的方向其实就是套用方法的方向,自己手里的方案是指导自己了解问题一个重要方向标,如果简单规则这个方法你没有掌握,你根本不会思考这个问题是不是一个规则就能解决。第三,方法的多少和质量决定了你能解决问题的程度,这个和集思广益思路一致,多人想,自然更容易想到更好的方法,更多的方法支撑你是否能想到足够好的方法。

所以,很多人问的一个问题:为什么大家工作之后还要持续学习持续看论文,答案很明显,就是扩充自己的知识面,以便解决更多更多复杂的问题,这个点放在很多领域都是正确的。

回到小标题本身,大家在成长的过程中,要逐步从模型套用解脱出来,不纠结于模型本身,考虑问题的解决方法,你会发现你成长了一大截。

扎心的话来了:如果给定一个问题,你张口就来一个方法,这时候记得反思自己是不是只会这个方法。

从单一指标到综合效果

指标是评价一个问题解决的重要手段,这点应该是毋庸置疑的,但是评价一个问题解决的手段能局限在几个指标里,而是应该多看几种甚至是为了观测某些问题情况去设计一些自己需要的指标。

现在有1个病人,99个正常人,现在我手里有一个判断人是否得病的手段,结果是所有人都正常,我们很容易算出准确率是99%,明眼人很容易看出来这个99%里面充满了水分,因为病人压根没检测出来,于是我们还要进一步设计一些指标来表达这个问题,于是我们设计了召回率,召回率显示我们能找到的病人占比为0%,于是轻松表达了这个问题。

这个问题的理解非常简单,但是道理却很深刻,我们需要明白的是,指标不是我们算法的目标,而是一个表达问题的方法是,我们借助指标来了解自己的问题现状如何,从而保证我们达到目标,我们最终追求的其实是一个比较模糊的东西——“综合效果”。

综合效果是什么?对于推荐系统,可能是用户的点击率,停留时间等,对于对话系统,可以是需求的满足率,可以是和用户的平均多轮次数,可以是对话任务的完成率,我们是通过观测这些指标,来判断我们需要怎么优化我们的方案,例如点击率高停留时间低,可能就要评估是不是要处理一下标题党,点击率本身就不高,是不是因为推荐的东西用户不喜欢等,最终,其实我们的综合效果是各种维度指标的全面提升,当然这不容易,但确实我们各个领域算法工程师所追求的。

另外需要讨论的两个关键点,是指标标准和评测集,这两个点直接影响的是指标的表达能力,最终影响我们对问题的判断。

首先是指标标准,举个例子,文本分类,什么叫做“天气”意图,我们需要有一个尽可能明确清晰的边界去划定什么是天气,或者什么不是天气,只有这个判断清楚了,指标才可能正确,因此,这值得我们花费很多时间来保证这个点。

然后是评测集,由于大部分指标的计算来源于大量的数据,即评测集,因此在这里谈评测集,是希望大家关注评测集的数量、分布、质量,这些方面的合理性才能支撑指标的准确,乃至对效果的评估。

因此回到问题,单一指标到综合效果,我们作为一名算法,虽然面向的是指标优化,但是我们最终希望得到的是综合效果比较好,这要求我们把思路打开,而又因为综合效果是依赖各种指标来表现的,因此我们要关注指标的构成,关键就是指标标准和评测集。

科研可能会让很多学生都关注于指标,指标的提升能带来论文(真实),但实际应用中太关注于指标可能会把你带到沟里去。

从实现本身到可拓展性

开始我只是接受老师、领导给出的任务,这个任务往往比较明确,问题给到我,甚至把解决方案都告诉我了,然后按着写代码就完事了,这个事情确实很简单,一般按部就班的就能完成,但逐步发现,很多时候完成任务并不是任务本身,很多时候还包含了很多没有在明面上。

  • 代码是否具备可读性和可拓展性。这是每一位工程师,不局限于算法工程师。
  • 思考方案是否具备通用性,是否可以用比较稳定可靠的方式来完成相似的任务,一方面可以平台化中台化,另一方面对自己则是可以把一些算法任务变成一个工程任务,提升效率降低风险,毕竟算法本身的项目风险较高,一不小心效果出问题就会延期。

前者其实是比较基本的开发能力,写代码,为了团队合作,为了自己日后的维护,代码要规范,很多设计的细节需要考虑到:

  • 命名、注释是否具有可读性。
  • 函数意识,很多重用的、结构复杂的东西,需要构造成类,这个能力对于面向过程入门的python同学,是非常需要培养的。
  • 工程服务的一些常见操作需要学习到,例如怎么向外提供服务、怎么热更新、怎么打日志等。
  • 服务性能的考虑,一些动不动上bert的同学,需要考虑这些问题哈~

至于后者,则是一个对解决问题更高的要求,就是你能不能想出一个类似问题都能解决的方案。

  • 这一类的问题都具有什么特点。
  • 有没有什么能够相似问题都用的模型、词典。
  • 在此基础上,设计好构造脚本,能快速完成。

不仅要学会打败一个人的方法,还需要学习打败一万个人的方法。

小结

洋洋洒洒快3千字了(em...有一大部分是代码),是一些自己在算法策略上的一些新的思路和总结,这些都有别于1年期、刚入门的自己,这些是思维的提升和觉醒是非常有利于真实能力的提升,模型固然是要学习提升,但是今天聊的种种其实都在告诫我们,不能局限于模型,不能局限于模型,不能局限于模型。

工作思路篇

算法工程师是职场内的岗位之一,从新人走来,自己是要负责或大或小的项目推进的,因此,如何在工作中保证自己的工作能正常推进将是不仅算法需要掌握的必修课,所以在模型思路之外,特地安排了一期有关工作思路相关的讨论。

从完成任务到解决问题

培养新人的其中一个思路是在基础比较扎实的前提下,开始给新人一些简单任务实践,让新人干中学,我就是从这么一个新人走过来的。

那么,接受的这种任务,一般都是比较明确的,类似新手村任务,任务中会告诉你怎么操作,教着你一步一步完成任务,但是随着时间发展,你成长起来后分配给你的任务可能就没有那么多支持了,给到你手里的可能就是一个问题,一个或模糊或清晰的问题,但是往往不能给到你什么思路,这时候需要你自己去思考怎样才能解决这个问题。

能到这个程度,一定情况说明老大是认可你的能力的,应该值得高兴,但是要时刻有一些意识:

  • 就是你手里的方法不够多的时候是无法解决问题的,我们不能沉迷与几个baseline模型,不能说想几条规则就完成,我们要持续去积累。
  • 思路从模型本身打开去,尽可能让自己脑子里有一个比较完整的解决方案,训练的数据怎么来,离线的模型怎么训,训练完成后模型在线怎么用,数据流怎么流进来的,接口协议怎么样,自己能想的越完整越好,总有一刻独当一面的时候你要解决这些所有大大小小的问题。
  • 机器和模型都是死的,人是活的,上下游的沟通要自己尝试去达成,不要等,主动负责起来。

从被动到主动

上面一点提到要把事情主动负责起来,需要展开说一下,这个非常重要。

从小大大,老师教知识,布置作业,我们都是被动的接受,哪怕到了大学很多人都还是比较安分地完成任务就行,但是未来的日子可不能这样,要是真的想把事情做好,想做自己想做的事,首先就是要主动,主动推进自己想做的事,无论是科研上需要自己主动阅读论文,还是工作上主动学习,主动推进某一件事,当一件事情推进不太顺利的时候,要自己主动找解决方案,找相关负责人,把这件事推进下去。

要主动,首先自己要明确问题和当前的难点,然后开始找解决方案,比较容易想到的是自己解决,但自己解决终究会有限制,例如技术上的难题、跨团队沟通等,需要自己的老大或者其他团队的大佬帮忙解决,此时自己要找到对应的人主动沟通,尽快推进处理,这种方式能更加有效地把事情搞定。

从学习到调研

大学以来,自己的学习更多是出于兴趣,以及后续的一些可能面对的工作压力,自己会去学习,看大量相关的技术文章,并且自由地开始进行尝试,这可以说是一个有点压力但还算轻松愉快的过程。

到了工作后,虽说加班不算严重,但是能自由学习的时间终究是被大大压缩,而吸收知识的形式,更多地是变成一种调研的方式。调研和学习的区别在于,调研的目的性会更加明确,而且是后续是要求落地的,所以要找的方案需要是能够快速可靠地实现,考虑到场景特定,我们可能还要加一些场景特定的策略,那我们在有限时间下就需要保证我们调研的主干方法不是短板。

那么调研的方式和学习,其实非常接近:

  • 读论文、读博客、读代码。

有的时候可能要出一份调研报告,总结技术相关的发展情况,介绍一下方法,这样一份文档下来,无论是自己还是老大,其实都对有关技术了解了。

这个过程对工作算是调研对自己其实也是一种学习和成熟,调研过程中自己也经常思考,这些方法的思路和设计原因是什么,这都很有利于自己后续方案设计的思考。

从点到面

学校可言一个比较尴尬的点就是,都是对点的研究,更可怕的是我们对这个点还不一定就很深。但是到了工作中,要求的很可能就不是会一个点就够了。

到你手里的可能是一个比较完整的任务,例如完整某个技能,那你需要会的就不只是一个文本分类、文本匹配就够了,你还要知道数据怎么处理会比较好,会比较方便,另一方面,要从聚焦于模型算法的思路扩展到工程、性能等的一些其实算法也应该考虑的技能技术上,广度在日常工作同样非常重要。

当然,这并不意味着就不需要关注深度,论文要跟,实验要尝试,我们仍要持续学习,持续分析,一技之长是自己突出拔尖的重要因素。

从模型到技术

无论是学校里做科研,还是在入门过程,我们毫无例外的首先接触的就是各种各样的模型,这导致我们在方案选择的时候只能想到模型,在效果不好的时候只能想在模型修改上,但是实际上我们还有大量可以学、需要学的东西。

  • 在效果调优上,规则词典的方式,模型组合的方式,算法架构的整体设计等。
  • 工程技术上,数据库类技术(mysql、redis等),大数据技术(hadoop、hdfs、hive),各种网络技术(http、grpc,以及zookeeper等),还有好多。

所以,借助工作实践,我们能扩大自己的知识面,让自己知道了很多自己原来压根就没听过的东西,我们都可以学起来。

模型固然要持续学习,但是工作中我们还需要用到大量的技术,有时间我们要把各种相关技术拾起,逐步成长起来。

独立思考

信息时代的我们其实并不非常缺乏足够我们决策的信息,我们实际上缺少的是辨别信息的能力,识别什么是有效信息,什么是可靠的信息,什么是我们需要的信息。有关独立思考我能写一篇很长的文章,后续我会聊,这里简单展开。

所谓的独立思考,其实是一种特质,在信息时代其实尤为重要,他是一种甄别信息的意识和能力,我们能在大量信息中查询或者筛选出自己需要的信息,这时候需要我们有明确的、主动的目标,从而能让我们从奶头乐、贩卖焦虑、错误冗余信息从解脱出来。

所谓的奶头乐,其实是一种简单的乐趣,当然我们生活中需要这种乐趣,但是不能任由这种乐趣充斥我们的世界,如我们在一些学习的时候不能被这个给带走了。

贩卖焦虑应该是我们这行最容易陷入的东西了,就是所谓的内卷。说实话,焦虑是真的焦虑,但是我们需要考虑这个东西其实应该更理性,我干脆展开聊得了,我们要思考的是这个问题:

  • 我到底是不是真的有问题,这个问题是否真的发生在我身上,要认清自己,明确问题。
  • 我们需要解决的不是焦虑本身,而是根源,很多人容易陷入这里,而我们需要的是行动,很多人的处理方式只是给自己一个安慰,并不是处理焦虑的根源,那焦虑会持续存在。
  • 不要被情绪所影响,解决问题,解决问题,解决问题。
  • 焦虑是看参照物的,平淡的我们不一定每天都和清北的比,我很坦然,现阶段要我年薪100w也是不太可能的,我只希望能比之前的自己强一些,成长一些,足够了。
  • 事情的发展总有过程,自己要有规划,或长或短,只要路径正确,自己一步一步走,基本没什么问题,所以我们需要正确的方向、正确的路线以及坚定路线的信心,有一个说法叫做“路线自信”。
  • 被报道多的,应该是更少的事,而不是多的。例如知乎上不是人均211985,首先具备发完整文章能力的人真的不多(这个是真的),其次混得不好的人大都不太会出来丢人现眼;例如年薪50w、100w的人被拿出来晒,托福110、120的被拿出来晒,为什么拿出来炫耀,因为值得炫耀,为什么值得炫耀,因为大家都没有,这么说懂了吧,想想自己在朋友圈放的,是不是都是不怎么平常的东西。所以不要被铺天盖地的这种信息给骗了。

错误冗余的信息经常会影响我们的判断,网上很多舆论带节奏能带起来就是因为这个,我们需要甄别,一方面我们自己要足调研,另一方面我们自己要有足够的知识储备,这些东西越多,我们能甄别的能力就越强。

小结

说实话,第三年末期自己的可见成长其实不是很大了,好像是到了一个瓶颈,这个瓶颈让自己多少会看不到进步的方向,但是近期盘算下来,其实只不过是因为有些东西不太好总结罢了,很模糊,和会了一个两个模型完全不同,有一些开悟的感觉,这种开悟不见得是在解决某一两个问题上,而是一系列问题上。

如果很早之前自己学的是武术,能打败一两个人甚至几个人,而现在学的是兵法,能打败的可能是一个军队,项羽本纪中有一段“剑一人敌,不足学,学万人敌”,“学万人敌”的重要性在此刻能逐步明白。

个人成长篇

技术人,还要一直做技术,总需要持续各级各个技术的发展,同时也要花时间来点亮自己的各个技能项,所以持续的学习成长就是必要的。

有关算法模型类

算法模型相关是算法工程师的必修课,我们需要更新自己的知识,完善自己的装备库武器库,从而保证甚至是提升自己的能力。

首先是基本的模型方案学习,虽如我经常谈到的,我们日常应用中使用模型的情况并不多,但是我依旧建议大家还是要持续看模型方面的论文和文章,原因不只是让大家学会这些模型方案,而是通过模型我们能吸收到的是我们日常其实能遇到的问题以及他的解决方案,问题我们是经常遇到,而方法确实多种多样的,我们要能和作者产生首先共鸣是我和他能遇到相似的问题,然后是我们看看是否可以借鉴他的方式或者是用什么降级或者升级方案来解决他的问题。

然后是完整的技术方案,非常建议大家好好看一下。这些资料大都来源于大厂的分享,一般大厂的分享会给大家介绍的都是一大个项目的完整方案,例如我的[前沿重器]栏目中就给大家介绍了不少,这些完整的技术方案其实为大家做技术设计提供了很多建议,同时也让大家的水平和大局观有提升,从小项目小问题的解决提升为更大项目的技术实现,这其实对个人晋升有很大好处。当然除此之外,自己所在项目相关的技术方案和整体架构也尽可能熟悉清楚,这会让自己对技术设计的敏感度有新的提升。

多看数据。众所周知算法项目本身是一个数据依赖性特别严重的,而且最终的算法效果也会随着数据的变化会产生变化,因此只有我们更加熟悉数据、了解数据,才能够更好地完善我们的数据方案。因此经常阅读数据是非常有利于解决问题的,另一方面读数据其实也对我们理解数据的能力有帮助,为什么会有人问为啥我看数据看不出问题,一定原因就和看数据不够有关,看的数据不够对比不出数据的特色,这个和看人识物一样的。建议产品经理也多看看,很多时候问题都反馈应在数据里,无论是单条的数据还是整体数据分布。

多实践。很多问题实践才会被暴露,对某些方法的理解才能得以加深,因此,我们在各种阅读吸收知识的同时,要记得多实践,对比多个方法之前的优缺点,这些优缺点的提炼其实非常有利于我们后续需要考虑的方案选择。

有关工程技术类

算法工程师是怎么都避不开工程的,这个入行后的各位应该都有所感受,而没入行的各位也需要时刻明白这点。而为了更好地应对这个问题,我们需要做的就是提升自己的工程能力。

总的来说,工作后我花了大概一年半的时间来集中补充工程方面的能力和知识,这个阶段的整体学习虽然让算法这块小幅度落后,但是工程这块不再成为短板,还算值得,我来简单聊聊我是怎么做的,我的思路是这几点:

  • 以工作为起点,去查询自己缺漏的技术点,然后按时学习。例如git、c /java、shell、hadoop大礼包相关,这些工作中经常遇到的一定要尽快学习起来。
  • 官方文档结合网上的教程,快速get起来是关键。
  • 通过工作来验证自己的技术,增强技术信心。

我们都知道我们的专长在于解决算法问题,但这不代表所有的工程问题都要丢给工程,或者说不见得所有工程都可以丢给工程做,例如一些数据流的操作,为了不太依赖工程,其实我们需要自己多掌握一些,从而保证很多事情的推进不依赖别人,同时自己的技术也有提升,这对于晋升还是有用的。

有关工作技能的成长

很多时候,我们会发现有些事情的进展不佳,不是因为我们的技术不行,而是一些诸如沟通、项目管理等问题导致,因此我们可以沉迷技术,其实还可以多读一些管理学、经济学甚至哲学之类的书籍来提升自己,这种学习我一般是当做闲书来看,平时轻松愉快地阅读一下其实也挺不错的,这块毕竟不是我们现阶段的重点,我不展开啦~

学习时间的安排

说实话,学习的时间真的被压缩到很少很少,比较无奈是正常的,我通常的学习时间就是通勤、晚上回家的时间,另外是工作过程有一些调研和方案分析的时候我们是可以借此来学习的,不要太说没时间,大部分时间都是因为自己摸鱼给浪费了。

另外还有一个比较关键的事情就是要学会总结和积累,有一个比较合理的笔记库,通过这个笔记库记录自己做过的事情,总结沉淀下来就是自己的东西了,此时很多东西能被快速记录从而实现快速成长,通过这种方式的成长在新人期其实收获会非常大,所以非常建议大家花点时间把基础的笔记体系建立起来。

小结

一连3篇的小结到此结束,这也算是自己的一个里程碑式的结点吧,毕竟没想到自己已经是一个3年的老人了,新人光环逐渐散去,很多事情也要开始独当一面,当然工作中会遇到很多困难,但是这些没打倒我的最终都会成为我的养料。

0 人点赞