自然语言处理(4)-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

自然语言处理(4)

简介:

语料库

关于语料库的三点基本认识:语料库中存放的是在语言的实际使用中真实出现过的语言材料;语料库是以电子计算机为载体承载语言知识的基础资源;真实语料需要经过加工(分析和处理),才能成为有用的资源。

语料库特征

语料库有三点特征

1)语料库中存放的是在语言的实际使用中真实出现过的语言材料,因此例句库通常不应算作语料库;

2)语料库是承载语言知识的基础资源,但并不等于语言知识;

3)真实语料需要经过加工(分析和处理),才能成为有用的资源。

语料库的发展经历了前期(计算机发明以前),第一代语料库,第二代语料库,到第三代语料库。

语料库在线

此网址内有大量的语料库信息:

语料库在线

使用CRF++进行中文分词

首先下载CRF++,我下载的地址是:

CRF++ toolkit 0.58

下载完成后,上传到你的工作目录:

image

解压缩,然后安装:

./configure 
 make
 sudo make install

然后下载人民日报语料:

人民日报语料

也可以到群nlp研究与讨论 413423481群文件中下载。

生成训练数据

通过下面python脚本,根据人民日报的语料库生成crf的测试和训练数据。原始数据中随机10%是测试数据,90%是训练数据。程序打印出来了不少调试信息,可以忽略。生成训练数据的时候,支持4tag和6tag两个格式,6tag的格式是:

S,单个词;B,词首;E,词尾;M1/M2/M,词中

4tag和6tag的区别就是没有词中顺序状态。具体代码:

#coding=utf8

import sys

#home_dir = "D:/source/NLP/people_daily//"

home_dir = "./"
def splitWord(words):
    uni = words.decode('utf-8')
    li = list()    
    for u in uni:
        li.append(u.encode('utf-8'))
    return li    

#4 tag

#S/B/E/M
def get4Tag(li):
    length = len(li)
    #print length
    if length   == 1:
        return ['S']
    elif length == 2:
        return ['B','E']
    elif length > 2:
        li = list()
        li.append('B')
    for i in range(0,length-2):
        li.append('M')
    li.append('E')
    return li
#6 tag
#S/B/E/M/M1/M2
def get6Tag(li):
    length = len(li)
    #print length
    if length   == 1:
        return ['S']
    elif length == 2:
        return ['B','E']
    elif length == 3:
        return ['B','M','E']
    elif length == 4:
        return ['B','M1','M','E']
    elif length == 5:
        return ['B','M1','M2','M','E']
    elif length > 5:
        li = list()
        li.append('B')
        li.append('M1')
        li.append('M2')
    for i in range(0,length-4):
        li.append('M')
    li.append('E')
    return li

def saveDataFile(trainobj,testobj,isTest,word,handle,tag):
    if isTest:
        saveTrainFile(testobj,word,handle,tag)
    else:
        saveTrainFile(trainobj,word,handle,tag)

def saveTrainFile(fiobj,word,handle,tag): 
    if len(word) > 0:
        wordli = splitWord(word)
        if tag == '4':
            tagli = get4Tag(wordli)
        if tag == '6':
            tagli = get6Tag(wordli)
        for i in range(0,len(wordli)):
            w = wordli[i]
            h = handle
            t = tagli[i]
            fiobj.write(w + '\t' + h + '\t' + t + '\n')
    else:
    #print 'New line'
        fiobj.write('\n')

#B,M,M1,M2,M3,E,S
def convertTag(tag):    
    fiobj    = open( home_dir + 'people-daily.txt','r')
    trainobj = open( home_dir + tag + '.train.data','w' )
    testobj  = open( home_dir + tag + '.test.data','w')

    arr = fiobj.readlines()
    i = 0
    for a in arr:
        i += 1
        a = a.strip('\r\n\t ')
        if a=="":continue
        words = a.split(" ")
        test = False
        if i % 10 == 0:
            test = True
        for word in words:
            print "---->", word
            word = word.strip('\t ')
            if len(word) > 0:        
                i1 = word.find('[')
            if i1 >= 0:
                word = word[i1+1:]
            i2 = word.find(']')
            if i2 > 0:
                w = word[:i2]
            word_hand = word.split('/')
            print "----",word
            w,h = word_hand
            #print w,h
            if h == 'nr':    #ren min
                #print 'NR',w
                if w.find('·') >= 0:
                    tmpArr = w.split('·')
                    for tmp in tmpArr:
                        saveDataFile(trainobj,testobj,test,tmp,h,tag)
                continue
            if h != 'm':
                saveDataFile(trainobj,testobj,test,w,h,tag)
            
            if h == 'w':
                saveDataFile(trainobj,testobj,test,"","",tag) #split

    trainobj.flush()
    testobj.flush()

if __name__ == '__main__':    
    if len(sys.argv) < 2:
        print 'tag[6,4] convert raw data to train.data and tag.test.data'
    else:
        tag = sys.argv[1]
        convertTag(tag)

将人民日报语料库跟python放在同一目录,生成数据时,通过最后一个参数是4还是6区别生成4tag数据还是6tag数据。执行python角本:

#生成6tag
python get_crf_train_test_data.py 6
#生成4tag
python get_crf_train_test_data.py 4

执行后可以看到:

image

进入到CRF++-0.58/example/seg的目录下可以看到:

image

编写模板:

# Unigram  
U00:%x[-1,0]  
U01:%x[0,0]  
U02:%x[1,0]  
U03:%x[-1,0]/%x[0,0]  
U04:%x[0,0]/%x[1,0]  
U05:%x[-1,0]/%x[1,0]

执行训练和测试:

#!/bin/sh  
crf_learn -f 3 -c 4.0 template 6.train.data 6.model > 6.train.rst  
crf_test -m 6.model 6.test.data > 6.test.rst

最后计算一下F值:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys

if __name__=="__main__":
    try:
        file = open(sys.argv[1], "r")
    except:
        print "result file is not specified, or open failed!"
        sys.exit()
    
    wc_of_test = 0
    wc_of_gold = 0
    wc_of_correct = 0
    flag = True
    
    for l in file:
        if l=='\n': continue
    
        _, _, g, r = l.strip().split()
     
        if r != g:
            flag = False
    
        if r in ('E', 'S'):
            wc_of_test += 1
            if flag:
                wc_of_correct +=1
            flag = True
    
        if g in ('E', 'S'):
            wc_of_gold += 1

    print "WordCount from test result:", wc_of_test
    print "WordCount from golden data:", wc_of_gold
    print "WordCount of correct segs :", wc_of_correct
            
    #查全率
    P = wc_of_correct/float(wc_of_test)
    #查准率,召回率
    R = wc_of_correct/float(wc_of_gold)
    
    print "P = %f, R = %f, F-score = %f" % (P, R, (2*P*R)/(P+R))

下图是得到的测试结果:

image

 

 

【参考文章列表】

CRF++中文分词使用指南

CRF++中文分词

 

作者:skyme 出处: http://www.niubua.com/

联系方式:

邮箱【cloudskyme@163.com】

QQ【270800073】

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章