自然语言处理之分词3

本节将介绍在自然语言处理分词或序列标注过程中应用较广泛的CRF条件随机场模型。

CRF算法是2001年提出,结合了最大熵模型和隐马尔科夫模型,是一个典型的判别式模型。近年来在分词、词性标注和命名实体识别等序列标注任务中取得了很好的效果。其基本思路是把分词转换为分类问题,通过给汉字打标签实现分词,不仅考虑文字词语出现的频率,同时考虑上下文语境,对歧异词和未登录词的识别效果较好,此外,对所有特征进行全局归一化,进而求得全局最优值。但是训练周期较长,计算量大,性能不如词典统计分词。本文使用开源的条件随机场工具包“CRF++:Yet Another CRF toolkit”实现中文分词,选用的训练语料是微软亚洲研究院提供的中文分词语料(如下图所示),测试语料来自backoff2005测试脚本。


自然语言处理之分词3_第1张图片
上图语料来自微软亚洲研究院提供的中文分词语料

CRF分词原理:
1、训练语料预处理。原始训练语料是已经分好词的预料,词与词之间通过空格隔开。按照如下定义字对数据进行格式化:①词首——用B表示 ②词中——用M表示 ③词尾——用E表示 ④单子词——用S表示。数据格式化脚本如下:

import codecs
import sys
def character_tagging(input_file, output_file): 
    #这里的codecs库保证了输入文件为utf-8格式,输出也为utf-8格式
    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: 
            #注意这里的“\tS\n”一定不能漏写,这是设置处理之后的数据的格式的重要部分  
            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 ####.py input output" 
        sys.exit(-1) 
    #这里的sys.argv[]是参数,需要在liunx环境下运行Python脚本时,输入的两个参数:输入文件位置,输出文件位置
    input_file = sys.argv[1] 
    output_file = sys.argv[2] 
    character_tagging(input_file, output_file)

格式化之后的数据如图所示:假设格式化后的文件为training_tag.utf8


自然语言处理之分词3_第2张图片
格式化处理后training_tag.utf8文件格式

2、训练模型。用格式化后的训练语料training_tag.utf8训练CRF模型。主要利用CRF工具中的crf_learn训练模型,执行如下命令:crf_learn -f 3 -c 4.0 template training_tag.utf8 crf_model。其中,crf_model即为训练过后的模型。
3、测试语料格式化。原始的测试语料是一个纯文本文件,没有任何处理,如图a所示。需要将其处理成CRF要求的输入格式,处理脚本如下所示。

自然语言处理之分词3_第3张图片
图a 原始测试语料
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 ####.py input output" 
        sys.exit()    
    input_file = sys.argv[1]    
    output_file = sys.argv[2]    
    character_split(input_file, output_file)    

格式化之后的数据如图所示:假设格式化后的文件为test_format.utf8

自然语言处理之分词3_第4张图片
test_format.utf8文件格式

4、测试模型。用格式化后的测试语料test_format.utf8测试CRF模型。主要利用CRF工具中的crf_test测试模型,执行如下命令:crf_test -m crf_model test_format.utf8>test_tag.utf8 。其中,crf_model即为训练过后的模型,test_format.utf8即为格式化后的测试文件,test_tag.utf8即为模型的标注结果。
5、分词结果显示。按照定义的分词格式,将标记结果转换为分词结果,即将B和E之间的字,以及S单字构成分词。脚本如下:

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 ####.py input output" 
        sys.exit()
    input_file = sys.argv[1]
    output_file = sys.argv[2]
    character_2_word(input_file, output_file)

得到分词结果文件test_result.utf8,样式如图所示

自然语言处理之分词3_第5张图片
分词结果文件test_result.utf8

6、分词结果测试。利用backoff2005测试样本对分词结果test_result.utf8进行测试。
执行./icwb2-data/scripts/score ./icwb2-data/gold/pku_training_words.utf8 ./icwb2-data/gold/pku_test_gold.utf8 test_result.utf8 > test_result.score
此处,pku_training_words.utf8 和pku_test_gold.utf8是测试文件中自带的,test_result.utf8即为上步生成的文件。test_result.score即为最后模型的评分。

上述步骤均可以复现,具体细节参考www.52nlp.cn/中文分词入门之字标注法4

你可能感兴趣的:(自然语言处理之分词3)