解凍後、以下のファイルを取り出してください:
トレーニングデータ: icwb2-data/training/pku_ training.utf8
テストデータ: icwb2-data/testing/pku_ test.utf8
正しい単語分割結果: icwb2-data /gold/pku_ test_ gold.utf8
スコアリングツール: icwb2-data/script/socre
2 アルゴリズムの説明
アルゴリズムは最も単純な前方最大一致 (FMM) です:
トレーニング データを使用して辞書を生成します
ペアテストデータを左から右にスキャンし、最も長い単語が見つかったら文の終わりまで分割します。 注: これは、この方法で、後で見ると、コードを 60 行以内に制御できます。テストの結果、数値の問題については数値の処理が追加されました。
3 ソースコードとコメント
#! /usr/bin/env python # -*- coding: utf-8 -*- # Author: minix # Date: 2013-03-20 import codecs import sys # 由规则处理的一些特殊符号 numMath = [u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9'] numMath_suffix = [u'.', u'%', u'亿', u'万', u'千', u'百', u'十', u'个'] numCn = [u'一', u'二', u'三', u'四', u'五', u'六', u'七', u'八', u'九', u'〇', u'零'] numCn_suffix_date = [u'年', u'月', u'日'] numCn_suffix_unit = [u'亿', u'万', u'千', u'百', u'十', u'个'] special_char = [u'(', u')'] def proc_num_math(line, start): """ 处理句子中出现的数学符号 """ oldstart = start while line[start] in numMath or line[start] in numMath_suffix: start = start + 1 if line[start] in numCn_suffix_date: start = start + 1 return start - oldstart def proc_num_cn(line, start): """ 处理句子中出现的中文数字 """ oldstart = start while line[start] in numCn or line[start] in numCn_suffix_unit: start = start + 1 if line[start] in numCn_suffix_date: start = start + 1 return start - oldstart def rules(line, start): """ 处理特殊规则 """ if line[start] in numMath: return proc_num_math(line, start) elif line[start] in numCn: return proc_num_cn(line, start) def genDict(path): """ 获取词典 """ f = codecs.open(path,'r','utf-8') contents = f.read() contents = contents.replace(u'\r', u'') contents = contents.replace(u'\n', u'') # 将文件内容按空格分开 mydict = contents.split(u' ') # 去除词典List中的重复 newdict = list(set(mydict)) newdict.remove(u'') # 建立词典 # key为词首字,value为以此字开始的词构成的List truedict = {} for item in newdict: if len(item)>0 and item[0] in truedict: value = truedict[item[0]] value.append(item) truedict[item[0]] = value else: truedict[item[0]] = [item] return truedict def print_unicode_list(uni_list): for item in uni_list: print item, def divideWords(mydict, sentence): """ 根据词典对句子进行分词, 使用正向匹配的算法,从左到右扫描,遇到最长的词, 就将它切下来,直到句子被分割完闭 """ ruleChar = [] ruleChar.extend(numCn) ruleChar.extend(numMath) result = [] start = 0 senlen = len(sentence) while start < senlen: curword = sentence[start] maxlen = 1 # 首先查看是否可以匹配特殊规则 if curword in numCn or curword in numMath: maxlen = rules(sentence, start) # 寻找以当前字开头的最长词 if curword in mydict: words = mydict[curword] for item in words: itemlen = len(item) if sentence[start:start+itemlen] == item and itemlen > maxlen: maxlen = itemlen result.append(sentence[start:start+maxlen]) start = start + maxlen return result def main(): args = sys.argv[1:] if len(args) < 3: print 'Usage: python dw.py dict_path test_path result_path' exit(-1) dict_path = args[0] test_path = args[1] result_path = args[2] dicts = genDict(dict_path) fr = codecs.open(test_path,'r','utf-8') test = fr.read() result = divideWords(dicts,test) fr.close() fw = codecs.open(result_path,'w','utf-8') for item in result: fw.write(item + ' ') fw.close() if __name__ == "__main__": main()
4 結果のテストとスコアリング
dw.py を使用してデータをトレーニングし、データをテストし、結果ファイルを生成します
スコアを使用してトレーニング データに基づいてスコアを付け、単語を修正しますセグメンテーションの結果と生成した結果
tail を使用して、結果ファイルの最後の数行の全体的なスコアを確認します。さらに、socre.utf8 は、比較結果がどこにあるかを見つけるために使用できます。独自の単語分割結果は十分ではありません
注: テストプロセス全体は Ubuntu で行われます。以下で完了します
$ python dw.py pku_training.utf8 pku_test.utf8 pku_result.utf8
$ perl スコア pku_training.utf8 pku_test_gold.utf8 pku_result .utf8 > スコア.utf8
$ テール -22 スコア.utf8
INS ERTIONS: 0
DELETIONS: 0
置換: 0
NCHANGE: 0
真実: 27
NTEST: 27
真実の言葉再現率: 1,000
テスト単語の精度: 1,000
=== 概要:
== = 合計挿入数: 4623
=== 合計削除数: 1740
=== 合計置換数: 66 50
=== 合計NCHANGE: 13013
=== 合計正解単語数: 104372
=== 合計テスト単語数: 107255
=== 合計正解単語再現数: 0.920
=== 合計テスト単語精度: 0 .895
= == F MEASURE: 0.907
=== OOV Rate: 0.940
=== OOV Recall Rate: 0.917
=== IV Recall Rate: 0.966
辞書に基づく FMM アルゴリズムは非常に優れています。基本的な単語分割アルゴリズム。効果はそれほど高くありませんが、十分にシンプルで簡単に始めることができます。学習が深まるにつれて、Python を使用して他の単語分割アルゴリズムを実装することもできます。もう一つの感覚は、本を読むときにできるだけそれを理解しようとすることです。そうすることで、理論の細部にまで注意を払うのに十分な熱意が得られ、それほど退屈で無力だと感じることはなくなります。