理论与工程
首先,小夕说一下自己目前对理论与工程的理解吧,这也是小夕当前研究理论和熟练工程时主要的出发点。(仅为个人思考,请勿当成真理
理论注重的是学科中各个知识点的大一统,将各种散乱的算法、现象、技巧来归结到一张大网中。这样在新理论、新技术到来的时候,你可以很快的从这张大网中get到新理论、新技术的本质,并将这些创新纳入你的大网,并且可以反思这张网,归结出其中的规律或者疑问,以此为突破点来“灵光一现”出创新的idea,说不定就是一篇轰动学术界的论文。
而工程,或者说用于实现想法的代码,则是对某个理论点的细节化实现。虽然在理论上只需要几个数学公式就描述清楚了,但是用代码实现的话往往充斥着大量细节需要仔细斟酌,一不小心就是一个bug。当然了,一些太过复杂的算法,如最优化算法,一般都在各种优秀的科学计算库里封装好了,调调API就可以了。但是每个工程总是有一些数学细节和小trick需要自己去实现或优化的。在工程里遇到的问题,有时也可以抽象成理论,反思一下或许也是一个改良模型的idea,发个小论文也行呀。
然后,鉴于大家喜欢听故事,就讲讲小夕自己的故事啦。
故事一
小夕是在大二暑假的时候接触的机器学习相关领域。在那之前,是移动计算特别火热的时代,就像现在是个程序员都喜欢吹嘘自己是做机器学习的一样,那时候好像身边的同学(当然包括小夕自己),都喜欢吹嘘自己Android开发/IOS开发多么多么厉害,又上架了一个IOS应用赚了几块钱之类的。
小夕也有幸在那个时代啪了好多代码(哪像现在,没敲多少行代码的就开始坐等几天的模型训练,然后改改参数,又开始坐等了),也因此熟悉了各类平台(linux、android、ios)。
然后那时候,形成的一种错误的思维就是“变成xx开发者/工程师无非就是将xx平台的API熟练一下,然后深入平台、框架的源码”,因此都快把数学丢干净了。
那时每天就是开脑洞,观察生活,搜集idea。然后借助xx语言在xx平台,甚至搬出单片机,来实现这个idea。在这个过程中,小夕发现用代码实现一个想法的时间远小于调试自己的烂代码的时间,于是扎进各种语言和平台的细节里无法自拔。
故事二
大二暑假,在机缘巧合下,被某个老师带去做人脸识别了(那时候实验室里没人知道深度学习是啥),然而小夕还是带着旧思维去做,最终的结果汇报如下:
“老师,这里我用PCA做的,效果还不错。但是我想试试SVD。”
(然后老师很慈爱的在心里默默说了一句“逗逼”。)
“小夕,你讲一下这部分怎么实现的”
“啊,好的。这里用两个for循环就可以了,第一层@#$%&,第二层#$%^&”
“停停停,别讲这些细节,讲原理”
“啊,好的。这里就是先用那个xxx函数预处理一下,然后用这个svm函数训练一个模型,然后调用模型的predict这个api得到结果”
“停停停,讲原理,讲原理!你为什么要用这个算法预处理?你为什么要用svm呢?”
“啊。。。因为我用了opencv里其他完成这个功能的api,效果都没这个好啊”
“@#¥%……%&*(”
没错,这是很真实的一次开会的内容。现在每次想到都深深的尴尬。。。
那时候,深深的感觉到玩弄黑匣子的笨拙,就好像试图用暴力法解决一切算法问题一样笨拙。
故事三
然而,你们没有想到的是,后来,小夕又矫枉过正了。在恶(chong)补(xue)了微积分、线性代数、概率统计后,一头扎入机器学习和图像处理算法无法自拔。以致于半年之内,除了用matlab练了几个小demo外,丝毫没有敲代码。
然后,都是泪...现在真想回大学里跟那位带我做人脸识别的老师说声谢谢。
正文
走上正轨是在上研究生以后,深刻的认识到在这个研究方向上,理论与工程缺一不可。于是摸索出如下自认为比较舒服、效率比较高、不易造成理论或工程断层的方法或原则:
精力划分:理论与工程基本7/3分。
编程语言:一门精,一门辅,剩下的备用。在完全切入这个领域之前,尽量避开C、C++、Java等编程范式或者说编程语言的感觉比较浓厚的编程语言(这句话讲的好奇怪),以防过多的编程语言细节干扰了你对算法的宏观理解,除非已经非常精通那门语言,且确保那门语言有该领域成熟的库。小夕首推精python,辅C++,备用matlab和java。
如何入手一个新算法/新模型:
除非工程任务压得紧,否则在学习一个新算法/新模型时尽量先从数学角度理解透,纳入理论的大网下,再去看形式化的算法过程。
而形式化的算法过程要尽量与数学过程对应起来,如果感觉断层大,要尽量试图找到断层。如果实在找不出,或者精力少,则一定要记下这个断层。
之后就可以用代码去实现形式化的算法了,在这个过程中,就不要再过多纠结它的数学原型了,而是要试图从“感性意义上”去理解算法过程,并且用代码去实现这个感性的算法过程。
如何入手一个新领域:比如你一直在做分类,然后要去做序列标注/预测相关的东西。这时就不是看一个新算法那么简单了,而是要尽量找到相关领域的综述性论文,或者比较权威的书籍,将这个新领域的各种算法概览、解决的任务类型、解决问题的一般化框架/流程给做到了然于胸,然后再去扎进其中具体的算法里。
如何应对紧迫的工程任务:
此时千万不要做一个“完美主义者”(这里是超级贬义词)。比如工程需要,老师让对该领域一无所知的你赶紧实现一个机器学习模型,可不要先看微积分、线代、概率统计,再看机器学习算法原理巴拉的。既没有必要又耽误了任务。
直接按照工程任务的标准找到符合该标准的最成熟的模型/算法,然后去找实现了该算法的库。如果连库都没有,说明要么你找的有问题,要么确实需要很新的算法去解决,那就stackOverFlow寻找新思路+github找代码呀。算法原理什么的,甚至算法的工作流程什么的,不出问题就不用细看,只粗看懂这个算法用在哪里,输入是什么,输出是什么,有哪些参数需要调,大神们说怎么调就可以了,实在不知道怎么调就交叉验证啊(只要数据量不是特别大)。
快速入门一个库或者框架时,切记别上来就啃工具书的第一页。官网的《get start》往往是最好的入门资料,别人写的书籍虽然看起来靠谱、厚实,但是别忘了,书籍作者也仅仅是个使用者,而不是开发这个工具的人,他理解的再深也难免有偏差甚至偏见,最要命的是,这些书籍的作者往往默认为你有一大堆的时间去品他的书,实际上你哪有这些时间啊。因此,官网的《get start》之后,一般对这个新的库或框架就有大概轮廓了,这时边着手将其用在你的工程任务上,边结合官网进一步的指导文档(如果有的话)进一步学习。有条件的话备一本大而全的工具书,没条件的话官网的API文档也足矣,用到哪里查哪里。
完成工程任务后,趁热打铁,记录下本任务过程中遇到的所有的黑匣子。如果黑匣子特别多,就先不要管了,按照第4条如何切入新领域的过程做。如果已对该领域有一定了解,则不妨从这些黑匣子算法或黑匣子框架入手,蔓延开自己的理论大网(经工程练手后的黑匣子会激发特别强的求知欲,往往理解和记忆更加深刻)
都说,真正愿意把看家本领教给你的只有父母和中学老师。然而,其实还有一个人,那就是小夕呀o(≧v≦)o~
当然啦,经验类的东西,有个体差异的,如果发觉小夕的经验让你的情况更糟糕了,赶紧stop,微调甚至舍弃这些方法。