1. 程式人生 > >CRF++/CRF/條件隨機場的特徵函式模板

CRF++/CRF/條件隨機場的特徵函式模板

由於最近想實現CRF,學完了理論後就開始怎麼想怎麼實現,想參照CRF++的開源實現,但首先要解決的怎麼理解特徵模板,所以寫了此文,主要參考了2篇文章,在此感謝。

  1. CRF++要求的訓練資料格式

對於訓練資料,首先需要多列,但不能不一致,既在一個檔案裡有的行是兩列,有的行是三列;其次第一列代表的是需要標註的字或詞最後一列是輸出位"標記tag"如果有額外的特徵,例如詞性什麼的,可以加到中間列裡,所以訓練集或者測試集的檔案最少要有兩列。

例如:下面所有例子都是以下列的分詞資料舉例

2.關於特徵模板

CRF++的特徵模板通常長下面這個樣子:

“%x[行位置,

列位置]”代表了相對於當前指向的token行偏移和列的絕對位置。

先來解釋以下Unigram特徵模板是什麼意思。

舉例:U00:%x[-2,0]

-2代表是當前行的之前的第2個字元(觀測),

0代表第2列,如果遍歷到的行如下圖:

3.10.1

將產生以下的特徵函式:(注:下列偽碼的x代表觀測,y代表狀態,也就是貼的標籤)

If(y==’B’&&x==’’) return 1 else return 0;

If(y==’E’&&x==’’) return 1 else return 0;

If(y==’M’&&x==’’) return 1 else return 0;

If(y==’S’&&x==’’) return 1 else return 0;

算一算將產生4*655364是狀態個數,65536是不同字元的個數),如果狀態數和觀測數一樣這就對應於HMM的發射矩陣。

這什麼意思呢?學過HMM的知道,這類似於發射矩陣,統計狀態下的觀測分佈。

有人可能要問?U01:%x[-1,0]U02:%x[0,0]2個會重複統計吧?確實是啊,目前我還不清楚為什麼這樣,我猜想這裡要表達的是,當前狀態下的觀測分佈不僅僅受當前觀測字元的影響,還受前第2U02:%x[0,0],前第1U01:%x[-1,0],後1U03:%x[1,0]等的影響。

至於下面這種特徵模板:

我想是統計當前狀態下,視窗為3周圍觀測的分佈,

以圖3.10.1舉例產生下面的特徵函式:

if(x1==’’&&x2==’’&x3==’1’&y==’B’) return 1 else return 0;

if(x1==’’&&x2==’’&x3==’1’&y==’M’) return 1 else return 0;

if(x1==’’&&x2==’’&x3==’1’&y==’E’) return 1 else return 0;

if(x1==’’&&x2==’’&x3==’1’&y==’S’) return 1 else return 0;

這樣想想確實CRFHMM一個發射矩陣表達了更多的資訊。

令人疑惑的是Bigram並沒有直接定義模板函式,只寫了一個B(如上圖),我在HanLp作者的部落格中找到這樣的解釋。如果只寫一個B的話,預設生成f(s', s),其中s't – 1時刻的標籤.也就是說,Bigram型別與Unigram大致機同,只是還要考慮到t – 1時刻的標籤.這意味著前一個output tokencurrent token將組合成bigram features

這樣的話唯一一個bigram特徵模板的所有特徵函式類似於HMM中的轉移矩陣。

還是以圖3.10.1舉例,將產生下列的特徵函式:下面y1是前一個狀態,y2是後一個狀態。

If(y1==’B’&&y2==’B’) return 1 else return 0; 當然這個特徵函式應該是不合理的,當前字元是Begin的狀態,下一個只能是Middle或者End。我們暫時不考慮是否演算法實現考慮了這個特徵函式,因為我也沒具體實現。

If(y1==’B’&&y2==’B’) return 1 else return 0;

If(y1==’B’&&y2==’M’) return 1 else return 0;

If(y1==’B’&&y2==’E’) return 1 else return 0;

If(y1==’B’&&y2==’S’) return 1 else return 0;

If(y1==’M’&&y2==’B’) return 1 else return 0;

If(y1==’M’&&y2==’M’) return 1 else return 0;

If(y1==’M’&&y2==’E’) return 1 else return 0;

If(y1==’M’&&y2==’S’) return 1 else return 0;

If(y1==’E’&&y2==’B’) return 1 else return 0;

If(y1==’E’&&y2==’M’) return 1 else return 0;

If(y1==’E’&&y2==’E’) return 1 else return 0;

If(y1==’E’&&y2==’S’) return 1 else return 0;

If(y1==’S’&&y2==’B’) return 1 else return 0;

If(y1==’S’&&y2==’M’) return 1 else return 0;

If(y1==’S’&&y2==’E’) return 1 else return 0;

If(y1==’S’&&y2==’S’) return 1 else return 0;

暫時學到這兒,等我實現了這個演算法將補充細節或者修正。