掌握动态规划,助你成为优秀的算法工程师

1.导论web


相信不少同窗已经在为今年的校招作准备了,随着AI的火热,愈来愈多的同窗涌入了算法的行当之中。那去年校招的算法岗是有多火热?在知乎上看到这么一条帖子,先不说内容哈,足足400w+的阅读量啊。面试

图片描述

不光是计算机或软件专业的学生,不少电子,通讯,自动化等相关专业的同窗也吸引了进来。固然,这应该是件好事。可是至关一部分同窗,在学习的过程当中,尤为是刚入门的时候,可能会有这样一个疑问:算法工程师的算法,为何不是指《算法导论》中的算法(如下称为经典算法,用以区分),而是指机器学习里的算法。都叫算法(Algorithm),但好像不是一回事啊,二者有什么关系,又有什么区别呢?算法

本文试图经过动态规划这一经典算法中的重要内容,同时又在机器学习算法中有着普遍的应用,来简单探讨一下这两种“算法”。网络

2.动态规划less


首先,动态规划(Dynamic Programming)是《算法导论》中的重要章节,同时也是在机器学习算法中有着很是重要应用的一种优化算法。能够说是,不管是不是算法工程师都应该掌握的一种算法。再功利一点说,动态规划也是诸多面试官特别喜欢考的一种题型,下面就带你们稍微温故一下。机器学习

按照教材[1]的介绍,动态规划一般须要按以下4个步骤来进行设计:ide

刻画一个最优解的结构特征。

递归地定义最优解的值。函数

计算最优解的值,一般采用自底向上的方法。学习

利用计算出信息构造一个最优解。优化

简单点说,动态规划算法的核心就是大问题拆成重复的小问题,同时记住已经解决了的小问题的解。那若是你去网上搜搞ACM或者OI大神的说法,他们都会说动态规划是一个框,是一种解决问题的思想,而不是某种具体的算法。下面咱们详细来看看,时髦的机器学习是怎么往动态规划这个框里填的。

2.1 编辑距离

说到编辑距离(Edit distance),你们可能都比较熟悉。在天然语言处理(Natural Language Processing,又NLP)中,编辑距离是计算文本类似度的一种基本距离计算方式。简单来讲,就是只能经过替换,删除,插入操做,将一串字符串变为另外一串字符串的操做数。而求最小编辑距离的过程,就是一个典型的动态规划的过程。

若是计算两个字符串的编辑距离,咱们能够看作是父问题,那他的子问题天然就是如何求更小字符串之间的编辑距离。那上面提到,动态规划不只要将父问题拆分红子问题,更要记下子问题的解,以达到节省空间和时间的效果。

下图能够看出,这个D矩阵,就是咱们用来存储这个子问题解的空间,假设两个字符串的长度分别为m和n。而D(i, j)如图所示,则是咱们定义的最优解的结构特征,实际表示的就是长度为i和长度为j的两个子序列之间的最小编辑距离,咱们把它从左至右,从下到上填到每一个格子里,一直到矩阵的右上角,就能够获得咱们要的最小编辑距离。那么最终咱们的空间复杂度为O(mn),而时间复杂度一样为O(mn),相比采用分治的思想递归地进行求解仍是要快不少。(这里篇幅有限,就不赘述代码了,有兴趣的同窗能够自行网上搜索)

图片描述

https://web.stanford.edu/clas...

2.2 动态时间规整

说完NLP里的类似度计算,我们再来看看语音识别里有没有相似的算法用到动态规划呢?答案是确定的。这个算法就叫动态时间规整(Dynamic time warping),简称DTW,一听名字是否是感受就很动态规划。DTW算法是传统语音识别中的重要方法,起初是用于孤立词的语音识别,判断两段语音是否为同一个单词。实际上,只要是时间序列,以下图[2],均可以用来计算类似度,不局限于语音识别当中,例如股市的交易策略,手势识别等等场景都有应用。

图片描述

在语音信号中,有一个很大的问题就是,信号长度并不相等,即便是同一我的说同一个单词,也会有语速上的差异。那这个时候基于欧几里得距离(Euclidean Distance)的方法就不奏效了,可是两个时间序列形状上又很是的类似,因而咱们就但愿能够经过某种对齐的方式来衡量这两个时间序列的类似性。如上图所示,箭头表明了两个时间序列中的类似点。咱们用全部类似点之间的距离和来表示这种类似度,称之为规整路径距离。

图片描述

你们看到这个“棋盘”好像和咱们上面讲到的编辑距离中的D矩阵很像。没错,假设n为序列A的长度,m为序列B的长度,D(m, n)就是上面这两个序列的规则路径距离。至于D(m, n)怎么求?又到了咱们的动态规划发挥威力的时候。仍是像求最小编辑距离同样,D(i, j)以下式所求,而且由左到右,由下到上填入D矩阵中,最终求得的右上角的值就是咱们的规整路径距离。时间复杂度依然为O(mn)。

图片描述

说到这里,好像动态规划不就是画个矩阵,按照D(i, j)的计算方法填满矩阵,获得右上角的最终解。嗯,好像也有点道理。那咱们接下来继续看看,这样说对不对。

2.3 维特比算法

若是说前面两种算法和机器学习只能算沾边的话,那咱们如今要说的维特比算法(Viterbi Algorithm)能够说是动态规划在机器学习当中的典范了,尤为若是是作天然语言处理方向的话,维特比算法更是不可不知,哪怕在现在deep learning当道的时代。在天然语言处理中,像分词、词性标注、命名实体识别、输入法等等任务中都有很是重要的应用。

除了前面介绍的计算两个序列之间的距离之外,动态规划还有一个重要的应用场景,就是计算有向无环图(DAG)中两个节点间的最短路径,而维特比算法就是针对篱笆网络(Lattice Network)这一特殊的有向无环图而提出的。

图片描述
如上图所示,这是一个部分的篱笆网络,中间咱们假设有N列,每列有4个节点,节点之间的权重咱们暂时忽略。这个时候,网络的最左边有一个节点为S,最右端有一个节点为E。若是我想求S到E之间的最短路径,理所固然,咱们若是穷举出全部的路径进行比较,也就是4N条路径,天然能够获得结果,但若是层数不少或者每层的节点数不少的时候,这种方法就显得不够友好了。

既然穷举法太过暴力,天然咱们想试试能不能用动态规划来解决。首先,篱笆网络有这么一个特色,就是假设咱们从第一列走到最后一列,咱们必定会通过其中的第i时刻的某个节点。这个固然是显而易见的,但给咱们带来了一个好处,那就是当咱们计算最终的最短路径时,假设第i列有k个节点,若是咱们已经计算了从开头到第i列全部k个节点的最短路径,那最终的最短路径必定是通过其中之一。第二,若是说最短路径P通过某个节点xij,那么从起始节点S到节点xij的这段子路径Q,必定是从起始节点S到xij的最短路径,不然总路径P也再也不是最短路径,这就自相矛盾了。

有了这两个特性,终于能够试试动态规划了。一样咱们从最左边的S节点出发,到第1列的4个节点,由于各只有一段距离,那天然这4个距离d(S, x1i)为S节点到这4个节点的最短距离。当咱们走到第2列时,根据以前的特性,必定会通过第1列的某个节点。此时的S节点到第2列某个节点的距离则为d(S, x2j)=d(S, x1i) + d(x1i, x2j)。而第1列有4个节点,因此d(S, x2j)应该是取4个距离中的最小值,固然在这一过程当中,咱们计算了4次,对于第2列的每一个节点,咱们都去进行如上的计算。因此在从第1列走到第2列的过程当中,咱们计算了4×4次,更关键的是咱们把d(S, x2j)都要保存下来,做为咱们下一次计算的基础。

而这个保存中间结果的过程,很明显地体现出了前文所述的动态规划的特色。接下来,咱们继续走到第3列,一样的,S节点到第3列某个节点的距离为d(S, x3k)=d(S, x2j) + d(x2j, x3k)。这个时候咱们发现,等式右边的第一项,能够直接取咱们刚刚保存的中间结果。对于d(S, x3k),咱们依然是计算4次,取最小值保存下来。一样,须要遍历第3列的4个节点,因此又是4×4次计算。也就是说,每往前走1列,咱们就计算了4×4次。以此类推,到最右边的节点E的时候,咱们须要计算N×42次,相比于穷举法的4N条路径,这个效率已是很是大的进步,把指数级的复杂度下降到了多项式级别!

2.4 CYK算法

这个CYK算法你们可能会有点陌生,全名为Cocke–Younger–Kasami算法,是以三位做者的姓名共同命名的。这个算法实际上是句法分析方向的一个经典算法,由于提出的时间是在基于规则的年代,因此即便是作NLP的同行,依然有不少同窗并不了解。因此这里给你们多交代一些背景知识。

首先,CYK算法是基于乔姆斯基(Chomsky)范式的上下文无关语法(Context Free Grammar)。感受越解释概念越多了哈。简单点说,乔姆斯基范式有两种形式。

图片描述

这里,ABC都是非终结符,就是像名词短语(NP),动词短语(VP)等等,x是终结符,好比单词就是终结符。对于A这个非终结符,要么拆分红更小的2个非终结符,要么就到此为止,右边是一个单词。例如:”吃药“这个动词短语,就能够按下面的方式进行句法分析。

图片描述

好了,介绍完了背景知识,咱们的任务就是给定一个句法规则的集合,对于任意一个句子,将它按照这个句法规则集合进行解析。下图就是咱们的一个句法解析树,也就是最终的一个结果。

图片描述

对于一次解析来讲,若是尝试去解析出全部的结果,那将是指数级的复杂度,而CYK算法就是利用动态规划的思想将复杂度下降到了多项式级。假设咱们的句子的单词数为n,咱们先画一个以下图的下三角矩阵,横坐标为位置i,纵坐标为跨度j。

图片描述

CYK算法过程以下:

图片描述

http://ccl.pku.edu.cn/doubtfi...

其中最关键的就是步骤2中的最内层循环,对于一个跨度内全部分割点k。简单点说,就是在给定了位置和跨度的一个短语中,不断调整中间的分割点位置,使得分割点两边的短语子串可以符合给定的句法规则。当子串符合句法规则时,把对应的结果记录下来,并为后续的解析所用,这就体现了动态规划思想的核心!

2.5 分词

上面咱们介绍过维特比算法,在分词任务中有重要的应用,但如今咱们又要来提分词了,那这里的动态规划和维特比有什么不同呢。首先,目前的分词的主流算法里有这么两种,一种是基于字的模型分词算法,还有一种则是基于词典的分词方法。前者,主要有基于隐马尔可夫(HMM)的生成式模型、基于条件随机场(CRF)的判别式模型以及基于神经网络的分词算法,在这些算法的解码部分,均可以使用维特比算法进行解码。那这节要说的动态规划则是基于词典的分词算法里用到的。

基于词典的分词算法是如何工做的呢?举一个简单的例子,"我来到达观数据"。首先,咱们根据词典将句子进行简单的匹配,将句中匹配到的词典词和全部的单字组合起来,做为节点,构形成一个分词的词图,以下图所示(边的权重假设都为1)。那这个图里从S节点到E节点的每条路径,都表明这一种分词的结果。咱们但愿正确的分词结果,理应是一条几率最大的的路径,这样才能把一个语言学的问题转化成一个数学的问题,从而让计算机能够辅助咱们获得正确的分词结果。

图片描述

由于句子是顺序的,因此这个词图表现为一个有向无环图。还记得前面讲到的维特比算法是针对特殊的有向无环图来计算最短路径,这里的词图就显得更为通常些。如何求得有向无环图的最短路径呢,这个时候,咱们须要先对词图进行拓扑排序,而后再利用动态规划求排序后的词图最大几率路径。拓扑排序的结果以下图:

图片描述

有了拓扑排序的结果,咱们就能够动态规划了。上面咱们讲Viterbi算法的时候,提到这么一个性质,若是最终的最短路径P通过某个节点i,那么通过这个节点的子路径Q必定是起始节点S到节点i的最短路径,不然最短路径P必定有比它更短的路径存在。在这里,咱们是求最大几率路径,其实原理是同样的。对于到最终节点E的路径Route(E),有:

图片描述

实际上,咱们能够一直写下去,而这些子路径就是动态规划中的最优子结构,咱们只须要再求解这些子结构中的最优解便可。相比于,列举出全部的分词路径,这种计算方法是要快上不少。在计算最大几率的过程当中,有很多小trick。期待后续的达观技术分享为你们详细介绍。

2.6 强化学习策略迭代

说到强化学习,这里不得不首先引用一下Sutton在《Reinforcement Learning: An Introduction》关于动态规划的一些表述。

DP provides an essential foundation for the understanding of the methods presented in the rest of this book. In fact, all of these methods can be viewed as attempts to achieve much the same effect as DP, only with less omputation and without assuming a perfect model of the environment.

虽然动态规划在实际的强化学习中,有诸多的限制,但动态规划所具备的理论基础是强化学习必不可少的,可见动态规划之于强化学习的重要意义!

强化学习和你们熟悉的机器学习有着很大的不一样,它没有用到标注数据进行supervise,并且当前的动做可能会影响到后续的结果。既然是动做,确定会考虑到不少因素。那么在强化学习里,咱们须要考虑哪些变量呢?首先确定是回报了,这里用R来表示,不一样的回报决定了不一样的动做。回报又分为长期的和短时间的,就比如作基础算法研究,短时间看没什么回报,但长期来讲就是技术的护城河。咱们经过衰减系数𝛾来表示,0≤𝛾<1。除此之外,咱们还要看当前所处的状态S来决定所作的动做。有了状态的集合,那天然要考虑状态之间的转移关系,就是咱们的P,状态转移矩阵,但由于对于不少实际问题,状态实在太多,因此每一个状态只能考虑前一个状态的相关状况,这样就大大简化了问题的复杂度,这种性质咱们也叫马尔科夫性。最后,加上咱们的一系列动做A,就有了马尔科夫决策过程(Markov Decision Process, MDP)。

图片描述

http://www0.cs.ucl.ac.uk/staf...

好了,如今有了这些基本要素了,下面要用这些要素作什么呢?好比机器学习里,咱们但愿是最小化损失函数。而在强化学习里,咱们则是但愿最大化的累积回报,好比下棋的时候,只要最终赢了便可,而不是要每步都要吃掉对方一些棋子。这时候,咱们就先定义一下这个累积回报,假设从t时刻开始到最终时刻T,而且加上以前提到的衰减系数𝛾,则有:

图片描述

既然这个G~t~是从t时刻到最终状态的累积回报,那就不光是一条路径的累积,而是全部的路径的总和,当状态过多的时候,咱们就无法计算。这个时候须要引入一个状态值函数,做为从某状态开始的回报总和的指望。

图片描述

这个状态值函数就是用来衡量某一个状态的好坏。除了咱们上面提到的几个要素之外,咱们在某个状态执行什么动做,并非固定的,那就须要引入新的概念策略𝜋,做为动做关于状态的分布。则上式就变为:
图片描述

问题又来了,这个指望其实也不太好算,由于其中一个状态的价值函数须要计算后续全部状态的回报。既然是马尔科夫决策过程,那天然会想到用迭代的思想去计算。获得其递归的形式Bellman方程,以下式(详细推导过程见7)
图片描述

这样,在给定策略的状况下,咱们就能够迭代地去求每个状态的值函数了。从这个更新公式,也能够看出,强化学习里的动态规划将围绕状态值函数的更新这个最优子结构而作文章。

对于从v1到最终的v的每次迭代vk,咱们利用上式对值函数进行更新,直到收敛于V(证实略)。这一步就叫作策略评估。这时候,咱们能够对于取得最大的动做值函数q而获得的新策略,对新的策略进行策略评估步骤。直到咱们的策略再也不变化,此时获得的策略即为最优策略。

3.总结


一会儿说了那么多涉及到动态规划的机器学习算法,相信读者朋友们还能够列举出更多(欢迎评论区留言)。咱们在动态规划这个框里填了那么多机器学习算法,而机器学习算法也很是依赖动态规划的高效率,可谓是你中有我,我中有你。

从上面举的不少例子你们也能够看到,动态规划更侧重于对问题求解的优化,好比求最短距离,其实是能够经过暴力方法进行求解的,而动态规划则是提升了求解的效率。但机器学习算法可不只仅是对问题的求解进行优化,它要解决的问题每每没有精确解,同时也无法经过穷举等暴力方法进行求解。须要对问题进行清晰地定义并建模,重点在于学习的过程,基于对训练数据的拟合来预测新的样本。

而说完动态规划,你们很容易又联想到贪心算法,一样也是经典算法中的一个重要的优化方法。好比word2vec中的霍夫曼树(Huffman Tree),好比seq2seq中须要用到的集束搜索(Beam Search),都是借鉴了贪心算法的思想。前面咱们提到了求最短路径问题虽然是动态规划,这实际上又涉及到经典算法中图论里的内容,相似的还有一系列的几率图模型(Probabilistic Graphical Model)。事实上,还有不少机器学习算法运用到了经典算法里的内容,这里就不一一列举了。

总之,对于一名优秀的算法工程师来讲,经典算法的掌握必不可少,对于机器学习算法的理解也有很大的帮助。但愿你们可以认真掌握,"触类旁通",在接下来的秋招中好好发挥。

参考资料
1.Cormen, Thomas H., Charles E. Leiserson, and Ronald L. Rivest. "算法导论." 第 2 版 机械工业出版社 (2006).

2.Salvador, Stan, and Philip Chan. "FastDTW: Toward Accurate Dynamic Time Warping in Linear Time and Space."

3.吴军. 数学之美. 人民邮电出版社, 2012.

4.宗成庆. 统计天然语言处理. 清华大学出版社, 2013

5.黄海安. https://www.zybuluo.com/Team/...

6.Wiering, Marco, and Martijn Van Otterlo. "强化学习." 机械工业出版社.

7.http://www0.cs.ucl.ac.uk/staf...

关于做者


杨慧宇:达观数据NLP技术专家,负责达观数据底层NLP算法效果的优化,以及财务审核相关产品的研发工做。

相关文章
相关标签/搜索