###1.前言 — 程序员是一个知识更新较为迅速的一个职业,这个行业的知识的更新速度,有的时候会超过你的学习速度。大部分的人都在不断的更新自己的知识体系,这里笔者要向读者安利一下机器学习(包含深度学习)的重要性,以及常见的知识。作为个人能力的提升,笔者觉得这一点是程序猿/媛,需要掌握的一想技能。 其实在互联网公司工作过的同学都应该有这样的感触,我们正在从IT到DT的转型,算法在应用中变得越来越重要了。
处在向DT转型中的我们也就理所当然的需要掌握DT的核心——算法。外界将大数据吵得如火如荼,但对于业内人来说,这些东西只是吵概念而已,简单的大数据是没有太大意义的,数据就好比是发动机运转需要的燃料,而算法则是发动机。只有有了发动机数据才能发挥它的价值。就像石油已经在地下沉睡千万年,在发动机产生前并没有人认识到它的价值,但发动机产生后,石油才成为像黄金一样珍贵的东西。所以我们必须掌握算法知识才能更好的驾驭DT这辆战车。
然而在实际的工作中所谓的算法工程师,实际上大部分应该叫做“算法应用工程师”,很少有算法工程师能够产生自己的算法。我这么说肯定有人要拍砖,但实际上确实是这样的。比如做一些分类问题用逻辑回归、SVM等常用算法,对于一些复杂问题,如图像分类用CNN处理,稍微复杂一点的NLP问题用RNN处理。很多算法工程师日常工作大部分用在数据处理、训练数据集选择、校验数据集选择等,不断的调节参数从而获得较好的效果。这里不是诋毁那些努力工作的算法同学,我在研究生的时候也是搞机器学习的,工作后,先搞工程、又混合着搞算法,如分类问题,类目映射(将A网站的商品映射到B网站的类目下)、接着搞NLP(基于RNN和CRF做slotfilling)…,接着又搞工程…。我想说的是算法没我们认为的那么复杂,但实际上又远比我们认识的复杂。
为什么说算法不复杂却又很复杂?其实这并不矛盾。说其不复杂是因为我们不必完全掌握背后复杂的公式推导,只需要知道背后的物理意义、知道响应的算法或模型适合处理的问题、知道如何调节相关的参数等即可。说其复杂是因为背后的推导确实很麻烦,就拿常用的SVM算法来说,读书的时候硬生生的是照着PPT推导了一周才推导成功(也反映出自己数学基础有点渣)…。继续说复杂性,要非常纯熟的掌握相应算法的核心,需要对线性代数、概率、微积分等重要的数学知识掌握和理解的较为透彻。这里不得不说我们的大学里相关的数学教育,感觉线性代数、概率、微积分讲得不彻底,只是学了知识点但背后的物理意义却没能讲清楚,比如矩阵相关运算的物理意义就是在实际的算法中才体会到的,数学真应该让计算机老师来讲。话说的有点多,但对于程序员来说我觉得数学知识必须要学的扎实,特别对于学校中的学生来说,其他课程可以不太用心,但数学相关必须牢牢地掌握,要用心,特别要掌握其背后的物理意义。
为什么我们要掌握算法呢?首先感觉是因为环境的变化,因为算法变得越来越重要,如之前的新闻,谷歌转型:把2.5万工程师变成机器学习专家,google都已经走在前列了,也足见机器学习越来越重要了。现在很多产品,工程只是对算法进行包装,很多产品的核心是算法,如滴滴、Uber。
其次,工程师懂算法,真的有点像流氓会武术,谁也拦不住了。一方面增加自己的核心竞争力,另一方面在团队沟通的时候也更加方便。很多算法工程师的架构、系统能力不足,如果工程师懂得算法,那么可以和算法同学顺畅沟通,有助于产品或项目的实现。
最后,对于在校生、再找工作、毕业生或者刚工作的同学,能够掌握机器学习的基本知识能够增加你的核心竞争力,在竞争面前更容易脱颖而出(特别是在面试的时候,不一定要有实战经验,你能讲的清楚也是很不错的)。
总之,个人觉得,对于工程师而言,学习机器学习相关算法是提升个人核心竞争力的重要一步。那么接下来笔者就在这里进一步阐述作为工程师应该掌握哪些相关算法、如何去学习相关算法。
###2.基础知识 — #####2.1 线性代数基础知识 个人觉得线性代数知识是在工作中用的最广的大学知识,特别是矩阵相关知识在实际应用中使用最为广泛。但从个人经验看,很多毕业生对于线性代数特别是矩阵相关知识掌握的很肤浅,对矩阵的理解很不到位,曾经问过一些毕业生,对于矩阵的SVD很多人会解,但背后的物理意义却模糊不清。 讲义链接:[Linear Algebra Review and Reference](http://ai-coder.com/batbus/pdf/cs229-linalg.pdf) #####2.2 概率基础知识 概率知识是也是实际工作中使用较为广泛的知识,从BAT的笔试题中可以看出,概率计算基本是逢考比用的。其中较为常用的就是贝叶斯定理了,在复习这部分的知识的时候,一定要弄清楚相关定理的前置条件。 讲义链接:[Review of Probability Theory](http://ai-coder.com/batbus/pdf/cs229-prob.pdf) #####2.3 凸优化 在许多机器学习算法中,我们最终是求一个目标函数的最大值或最小值,很多时候这种问题最终归咎为目标函数的优化问题,实质是一种凸优化问题,所以读者需要掌握一些凸优化问题的基础知识。 讲义链接:[Convex Optimization Overview](http://ai-coder.com/batbus/pdf/cs229-cvxopt.pdf) ######注:讲义来源于Stanford深度学习与NLP课程前置基础知识 — ###3.应该了解哪些算法 这里不会对相关的算法做展开,只想从个人转型的经历向读者阐述,应该掌握哪些常见的机器学习算法,以及学习中应该注意的事项。相关的算法以及有很多博客可以参考,但个人觉得还是要先读一遍原论文,读不懂没关系,能理解多少理解多少,再参考别人写的解释理解一遍。如果直接读别人的博客,有可能被误导,之后再反过头来再读一读原论文,这样感觉理解的能好一些。当然也推荐大家直接学习Andrew Ng的公开课,讲的比较容易懂。而且已经好几年了,相关的讨论、讲义标注都很全面了,对于初学者来说是一个好的学习资源。 — ####3.1 常见的特征提取方法 其实特征选择(提取)是作为监督学习中特别重要的一个环节。往往我们要处理的问题可能供处理的特征特别多,我们减少特征的数量,比如图像处理,如果完全用像素,对于一张1000*1000的图片,那么特征就是一个1000*1000这种高维的特征,我们需要降低这个特征的维度,这个过程就叫做特征提取(选择)。对于图像我们常用sift特征。常用的降维方法包括(个人常用): ######1.PCA(主成分分析) 这是一种无监督的降维方法,准确的说应该是一种空间映射方法,PCA一次寻找一组正交的映射空间,并且使得能够在这个映射空间上方差最大。这个方法使用的频率较高,也比较典型,比较容易掌握。一般的教材书中都有相关的介绍,在Andrew Ng的课程中有相关介绍,可以直接学习。 ######2.基于树的方法 这里吗需要读者理解一些常用的概念如”熵”,”信息增益”等,基于树的方法,可以通过剪枝的方式来去掉那些对于结果没什么大的影响的特征。这里面对于”熵”的理解,要强调一下,”熵”可以理解为不确定性,你可以认为是”商量”,熵越大,不确定性越高,就越需要”商量”,越小,代表确定性越高。关于树的相关方法,在国内的机器学习教材中都有明确的阐释。
######3.SVD(矩阵分解) 矩阵分解这是机器学习里面非常重要的一个线性代数知识,能够很好的起到降维的效果。在自然语言处理中较为常用。比如X是word->document的矩阵,关于SVD虽然在公开课中有讲解,但感觉还是语言的理解有问题,理解的不是很透彻,发现这个哥们写的相关机器学习的博客讲的还都比较通透,所以读者可以参考他的这篇博文理解一下。
相关博文:强大的矩阵奇异值分解
####3.2 常用机器学习算法 这里面会向读者介绍一下工作中常用的相关机器学习算法,当然这里也不会详细解释,这里只是告诉读者存在并且常用这些算法,笔试和面试中往往会考察面试者对于这些知识的掌握。对于如何学习,笔者觉得最好优先读paper,再看看公开课和相关博客。 ##### 3.2.1 常见聚类算法 聚类算法是我们常用的算法其思想比较容易理解,符合大脑处理问题的思维逻辑。我们常见的聚类算法包括Kmeans、EM算法等,下面简单罗列一下: SimpleKmeans算法:接受输入参数K,然后将数据集划分为K歌聚簇,同一个聚簇中的相似度较高,不同聚簇的相似度较小。 Xmeans算法:Kmeans的改进,在总体中通过Kmeans产生聚类,再分别对每个聚类进行Kmeas的迭代,将某些子类进行聚类,直到达到用户设定的次数为止。 EM算法:期望最大化算法(Expectation Maximization Algorithm),是一种迭代算法,用于含有隐变量(hidden variable)的概率参数模型的最大似然估计或极大后验概率估计。这里需要说下,EM算法背后的理论、推导最好好好掌握,这个掌握了,大部分的推导和理论基本都cover了。 相关博文:[常用聚类算法介绍之聚类种类和算法列表](http://ai-coder.com/batbus/html/blog_detail.php?blog_id=250) ##### 3.2.2 常见分类、回归算法 分类和回归问题,其实可以拿到一起来讲。如果我的问题最终是要将待处理的数据明确分为若干类别(常用的有二元分类、多元分类),那么就是分类问题,如果最终需要映射到一个数值区间,那么就是回归问题,比如预测一个人犯罪的概率,如果需要判断是否犯罪,那么就是一个分类问题(是和否),如果要给个概率那么就是一个回归问题。 这里面我们常用的算法有SVM、LR、随机森林、朴素贝叶斯。 线性回归(Linear Regression):结果易于理解,计算上不复杂,但对非线性数据拟合不好。应该是线上应用最为广泛的模型,简约而不简单,更重要的是快!LR的推导是必须要掌握的! SVM:通俗的讲,SVM是一种二类分类模型,其模型的定义为特征空间上的间隔最大的线性分类器。其学习策略是使得间隔最大化,最终可以转化为凸优化问题。简单的理解就是,在低维空间中难以划分的问题,将其映射到一个高维空间,在高维空间使得数据可以线性划分。 朴素贝叶斯:朴素贝叶斯是贝叶斯理论的一部分,是一种概率模型,即选择较高概率的决策。其前置条件是: (1)每个特征之间相互独立。 (2)每个特征同等重要。 在数据较少的情况下仍然有效,可以处理多类别问题。但对于输入数据较为敏感。 随机森林(Random Forest):随机森林比较适合做多分类问题,其优点是: 训练和预测速度快; 对训练数据的容错能力好; 实现简单且易并行 当数据集中有大比例的数据缺失时仍然可以保持精度不变和能够有效地处理大的数据集;可以处理没有删减的成千上万的变量;能够在分类的过程中可以生成一个泛化误差的内部无偏估计;能够检测到特征之间的相互影响以及重要性程度。但容易出现过度拟合。 实际上该算法实际上可以理解为专投票算法,一个森林可以拆解成很多树,每个树都是一个决策算法,可以理解成一个领域专家,众多专家组合成一个森林,对于待处理的问题,专家组进行投票,最终少数服从多数,由票数决定结果。 ####3.3 深度学习相关算法 深度学习是近几年较为火的一种学习方式,目前在实际工作中使用的越来越广,往往不需要较为复杂的调优就能达到其他常用的调优过后的机器学习算法达到的水平,也就是说,他的baseline很高,随着向caffee、tensorflow等框架使用的推广,这些深度模型实现起来越来越简单,所以工程师就越来越有必要掌握这些深度学习算法。你可以在机器上安装tensorflow就能够尝试在本机上进行手写体识别、word2Vector训练等,赶紧动起来吧。 关于学习,可以参考Stanford深度学习和NLP的公开课,讲的还比较透彻,但需要读者掌握在文章第二部分提到的一些数学知识。 ##### 3.3.1 RNN(Recursive Neural Network) RNN是较为常用的深度模型,常用的有两种变体,一种是时间递归神经网络(Recurrent neural network),另一种是结构递归神经网络(Recursive neural network)。时间递归神经网络的神经元间连接构成有向图,而结构递归神经网络利用相似的神经网络结构递归构造更为复杂的深度网络。两者训练的算法不同,但属于同一算法变体。 Recurrent是在时间维度的展开,能够有效的表示信息在时间维度上从前往后的的传递和积累,你可以和马尔科夫链做类比。 Recursive是在空间维度的展开,你可以认为他是一种结构上递归的结构,对应为棵树。在NLP领域用的较为广泛,能够很好的提取出结构信息,其示意图如下
二相比之下时间递归神经网络如下:
##### 3.3.2 RNN(Recurrent Neural Network) 常见的示意图如下所示,其核心就是每轮的运算都充分结合上一轮的迭代结果。
目前最为常见的时间递归神经网络就是LSTM(Long-Short-Term-Memories)。按照时间序列进行展开如下图
由上图可见一般包括书入门、忘记门、输出门,能够很好的学习当前特征同时兼顾上下文信息。目前较多的用于NLP范畴,其能够较好的保留上下文信息,这样在语义理解、摘要生成、情感分析等问题处理上都能得到一个较好的结果。
读者可以不去掌握其复杂的推导,但其背后的物理意义、这种思想是必须掌握的,应用的时候,大部分都是利用现有框架去处理。所以这里再强调一遍,如果精力有限那么就要重其意。
3.3.3 RNN模型比较
其实两种模型的区别在3.3.1中已经做了区分,这里按照Stanford深度学习和NLP课程中所述进行一下模型对比。
Recursive Neural Network:在语言层解释性较好,能够保留骨干信息,可应用在句法分析、短语识别。
Recurrent Neural Network: 在语意上解释性较好,很多人利用其做了很多好玩的,如自动写诗之类的,训练是一个个字符的读取后训练。通常情况下虽然不是最好的结果,但是结果也不差,特别是在引入了”门”之后,提示较为明显。
3.3.4 CNN(Convolutional Neural network)
卷积神经网络由于避免了对图像的复杂前期预处理,可以直接输入原始图像(需要尺寸format处理),因而得到了更为广泛的应用。
一般地,CNN的基本结构包括两层,其一为特征提取层,每个神经元的输入与前一层的局部接受域相连,并提取该局部的特征。一旦该局部特征被提取后,它与其它特征间的位置关系也随之确定下来;其二是特征映射层,网络的每个计算层由多个特征映射组成,每个特征映射是一个平面,平面上所有神经元的权值相等。
CNN主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。由于CNN的特征检测层通过训练数据进行学习,所以在使用CNN时,避免了显示的特征抽取,而隐式地从训练数据中进行学习。
这里读者需要掌握卷积的物理意义、全链接和局部链接、知道为什么要池化、常见的池化方法等,这样对CNN就基本掌握了,剩下的就是应用了。
4.总结
无论是学士还是已经工作的工程师,掌握一些机器学习算法,对于自己都是增加了自己的核心竞争力,在DT转型的过程中,会让自己走的更远。如今无论是Google、微软还是Amazon都在开放自己的机器学习平台,阿里云上的机器学习平台也可以直接使用,这些平台的开放大大降低了我们对于算法的使用难度,我们无需向那些真正的算法专家一样去发明算法,只要我们知其然、也知其所以然,就能够利用这些知识去解决实际问题。
对于还在学校里学习的同学要充分利用自己的时间,在数学基础上打捞,对常用的机器学习算法和深度学习算法都有所掌握。对于开源的tensorflow、caffee等代表性平台和框架,要勇于尝试,在未来的笔试和面试中一定会脱颖而出的。