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
假設每種可能的路徑的分數為,共有
條路徑,則路徑的總分是:
,
是一個數學常量。(下節會詳細介紹如何計算
,這里你可以把它當作這條路徑的分數)。
如果第十條路徑是真實路徑,也就是說第十條是正確預測結果,那么應該是所有可能路徑里分數最高的。根據如下損失函數,在訓練過程中,BiLSTM-CRF模型的參數值將隨着訓練過程的迭代不斷更新,使得真實路徑所占的比值越來越大。
那么現在的問題就是:
- 如何定義路徑的分數
- 怎么計算所有路徑的分數
- 當計算所有的路徑分時,是否需要窮舉多有可能的路徑?(答案是不需要)
四、真實路徑分數
很明顯,在所有的可能的路徑中有一條是真實的路徑。比如在上述的類別序列中,“START B-Person I-Person O B-Organization O END”是一條真實的路徑。不正確的路徑如“START B-Person B-Organization O I-Person I-Person B-Person”。是第
條路徑的分數。
在訓練階段,crf的損失函數只需要兩種類別的分數,真實路徑的分數 和 所有路徑的總分數。在所有的可能路徑的分數中,真實路徑的分數應該是最高的。
當然計算是十分簡單的,下面讓我們聚焦如何來計算
。
我們假設“START B-Person I-Person O B-Organization O END”是一條真實的路徑:
- 一個句子中有5個單詞,分別是
- 添加開始和結尾單詞,分別是
包含兩個部分,
tips:Emission Score 和 Transition Score在《BiLSTM中的CRF層(二)CRF層》一文中已經介紹。
(1)Emission Score(發射分數):
是第
索引的單詞被標注為
的分數
這些分數來自前一層BiLstm的輸出
可以設置為0
(2)Transition Score(轉移分數):
是從label1轉移到label2的分數
- 這些分數來自於CRF層。換句話說,這些分數其實是CRF層的參數
五、所有路徑的分數
上面提到所有路徑的分數。計算所有路徑的總分最簡單的方式是:窮舉所有可能的路徑,分別計算路徑分,最后求和。但是這種方式是十分低效的,而且訓練時間也是不可忍受的。
下面以一個簡單的例子來說明如何高效的計算所有路徑的分數。
Step1: recall the CRF loss function
CRF損失函數的定義是,我們把它變成log損失函數如下:
,由於我們訓練的目標通常是最小化損失函數,所以我們加上負號:
(原文中在求真實路徑的分數的時候,求和用的是N和N-1,但是從上面的求解發射分數和轉移分數公式看,這里的N應該是句子的長度words,N-1應該是標簽數num_tag,所有的路徑總數N應該是N=(num_tag)^(words),否則對應不上。不知道是不是作者為了簡化統一用N表示,還是本人理解錯誤。。。囧囧囧)
在上面,我們已經知道如何計算真實路徑的分數,下面我們只需要找到一種高效的方式來計算。
Step2:recall the Emission and Transition Score
為了簡化說明,這里我們假設我們訓練模型的句子只有3的長度,標簽只有2種:
我們從Bi-Lstm層獲得的發射分數如下:
![]() |
![]() |
|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
tips:表示單詞
被標簽為
的分數。
從CRF層獲得的轉移分數如下:
![]() |
![]() |
|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
tips:表示從標簽
轉移到標簽
的分數
Step3:START FIGHTING!
首先要記得我們的目標是
整個過程其實是分數累加的過程。它的思想和動態規划如出一轍。總而言之就是,首先單詞的所有路徑的總分被計算出來;然后,計算從
的所有路徑的得分,最后計算
的所有路徑的得分,也就是我們最終要的結果。
接下來,你會看到兩個變量:obs和 previous。previous存儲了之前步驟的結果,obs代表當前單詞的信息。
=======================================================================================================
:
如果我們的句子只有一個單詞,前一個步驟沒有任何的結果,因此previous=None。另外,我們只能獲取到
,
和
是上面提到的從BiLSTM層獲得的發射分數。
因此,這里單詞的所有路徑分數為:
=======================================================================================================
:
(1) 將previous擴展為:
(2) 將obs擴展為:
將previos和obs擴展是為了計算總分更加高效。下面將會看到
(3) 對previou、obs和轉移分數求和:
然后改變previos的值
到這里,第二次迭代實際上已經完成了。然后,我們使用新的previous值來計算的所有路徑總分:
從上面公式可以看出,這就是我們的求解目標
在上述公式中:
=======================================================================================================
下面的手碼太累了,直接貼原文的截圖,截圖出自(https://createmomo.github.io/2017/11/11/CRF-Layer-on-the-Top-of-BiLSTM-5/),原理是一樣的。
=======================================================================================================
上述過程建議用手推一遍,對理解這個過程十分有用。。。
至此,我們完成了的求解過程。
六、如何利用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/
這里不再講述,因為整個過程十分簡單,理解了第五節中的求解過程即可。