心法利器[21] | 算法在岗3年小结:模型策略篇

【心法利器】

本栏目主要和大家一起讨论近期自己学习的心得和体会,与大家一起成长。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。

往期回顾

  • 心法利器[16] | 向量表征和向量召回

  • 心法利器[17] | 算法服务及其相关配件

  • 心法利器[18] | cqr&ctr:文本匹配的破城长矛

  • 心法利器[19] | 算法问题下模型之外的问题:概述

  • 心法利器[20] | NLU落地场景-智能对话交互

掐指一算,还剩几个月就工作3年了(含实习),时间过得挺快的,接着即将到来的假期,对自己的成长和思路进行了总结,我会分几个角度来总结下自己,并且展望一下自己后续的计划。

  • 模型策略篇。讨论算法方案的思考。

  • 工作思路篇。工作思维,结果导向。

  • 个人成长篇。如何让自己更好地解决更多问题。

这次给大家介绍的是自己在解决特定算法问题下的模型和策略思路上的经验。

懒人目录:

  • 从模型套用到方案设计:模型的套用和调参是不能解决所有问题的。

  • 从单一指标到综合效果:优化不能只盯着一成不变的指标。

  • 从实现本身到可拓展性:开拓思路,思考战胜更多问题的方法。

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

从模型套用到方案设计

在我刚学习机器学习的时候(大概是16、17年的时候吧),踌躇满志,自以为拿到一把屠龙宝刀,自然是想霍霍一下,找到一个问题,开始张罗准备数据,然后就开始整分类了,本以为效果非常好结果不行,手足无措的我开始了效果调优(当时写的还是py2):

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年期、刚入门的自己,这些是思维的提升和觉醒是非常有利于真实能力的提升,模型固然是要学习提升,但是今天聊的种种其实都在告诫我们,不能局限于模型,不能局限于模型,不能局限于模型。

心法利器[21] | 算法在岗3年小结:模型策略篇_第1张图片

你可能感兴趣的:(算法,大数据,编程语言,python,人工智能)