>  기사  >  백엔드 개발  >  Python으로 간단한 중국어 단어 분할기 작성

Python으로 간단한 중국어 단어 분할기 작성

高洛峰
高洛峰원래의
2016-10-18 11:45:531491검색

압축을 푼 후 다음 파일을 꺼냅니다.

훈련 데이터: 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(Forward Maximum Matching)입니다.

훈련 데이터를 사용하여 사전을 생성합니다.

테스트 데이터를 왼쪽에서 오른쪽으로 스캔하고 가장 긴 것을 만나면 분할합니다. 문장 끝까지 내려갑니다

참고: 원래의 알고리즘은 이 방법으로 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 학습 데이터를 사용하여 데이터를 테스트하고 결과 파일 생성

score를 사용하여 학습 데이터, 올바른 단어 분할 결과 및 생성된 결과를 기반으로 점수를 매깁니다.

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 > Score.utf8

$ tail -22 Score.utf8

삽입: 0

삭제: 0

교체: 0

NCHANGE: 0

진실: 27

NTEST: 27

참 단어 기억: 1.000

테스트 단어 정밀도: 1.000

=== 요약:

=== 총 삽입 수: 4623

=== 총 삭제 수: 1740

=== 총 대체 수: 6650

=== 총 변경 수: 13013

=== 총 TRUE WORD 개수: 104372

=== 총 테스트 단어 개수: 107255

=== 총 참 단어 기억률: 0.920

=== 총 테스트 단어 정밀도: 0.895

=== F 측정: 0.907

=== OOV 비율: 0.940

=== OOV 재현율: 0.917

=== IV 재현율 : 0.966


사전 기반 FMM 알고리즘은 아주 기본적인 단어 분할 알고리즘이지만 효과는 그다지 좋지는 않지만 충분히 간단하고 시작하기 쉽습니다. 연구가 심화되면 Python을 사용하여 다른 단어 분할 알고리즘을 구현할 수도 있습니다. 또 다른 느낌은 책을 읽을 때 가능한 한 많이 실현하려고 노력하면 이론의 모든 세부 사항에주의를 기울일만큼 충분한 열정을 갖게되고 너무 지루하고 무력감을 느끼지 않을 것이라는 것입니다.


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.