雷鋒網 AI 科技評論按,本文作者[韋陽](https://www.zhihu.com/people/godweiyang/posts "韋陽"),本文首發于知乎專欄[自然語言處理與深度學習](https://zhuanlan.zhihu.com/godweiyang "自然語言處理與深度學習"),雷鋒網 AI 科技評論獲其授權轉載。 **論文位址:**[Unsupervised Recurrent Neural Network Grammars](http://arxiv.org/abs/1904.03746) **代碼位址:**[github](https://github.com/harvardnlp/urnng) # 介紹 --- 這篇是新鮮出爐的 NAACL19 的關于無監督循環神經網絡文法(URNNG)的論文,在語言模型和無監督成分句法分析上都取得了非常不錯的結果,主要采用了變分推理和 RNNG。本文公式量較大,是以我也推了好久,算法也挺多的,首先上一張我推導的公式筆記:  我這篇部落格就不按照論文的順序來講了,就按照我上面這張筆記講一講我的了解吧,很多細節可能會忽略,請參見原文吧。 首先對于無監督成分句法分析,正常做法就是學習一個生成模型,就比如 RNNG 就是一個生成模型,但是缺少句法樹 z 的監督信号怎麼辦呢?現在給你的輸入隻有句子 x,那麼隻能用語言模型來做監督了。習慣上我們喜歡取對數,也就是:  這裡就存在幾個問題,比如 z 的狀态空間太大了,不可能窮舉所有的,是以接下來按步驟講解如何求解。 # URNNG模型 --- 先上一張模型圖,讓大家對整體模型有個大概的認知:  左邊是一個推理網絡(Inference Network),用來根據輸入 x 推理出隐變量也就是句法樹 z 的機率分布。右邊是一個生成模型(Generative Model),用來計算從推理網絡中采樣出來的句法樹 z 的聯合機率,最後根據上面語言模型算出句子的機率,最大化這個機率即可。 接下來分别講解這兩個部分和具體的優化方法。  首先将詞向量和位置向量拼接,作為推理網絡 LSTM 的輸入:  然後算出的得分,計算方式和以往一樣,用 BiLSTM 前後向輸出做差,然後通過一個前饋神經網絡得到分數:  接下來就需要計算句法樹的機率分布了,這裡不直接計算句法樹 z,而是計算它的鄰接矩陣 B 的機率分布,這個鄰接矩陣意思就是如果存在,那麼,否則的話。然後就可以用 CRF 計算出鄰接矩陣 B 對應的機率:  其中是配分函數,也就是用來将機率歸約到 0 到 1 之間的:  注意這裡的并不是所有的 01 矩陣集合,而是必須滿足能産生合法句法樹的矩陣,情況也很多,不能窮舉求解,在這裡采用經典的 inside 算法來求解這個配分函數:  不過我覺得這裡是錯的!就是這裡的兩處應該改成。不過具體代碼實作的時候并沒有這麼做,初始值一樣都是,但是遞推的時候采用了如下式子:  其實就是用來取代了,化簡後就是代碼實作這個式子,應該是為了防止數值溢出。 然後就是采樣了,推理網絡的目的就是計算出句法樹的機率分布,然後根據這個分布采樣出若幹個句法樹,那麼現在給定一棵句法樹可以根據上面的算法計算出它的機率了,那怎麼采樣呢?其實還是可以通過剛剛計算得出的數組來采樣,采樣算法如下:  其實就是自頂向下的根據機率分布來采樣每個 span 的 split,用一個隊列來儲存所有還沒有采樣出 split 的 span,然後把所有采樣出的 span 在鄰接矩陣中的對應值标為1。 最後推理網絡采樣出了若幹個句法樹 z,然後根據 CRF 計算出每個句法樹的機率,後面的事情就交給生成網絡了。  上面的推理網絡采樣出了若幹個句法樹 z,生成網絡的目的就是計算它的聯合機率。這個其實不難,在之前的 RNNG 論文筆記中,我已經大緻講過了,可以去複習一下:[Recurrent Neural Network Grammars](https://godweiyang.com/2018/09/02/RNNG/),這裡稍稍做了一些改進。 首先需要定義一個棧用來存放轉移的曆史狀态,這裡定義棧裡放的元素為二進制組(h, g),一個是 stack-LSTM 編碼的輸出,一個是子樹的結構表示。首先需要預測下一步的 action 是什麼,是以取出棧頂的元素,預測 action 的時候隻要用到隐含層輸出:  然後根據這個機率預測 action 是 SHIFT 還是 REDUCE,下面分兩種情況讨論。 如果是 SHIFT,那麼因為是生成模型,是以需要預測下一個移進的單詞是什麼:  然後将單詞 x 的詞向量輸入到 stack-LSTM 中得到下一個時刻的隐含層輸出:  最後将推進棧裡。 如果是 REDUCE,那麼首先需要取出棧頂的兩個元素和,然後用 TreeLSTM 計算出兩個子結點合并後的子樹的表示:  接着還是計算 stack-LSTM 下一個時刻的隐含層輸出:  最後将推進棧裡。 為了防止數值溢出,正常上我們計算聯合機率的對數:  從這個式子可以看出,聯合機率定義為所有給定某段單詞和 action 預測下一個單詞和給定某段單詞和 action 預測下一個 action 的機率之積。 如果是監督任務比如 RNNG,那麼隻需要最大化這個聯合機率就足夠了,但是現在要做無監督,沒有 z,注意别搞混了,推理網絡采樣出的 z 可不能用來監督哦,因為那本來就不是正确的,是以接下來要采用語言模型來作為最終的目标函數。 ## Variational Inference 句子 x 的對數機率定義為:  其中是所有合法句法樹的集合,但是這裡不可能窮舉所有的句法樹,是以就要用到變分推理,具體的理論知識不仔細介紹了,可以去查閱變分推理相關知識,下面直接推導。  其中最後一行叫做先驗的證據下界(ELBO),要想最大化先驗,可以最大化這個 ELBO,如果我們對這個 ELBO 變化一下形式可以得到:  是以這個 ELBO 和先驗就相差了一個 KL 散度,最大化 ELBO 的話等價于最小化 KL 散度,也就是使推理網絡産生句法樹的機率分布和生成模型盡量接近。 但是這個 ELBO 還是不好算,盡管它把移到了求和符号也就是期望裡面,是以轉換一下形式:  因為模型一共有兩組參數,一個是推理網絡的參數,一個是生成網絡的參數,是以下面分别對兩個參數求導。 首先對求偏導,因為隻有第一項有這個參數,是以偏導為:  這個偏導可以按照機率采樣得到:  然後對求偏導,因為有兩項含有這個參數,分别求偏導。第二項是熵,它的值其實可以用之前的數組算出來,算法如下:  然後偏導可以交給深度學習庫的自動微分,就不用你自己求啦。 至于第一項的偏導可以用類似于政策梯度的方法解決:  這裡最後也是轉化為了采樣,和政策梯度做法類似,這裡加入 baseline 來提升性能:  其中定義為所有其他的對數聯合機率的均值:  至此所有偏導都已求出來了,兩個通過采樣得到,一個通過 inside 算法結果自動微分得到,是以去掉導數符号并相加就得到了最終的損失函數:  一定要注意,這裡的在代碼實作的時候不能傳入梯度,不然的話對的偏導就會多出這一項的偏導了! # 實驗 --- 實驗結果這裡就不多說了,細節具體看論文吧,就貼兩個結果,一個是語言模型:  可以看出在标準的 PTB 資料集上,URNNG 效果隻比監督學習的 RNNG 和用 URNNG 損失函數微調後的 RNNG 效果略差一點,但是在大資料集上,URNNG 的優勢就展現出來了。 另一個是無監督成分句法分析,這裡是用的全部長度的測試集:  這個任務上 URNNG 效果是最好的。 # 結論 --- 和之前兩篇語言模型做無監督成分句法分析類似,這篇論文用推理網絡學習句法樹的機率分布并采樣句法樹,再用生成網絡計算這些句法樹和句子的聯合機率,最後用變分推理最大化句子的機率,也就是學習出一個好的語言模型。 雷鋒網 (公衆号:雷鋒網)
雷鋒網版權文章,未經授權禁止轉載。詳情見轉載須知。