掌握動態規劃,助你成爲優秀的算法工程師

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算法效果的優化,以及財務審覈相關產品的研發工做。

相關文章
相關標籤/搜索