CRF簡介入門

CRF簡介

Conditional Random Field:條件隨機場,一種機器學習技術(模型)dom

CRFJohn Lafferty最先用於NLP技術領域,其在NLP技術領域中主要用於文本標註,並有多種應用場景,例如:iphone

  • 分詞(標註字的詞位信息,由字構詞)
  • 詞性標註(標註分詞的詞性,例如:名詞,動詞,助詞)
  • 命名實體識別(識別人名,地名,機構名,商品名等具備必定內在規律的實體名詞)

本文主要描述如何使用CRF技術來進行中文分詞。機器學習

CRF VS 詞典統計分詞

  • 基於詞典的分詞過分依賴詞典和規則庫,所以對於歧義詞和未登陸詞的識別能力較低;其優勢是速度快,效率高
  • CRF表明了新一代的機器學習技術分詞,其基本思路是對漢字進行標註即由字構詞(組詞),不只考慮了文字詞語出現的頻率信息,同時考慮上下文語境,具有較好的學習能力,所以其對歧義詞和未登陸詞的識別都具備良好的效果;其不足之處是訓練週期較長,運營時計算量較大,性能不如詞典分詞

CRF VS HMM,MEMM

  • 首先,CRFHMM(隱馬模型)MEMM(最大熵隱馬模型)都經常使用來作序列標註的建模,像分詞、詞性標註,以及命名實體標註
  • 隱馬模型一個最大的缺點就是因爲其輸出獨立性假設,致使其不能考慮上下文的特徵,限制了特徵的選擇
  • 最大熵隱馬模型則解決了隱馬的問題,能夠任意選擇特徵,但因爲其在每一節點都要進行歸一化,因此只能找到局部的最優值,同時也帶來了標記偏見的問題,即凡是訓練語料中未出現的狀況全都忽略掉
  • 條件隨機場則很好的解決了這一問題,他並不在每個節點進行歸一化,而是全部特徵進行全局歸一化,所以能夠求得全局的最優值。

CRF分詞原理

1. CRF把分詞當作字的詞位分類問題,一般定義字的詞位信息以下:ide

  • 詞首,經常使用B表示
  • 詞中,經常使用M表示
  • 詞尾,經常使用E表示
  • 單子詞,經常使用S表示

2. CRF分詞的過程就是對詞位標註後,將B和E之間的字,以及S單字構成分詞函數

3. CRF分詞實例:工具

  • 原始例句:我愛北京天安門
  • CRF標註後:我/S 愛/S 北/B 京/E 天/B 安/M 門/E
  • 分詞結果:我/愛/北京/天安門

CRF分詞工具包

上面介紹了CRF技術思想以及如何用於分詞,下面將介紹如何在實際開發中使用CRF進行分詞工做。目前常見的CRF工具包有pocket crf, flexcrf 車crf++,目前網上也有一些它們3者之間的對比報告,我的感受crf++在易用性,穩定性和準確性等綜合方面的表現最好,同時在公司的項目開發中也一 直在使用,所以下面將概述一下crf++的使用方法(具體細節能夠到crf++官方主頁去查 閱,http://crfpp.sourceforge.net/)性能

1.安裝
編譯器要求:C++編譯器(gcc 3.0或更高)
命令:
% ./configure
% make
% su
# make install
注:只有擁有root賬號的用戶才能成功安裝。學習

2.使用
2.1訓練和測試文件的格式
訓練和測試文件必須包含多個tokens,每一個token包含多個列。token的定義可根據具體的任務,如詞、詞性等。每一個token必須寫在一行,且各列之間用空格或製表格間隔。一個token的序列可構成一個sentence,sentence之間用一個空行間隔。
最後一列是CRF用於訓練的正確的標註形式。
例如:
iphone ASCII S
是 CN S
一 CN S  >> 當前token
款 CN S
不 CN B
錯 CN E
的 CN S
手 CN B
機 CN E
, PUNC S
還 CN S
能 CN S
聽 CN B
歌 CN E
。PUCN S
我上面的例子每一個token包含3列,分別爲字自己、字類型(英文數字,漢字,標點等)和詞位標記。
注意:若是每個token的列數不一致,系統將不能正確運行。
2.2準備特徵模板
使用CRF++的用戶必須本身肯定特徵模板。
1)基本模板和宏
模板文件中的每一行表明一個template。每個template中,專門的宏%x[row,col]用於肯定輸入數據中的一個token。row用於肯定與當前的token的相對行數。col用於肯定絕對行數。
如已知下面的輸入數據:
iphone ASCII S
是 CN S
一 CN S  >> 當前token
款 CN S
不 CN B
錯 CN E
的 CN S
手 CN B
機 CN E
特徵模板形式爲:
# Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-1,0]/%x[0,0]
U06:%x[0,0]/%x[1,0]
U07:%x[-1,0]/%x[1,0]
U08:%x[0,1]
U09:%x[-1,1]/%x[0,1]
# Bigram
B
2)模板類型
有兩種模板類型,它們可由template的第一個字符肯定。
第一種是Unigram template:第一個字符是U
這是用於描述unigram feature的模板。當你給出一個模板"U02:%x[0,0]",CRF會自動的生成一個特徵函數集合(func1 ... funcN),如:
func1 = if (output = B and feature="U02:一") return 1 else return 0
func2 = if (output = M and feature="U02:一") return 1 else return 0
func3 = if (output = E and feature="U02:一") return 1  else return 0
func4 = if (output = S and feature="U02:一") return 1  else return 0
...
funcX = if (output = B and feature="U02:的") return 1  else return 0
funcY = if (output = S and feature="U02:的") return 1  else return 0
...
一個模型生成的特徵函數的個數總數爲L*N,其中L是輸出的類別數,N是根據給定的template擴展出的unique string的數目。
第二種類型Bigram template:第一個字符是B
這 個模板用於描述bigram features。使用這個模板,系統將自動產生當前輸出token與前一個輸出token(bigram)的組合。產生的可區分的特徵的總數是 L*L*N,其中L是輸出類別數,N是這個模板產生的unique features數。當類別數很大的時候,這種類型會產生許多可區分的特徵,這將會致使訓練和測試的效率都很低下。
3)使用標識符區分相對位置
若是用戶須要區分token的相對位置時,可使用標識符。
好比在下面的例子中,宏"%x[-2,0]"和"%x[1,0]"都表明「北」,可是它們又是不一樣的「北「。
北 CN B
京 CN E
的 CN S  >> 當前token
北 CN S
部 CN S
爲了區分它們,能夠在模型中加入一個惟一的標識符(U00: 或 U03:),即:
U00:%x[-2,0]
U03:%x[1,0]
在這樣的條件下,兩種模型將被認爲是不一樣的,由於他們將被擴展爲」U00:北「和」U03:北」。只要你喜歡,你可使用任何標識符,可是使用數字序號區分更頗有用,由於它們只需簡單的與特徵數相對應。
3.訓練(編碼)
使用crf_learn 命令:
% crf_learn template_file train_file model_file
其中,template_file和train_file需由使用者事先準備好。crf_learn將生成訓練後的模型並存放在model_file中。
通常的,crf_learn將在STDOUT上輸出下面的信息。還會輸出其餘的和LBFGS迭代相關的信息。
% crf_learn template_file train_file model_file
CRF++: Yet Another CRF Tool Kit
Copyright (C) 2005 Taku Kudo, All rights reserved.
reading training data:
Done! 0.32 s
Number of sentences:          77
Number of features:           32856
Freq:                         1
eta:                          0.0001
C(sigma^2):                   10
iter=0 terr=0.7494725738 serr=1 obj=2082.968899 diff=1
iter=1 terr=0.1671940928 serr=0.8831168831 obj=1406.329356 diff=0.3248438053
iter=2 terr=0.1503164557 serr=0.8831168831 obj=626.9159973 diff=0.5542182244
其中:
iter:迭代次數
terr:和tags相關的錯誤率(錯誤的tag數/全部的tag數)
serr:與sentence相關的錯誤率(錯誤的sentence數/全部的sentence數)
obj:當前對象的值。當這個值收斂到一個肯定的值是,CRF模型將中止迭代
diff:與上一個對象值之間的相對差
有兩個主要的參數用於控制訓練條件:
-c float:使用這個選項,你能夠改變CRF的hyper-parameter。當取一個極大的C值,CRF將可能對訓練數據產生過擬合 (overfitting)現象。這個參數將會調節overfitting和underfitting之間的平衡。結果將會對參數帶來有意義的影響。使用 者能夠經過使用held-out data或者更多的通用模型的選擇方法如十字交叉驗證法(cross validation)得到最有的值。
-f NUM:這個參數用於設置特徵的cut-off閾值。CRF++訓練時只使用出現次數很多於NUM次數的特徵進行訓練。默認值爲1。當使用CRF++訓練大規模數據時,單一特徵的數量將達到數百萬,此時選擇這個參數頗有用。
這裏有一個使用這兩個參數的例子:
% crf_learn -f 3 -c 1.5 template_file train_file model_file
4.測試(解碼)
使用crf_test 命令:
% crf_test -m model_file test_files ...
其中,model_file是crf_learn建立的。在測試過程當中,使用者不須要指定template file,由於,mode file已經有了template的信息。test_file是你想要標註序列標記的測試語料。這個文件的書寫格式應該與訓練文件一致。
下面是一個crf_test輸出的例子:
% crf_test -m model test.data
Rockwell        NNP     B       B
International   NNP     I       I
Corp.   NNP     I       I
's      POS     B       B
Tulsa   NNP     I       I
unit    NN      I       I
..
其中,最後一列是模型估計的tag。若是第三列是標準的tag,則能夠經過簡單的比較第三列和第四列之間的差異計算出準確率。
詳細的層次(verbose level)
-v選項:將設置verbose level。默認值爲0。經過增長層次,你能夠從CRF++得到額外的信息。
層次1:
你 能夠對每一個tag使用邊緣機率(marginal probabilities)(這是一種對輸出tag的confidence measure),對輸出使用條件機率(conditional probably)(針對整個輸出的confidence measure)。
例如:
% crf_test -v1 -m model test.data| head
# 0.478113
Rockwell        NNP     B       B/0.992465
International   NNP     I       I/0.979089
Corp.   NNP     I       I/0.954883
's      POS     B       B/0.986396
Tulsa   NNP     I       I/0.991966
...
其中,第一行的"# 0.478113"便是輸出的條件機率,並且每個輸出tag各自含有一個機率,表示形式如「B/0.992465」。
層次2:
你能夠對全部的其餘候選求邊緣機率。
例如:
% crf_test -v2 -m model test.data
# 0.478113
Rockwell        NNP     B       B/0.992465      B/0.992465      I/0.00144946    O/0.00608594
International   NNP     I       I/0.979089      B/0.0105273     I/0.979089      O/0.0103833
Corp.   NNP     I       I/0.954883      B/0.00477976    I/0.954883      O/0.040337
's      POS     B       B/0.986396      B/0.986396      I/0.00655976    O/0.00704426
Tulsa   NNP     I       I/0.991966      B/0.00787494    I/0.991966      O/0.00015949
unit    NN      I       I/0.996169      B/0.00283111    I/0.996169      O/0.000999975
..
N-best outputs
-n選項:使用這個選項將得到N-best結果,它根據CRF計算出的條件機率排序獲得。當選擇了N-best結果,CRF++會自動添加一行,形式爲「# N prob」,其中N是排序後的輸出結果,從0開始。prob表示output的條件機率。
須要注意的是,若是CRF++不能找到足夠的N條路徑是,它將放棄列舉N-best結果。這種狀況在所給的句子很短的狀況下常出現。
CRF++使用前向Viterbi和後向A*搜索相結合的方法。這種結合適應了n-best結果的需求。
下面是一個N-best結果的例子:
% crf_test -n 20 -m model test.data
# 0 0.478113
Rockwell        NNP     B       B
International   NNP     I       I
Corp.   NNP     I       I
's      POS     B       B
...
# 1 0.194335
Rockwell        NNP     B       B
International   NNP     I       I測試

相關文章
相關標籤/搜索