基於結構化平均感知機的分詞器Java實現

adnb34g發表於2019-01-14

基於結構化平均感知機的分詞器 Java實現

最近高產似母豬,寫了個基於 AP的中文分詞器,在Bakeoff-05的MSR語料上F值有96.11%。最重要的是,只訓練了5個迭代;包含語料載入等IO操作在內,整個訓練一共才花費23秒。應用裁剪演算法去掉模型中80%的特徵後,F值才下降不到0.1個百分點,體積控制在11兆。如果訓練一百個迭代,F值可達到96.31%,訓練時間兩分多鐘。

資料在一臺普通的 IBM相容機上得到:

 

本模組已整合到 HanLP 1.6以上版本開源,文件位於專案wiki中,歡迎使用!【 hanlp1.7新版本已經發布,可以去新版本查到看使用

結構化預測

關於結構化預測和非結構化預測的區別一張講義說明如下:

 

更多知識請參考 Neubig的講義《The Structured Perceptron》。

 

本文實現的 AP分詞器預測是整個句子的BMES標註序列,當然屬於結構化預測問題了。

感知機

二分類

感知機的基礎形式如《統計學習方法》所述,是定義在一個超平面上的線性二分類模型。作為原著第二章,實在是簡單得不能再簡單了。然而實際運用中,越簡單的模型往往生命力越頑強。

這裡唯一需要補充的是,感知機是個線上學習模型,學習一個訓練例項後,就可以更新整個模型。

多分類

怎麼把二分類擴充到多分類呢?可以用多個分類器,對於 BMES這4種分類,就是4個感知機了。每個感知機分別負責分辨“是不是B”“是不是M”“是不是E”“是不是S”這4個二分類問題。在實現中,當然不必傻乎乎地建立4個感知機啦。把它們的權值向量拼接在一起,就可以輸出“是B的分數”“是M的分數”“是E的分數”“是S的分數”了。取其最大者,就可以初步實現多分類。但在分詞中,還涉及到轉移特徵和HMM-viterbi搜尋演算法等,留到下文再說。

平均感知機

平均感知機指的是記錄每個特徵權值的累計值,最後平均得出最終模型的感知機。為什麼要大費周章搞個平均演算法出來呢?

前面提到過,感知機是個線上學習模型,學習一個訓練例項後,就可以更新整個模型。假設有 10000個例項,模型在前9999個例項的學習中都完美地得到正確答案,說明此時的模型接近完美了。可是最後一個例項是個噪音點,樸素感知機模型預測錯誤後直接修改了模型,導致前面9999個例項預測錯誤,模型訓練前功盡棄。

有什麼解決方案呢?一種方案是投票式的,即記錄每個模型分類正確的次數,作為它的得票。訓練結束時取得票最高的模型作為最終模型。但這種演算法是不實際的,如果訓練 5個迭代,10000個例項,那麼就需要儲存50000個模型及其票數,太浪費了。

 

最好用的方法是平均感知機,將這 50000個模型的權值向量累加起來,最後除以50000就行了,這樣任何時候我們只額外記錄了一個累加值,非常高效了。關於平均感知機的詳情請參考《200行Python程式碼實現感知機詞性標註器》。雖然那篇文章是講解詞性標註的,但相信作為萬物靈長的讀者一定擁有舉一反三的泛化能力。

語言模型

HMM

我們不是在講解感知機分詞嗎?怎麼跟 HMM扯上關係了?

其實任何基於序列標註的分詞器都離不開隱馬爾科夫鏈,即 BMES這四個標籤之間的Bigram(乃至更高階的n-gram)轉移機率。作為其中一員的AP分詞器,也不例外地將前一個字元的標籤作為了一個特徵。該特徵對預測當前的標籤毫無疑問是有用的,比如前一個標籤是B,當前標籤就絕不可能是S。

這種類似於 y[i-1]的特徵線上性圖模型中一般稱為轉移特徵,而那些不涉及y[i-1]的特徵通常稱為狀態特徵。

viterbi

由於 AP分詞器用到了轉移特徵,所以肯定少不了維特比搜尋。從序列全體的準確率考慮,搜尋也是必不可少的。給定隱馬爾可夫模型的3要素,我用Java寫了一段“可執行的偽碼”:

 

 

上述實現是個重視條理勝於效率的原型,古人云 “過早最佳化是魔鬼”。相信聰明的讀者一定能看懂這裡面在幹什麼。

特徵提取

定義字元序列為 x,標註序列為y。

轉移特徵

轉移特徵就是上面說的 y[i-1]。

狀態特徵

我一共使用了 7種狀態特徵:

 

在鄧知龍的《基於感知器演算法的高效中文分詞與詞性標註系統設計與實現》中提到,要利用更復雜的字元 n-gram、字元類別n-gram、疊字、詞典等特徵。但在我的實踐中,除了上述7種特徵外,我每減少一個特徵,我的AP分詞器的準確率就提高一點,也許是語料不同吧,也許是特徵提取的實現不同。總之,主打精簡、高效。

訓練

迭代數目其實不需要太多,在 3個迭代內模型基本就收斂了:

 

4個迭代似乎幫了倒忙,但萬幸的是,我們使用的是平均感知機。權值平均之後,模型的效能反而有所提升。

此時模型大小:

 

模型裁剪

《基於感知器演算法的高效中文分詞與詞性標註系統設計與實現》提到的模型裁剪策略是有效的,我將壓縮率設為 0.2,即壓縮掉20%的特徵,模型準確率沒有變化:

 

由於我使用了隨機 shuffle演算法,所以每次訓練準確率都略有微小的上下波動。此時可以看到模型裁剪過程花了額外的1分鐘,裁剪完畢後準確率維持96.11不變。

此時模型大小:

 

裁減掉 50%如何呢?

 

此時模型大小:

 

可見裁剪了 80%的特徵,體積從54M下降到11M,模型的準確率才跌了不到0.1個百分點!這說明大部分特徵都是沒用的,特徵裁剪非常有用、非常好用!

Reference

鄧知龍 《基於感知器演算法的高效中文分詞與詞性標註系統設計與實現》


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31524777/viewspace-2554485/,如需轉載,請註明出處,否則將追究法律責任。

相關文章