統計中文分詞(最大熵)

在機器學習中,序列標註(Sequence labeling)是一種常見的模式識別任務,它用來給一組可觀察對象打上狀態(類別)標籤。它可以解決NLP中的分詞(Word Segement)、詞性標註(Part-Of-Speech Tagging)、命名實體識別(Named Entity Recognition )等問題。常見的概率統計模型有:HMM、MEMM、CRF。
下面介紹利用最大熵統計算法進行分詞的步驟。

第一步:工具包開發環境搭建

下載MEMM工具包,這裏利用的是張樂博士最大熵模型工具包,參照裏面的INSTALL步驟安裝,同時,參照python文件夾的README安裝python相關的包(Python extension of the C++ Maximum Entropy Modeling Toolkit)。

第二步:準備語料

這裏利用的是SIGHAN提供的backoff 2005語料,將熟語料轉換成工具包所需格式,即4-tag(BMES)格式。可參考52NLP網站的python代碼

第三步:訓練模型

工具包的example目錄自帶了一個python訓練工具。執行:

 
./postrainer.py tagger.model -f train.data --iters 100

(注意迭代次數iters前面是兩個-號)。

第四步:利用模型執行分詞

利用上步得到的tagger.model執行分詞。首先,準備所需語料,把生語料進行原子切分,如:“揚帆遠東做與中國合作的先行”切分成“揚 帆 遠 東 做 與 中 國 合 作 的 先 行”。執行最大熵標註腳本即可得到字標註結果,得到的格式如下:“揚/B 帆/M 遠/M 東/M 做/E 與/S 中/B 國/E 合/B 作/E 的/S 先/B 行/E “,最後利用python程序合併成分詞結果文件,如:“揚帆遠東做 與 中國 合作 的 先行”。

第五步:評測

利用backoff2005的測試腳本來測分詞的效果:

    
=== SUMMARY:
=== TOTAL INSERTIONS:   5456
=== TOTAL DELETIONS:    4439
=== TOTAL SUBSTITUTIONS:    12205
=== TOTAL NCHANGE:  22100
=== TOTAL TRUE WORD COUNT:  106873
=== TOTAL TEST WORD COUNT:  107890
=== TOTAL TRUE WORDS RECALL:    0.844
=== TOTAL TEST WORDS PRECISION: 0.836
=== F MEASURE:  0.840
=== OOV Rate:   0.026
=== OOV Recall Rate:    0.565
=== IV Recall Rate: 0.852

可以看到召回率是84.4%,準確率是83.6%,不是很高,這和語料規模有關。

詳情可參考52NLP的網站文章,在character_2_word.py第16行增加if(len(line.strip())>0):判斷,防止最終分詞結果出現空行,否則這樣score打分腳本會報錯。

    
def character_tagging(input_file, output_file):
    input_data = codecs.open(input_file, 'r', 'utf-8')
    output_data = codecs.open(output_file, 'w', 'utf-8')
    for line in input_data.readlines():
        word_list = line.strip().split()
        for word in word_list:
            if len(word) == 1:
                output_data.write(word + "\tS\n")
            else:
                output_data.write(word[0] + "\tB\n")
                for w in word[1:len(word)-1]:
                    output_data.write(w + "\tM\n")
                output_data.write(word[len(word)-1] + "\tE\n")
        output_data.write("\n")
    input_data.close()
    output_data.close()
    
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章