条件随机场 python_利用条件随机场工具CRF完成中文分词

之前用maxent进行中文分词,发现效果不是特别理想,所以又实验了下用CRF来进行中文分词。

这里先简单介绍下什么是CRF(条件随机场):

introduction

Conditional random fields (CRFs) are a probabilistic framework for labeling and segmenting structured data, such as sequences, trees and lattices. The underlying idea is that of defining a conditional probability distribution over label sequences given a particular observation sequence, rather than a joint distribution over both label and observation sequences. The primary advantage of CRFs over hidden Markov models is their conditional nature, resulting in the relaxation of the independence assumptions required by HMMs in order to ensure tractable inference. Additionally, CRFs avoid the label bias problem, a weakness exhibited by maximum entropy Markov models (MEMMs) and other conditional Markov models based on directed graphical models. CRFs outperform both MEMMs and HMMs on a number of real-world tasks in many fields, including bioinformatics, computational linguistics and speech recognition.

上面这段介绍,把CRF和MEMM(最大熵模型)以及HMM(隐马尔可夫模型)作了对比,介绍了CRF跟HEMM和HMM相比的优势。CRF其实也是HMM的一种扩展,是一种计算联合概率分布的有效模型。

安装CRF和安装maxent差不多,都是./configure,make,sudo su,make install。CRF提供了各种语言的工具包,有java、python、perl等。我用的是python语言工具包,所以还要安装python工具包:python setup.py build ,(sudo) python setup.py install。安装完成后,可以打开python shell ,然后输入 import CRFPP,看看是否可以成功import,如果可以,就说明安装成功了。

CRF的example里有一个seg目录,里面是一个关于日文分词的例子。日文和中文很相似,所以用这个例子来训练model最合适了。

这里的训练集还是之前用到的icwb2-data,为了得到适合拿来训练的数据集(4-tag标记),用到一个python脚本--make_crf_train_data.py:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

#make_crf_train_data.py

#得到CRF++要求的格式的训练文件

#用法:命令行--python make_crf_train_data.py input_file output_file

#4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single)

import codecs

import sys

def character_tagging(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():

word_list = line.strip().split()

for word in word_list:

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 make_crf_train_data.py input output"

sys.exit()

input_file = sys.argv[1]

output_file = sys.argv[2]

character_tagging(input_file, output_file)

执行“python make_crf_train_data.py ./icwb2-data/training/msr_training.utf8 msr_training.tagging4crf.utf8” 即可得到CRF++要求的格式的训练文件msr_training.tagging4crf.utf8

有了训练语料,接下来就可以利用crf的训练工具crf_learn来训练模型了,切换到CRF++0.58目录下,执行如下命令即可:

crf_learn -f 3 -c 1.5 ./example/seg/template ../msr_training.tagging4crf.utf8 crf_model,得到crf_model。

最后执行“python crf_segmenter.py  crf_model blog_test.utf8  blog_test_segment.utf8”

crf_segmenter.py:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

#crf_segmenter.py

#用法:命令行输入--python crf_segmenter.py crf_model input_file output_file

# 利用CRF自带的python工具包,对输入文本进行分词

import codecs

import sys

import CRFPP

def crf_segmenter(input_file, output_file, tagger):

input_data = codecs.open(input_file, 'r', 'utf-8')

output_data = codecs.open(output_file, 'w', 'utf-8')

for line in input_data.readlines():

tagger.clear()

for word in line.strip():

word = word.strip()

if word:

tagger.add((word + "\to\tB").encode('utf-8'))

tagger.parse()

size = tagger.size()

xsize = tagger.xsize()

for i in range(0, size):

for j in range(0, xsize):

char = tagger.x(i, j).decode('utf-8')

tag = tagger.y2(i)

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 + ' ')

output_data.write('\n')

input_data.close()

output_data.close()

if __name__ == '__main__':

if len(sys.argv) != 4:

print "pls use: python crf_segmenter.py model input output"

sys.exit()

crf_model = sys.argv[1]

input_file = sys.argv[2]

output_file = sys.argv[3]

tagger = CRFPP.Tagger("-m " + crf_model)

crf_segmenter(input_file, output_file, tagger)

这里的blog_test.utf8同样是之前的《Some important suggestions for jobseeker》这篇blog , blog_test_segment.utf8就是最后分好词的文本。

blog_test_segment.utf8:

下面 这些 建议 都是 我 在 《 Th eG oo gl eR es um e: Ho wt op re pa re fo ra ca re er an dl an da jo ba tA pp le ,M ic ro so ft ,G oo gl e, or an yT op Te ch Co mp an y 》 ( 中 文名 比 较俗 : 《 金领 简历 敲开 苹果 、 微软 、 谷歌 的 大门 》 ) 这 本 书上 看到 的 。 我 对 一些 内容 进行 了 去粗 取精 。 有 兴趣 的 可以 去看 原书 。

1. 建立 自己 的 成就 记录 。 招聘 人员 想 知道 你 能够 设定 宏达 目标 , 并 拥有 完成 这些 目标 的 能力 。 你 的 成就 可以 体现 在 学业 、 项目 工作 、 志愿者 工作 、 职业 经历 和 体育 活动 上 。

2. 具备 良好 的 笔头 和 口头 表达 能力 。 不管 是 书面 沟通 还是 口头 沟通 都 对 你 未来 的 职业 发展 至关 重要 。 如果 你 还 做 不 到 游刃 有余 地 在 公众 面前 演讲 , 那 就 得 多加 练习 。 如果 你 的 写作 能力 比较 薄弱 , 可以 上 一门 写作 课或 是 写博 客来 锻炼 自己 。 你 不 需要 博览 群书 或 提笔 成章 , 但 确实 需要 表述 得 清晰 、 专业 。

3. 做 得 精而 不是 做 得杂 。 ( 关于 这点 必须 做 一个 取舍 。 你 做 的 事情 越 多 越杂 , 就 越 有 可能 掌握 通用 技能 。 但 如果 你 想 专于 一个 领域 的 话 , 就 得学 会 专注 。 )

4. 成为 一 名 领导者 。

从上面的结果可以看出,效果也不比之前的maxent理想,但这里主要是我的电脑在作孽,由于原来的训练数据太大了,大概有400多万行数据,我在电脑上跑了三次,结果三次都导致了系统崩溃,最后一次我从晚上十点开始跑数据,一直到第二天凌晨一点还没好,后来我就去睡觉了,电脑开着让它继续运行,结果第二天醒来,程序又崩溃了,所以后来我就截取了训练数据里的大概五万行数据用来训练model,结果就导致了正确率不高的问题,其实如果电脑给力的话,分词准确率大概有96%。这也是CRF的一个特点,它需要大量的数据来进行训练才能得到理想的效果。

最终分词效率:

=== SUMMARY:

=== TOTAL INSERTIONS: 99

=== TOTAL DELETIONS: 30

=== TOTAL SUBSTITUTIONS: 156

=== TOTAL NCHANGE: 285

=== TOTAL TRUE WORD COUNT: 821

=== TOTAL TEST WORD COUNT: 890

=== TOTAL TRUE WORDS RECALL: 0.773

=== TOTAL TEST WORDS PRECISION: 0.713

=== F MEASURE: 0.742

=== OOV Rate: 0.141

=== OOV Recall Rate: 0.259

=== IV Recall Rate: 0.858

### blog_test_segment.utf8 99 30 156 285 821 890 0.773 0.713 0.742 0.141 0.259 0.858

2 thoughts on “利用条件随机场工具CRF完成中文分词”

我按照你的步骤来做这个CRF的分词,可是在运行python crf_segmenter.py crf_model blog_test.utf8 blog_test_segment.utf8这条命令时,报错:

Traceback (most recent call last):

File "crf_segmenter.py", line 10, in

import CRFPP

ImportError: No module named CRFPP

请问你的程序都在linux下运行的吗?请问这个问题应该怎么解决?

首先我的程序都是在ubuntu下运行测试的,当然你也可以在windows下运行,因为考虑到windows下安装以及编码问题比较麻烦。你遇到的上面这个问题,是因为你电脑上没安装过CRF++,你google下这个开源工具,后面所有的程序都是基于这个软件包的。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

姓名 *

电子邮件 *

站点

评论

您可以使用这些HTML标签和属性:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于条件随机场模型的中文分词代码,使用CRF++工具包: 1. 数据准备 首先将训练数据和测试数据转换成CRF++的格式,格式为每个词和标注用空格隔开,句子之间用空行隔开,例如: 中 B 国 E 是 S 一个 S 伟 B 大 E 的 S 国 S 2. 模型训练 使用CRF++工具包进行模型训练,需要准备好训练数据和模板文件。模板文件指定了特征模板,例如: 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] 其中,%x[i,j]表示当前位置加上偏移量(i,j)的词和标注,U00-U07则是特征函数的名称。训练命令如下: crf_learn -f 3 -c 4.0 template train.data model 其中,-f指定特征函数的截断阈值,-c指定正则化参数。训练完成后会生成一个模型文件model。 3. 模型测试 使用CRF++工具包进行模型测试,需要准备好测试数据和模型文件。测试命令如下: crf_test -m model test.data > result 其中,-m指定模型文件,test.data是测试数据文件,> result表示将结果输出到result文件中。测试结果为每个词和标注用空格隔开,例如: 中 B 国 E 是 S 一个 S 伟 B 大 E 的 S 国 S 4. 结果评估 使用Python脚本进行结果评估,代码如下: ```python import sys def evaluate(gold_file, pred_file): gold = [] with open(gold_file, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if line: word, label = line.split() gold.append(label) pred = [] with open(pred_file, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if line: word, label = line.split() pred.append(label) assert len(gold) == len(pred) correct = 0 for i in range(len(gold)): if gold[i] == pred[i]: correct += 1 accuracy = correct / len(gold) return accuracy if __name__ == '__main__': gold_file = sys.argv[1] pred_file = sys.argv[2] accuracy = evaluate(gold_file, pred_file) print('Accuracy: {:.2%}'.format(accuracy)) ``` 将正确的标注文件和预测的标注文件作为参数传入,即可计算准确率。例如: python evaluate.py test.gold result 输出结果为准确率的百分比。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值