CRF进行实体的识别

最近在研究实体的识别,之前在博客中介绍过基于深度学习的实体识别。实验效果还可以!后来对我们所使用的语料进行了分析发现,语料的描述都是很像的,于是在想用传统的机器学习算法效果如何呢?于是尝试了CRF

什么是CRF

Conditional Random Field:条件随机场,一种机器学习技术(模型)

语料格式

训练和测试文件必须包含多个tokens,每个token包含多个列。token的定义可根据具体的任务,如词、词性等。每个token必须写在一行,且各列之间用空格或制表格间隔。一个token的序列可构成一个sentence,sentence之间用一个空行间隔。
最后一列是CRF用于训练的正确的标注形式。

如下所示就是训练语料的格式,只使用了当前字,其他的特征没有加入进来

训练的命令:

crf_learn.exe template train.txt model 

在linux系统下进行训练时,将后面的.exe进行去除即可,下面的测试命令做相同的修改

其中template是模板文件,train.txt是训练语料,都需要事先准备好;model是CRF++根据模板和训练语料生成的文件,用于解码。

测试的命令:

crf_test.exe -m model test.txt  -o result.txt
其中 model是刚才生成的model文件,test是待测试语料,指将屏幕输出直接输出到文件result.txt中。

模板简单介绍

特征模版是一个文本文件,其内容如下所示,其中每行表示一个特征。如下模板使用了unigram特征,并且仅以字符本身作为特征而不考虑其他特征。除当前字符外,还使用了其前后3个字,以及上下文的组合作为特征。CRF++会根据特征模版生成相关的特征函数
#Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U5:%x[-2,0]/%x[-1,0]
U6:%x[-1,0]/%x[0,0]
U7:%x[0,0]/%x[1,0]
U8:%x[1,0]/%x[2,0]

对上述的模板进行举例子解释一下:

句子:中华人民共和国

U00:%x[-2,0]  ====》中
U01:%x[-1,0]  ====》华
U02:%x[0,0]  ====》人
U03:%x[1,0]  ====》民
U04:%x[2,0]  ====》共
U5:%x[-2,0]/%x[-1,0]  ====》中/华
U6:%x[-1,0]/%x[0,0]  ====》华/人
U7:%x[0,0]/%x[1,0]  ====》人/民
U8:%x[1,0]/%x[2,0]  ====》民/共

1、训练的模板内容:
# Unigram
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
# Bigram
B

训练的过程显示:

实验的结果显示如下所示:

特征只用了当前字,特征模板也比较的简单,但实验的效果还是可以接受的

2、特征模板制作复杂一点,如下所示:

# Unigram
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U01:%x[-1,0]/%x[0,0]
U01:%x[0,0]/%x[1,0]
# Bigram
B

 

3、特征模板也可以修改成如下所示:

# Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-2,0]/%x[-1,0]/%x[0,0]
U06:%x[-1,0]/%x[0,0]/%x[1,0]
U07:%x[0,0]/%x[1,0]/%x[2,0]
U08:%x[-1,0]/%x[0,0]
U09:%x[0,0]/%x[1,0]
# Bigram
B

下面是做实验过程的一个测试:
 

# coding:utf-8
import os

str1 = '某人民检察院指控,2032年7月18日12时许,被告人李某甲、孙某甲经事先商议,驾驶一辆银白色踏板摩托车窜至嵊州市三界镇西村,爬窗进入该村150号张三家中,窃得人民币42.2元。而后,由被告人孙某甲望风,被告人李某甲踹门进入西村下岙145号张某家中,窃得电动机废铜线37.4千克,计价值人民币1720.4元。'


def handle_2(word, label):  # 该函数主要是实现将实体识别出的结果进行正常话处理
    result = []
    str1 = ''
    for i in range(len(word)):
        if label[i].find('B-') != -1:
            if str1 == '':
                str1 = label[i].split('-')[-1] + ':' + word[i]
            else:
                result.append(str1)
                str1 = label[i].split('-')[-1] + ':' + word[i]
        elif label[i].find('I-') != '' and str1.find(label[i].split('-')[-1]) != -1:
            str1 = str1 + word[i]
        elif label[i].find('-') == -1:
            if str1 != '':
                result.append(str1)
                str1 = ''
    return result

with open('ceshi_test.txt', 'w') as fp:
    for each in str1.decode('utf-8'):
        fp.write(each.encode('utf-8') + ' O' + '\n')

os.system('crf_test.exe -m model_ner_1227 ceshi_test.txt  -o jieguo.txt')

#
word = []
label = []
with open('jieguo.txt') as fp:
    for line in fp.readlines():
        line = line.strip()
        if line == '':
            continue
        line = line.split()
        word.append(line[0])
        label.append(line[-1])
for each in handle_2(word, label):
    print each
'''
打印出的结果:
riqi:2032年7月18日12时许
dizhi:嵊州市三界镇西村
shouduan:爬窗进入
dizhi:该村150号张三家中
dizhi:西村下岙145号张某家中
caiwu:电动机废铜线37.4千克
'''

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小杨算法屋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值