Schreiben Sie einen einfachen chinesischen Wortsegmentierer in Python

高洛峰
Freigeben: 2016-10-18 11:45:53
Original
1471 Leute haben es durchsucht

Entnehmen Sie nach dem Entpacken die folgenden Dateien:

Trainingsdaten: icwb2-data/training/pku_training.utf8

Testdaten: icwb2-data/testing/pku_test.utf8

Korrektes Wortsegmentierungsergebnis: icwb2-data/gold/pku_ test_ gold.utf8

Bewertungstool: icwb2-data/script/socre

2 Algorithmusbeschreibung

Algorithmus Es handelt sich um das einfachste Vorwärts-Maximum-Matching (FMM):

Erzeugen Sie ein Wörterbuch mithilfe der Trainingsdaten.

Scannen Sie die Testdaten von links nach rechts und segmentieren Sie sie, wenn Sie auf die längste Zeit stoßen Wort. Bis zum Ende des Satzes

Hinweis: Dies ist der ursprüngliche Algorithmus. Auf diese Weise kann der Code innerhalb von 60 Zeilen gesteuert werden Das Nummernproblem wurde nicht gut gelöst, daher wurde die Nummernverarbeitung hinzugefügt.

3 Quellcode und Kommentare

#! /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()
Nach dem Login kopieren

4 Test- und Bewertungsergebnisse

Verwenden Sie dw.py-Trainingsdaten, um die Daten zu testen und die Ergebnisdatei zu generieren

Verwenden Sie die Bewertung, um basierend auf den Trainingsdaten, den Ergebnissen der korrekten Wortsegmentierung und den von uns generierten Ergebnissen zu bewerten.

Verwenden Sie tail, um zusätzlich die Gesamtbewertung der letzten paar Zeilen der Ergebnisdatei anzuzeigen , socre.utf8 bietet auch eine große Anzahl von Vergleichsergebnissen. Es kann verwendet werden, um herauszufinden, wo Ihre eigenen Wortsegmentierungsergebnisse nicht gut genug sind

Hinweis: Der gesamte Testprozess wird unter Ubuntu abgeschlossen

$ python dw.py pku_training.utf8 pku_test.utf8 pku_result.utf8

$ perlScore pku_training.utf8 pku_test_gold.utf8 pku_result.utf8 >Score.utf8

$ Tail -22 Score.utf8

EINFÜGEN: 0

LÖSCHUNGEN: 0

ERSATZE: 0

NVERÄNDERUNG: 0

NUTRUTH: 27

NTEST: 27

WÄHRENDE WÖRTER ERINNERN: 1.000

PRÄZISION DER TESTWÖRTER: 1.000

=== ZUSAMMENFASSUNG:

=== EINFÜGUNGEN INSGESAMT: 4623

=== LÖSCHUNGEN INSGESAMT: 1740

=== ERSETZUNGEN INSGESAMT: 6650

=== NÄNDERUNGEN INSGESAMT: 13013

=== INSGESAMT WAHR WORTANZAHL: 104372

=== GESAMTZAHL DER TESTWÖRTER: 107255

=== GESAMTZAHL DER ECHTEN WÖRTER: 0,920

=== GESAMTZAHL DER TESTWÖRTER: 0,895

=== F-MESSUNG: 0,907

=== OOV-Rate: 0,940

=== OOV-Rückrufrate: 0,917

=== IV-Rückruf Rate: 0,966


Der wörterbuchbasierte FMM-Algorithmus ist ein sehr einfacher Wortsegmentierungsalgorithmus. Der Effekt ist nicht so gut, aber er ist einfach genug und leicht zu verwenden Wenn ich das Studium vertiefe, kann ich Python auch verwenden, um andere Wortsegmentierungsalgorithmen zu implementieren. Ein anderes Gefühl ist, dass Sie beim Lesen eines Buches versuchen, es so weit wie möglich zu verwirklichen. Dies wird Ihnen genug Begeisterung geben, um jedem Detail der Theorie Aufmerksamkeit zu schenken, und Sie werden sich nicht so langweilig und machtlos fühlen.


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!