Python で簡単な中国語単語セグメンターを作成する

高洛峰
リリース: 2016-10-18 11:45:53
オリジナル
1471 人が閲覧しました

解凍後、以下のファイルを取り出してください:

トレーニングデータ: 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 &#39;Usage: python dw.py dict_path test_path result_path&#39;
        exit(-1)
    dict_path = args[0]
    test_path = args[1]
    result_path = args[2]
    
    dicts = genDict(dict_path)
    fr = codecs.open(test_path,&#39;r&#39;,&#39;utf-8&#39;)
    test = fr.read()
    result = divideWords(dicts,test)
    fr.close()
    fw = codecs.open(result_path,&#39;w&#39;,&#39;utf-8&#39;)
    for item in result:
        fw.write(item + &#39; &#39;)
    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 を使用して他の単語分割アルゴリズムを実装することもできます。もう一つの感覚は、本を読むときにできるだけそれを理解しようとすることです。そうすることで、理論の細部にまで注意を払うのに十分な熱意が得られ、それほど退屈で無力だと感じることはなくなります。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!