http://www.52nlp.cn/%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D%E5%85%A5%E9%97%A8%E4%B9%8B%E5%AD%97%E6%A0%87%E6%B3%A8%E6%B3%954
上一節主要介紹的是利用最大熵工具包來做字標注中文分詞,這一節我們直奔主題,借用條件隨機場工具“CRF++: Yet Another CRF toolkit”來完成字標注中文分詞的全過程。
關于條件隨機場(CRF)的背景知識,推薦參考閱讀一些經典的文獻:《條件隨機場文獻閱讀指南》,另外再額外推薦一個tutorial:《Classical Probabilistic Models and Conditional Random Fields》, 這份關于CRF的文檔分別從概率模型(NB,HMM,ME, CRF)之間的關系以及概率圖模型背景來介紹條件隨機場,比較清晰:
While a Hidden Markov Model is a sequential extension to the Nave Bayes Model, Conditional Random Fields can be understood as a sequential extension to the Maximum Entropy Model.
如果這些還不夠過癮,推薦課程圖譜上收錄的Coursera創始人之一Daphne Koller的“概率圖模型公開課”,相信拿下這門課之后,對于上述概率模型,會有一種“一覽眾山小”的感覺。
不過我們還是要從安裝CRF++工具包說起,在Linux或者Mac OS系統下,下載C++源代碼安裝包(這里用的是?CRF++-0.58.tar.gz?)之后,依然是 “configure & make & (sudo) make install”,安裝完畢之后,可以cd python進入到其同樣用SWIG生成的Python工具包下,安裝python包:python setup.py build & (sudo) python setup.py install。安裝完畢之后,可以在python解釋器下測試,是否能成功import CRFPP,如果ok,則準備工作就緒。
上一節我們利用最大熵模型工具包里自帶的詞性標注工具進行的中文分詞,稍微有些曲折,這一節我們依然利用CRF++ example里的樣例進行測試,不過好處是,CRF++ example里有個seg目錄,這個seg目錄對應的是一個日文分詞的樣例,正好可以套用到我們的中文分詞中來。在安裝包目錄下,cd example, cd seg目錄后,有4個文件:
exec.sh(執行腳本)
template(特征模板)
test.data(測試集)
train.data(訓練集)
有了這4個文件,我們可以做得事情就比較簡單,只要按測試集,訓練集的格式準備數據就可以了,特征模板和執行腳本可以套用,不過這里簡單解讀一下這幾個CRF++文件。首先來看訓練集:
1 2 3 4 5 6 7 8 9 10 | 毎 k ? B 日 k ? I 新 k ? I 聞 k ? I 社 k ? I 特 k ? B 別 k ? I 顧 k ? B 問 k ? I ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 4 n ? B |
這里第一列是待分詞的日文字,第二列暫且認為其是詞性標記,第三列是字標注中的2-tag(B, I)標記,這個很重要,對于我們需要準備的訓練集,主要是把這一列的標記做好,不過需要注意的是,其斷句是靠空行來完成的。
再來看測試集的格式:
1 2 3 4 5 6 7 8 9 10 | よ h ? I っ h ? I て h ? I 私 k ? B た h ? B ち h ? I の h ? B ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 世 k ? B 代 k ? I が h ? B |
同樣也有3列,第一列是日文字,第二列第三列與上面是相似的,不過在測試集里第三列主要是占位作用。事實上,CRF++對于訓練集和測試集文件格式的要求是比較靈活的,首先需要多列,但不能不一致,既在一個文件里有的行是兩列,有的行是三列;其次第一列代表的是需要標注的“字或詞”,最后一列是輸出位”標記tag”,如果有額外的特征,例如詞性什么的,可以加到中間列里,所以訓練集或者測試集的文件最少要有兩列。
接下里我們再來詳細的分析一下特征模板文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # Unigram U00:%x[-2,0] U01:%x[-1,0] U02:%x[0,0] U03:%x[1,0] U04:%x[2,0] U05:%x[-2,0]/%x[-1,0]/%x[0,0] U06:%x[-1,0]/%x[0,0]/%x[1,0] U07:%x[0,0]/%x[1,0]/%x[2,0] U08:%x[-1,0]/%x[0,0] ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? U09:%x[0,0]/%x[1,0] # Bigram B |
關于CRF++中特征模板的說明和舉例,請大家參考官方文檔上的“Preparing feature templates”這一節,而以下部分的說明拿上述日文分詞數據舉例。在特征模板文件中,每一行(如U00:%x[-2,0])代表一個特征,而宏“%x[行位置,列位置]”則代表了相對于當前指向的token的行偏移和列的絕對位置,以上述訓練集為例,如果當前掃描到“新 k I”這一行,
1 2 3 4 5 6 7 8 9 10 | 毎 k ? B 日 k ? I 新 k ? I ? <== 掃描到這一行,代表當前位置 聞 k ? I 社 k ? I 特 k ? B 別 k ? I 顧 k ? B 問 k ? I 4 n ? B |
那么依據特征模板文件抽取的特征如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # Unigram U00:%x[-2,0] ==> 毎 U01:%x[-1,0] ==> 日 U02:%x[0,0] ?==> 新 U03:%x[1,0] ?==> 聞 U04:%x[2,0] ?==> 社 U05:%x[-2,0]/%x[-1,0]/%x[0,0] ==> 每/日/新 U06:%x[-1,0]/%x[0,0]/%x[1,0] ?==> 日/新/聞 U07:%x[0,0]/%x[1,0]/%x[2,0] ? ==> 新/聞/社 U08:%x[-1,0]/%x[0,0] ? ? ? ? ?==> 日/新 U09:%x[0,0]/%x[1,0] ? ? ? ? ? ==> 新/聞 # Bigram B |
CRF++里將特征分成兩種類型,一種是Unigram的,“U”起頭,另外一種是Bigram的,“B”起頭。對于Unigram的特征,假如一個特征模板是”U01:%x[-1,0]”, CRF++會自動的生成一組特征函數(func1 … funcN) 集合:
1 2 3 4 5 | func1 = if (output = B and feature="U01:日") return 1 else return 0 func2 = if (output = I and feature="U01:日") return 1 else return 0 .... funcXX = if (output = B and feature="U01:問") return 1 ?else return 0 funcXY = if (output = I and feature="U01:問") return 1 ?else return 0 |
生成的特征函數的數目 = (L * N),其中L是輸出的類型的個數,這里是B,I這兩個tag,N是通過模板擴展出來的所有單個字符串(特征)的個數,這里指的是在掃描所有訓練集的過程中找到的日文字(特征)。
而Bigram特征主要是當前的token和前面一個位置token的自動組合生成的bigram特征集合。最后需要注意的是U01和U02這些標志位,與特征token組合到一起主要是區分“U01:問”和“U02:問”這類特征,雖然抽取的日文”字”特征是一樣的,但是在CRF++中這是有區別的特征。
最后我們再來看一下執行腳本:
1 2 3 4 5 6 7 | #!/bin/sh ../../crf_learn -f 3 -c 4.0 template train.data model ../../crf_test -m model test.data ../../crf_learn -a MIRA -f 3 template train.data model ../../crf_test -m model test.data rm -f model |
執行腳本告訴了我們如何訓練一個CRF模型,以及如何利用這個模型來進行測試,執行這個腳本之后,對于輸入的測試集,輸出結果多了一列:
1 2 3 4 5 6 7 8 9 10 | よ h ? I ? B っ h ? I ? I て h ? I ? B 私 k ? B ? B た h ? B ? B ち h ? I ? I の h ? B ? B ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 世 k ? B ? B 代 k ? I ? I が h ? B ? B |
而這一列才是模型預測的改字的標記tag,也正是我們所需要的結果。到此為止,關于日文分詞樣例的介紹已經完畢,讀者應該可以猜測到接下來我們會如何做中文分詞吧?
和上一節利用最大熵模型進行中文分詞相似,第一步仍然是將backoff2005里的訓練數據轉化為CRF++所需的訓練數據格式,還是以微軟亞洲研究院提供的中文分詞語料為例,依然采用4-tag(B(Begin,詞首), E(End,詞尾), M(Middle,詞中), S(Single,單字詞))標記集,只處理utf-8編碼文本。原始訓練集./icwb2-data/training/msr_training.utf8的形式是人工分好詞的中文句子形式,如:
1 2 3 4 5 6 7 8 9 10 | “ ?人們 ?常 ?說 ?生活 ?是 ?一 ?部 ?教科書 ?, ?而 ?血 ?與 ?火 ?的 ?戰爭 ?> ? ? ?更 ?是 ?不可多得 ?的 ?教科書 ?, ?她 ?確實 ?是 ?名副其實 ?的 ?‘ ?我 ?的 ?> ? ? ?大學 ?’ ?。 “ ?心 ?靜 ?漸 ?知 ?春 ?似 ?海 ?, ?花 ?深 ?每 ?覺 ?影 ?生 ?香 ?。 “ ?吃 ?屎 ?的 ?東西 ?, ?連 ?一 ?捆 ?麥 ?也 ?鍘 ?不 ?動 ?呀 ?? 他 ?“ ?嚴格要求 ?自己 ?, ?從 ?一個 ?科舉 ?出身 ?的 ?進士 ?成為 ?一個 ?偉> ? ? ?大 ?的 ?民主主義 ?者 ?, ?進而 ?成為 ?一 ?位 ?杰出 ?的 ?黨外 ?共產主義 ?戰 士 ?, ?獻身 ?于 ?崇高 ?的 ?共產主義 ?事業 ?。 “ ?征 ?而 ?未 ?用 ?的 ?耕地 ?和 ?有 ?收益 ?的 ?土地 ?, ?不準 ?荒蕪 ?。 “ ?這 ?首先 ?是 ?個 ?民族 ?問題 ?, ?民族 ?的 ?感情 ?問題 ?。 ’ ?我 ?扔 ?了 ?兩顆 ?手榴彈 ?, ?他 ?一下子 ?出 ?溜 ?下去 ?。 “ ?廢除 ?先前 ?存在 ?的 ?所有制 ?關系 ?, ?并不是 ?共產主義 ?所 ?獨具 ?的 ? ? ? ?特征 ?。 “ ?這個 ?案子 ?從 ?始 ?至今 ?我們 ?都 ?沒有 ?跟 ?法官 ?接觸 ?過 ?, ?也 ?> ? ? ?沒有 ?跟 ?原告 ?、 ?被告 ?接觸 ?過 ?。 “ ?你 ?只有 ?把 ?事情 ?做好 ?, ?大伙 ?才 ?服 ?你 ?。 |
這里同樣提供一個腳本?make_crf_train_data.py,將這個訓練語料轉換為CRF++訓練用的語料格式(2列,4-tag):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/usr/bin/env python # -*- coding: utf-8 -*- # Author: 52nlpcn@gmail.com # Copyright 2014 @ YuZhen Technology # # 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single) import codecs import sys 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() if __name__ == '__main__': ? ? if len(sys.argv) != 3: ? ? ? ? print "pls use: python make_crf_train_data.py input output" ? ? ? ? sys.exit() ? ? input_file = sys.argv[1] ? ? output_file = sys.argv[2] ? ? character_tagging(input_file, output_file) |
只需要執行“python make_crf_train_data.py ./icwb2-data/training/msr_training.utf8 msr_training.tagging4crf.utf8” 即可得到CRF++要求的格式的訓練文件msr_training.tagging4crf.utf8,樣例如下:
1 2 3 4 5 6 7 8 9 10 11 | “ S 人 B 們 E 常 S 說 S 生 B 活 E 是 S ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 一 S 部 S ... |
有了這份訓練語料,就可以利用crf的訓練工具crf_learn來訓練模型了,執行如下命令即可:
crf_learn -f 3 -c 4.0 template msr_training.tagging4crf.utf8 crf_model
這次訓練的時間稍微有些長,在我的4G內存的mac pro上跑了將近700輪,大約2個小時,最終訓練的crf_model約51M。有了模型,現在我們需要做得還是準備一份CRF++用的測試語料,然后利用CRF++的測試工具crf_test進行字標注。原始的測試語料是icwb2-data/testing/msr_test.utf8 ,樣例如下:
1 2 3 4 5 6 7 8 9 10 | 揚帆遠東做與中國合作的先行 希臘的經濟結構較特殊。 海運業雄踞全球之首,按噸位計占世界總數的17%。 另外旅游、僑匯也是經濟收入的重要組成部分,制造業規模相對較小。 多年來,中希貿易始終處于較低的水平,希臘幾乎沒有在中國投資。 十幾年來,改革開放的中國經濟高速發展,遠東在崛起。 瓦西里斯的船只中有40%駛向遠東,每個月幾乎都有兩三條船停靠中國港口。 他感受到了中國經濟發展的大潮。 他要與中國人合作。 他來到中國,成為第一個訪華的大船主。 |
這里我們同樣提供一個python腳本?make_crf_test_data.py?對測試語料進行處理,將其轉換為CRF++要求的格式(2列,B作為最后一列的占位符)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/usr/bin/env python # -*- coding: utf-8 -*- # Author: 52nlpcn@gmail.com # Copyright 2014 @ YuZhen Technology # # 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single) import codecs import sys def character_split(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(): ? ? ? ? for word in line.strip(): ? ? ? ? ? ? word = word.strip() ? ? ? ? ? ? if word: ? ? ? ? ? ? ? ? output_data.write(word + "\tB\n") ? ? ? ? output_data.write("\n") ? ? input_data.close() ? ? output_data.close() if __name__ == '__main__': ? ? if len(sys.argv) != 3: ? ? ? ? print "pls use: python make_crf_test_data.py input output" ? ? ? ? sys.exit() ? ? input_file = sys.argv[1] ? ? output_file = sys.argv[2] ? ? character_split(input_file, output_file) |
執行“python make_crf_test_data.py ./icwb2-data/testing/msr_test.utf8 msr_test4crf.utf8”即可得到可用于CRF++測試的測試語料msr_test4crf.utf8,樣例如下:
1 2 3 4 5 6 7 8 9 10 11 | 揚 B 帆 B 遠 B 東 B 做 B 與 B 中 B 國 B 合 B 作 B ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ... |
現在執行crf_test即可得到字標注結果:
crf_test -m crf_model msr_test4crf.utf8 > msr_test4crf.tag.utf8
msr_test4crf.tag.utf8即是標注結果,樣例如下:
1 2 3 4 5 6 7 8 9 10 11 | 揚 B ? B 帆 B ? E 遠 B ? B 東 B ? E 做 B ? S 與 B ? S 中 B ? B 國 B ? E 合 B ? B 作 B ? E ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ... |
最后我們還需要一個腳本,按標注的詞位信息講這份結果再轉化為分詞結果,這里我們仍然提供一個轉換腳本?crf_data_2_word.py?:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #!/usr/bin/env python # -*- coding: utf-8 -*- # Author: 52nlpcn@gmail.com # Copyright 2014 @ YuZhen Technology # # 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single) import codecs import sys def character_2_word(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(): ? ? ? ? if line == "\n": ? ? ? ? ? ? output_data.write("\n") ? ? ? ? else: ? ? ? ? ? ? char_tag_pair = line.strip().split('\t') ? ? ? ? ? ? char = char_tag_pair[0] ? ? ? ? ? ? tag = char_tag_pair[2] ? ? ? ? ? ? if tag == 'B': ? ? ? ? ? ? ? ? output_data.write(' ' + char) ? ? ? ? ? ? elif tag == 'M': ? ? ? ? ? ? ? ? output_data.write(char) ? ? ? ? ? ? elif tag == 'E': ? ? ? ? ? ? ? ? output_data.write(char + ' ') ? ? ? ? ? ? else: # tag == 'S' ? ? ? ? ? ? ? ? output_data.write(' ' + char + ' ') ? ? input_data.close() ? ? output_data.close() if __name__ == '__main__': ? ? if len(sys.argv) != 3: ? ? ? ? print "pls use: python crf_data_2_word.py input output" ? ? ? ? sys.exit() ? ? input_file = sys.argv[1] ? ? output_file = sys.argv[2] ? ? character_2_word(input_file, output_file) |
只需執行“python crf_data_2_word.py msr_test4crf.tag.utf8 msr_test4crf.tag2word.utf8” 即可得到合并后的分詞結果文件 msr_test4crf.tag2word.utf8,樣例如下:
1 2 3 4 5 6 7 8 9 10 11 | 揚帆 ?遠東 ?做 ?與 ?中國 ?合作 ?的 ?先行? ?希臘 ?的 ?經濟 ?結構 ?較 ?特殊 ?。? ?海運 ?業 ?雄踞 ?全球 ?之 ?首 ?, ?按 ?噸 ?位 ?計 ?占 ?世界 ?總數 ?的 ?17% ?。? ?另外 ?旅游 ?、 ?僑匯 ?也是 ?經濟 ?收入 ?的 ?重要 ?組成部分 ?, ?制造業 ?規模 ?相對 ?較小 ?。? ?多年來 ?, ?中 ?希 ?貿易 ?始終 ?處于 ?較低 ?的 ?水平 ?, ?希臘 ?幾乎 ?沒有 ?在 ?中國 ?投資 ?。? ?十幾年 ?來 ?, ?改革開放 ?的 ?中國 ?經濟 ?高速 ?發展 ?, ?遠東 ?在 ?崛起 ?。? ?瓦西里斯 ?的 ?船只 ?中 ?有 ?40% ?駛 ?向 ?遠東 ?, ?每個 ?月 ?幾乎 ?都 ?有 ?兩三條 ?船 ?停靠 ?中國 ?港口 ?。? ?他 ?感受 ?到 ?了 ?中國 ?經濟 ?發展 ?的 ?大潮 ?。? ?他 ?要 ?與 ?中國人 ?合作 ?。? ?他 ?來到 ?中國 ?, ?成為 ?第一個 ?訪 ?華 ?的 ?大船 ?主 ?。 ?... |
有了這個CRF字標注分詞結果,我們就可以利用backoff2005的測試腳本來測一下這次分詞的效果了:
./icwb2-data/scripts/score ./icwb2-data/gold/msr_training_words.utf8 ./icwb2-data/gold/msr_test_gold.utf8 msr_test4crf.tag2word.utf8 > msr_crf_segment.score
結果如下:
=== SUMMARY:
=== TOTAL INSERTIONS: 1412
=== TOTAL DELETIONS: 1305
=== TOTAL SUBSTITUTIONS: 2449
=== TOTAL NCHANGE: 5166
=== TOTAL TRUE WORD COUNT: 106873
=== TOTAL TEST WORD COUNT: 106980
=== TOTAL TRUE WORDS RECALL: 0.965
=== TOTAL TEST WORDS PRECISION: 0.964
=== F MEASURE: 0.964
=== OOV Rate: 0.026
=== OOV Recall Rate: 0.647
=== IV Recall Rate: 0.974
### msr_test4crf.tag2word.utf8 1412 1305 2449 5166 106873 106980 0.965 0.964 0.964 0.026 0.647 0.974
這次我們獲得了一個準確率,召回率以及F值都在96%以上的結果,相對于前面幾節的測試結果,這個CRF字標注分詞結果還相對不錯。不過是不是感覺上面的步驟有些繁瑣,有沒有一次到位的CRF分詞器,這里我們同樣提供一個CRF分詞腳本?crf_segmenter.py?,利用CRF++的python工具包,做到一次輸入,一次輸出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #!/usr/bin/env python # -*- coding: utf-8 -*- # Author: 52nlpcn@gmail.com # Copyright 2014 @ YuZhen Technology # # CRF Segmenter based character tagging: # ? ? 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single) import codecs import sys import CRFPP def crf_segmenter(input_file, output_file, tagger): ? ? input_data = codecs.open(input_file, 'r', 'utf-8') ? ? output_data = codecs.open(output_file, 'w', 'utf-8') ? ? for line in input_data.readlines(): ? ? ? ? tagger.clear() ? ? ? ? for word in line.strip(): ? ? ? ? ? ? word = word.strip() ? ? ? ? ? ? if word: ? ? ? ? ? ? ? ? tagger.add((word + "\to\tB").encode('utf-8')) ? ? ? ? tagger.parse() ? ? ? ? size = tagger.size() ? ? ? ? xsize = tagger.xsize() ? ? ? ? for i in range(0, size): ? ? ? ? ? ? for j in range(0, xsize): ? ? ? ? ? ? ? ? char = tagger.x(i, j).decode('utf-8') ? ? ? ? ? ? ? ? tag = tagger.y2(i) ? ? ? ? ? ? ? ? if tag == 'B': ? ? ? ? ? ? ? ? ? ? output_data.write(' ' + char) ? ? ? ? ? ? ? ? elif tag == 'M': ? ? ? ? ? ? ? ? ? ? output_data.write(char) ? ? ? ? ? ? ? ? elif tag == 'E': ? ? ? ? ? ? ? ? ? ? output_data.write(char + ' ') ? ? ? ? ? ? ? ? else: # tag == 'S' ? ? ? ? ? ? ? ? ? ? output_data.write(' ' + char + ' ') ? ? ? ? output_data.write('\n') ? ? input_data.close() ? ? output_data.close() if __name__ == '__main__': ? ? if len(sys.argv) != 4: ? ? ? ? print "pls use: python crf_segmenter.py model input output" ? ? ? ? sys.exit() ? ? crf_model = sys.argv[1] ? ? input_file = sys.argv[2] ? ? output_file = sys.argv[3] ? ? tagger = CRFPP.Tagger("-m " + crf_model) ? ? crf_segmenter(input_file, output_file, tagger) |
只需執行“python crf_segmenter.py crf_model ./icwb2-data/testing/msr_test.utf8 msr_test.seg.utf8”即可得到與前面幾步得到的分詞結果完全一致的CRF分詞結果:msr_test.seg.utf8 。
好了,到此為止,關于字標注中文分詞的系列終于可以畫上句號了,這個系列中所舉的例子以及所提供的腳本都是toy級別的中文分詞工具,距離一個真正實用的中文分詞器還有很多路要走,不過既然路已經打開,歡迎大家和我們一起繼續探索中文分詞的奧秘。
注:原創文章,轉載請注明出處“我愛自然語言處理”:www.52nlp.cn
本文鏈接地址:http://www.52nlp.cn/中文分詞入門之字標注法4