[轉] LSTM+ CRF中的損失函數


from https://blog.csdn.net/u013963380/article/details/108696552

本文翻譯,原文地址:

https://createmomo.github.io/2017/10/08/CRF-Layer-on-the-Top-of-BiLSTM-3/

https://createmomo.github.io/2017/10/17/CRF-Layer-on-the-Top-of-BiLSTM-4/

https://createmomo.github.io/2017/11/11/CRF-Layer-on-the-Top-of-BiLSTM-5/

三、CRF損失函數

CRF損失函數由兩部分組成,真實路徑的分數 和 所有路徑的總分數。真實路徑的分數應該是所有路徑中分數最高的。

例如,我們的數據集中有如下幾種類別:

Label Index
B-Person 0
I-Person 1
B-Organization 2
I-Organization 3
O 4
START 5
END 6

一個包含5個單詞的句子,可能的類別序列如下:

  • 1) START B-Person B-Person B-Person B-Person B-Person END
  • 2) START B-Person I-Person B-Person B-Person B-Person END
  • 10) START B-Person I-Person O B-Organization O END
  • N) O O O O O O O

假設每種可能的路徑的分數為P_{i},共有N條路徑,則路徑的總分是:

P_{total}=P_{1}+P_{2}+...+P_{N}=e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}e是一個數學常量。(下節會詳細介紹如何計算S_{i},這里你可以把它當作這條路徑的分數)。

如果第十條路徑是真實路徑,也就是說第十條是正確預測結果,那么P_{10}應該是所有可能路徑里分數最高的。根據如下損失函數,在訓練過程中,BiLSTM-CRF模型的參數值將隨着訓練過程的迭代不斷更新,使得真實路徑所占的比值越來越大。

LossFunction=\frac{P_{RealPath}}{P_{1}+P_{2}+...+P_{N}}

那么現在的問題就是:

  • 如何定義路徑的分數
  • 怎么計算所有路徑的分數
  • 當計算所有的路徑分時,是否需要窮舉多有可能的路徑?(答案是不需要)

四、真實路徑分數

很明顯,在所有的可能的路徑中有一條是真實的路徑。比如在上述的類別序列中,“START B-Person I-Person O B-Organization O END”是一條真實的路徑。不正確的路徑如“START B-Person B-Organization O I-Person I-Person B-Person”。e^{S_{1}}是第i條路徑的分數。

在訓練階段,crf的損失函數只需要兩種類別的分數,真實路徑的分數 和 所有路徑的總分數。在所有的可能路徑的分數中,真實路徑的分數應該是最高的。

當然計算e^{S_{1}}是十分簡單的,下面讓我們聚焦如何來計算S_{i}

我們假設“START B-Person I-Person O B-Organization O END”是一條真實的路徑:

  • 一個句子中有5個單詞,分別是w_{1},w_{2},w_{3},w_{4},w_{5}
  • 添加開始和結尾單詞,分別是w_{0},w_{6}
  • S_{i}包含兩個部分,S_{i}=EmissionScore+TransitionScore

tips:Emission Score 和 Transition Score在《BiLSTM中的CRF層(二)CRF層》一文中已經介紹。

(1)Emission Score(發射分數):

EmissionScore=x_{0,START}+x_{1,B-Person}+x_{2,I-Person}+x_{3,O}+x_{4,B-Organization}+x_{5,O}+x_{6,END}

  • x_{index,label}是第index索引的單詞被標注為label的分數
  • x_{1,B-Person},x_{2,I-Person},x_{3,O},x_{4,B-Organization},x_{5,O}這些分數來自前一層BiLstm的輸出
  • x_{0,START},x_{6,END}可以設置為0

(2)Transition Score(轉移分數):

TransitionScore=t_{START->B-Person}+t_{B-Person->I-Person}+t_{I-Person->O}+t_{O->B-Organization}+t_{B-Organization->O}+t_{O->END}

  • t_{label1->label2}是從label1轉移到label2的分數
  • 這些分數來自於CRF層。換句話說,這些分數其實是CRF層的參數

五、所有路徑的分數

上面提到所有路徑的分數P_{total}=P_{1}+P_{2}+...+P_{N}=e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}。計算所有路徑的總分最簡單的方式是:窮舉所有可能的路徑,分別計算路徑分,最后求和。但是這種方式是十分低效的,而且訓練時間也是不可忍受的。

下面以一個簡單的例子來說明如何高效的計算所有路徑的分數。

Step1: recall the CRF loss function

CRF損失函數的定義是LossFunction=\frac{P_{RealPath}}{P_{1}+P_{2}+...+P_{N}},我們把它變成log損失函數如下:

LogLossFunction=log\frac{P_{RealPath}}{P_{1}+P_{2}+...+P_{N}},由於我們訓練的目標通常是最小化損失函數,所以我們加上負號:

LogLossFunction=log\frac{P_{RealPath}}{P_{1}+P_{2}+...+P_{N}}\\=-log\frac{e^{S_{RealPath}}}{e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}}\\=-(loge^{S_{RealPath}}-log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}))\\ =-(S_{RealPath}-log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}))\\ =-(\sum_{i=1}^{N}x_{iyi}+\sum_{i=1}^{N-1}t_{yiyi+1}-log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}))

(原文中在求真實路徑的分數的時候,求和用的是N和N-1,但是從上面的求解發射分數和轉移分數公式看,這里的N應該是句子的長度words,N-1應該是標簽數num_tag,所有的路徑總數N應該是N=(num_tag)^(words),否則對應不上。不知道是不是作者為了簡化統一用N表示,還是本人理解錯誤。。。囧囧囧)

在上面,我們已經知道如何計算真實路徑的分數,下面我們只需要找到一種高效的方式來計算log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}})

Step2:recall the Emission and Transition Score

為了簡化說明,這里我們假設我們訓練模型的句子只有3的長度,標簽只有2種:

x=[w_{0},w_{1},w_{2}]

labelset=[l_{1}, l_{2}]

我們從Bi-Lstm層獲得的發射分數如下:

  l_{1} l_{2}
w_{0} x_{01} x_{02}
w_{1} x_{11} x_{12}
w_{2} x_{21} x_{22}

tips:x_{ij}表示單詞w_{i}被標簽為l_{j}的分數。

從CRF層獲得的轉移分數如下:

  l_{1} l_{2}
l_{1} t_{11} t_{12}
l_{2} t_{21} t_{22}

tips:t_{ij}表示從標簽i轉移到標簽j的分數

Step3:START FIGHTING! 

首先要記得我們的目標是log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}})

整個過程其實是分數累加的過程。它的思想和動態規划如出一轍。總而言之就是,首先單詞w_{0}的所有路徑的總分被計算出來;然后,計算從w_{0}->w_{1} 的所有路徑的得分,最后計算w_{0}->w_{1}->w_{2}的所有路徑的得分,也就是我們最終要的結果。

接下來,你會看到兩個變量:obs和 previous。previous存儲了之前步驟的結果,obs代表當前單詞的信息。

=======================================================================================================

w_{0}

obs=[x_{01},x_{02}]

previous=None

如果我們的句子只有一個單詞w_{0},前一個步驟沒有任何的結果,因此previous=None。另外,我們只能獲取到obs=[x_{01},x_{02}]x_{01}x_{02}是上面提到的從BiLSTM層獲得的發射分數。

因此,這里單詞w_{0}的所有路徑分數為:

TotalScore(w_{0})=log(e^{x_{01}}+e^{x_{02}})

=======================================================================================================

w_{0}->w_{1}

obs=[x_{11},x_{12}]

previous=[x_{01},x_{02}]

(1) 將previous擴展為:

previous=\begin{pmatrix} x_{01} & x_{01} \\ x_{02} & x_{02} \end{pmatrix}

(2) 將obs擴展為:

obs=\begin{pmatrix} x_{11} & x_{12} \\ x_{11} & x_{12} \end{pmatrix}

將previos和obs擴展是為了計算總分更加高效。下面將會看到

(3) 對previou、obs和轉移分數求和:

scores=\begin{pmatrix} x_{01} & x_{01}\\ x_{02} & x_{02} \end{pmatrix} + \begin{pmatrix} x_{11} & x_{11}\\ x_{12} & x_{12} \end{pmatrix} + \begin{pmatrix} t_{11} & t_{12}\\ t_{21} & t_{22} \end{pmatrix}

score=\begin{pmatrix} x_{01}+x_{11}+t_{11} & x_{01}+x_{12}+t_{12}\\ x_{02}+x_{11}+t_{21} & x_{02}+x_{12}+t_{22} \end{pmatrix}

然后改變previos的值

previous=[log(e^{x_{01}+x_{11}+t_{11}}+e^{x_{02}+x_{11}+t_{21}}),log(e^{x_{01}+x_{12}+t_{12}}+e^{x_{02}+x_{12}+t_{22}})]

到這里,第二次迭代實際上已經完成了。然后,我們使用新的previous值來計算w_{0}->w_{1}的所有路徑總分:

TotalScore(w_{0}->w_{1})\\ =log(e^{previous[0]}+e^{previous[1]})\\ =log(e^{log(e^{x_{01}+x_{11}+t_{11}}+e^{x_{02}+x_{11}+t_{21}})}+e^{log(e^{x_{01}+x_{12}+t_{12}}+e^{x_{02}+x_{12}+t_{22}})})\\ =log(e^{e^{x_{01}+x_{11}+t_{11}}}+e^{x_{02}+x_{11}+t_{21}}+e^{x_{01}+x_{12}+t_{12}}+e^{x_{02}+x_{12}+t_{22}})

從上面公式可以看出,這就是我們的求解目標log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}})

在上述公式中:

  • S_{1}=x_{01}+x_{11}+t_{11}\ (label1->label1)
  • S_{2}=x_{02}+x_{11}+t_{21}\ (label2->label1)
  • S_{3}=x_{01}+x_{12}+t_{12}\ (label1->label2)
  • S_{4}=x_{02}+x_{12}+t_{22}\ (label2->label2)

=======================================================================================================

下面的手碼太累了,直接貼原文的截圖,截圖出自(https://createmomo.github.io/2017/11/11/CRF-Layer-on-the-Top-of-BiLSTM-5/),原理是一樣的。

=======================================================================================================

上述過程建議用手推一遍,對理解這個過程十分有用。。。

至此,我們完成了log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}})的求解過程。

六、如何利用CRF來推理

前面幾節介紹了Bi-Lstm-CRF的模型結構以及CRF損失函數。我們可以使用開源的深度學習框架(Keras、tensorflow等)來實現一個Bi-Lstm-CRF模型。而且用這些框架最好的是不用自己來實現反向傳播這個過程,更有的框架已經實現了CRF層,只需要添加一行代碼就可以完全實現Bi-Lstm-CRF模型。

推理的過程和上述求解所有路徑總分的過程有點相似,每次獲取得分最高的路徑,最終選擇所有路徑中得分最高的路徑為最佳路徑。

詳細過程見原文:https://createmomo.github.io/2017/11/24/CRF-Layer-on-the-Top-of-BiLSTM-6/

這里不再講述,因為整個過程十分簡單,理解了第五節中的求解過程即可。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM