原文鏈接:
https://godweiyang.com/2019/08/15/con-parsing-summary-v2/
本文對成分句法分析近年來的進展做了一個比較完善的總結。分析了多種不同類型的成分句法分析模型(基於轉移,動態規划和序列到序列等),比較了它們之間的優缺點,並總結了一些提升它們性能的技巧。最后,本文對成分句法分析的未來發展趨勢表明了自己的一些看法。
介紹
成分句法分析近年來取得了飛速的發展,特別是深度學習興起之后,神經句法分析器的效果得到了巨大的提升。一般來說,句法分析器都可以分為編碼模型和解碼模型兩個部分。編碼模型用來獲取句子中每個單詞的上下文表示,隨着表示學習的快速發展,編碼模型也由最初的LSTM逐漸進化為了表示能力更強的Transformer (VaswaniSPUJGKP17)。而解碼模型方面,也誕生了許多不同類型的解碼算法,比如基於轉移系統(transition-based)的解碼算法(WatanabeS15, CrossH16, LiuZ17a),基於動態規划(chart-based)的解碼算法(SternAK17, KleinK18)和基於序列到序列(sequence-to-sequence)的解碼算法(BengioSCJLS18, Gomez-Rodriguez18)等等。
基於轉移系統的句法分析模型主要通過預測生成句法樹的動作序列來還原出一棵句法樹。按照遍歷樹的順序,具體還可以分為自底向上(bottom-up)的轉移統(CrossH16),自頂向下(top-down)的轉移系統(WatanabeS15)和基於中序遍歷(in-order)(LiuZ17a)的轉移系統。基於轉移系統的句法分析模型優點是速度快,因為它解碼的時間復雜度是線性的。而缺點就是在解碼的時候無法考慮短語的邊界信息,這會導致解碼的精度上相比於基於動態規划的模型稍微差一點。
基於動態規划的句法分析模型主要通過遞歸地預測每個短語得分最高的子短語,最后回溯還原出最優句法樹。優點就是可以枚舉出搜索空間中的所有句法樹,解碼效果比較好。但是動態規划算法時間消耗較大,復雜度是句子長度的平方級別的。所以針對這個缺點,又提出了近似的自頂向下的貪心解碼算法(SternAK17),按照句法樹的前序遍歷順序進行搜索,在不損失太多性能的前提下,能大大加快解碼的速度。
基於序列到序列的句法分析模型主要思想就是將句法樹映射為一個唯一對應的序列表示,然后通過序列標注(Gomez-Rodriguez18)或者序列生成(VinyalsKKPSH15)的方式來預測出這個序列。根據句法樹序列化的不同定義方式,模型也有許多不同的變體。這一類模型的優點就是速度極快,因為時間復雜度也是線性的,並且模型參數量比基於轉移系統的模型少了很多。缺點也是顯而易見的,由於預測出的序列需要有很強的約束,不然不能保證可以還原出一棵完整的句法樹,所以最終的效果也沒有前面兩種模型理想。
此外還有許多其他類型的解碼算法,比如直接利用神經網絡來預測語法產生式的概率,模擬上下文無關文法,最后再利用傳統的CKY算法來進行解碼(TengZ18)。該模型最終也取得了非常不錯的效果,在單模型上的結果超過了之前的幾種模型。
成分句法分析可以應用到許多下游任務中去,比如情感分析任務中,可以采用樹狀LSTM(Tree-LSTM)來對句子的句法樹進行建模,從而分析出句子的情感(ZhuSG15)。也可以應用到其他基礎任務中去,比如可以將訓練好的成分句法樹根據規則轉化為依存句法樹,從而提升依存句法分析的准確率(Gildea04)。
任務定義
成分句法分析是自然語言處理中的一個基礎任務,它的任務是給定一個長度為$n$的句子$(w_0, w_1, \ldots, w_{n-1})$,分析出句子的短語結構句法樹$T$。例如給定句子“The little boy likes red tomatoes .”,它的成分句法樹如圖1所示。

對於句法樹$T$,有多種方式來對它進行表示。目前比較常用的是基於跨度(span)的表示(CrossH16),也就是將句法樹表示成組成它的所有短語的集合。而對於每個短語,可以用三元組$(i, j, \ell)$來表示它,其中$i$和$j$表示這個短語的范圍是從單詞$w_i$到$w_j$,而$\ell$表示這個短語的非終結符標簽。這樣句法樹$T$就可以表示為三元組$(i, j, \ell)$的集合:
$$
T = {(i, j, \ell) | (i, j, \ell) \in T}.
$$
這樣預測句法樹的任務就可以轉化為預測三元組$(i, j, \ell)$集合了。
當然一般還存在兩個小問題,一是如果存在一元產生式怎么辦?一種解決方法就是將一元產生式上面的所有非終結符全部拼接成一個新的非終結符,這樣整個一元產生式就可以看成一個非終結符了。另一個問題是句法樹不一定是二叉樹,那么解碼的時候就會增加許多搜索的復雜度。解決方法就是新增一個空的非終結符$\varnothing$,將非二叉產生式全部轉化為多個二叉產生式,其中新增加的臨時結點的非終結符全部定義為這個空的非終結符$\varnothing$,在還原句法樹的時候直接忽略它就行了。
編碼模型
給定句子$(w_0, w_1, \ldots, w_{n-1})$,編碼模型的目的就是獲得每個單詞的上下文表示,並進一步計算出每個短語的向量表示。在實際實現中,一般將單詞$x_i$的輸入向量分為三部分。首先是它對應的隨機初始化的嵌入向量$e_i$。然后是這個單詞的詞性對應的隨機初始化的嵌入向量$p_i$,一般它的詞性可以通過外部詞性標注器來得到。最后是這個單詞的字符級別表示$c_i$,這個一般可以通過字符級別的CNN或者LSTM來得到。最后將三部分向量拼接得到最終的輸入向量$x_i$:
$$
x_i = [e_i; p_i; c_i].
$$
然后將輸入向量送入編碼器,得到每個單詞的上下文表示。而根據采用的編碼器的不同,又可以將編碼模型分為以下幾種主要類型。
LSTM編碼
這是最為常用的一種編碼方式了,首先將所有$x_i$輸入到雙向LSTM中,得到每個位置的前向隱層表示$\mathord{\buildrel{\hbox{$\scriptscriptstyle$}}\over{h}}_i$和后向隱層表示$\mathord{\buildrel{\hbox{$\scriptscriptstyle\leftarrow$}}\over{h}}i$。然后對於短語$(i, j)$,它可以表示為:
$$
s{ij} = [\mathord{\buildrel{\hbox{$\scriptscriptstyle\rightarrow$}}\over{h}}_j - \mathord{\buildrel{\hbox{$\scriptscriptstyle\rightarrow$}}\over{h}}_i; \mathord{\buildrel{\hbox{$\scriptscriptstyle\leftarrow$}}\over{h}}_i - \mathord{\buildrel{\hbox{$\scriptscriptstyle\leftarrow$}}\over{h}}j].
$$
這樣就得到了短語$(i, j)$的向量表示$s{ij}$,接着就可以計算出它的得分,然后利用解碼模型解碼出最優的句法樹。
Transformer編碼
雖然LSTM編碼用的最多,但是要問最近這段時間最火的模型是什么,那當然是Transformer了(VaswaniSPUJGKP17)。它可以充分利用GPU的並行計算優勢,加快計算速度。還可以利用注意力機制,增強對句子的表示能力。

Transformer的輸入有三個,查詢(query)向量矩陣$Q$,鍵(key)向量矩陣$K$和值(value)向量矩陣$V$。
輸出就是查詢向量對每個鍵向量的注意力,然后對值向量加權求和的結果。用矩陣形式表示就是:
$$
{\rm Attention}(Q, K, V) = {\rm softmax}(\frac{QK^{\top}}{\sqrt{d_k}})V.
$$
當然還可以加入多頭(multi-head)注意力機制,增強表示能力,具體這里不再贅述,可以參看原論文。最后將輸出乘以參數矩陣${\bf W}_O$映射回需要的輸出維度,得到最終的輸出矩陣$H$,具體結構如圖2所示。
在本文中,$Q$,$K$和$V$三個矩陣都是通過對句子的輸入向量拼接而成的矩陣$X$,分別乘以參數矩陣${\bf W}_Q$,${\bf W}_K$和${\bf W}_V$得到的。但是要注意的一點是,在此前的輸入向量$x_i$的基礎之上,還得再拼接上每個單詞的位置向量$p_i$,不然矩陣運算會丟失單詞的位置信息。
得到輸出矩陣之后,接下來計算短語的表示方法和LSTM編碼是類似的。
遞歸神經網絡編碼
遞歸神經網絡在自然語言處理中的應用最早是在(SocherBMN13)中提出的。雖然當時取得了不錯的效果,但是近些年來遞歸神經網絡已經很少有人使用了,主要因為它存在梯度消失,需要句法樹等問題,並且它的初衷(編碼樹結構信息)由循環神經網絡LSTM基本也可以學到,所以沒有必要用這種不能並行的網絡結構。
對於短語$(i, j)$,如果它的兩個兒子結點是$(i, k)$和$(k, j)$,那么$s_{ij}$就可以由$s_{ik}$和$s_{kj}$計算得到:
$$
s_{ij} = f({\bf W}[s_{ik};s_{kj}]+{\bf b}),
$$
其中,$f$是激活函數,一般可以取${\rm tanh}$。
當然這種結構現在已經很少使用了,現在用的較多的遞歸結構是樹狀LSTM,網絡結構和遞歸神經網絡基本相同,唯一的區別就是將計算單元$f$替換成LSTM中的隱層單元,這樣可以有效地解決梯度消失和長距離依賴的問題。
得分計算
采用以上幾種編碼模型得到了每個短語的向量表示之后,接下來可以用兩層前饋神經網絡計算出它的得分:
$$
\begin{aligned}
s_{\rm{label}}(i, j, \ell) & = {\bf v}{\ell}^{\top}f({\bf W}{\ell}^2f({\bf W}{\ell}^1s{ij} + {\bf b}{\ell}^1) + {\bf b}{\ell}^2), \
s_{\rm{span}}(i, j) & = {\bf v}s^{\top}f({\bf W}{s}^2f({\bf W}{s}^1s{ij} + {\bf b}{s}^1) + {\bf b}{s}^2),
\end{aligned}
\tag{1}
$$
其中$f$是激活函數,這里通常取${\rm ReLU}$。這里我們將短語$(i, j)$的得分分成了兩部分,一部分是它的非終結符$\ell$的得分$s_{\rm{label}}(i, j, \ell)$,一部分是跨度的得分$s_{\rm{span}}(i, j)$。
最后,定義一棵句法樹的總得分為它包含的所有短語的標簽得分與跨度得分之和:
$$
s_{\rm tree}(T) = \sum\limits_{(i, j, \ell) \in T}{s_{\rm{label}}(i, j, \ell) + s_{\rm{span}}(i, j)}.
$$
而接下來要介紹的解碼模型的任務,就是去尋找一棵句法樹,使得它的得分最高。
基於轉移系統的解碼算法
基於轉移系統的解碼模型主要分為三種。第一種是自底向上的轉移系統,第二種是自頂向下的轉移系統,最后一種是基於中序遍歷的轉移系統。這些轉移系統的共同點是都包含兩個組成成分,一個是棧(stack),用來存放已分析的句法結構,另一個是緩存(buffer),用來存放待分析的句子。而預測句法樹結構就轉化為了預測轉移系統每一個時刻應該采取的動作(action)序列。下面我們分別介紹幾種不同的轉移系統,我們用三元組$[S, B, T]$來表示轉移系統每一個時刻的狀態,分別代表棧頂元素、緩存的第一個單詞和句法分析結束標志。
自底向上的轉移系統
自底向上的轉移系統是根據句法樹的后序遍歷(post-order)順序進行句法分析的,首先將緩存中的單詞移進棧里,然后將棧頂的若干個單詞歸約為它們的父結點,直至最后緩存為空並且棧里只有一個根節點。

自底向上轉移系統的動作形式化定義如圖3所示,其中移進(SHIFT)動作就是將緩存里面的第一個單詞移進棧里。歸約(REDUCE-L/R-X)動作就是將棧頂的兩個元素出棧,並且歸約為它們的父結點X,然后再將父結點入棧,而L和R就是用來區分左兒子和右兒子誰是頭結點。一元(Unary-X)動作就是將棧頂元素出棧,並且歸約為父結點X,這個動作是用來預測一元產生式的。最后完成(FINISH)動作用來判斷句法分析是否結束。
注意到這里有一個問題,自底向上轉移系統一般要提前對句法樹進行二叉化。主要原因是因為自底向上系統有個弊端,就是在不停地移進之后,你不僅要預測哪一步開始歸約,還得預測歸約的話要歸約棧頂的多少個元素,這樣預測的狀態數就大大增加,導致訓練時間也增加了許多。而二叉化后每次預測就只需要預測哪一步歸約就行了,每次歸約只歸約棧頂的兩個元素。

對於圖1中的句法樹,用自底向上轉移系統分析的過程如圖4所示。
自底向上轉移系統的優點就是可以充分利用已經生成的子樹信息,來幫助父結點的非終結符預測。但是缺點也很顯然,因為無法知道父結點以及再上層的父結點信息,所以丟失了許多有用的全局信息。另一個缺點就是需要提前進行二叉化,雖然二叉化加入了頭結點(head)信息,事實證明是很有用的,但是頭結點的標注需要許多語義學知識,非常的耗時耗力。一個較為簡潔的做法就是,用空結點$\varnothing$來作為句法分析中臨時結合兩個子結點而產生出的,但是在正確句法樹中不存在的結點。在還原樹結構的時候忽略這種空結點,這樣就可以隱式地進行二叉化操作了。
自頂向下的轉移系統
自頂向下的轉移系統利用的是句法樹的前序遍歷(pre-order)序列,首先將父結點入棧,然后不斷操作直到它的子結點全部入棧,這時將父結點連同所有子結點全部歸約為一個結點,也就是這個父結點自身。

自頂向下轉移系統的動作形式化定義如圖5所示,其中移進動作和之前一樣,都是將緩存的第一個單詞入棧。而非終結符(NT-X)動作就是將非終結符X入棧,也就是接下來的子樹的父結點就是X。歸約動作就是將棧頂若干個元素,一直到之前移進的那個父結點為止都出棧,然后歸約為一個結點,再次入棧。注意到這里不同於自底向上轉移系統的地方是沒有完成動作,因為自底向上系統存在一元動作,所以最后根節點可能會無限歸約下去,因此需要通過完成動作來提前終止分析。當然其實轉移系統的動作定義並沒有嚴格的要求,不同論文定義的也都不一樣,但是都大同小異,也就是都存在移進和歸約這兩個動作,所以這些轉移系統又可以叫做移進-歸約系統。
對於圖1中的句法樹,用自頂向下系統分析的過程如圖6所示。

自頂向下轉移系統的優缺點和自底向上轉移系統恰好互補。優點就是可以充分利用全局信息,例如父結點的信息,並且不需要提前進行二叉化,因為歸約的時候只要找到棧里第一個非終結符就行了。而缺點就是無法利用局部信息,也就是已經分析好的子樹信息,同樣非終結符動作也可能會出現無限多次執行的情況,所以要加上一些限制條件。
基於中序遍歷的轉移系統
基於中序遍歷的轉移系統利用的是句法樹的中序遍歷(in-order)序列,首先將最左邊的子結點移進棧里,然后將父結點入棧,再不斷操作直到該父結點的剩余子結點全部入棧,然后對它們進行歸約。
[外鏈圖片轉存失敗(img-Zda1Ncq9-1565857336610)(https://godweiyang.com/2019/08/15/con-parsing-summary-v2/in_order.png)]
基於中序遍歷的轉移系統的動作形式化定義如圖7所示,其中移進動作和之前一樣,都是將緩存的第一個單詞入棧。映射非終結符(PJ-X)動作是預測出當前棧頂的元素的父結點X。歸約動作就是將棧頂的若干個元素歸約為最里面倒數第二個元素,也就是它們的父結點。

對於圖1中的句法樹,用基於中序遍歷的系統分析的過程如圖8所示。
根據經驗,當我們讀一個短語時,我們通常會注意到它的第一個單詞,然后我們可以根據觀察到的詞推斷出短語的類型。例如,當我們讀到“likes”這個詞時,我們可以假設緊跟着這個詞的是一個動詞短語。而后面的單詞“red tomotoes”只是這個動詞短語的賓語。與自頂向下的轉移系統相比,“likes”中的局部信息對於識別這是一個動詞短語可能至關重要。此外,動詞短語(VP)中的全局信息也有利於之后的預測。
基於中序遍歷的轉移系統的優點恰好結合了前面兩種轉移系統,既可以考慮到局部信息,又可以考慮到全局信息。
生成模型
之前介紹的三種轉移系統都屬於判別式模型,而基於自頂向下轉移系統,又誕生出了一種生成式模型——循環神經網絡文法(RNNG)。循環神經網絡文法本質上就是自頂向下的轉移系統,動作定義和章節自頂向下的轉移系統介紹的基本一致。只是之前介紹的自頂向下的轉移系統是判別式模型,每次移進的單詞都是緩存中給定正確的單詞。而循環神經網絡文法每次移進的單詞需要通過動作生成(GEN-X)預測得出,最終模型對預測出來的句子分析出句法樹。
正式定義就是,對於句子$x$和對應的句法樹$y$,判別式模型是對條件概率$p(y | x)$進行建模,而生成式模型是對聯合概率$p(x, y)$進行建模。
而循環神經網絡文法的另一個重要應用是語言模型(language model),也就是建模$p(x)$。因為$p(x) = \sum\nolimits_{y \in \mathcal{Y}(x)} {p(x,y)}$,所以只需要枚舉出所有可能的句法樹$y$即可,但是這是指數級別的,顯然不現實,這時候就需要用到“重要性采樣(importance sampling)” (doucet2009tutorial)。
令$q(y | x)$為循環神經網絡文法作為判別式模型的時候產生句子$y$的條件概率,那么$p(x)$可以改寫為
$$
\begin{aligned}
p(x) & = \sum\nolimits_{y \in \mathcal{Y}(x)} {p(x,y)} \
& = \sum\nolimits_{y \in \mathcal{Y}(x)} {q(y|x)w(x,y)} \
& = {\mathbb {E}{q(y|x)}}w(x,y),
\end{aligned}
$$
其中$w(x,y)=p(x,y)/q(y|x)$。然后就可以采用蒙特卡羅方法進行采樣了,從分布$q(y | x)$中采樣$N$個樣本:
$$
{y^{(i)}} \sim q(y|x),i = 1,2, \ldots ,N.
$$
那么$p(x)$就可以近似表示為:
$$
\begin{aligned}
p(x) & = {\mathbb{E}{q(y|x)}}w(x,y) \
& \mathop \approx \limits^{\rm MC} \frac{1}{N}\sum\limits_{i = 1}^N {w(x,{y^{(i)}})}.
\end{aligned}
$$
在實驗效果上,生成模型的效果要明顯好於判別模型,因為它不僅對句法樹的概率進行了建模,還對整個句子的語言模型概率也進行了建模。當然在實現上也稍微復雜了一些,主要采樣這個操作耗時比較多,因此采樣數量不能太多,通常個位數就夠了,程序運行時間會成倍增加。
基於動態規划的解碼算法及其變體

這一類解碼算法是由傳統的CKY算法啟發而來的(cocke1970programming)。傳統的CKY算法是通過枚舉每一個結點處的產生式來狀態轉移到下一個子結點,然后尋找出概率最大的那一個產生式。而這里的基於動態規划的解碼算法是采用神經網絡,計算出每個短語的得分,然后枚舉它的所有子短語,計算出總得分最高的那棵子樹。圖9是這一類解碼算法加上編碼模型整體的模型結構。
動態規划解碼
解碼算法的初衷是求出得分最高的那棵子樹,但是狀態空間太大了,不可能枚舉所有的句法樹,所以就只能用動態規划算法求解了。
對於任意一個跨度$(i, j)$,我們利用公式1計算所有它所有非終結符的得分。直接取得分最高的那一個非終結符$\hat \ell_{ij}$作為最優的非終結符。
而對於子短語,我們只需要預測出$(i, j)$的最優分割點即可。遍歷所有的分割點$k$,取兩個子結點$(i,k)$,$(k,j)$與結點$(i, j)$得分之和最高的那個分割點即可:
$$
\begin{aligned}
s_{\rm split}(i, j, k) & = s_{\rm label}(i, j, \hat \ell_{ij}) \
& + s_{\rm label}(i, k, \hat \ell_{ik}) + s_{\rm label}(k, j, \hat \ell_{kj}).
\end{aligned}
$$
注意這里計算得分取了非終結符的得分$s_{\rm label}(i, j, \ell)$,並沒有取跨度的得分$s_{\rm span}(i, j)$。因為在實際實現中,發現加不加這部分得分影響不大,所以為了簡化運算,去掉了這項得分。
動態規划解碼算法的時間復雜度是$O(n^3)$的,所以對於稍長一點的句子,運行起來還是挺慢的。但是好處是可以搜索到所有的狀態空間,所以准確率上比較高。
自頂向下貪心解碼
因為動態規划解碼算法時間復雜度太高了,所以可以用貪心解碼來近似求解最優句法樹。思路是自頂向下、貪心地去選擇每一個跨度$(i,j)$的最優分割點和最優非終結符$\hat \ell_{ij}$,這樣時間復雜度將降到$O(n^2)$。
具體實現如下,首先從根結點也就是$(0, n)$開始,選擇一個分割點$\hat k$,使得兩個子結點$(0, \hat k)$,$(\hat k, n)$與根結點$(0, n)$的得分之和最高,而非終結符還是像之前那樣直接通過短語的向量表示計算得出。具體公式為:
$$
\begin{array}{l}
\hat \ell = \mathop {\arg \max }\limits_l [{s_{\rm label}}(i,j,\ell)] \
\hat k = \mathop {\arg \max }\limits_k [{s_{\rm split}}(i,j,k)].
\end{array}
$$
自頂向下貪心解碼時間復雜度低,而且實際運行中並沒有損失太多精度,所以可以很好地近似動態規划解碼算法。而由轉移系統的三種遍歷順序,自然而然還可以想到,這里也能推廣到自底向上和中序遍歷的貪心解碼,但是由於這里預測的時候只利用到了局部的短語特征,所以僅僅更改遍歷的順序是沒有效果的,還得充分利用到預測的歷史信息才行。
基於序列到序列的解碼算法
前面幾個章節都是將句法樹視為若干跨度的集合,並預測這個集合,最后還原出句法樹。這個章節將要介紹的方法都是基於序列的,也就是將句法樹序列化,通過預測句法樹對應的序列,然后還原出句法樹。
基於括號表達式

括號表達式是句法樹最為常見的一種序列化方法,圖10展示了句子“John has a dog .”對應的括號表達式。可以證明,括號表達式和句法樹是一一對應的,所以只要預測出了括號表達式,就可以唯一映射到一棵句法樹。這樣句法分析任務就轉化為了輸入一個句子,輸出一個括號表達式序列,這可以用常見的序列到序列模型來解決(VinyalsKKPSH15)。類比到機器翻譯任務,可以把輸入句子當成源語言,輸出的括號表達式當做目標語言,這就轉化為了一個翻譯任務。
但是這種序列化方法存在一個較大的問題,就是限制性太強了,必須要滿足輸出的序列是一個合法的括號表達式,這就大大增加了預測的難度。所以一般這種序列化方法都是用來重排序的,也就是先用現成的句法分析器預測出概率最大的若干棵句法樹,然后預測這幾棵句法樹對應的括號表達式的語言模型概率,挑選出概率最高的一棵作為最終的模型輸出。
基於句法距離

句法距離(syntactic distance)是由(ShenLHC18)首次提出的新概念,句子中相鄰兩個單詞的句法距離定義為它們倆的最近公共祖先的高度。圖11展示了句子“She enjoys playing tennis .”的句法距離序列,對於長度為$n$的句子,它的句法距離序列長度為$n - 1$,並且滿足如下條件:對於任意兩個相鄰的單詞對,它們的最近公共祖先高度越高,那么它們倆的句法距離就越大(BengioSCJLS18)。
以圖11為例,“She”和“enjoys”的最近公共祖先是“S”,所以高度最高,對應的句法距離也最大。“enjoys”和“playing”的最近公共祖先是“VP”,高度排第三,所以對應的句法距離大小也是排第三。依次類推,剩下的句法距離也滿足這個性質。可以證明,這個數字序列和句法樹是一一對應的。更進一步可以發現,這個序列其實就是“中序遍歷的結點的高度”,原文中將其稱為句法距離。
當然實際實現中,句法距離並不一定要和結點高度完全對應,甚至不需要是整數,只需要反映出彼此之間的大小關系就行了。預測這個序列也很簡單,原文中並沒有使用傳統的雙向LSTM序列標注的模型結構,而是首先將句子輸入到一個雙向LSTM,然后將每相鄰兩個單詞的隱層輸出做一次卷積操作(因為要預測相鄰兩個單詞的最近公共祖先的高度),然后再將卷積輸出送到一個雙向LSTM中去,最后通過一個前饋神經網絡得到每相鄰兩個單詞的句法距離。
解碼過程十分簡單,對於一個句法距離序列$d_1, d_2, \ldots, d_n$,首先找出序列中最大的元素$d_i$,然后下標小於$i$的句子構成了左子樹,大於等於$i$的部分構成了右子樹,即句法樹的括號表達式為$((x_{<i})(x_{\ge i}))$。而對於左右兩棵子樹,只需要遞歸解碼下去就行了。
當然這種解碼方式仍然存在一個問題,就是句法距離序列並不一定能唯一映射回句法樹。例如對於序列$(1, 1, 1, 1)$,當出現相同句法距離時,最大的句法距離並不唯一,這時候選誰做根節點都有可能,所以這個句法距離序列可以對應到任意一棵二叉樹。當然在實際運行中,因為預測結果都是浮點數,所以幾乎不會出現這種情況。
其他解碼算法
除了以上介紹的基於轉移系統的、基於動態規划的和基於序列預測的解碼算法以外,還有一些其他的解碼算法。
比如(TengZ18)提出了兩種局部模型。一種是直接預測每個跨度$(i, j)$屬於句法樹的概率,然后使用CKY算法來進行解碼。另一種是預測產生式$(i, j) \to (i, k) (k, j)$的概率,然后還是使用CKY算法來進行解碼。這兩種模型都取得了非常高的F1值。
再比如(TuZZ18)提出了高斯混合隱向量文法(GM-LVeGs),來學習產生式的向量表示,最終的效果也是要好於之前的組合向量文法(CVG)(SocherBMN13)。
若干改進
上面介紹的幾種經典的句法分析模型或多或少都有一些問題,有些解碼速度很慢,有些效果不是很理想,有些實現起來比較麻煩,對於不同模型要做出不同的設計調整,因此許多工作針對這些模型提出了許多優化,下面選取兩個典型的優化來詳細說明。
動態指導
在基於轉移系統的模型和動態規划模型的自頂向下近似解碼模中,都使用到了貪心的解碼算法。這樣就會出現一個問題,就是訓練的時候因為有標准的句法樹,所以不論你解碼到哪一步,都可以繼續按照正確的結果走下去。但是如果在測試階段,如果你預測出了一個從來沒有在訓練階段出現過的狀態,那模型可能就無法知道下一步該往哪走了。這時候就要采用動態指導(dynamic oracle),來告訴模型在錯誤的狀態該往哪走。
這里只簡單說明一下動態規划模型的自頂向下近似解碼中動態指導的定義,基於轉移系統的模型的動態指導類似。
假設現在模型預測出了一個跨度$(i, j)$,那么下面就要預測它的非終結符和分割點。
首先對於非終結符,如果$(i, j)$在標准的句法樹中,那么它的非終結符就是標准的非終結符,否則的話就定義為空集$\varnothing$。
然后對於分割點,如果$(i, j)$在標准的句法樹中,那么分割點就是標准的分割點。否則的話就在標准的句法樹中尋找包含$(i, j)$的最小的跨度$(i', j')$,然后找出$(i', j')$的所有分割點中,位於$(i, j)$之間的分割點,任意取一個都可以作為動態指導。在實際實現中,取滿足條件的最左邊一個分割點。不同的分割點對應了不同的二叉化方式,其實無關緊要。在(CrossH16)中有關於動態指導詳細的證明過程。
策略梯度
除了動態指導解決的問題之外,貪心解碼還存在一個問題,就是它只針對當前時刻來進行優化,而不是針對全局優化,所以得到的並非是全局最優解。此外動態指導針對不同的模型要進行單獨的設計,這就比較麻煩,所以可以采用強化學習中的策略梯度(policy gradient)來替代它(FriedK18)。
首先用風險函數(risk objective)來作為模型的損失函數:
$$
\mathcal{R}(\theta ) = \sum\limits_{i = 1}^N {\sum\limits_y {p(y|{x^{(i)}};\theta )\Delta (y,{y^{(i)}})} },
$$
其中$(x^{(i)}, y^{(i)})$是訓練集中的標准數據。可以看出,風險函數其實就是所有可能的句法樹和標准樹的差異${\Delta (y,{y^{(i)}})}$的期望,訓練的目的就是最小化所有句法樹和標准樹的差異,這樣就解決了之前提到的兩個問題。
但是顯然不可能枚舉所有可能的句法樹,這就得用到重要性采樣(important sampling)方法。但是不能直接對風險函數進行重要性采樣,不然采樣后的函數$\theta$消失了,就沒有辦法對其求導了,所以要先對風險函數求導得到:
$$
\nabla \mathcal{R}(\theta ) \approx \sum\limits_{i = 1}^N {\sum\limits_{y \in \mathcal{Y}({x^{(i)}})} {\Delta (y,{y^{(i)}})\nabla \log p(y|{x^{(i)}};\theta )} },
$$
這里的$y$是根據分布$p(y|x^{(i)})$采樣得到的結果。具體實現中可以將標准樹也加入到采樣結果中,可以提升准確率。
實驗
數據集
成分句法分析使用最為廣泛的英文數據集是華爾街日報的PTB數據集,其中第2~21章節划分為了訓練集,22章節為驗證集,23章節為測試集。中文數據集為CTB數據集,目前已經有5.0,6.0以及8.0等多個版本,但是使用最為廣泛的還是5.0版本。
實驗結果

表1列舉了一些句法分析模型的測試結果,分為了單模型和非單模型兩部分。其中單模型就是不使用任何外部知識及重排序等操作的模型,而非單模型則使用了外部語料、預訓練模型、模型融合和重排序等各種方法。目前單模型最好的結果來自於(KleinK18),他們采用了Transformer作為編碼器,使其結果得到了大大提升。由此可見,目前成分句法分析領域編碼器的影響要遠遠大於解碼器。而非單模型領域最好結果則來自於相同團隊的工作(abs-1812-11760),這里他們使用了更為強大的預訓練模型BERT,使結果上升到了一個難以逾越的高度。
總結與未來展望
本文介紹了成分句法分析領域近些年來的進展,列舉了幾種不同類型的成分句法分析模型(基於轉移系統、基於動態規划、基於序列到序列),並對比分析了它們之間的優缺點,最后提出了幾種常見的改進。
可以預見,未來成分句法分析的研究方向將會是在編碼模型方面,因為解碼模型對性能的提升已經到了瓶頸期,而編碼模型不僅可以大大提升模型效果,還可以運用在無監督成分句法分析上。
參考文獻
- Attention is All you Need
- Transition-based Neural Constituent Parsing
- Span-Based Constituency Parsing with a Structure-Label System and Provably Optimal Dynamic Oracles
- In-Order Transition-based Constituent Parsing
- A Minimal Span-Based Neural Constituency Parser
- Constituency Parsing with a Self-Attentive Encoder
- Straight to the Tree: Constituency Parsing with Neural Syntactic Distance
- Constituent Parsing as Sequence Labeling
- Grammar as a Foreign Language
- Two Local Models for Neural Constituent Parsing
- Long Short-Term Memory Over Tree Structures
- Dependencies vs. Constituents for Tree-Based Alignment
- A tutorial on particle filtering and smoothing: Fifteen years later
- Programming languages and their compilers: Preliminary notes
- Parsing with Compositional Vector Grammars
- Policy Gradient as a Proxy for Dynamic Oracles in Constituency Parsing
- Multilingual Constituency Parsing with Self-Attention and Pre-Training
- Fast and Accurate Shift-Reduce Constituent Parsing
- Shift-Reduce Constituent Parsing with Neural Lookahead Features
- Linear-time Constituency Parsing with RNNs and Dynamic Programming
- Recurrent Neural Network Grammars
- Effective Inference for Generative Neural Parsing
- Parsing as Language Modeling
- Extending a Parser to Distant Domains Using a Few Dozen Partially Annotated Examples
- Improving Neural Parsing by Disentangling Model Combination and Reranking Effects
- Neural Language Modeling by Jointly Learning Syntax and Lexicon
- Gaussian Mixture Latent Vector Grammars
