在用LSTM+CRF做命名實體識別任務時,由於pytorch框架的crf需要自己實現,網上的很多教程都跳過了一些關鍵部分導致自己難以理解。本文用來記錄自己的相關理解,僅針對線性鏈式的CRF。歡迎指正。
1. log linear model
CRF、MEMM、N元邏輯迴歸都屬於log linear model。我們先來理解這個大類。
p(y∣x;w∣J∣)=∑y′∈Yexp(w∣J∣⋅F∣J∣(x,y′))exp(w∣J∣⋅F∣J∣(x,y))
其中w爲模型參數,F∣J∣(x,y)爲給定輸入特徵x,輸出標籤y的特徵向量。
注意:這裏模型參數和特徵向量都爲J, 物理意義是該模型一共有J個特徵。點乘表示用這J個特徵計算一個分數。與NLP任務中輸入序列長度無關!
1.2 邏輯迴歸
各種log linear model模型的區別,僅僅是在特徵函數F∣J∣(x,y)的定義不同。對於邏輯迴歸,假設特徵x長度爲M, 標籤類別數爲N, 那麼J=M∗N。且Fj=flaten(x×Iy=C)
1.1 CRF與邏輯迴歸的區別
CRF與邏輯迴歸的不同,在於
- (1)CRF的特徵函數F∣J∣(x,y)考慮了輸入數據中的時序信息
F∣J∣(x,y)=i=2∑Tf∣J∣(xi,yi,yi−1)(1.1)
- (2)CRF的y與x都增加了一個維度,即序列長度T
2. NER中的LSTM+CRF
2.1 CRF的特徵定義
對於NER任務中,序列長度爲T,標籤類別數爲n的數據,LSTM的輸出特徵矩陣BT×n作爲CRF層的輸入,Bi,j爲第i個時間步爲標籤j的概率。NER任務的CRF中我們定義了兩個特徵函數:
- 輸入特徵B (代碼中的feats, 可以理解爲發射概率矩陣)
- 和轉移特徵A (代碼中的transition矩陣)
權重w=[1,1]現在重寫CRF的特徵如下,並將其定義爲score:
score(y∣A,B)=w∣J∣⋅F∣J∣(x,y))=w⋅i=2∑Tf∣J∣(xi,yi,yi−1)=B1,y1+i=2∑T(Bi,yi+Ayi−1,yi)
理解了這兩個特徵,就成功的將CRF於NER任務結合了。下面要知道如何估計特徵參數,即反向傳播A和B。
2.2 參數估計
對於一個訓練樣本,有一個輸入序列x和一個tag序列y。x經過LSTM層得到特徵矩陣B。
我們的目標是求現有參數下的概率p(y∣A,B),並最大化這個值,按照老規矩使用其負對數作爲loss, 回到log-linear model的定義,:
loss=−log(p(y∣A,B))=−log(∑y^exp(score(y^∣A,B))exp(score(y∣A,B)))=log(y^∑exp(score(y^∣A,B)))−score(y∣A,B)=log_sum_exp(score(y^∣A,B)))
一旦loss確定,剩下的事就可以交給pytorch框架來自動優化了。但是上面這個loss怎麼計算呢?score(y∣A,B)這一項好說,線性複雜度O(T)。
2.3 全局正則項的計算推導
Z=log(∑y^exp(score(y^∣A,B)))這一項,如果用暴力計算,就是要先算出每一個時間步的所有可能路徑,複雜度爲O(TnT), 分類數稍多一點就會涼。需要想辦法消掉指數複雜度,而很巧的是,這確實可以在輸入序列上轉換爲子問題,從而使用動態規劃算法。根據上述score的計算公式,可以將輸入序列長度爲T的正則項寫爲:
Z=log(y^∑exp(score(y^(1,T−1)∣A,B)+score(y^(T−1,T)∣A,B)))=log(y^∑(escore(y^(1,T−1)∣A,B)⋅escore(y^(T−1,T)∣A,B)))
注意這裏score(y^(T−1,T)∣A,B)=BT,yT+AyT−1,yT,表示所有路徑在第T-1到第T步的分數,將其作爲係數,合併同類項:
Z(T)=log(∑escore(y^(T−1,T)∣A,B))y^∑(escore(y^(1,T−1)∣A,B))=Z(T−1)+log_sum_exp(score(y^(T−1,T)∣A,B))
到這裏就該知道是標準的動態規劃了。
參考文獻
- Pytorch Bi-LSTM + CRF 代碼詳解
- Bi-LSTM-CRF for Sequence Labeling
- Bi-LSTM Conditional Random Field Discussion
- 系列文章:CRF Layer on the Top of BiLSTM - 5