使用Python,字标注及最大熵法进行中文分词

在前面的博文中使用python实现了基于词典及匹配的中文分词,这里介绍另外一种方法, 这种方法基于字标注法,并且基于最大熵法,使用机器学习方法进行训练,将训练出的模型 用于中文分词,效果优于基于词典及匹配的分词方法。

1 背景知识

2002年以前,自动分词方法基本上基于词(或词典)的,在此基础上可以进一步分成基于规则和 基于统计两大类。同时,在分词工作中,未登录词对分词精度的影响非常大。所谓未登录词即没有 在词典中出现过的词,对于这种词,基于词典的方法无能为力,因此中文分词需要新的方法才能有 革命性的进展。

Nianwen Xue等人在2002年提出了以字分词的方法,并于2003年使用最大熵模型配合以字标注,参加了Bakeoff-2003的评测, 在AS语料库与HK语料库的测试中,其未登录词召回率均居榜首。在此后的Bakeoff-2005中,基于字标注的分词方法大放异彩, Jin Kiat Low等人采用最大熵模型及字标注的系统在四项开放测试中取得三个冠军,Huihsin Tseng等人采用条件随机场 及字标注的系统在封闭测试中取得两个冠军。

2 分词思想

 

2.1 以字分词

首先介绍以字分词。先看一个句子:我是一名程序员。再将所有字分为4类,S表示单字,B表示词首,M表示词中,E表示词尾。

如果我们知道上述句子中每个字的类别,即:

我/S 是/S 一/B 名/E 程/B 序/M 员/E 。/S

那么我们就可以知道这个句子的分词结果:我 是 一名 程序员 。

从这里可以看出,分词问题转化成了一个分类问题,即对每个字分类。我们知道,机器学习方法可以很好地处理分类问题。 所以接下来,我们需要用机器学习的方法来解决分词。

2.2 机器学习

机器学习处理问题的基本思想是,首先对标注好的数据进行训练,得到模型,再根据模型对新数据进行预测。这样我们将 问题转化为三个子问题:

  • 标注数据是什么?
  • 模型是什么?
  • 如何使用模型进行预测?

具体到以字分词问题,我们简单地回答上述三个问题。

  • 标注好的数据就是:字x在情境A下类别为a,字y在情境B下类别为c,字x在情境C下类别为e …
  • 模型就是:一些公式。这些公式是对数据的一种描述,其中包含了标注好的数据的信息,以及一些未知的参数,

对模型的训练就是采用机器学习的方法,赋予未知的参数一些合适的值,这些值使得公式的值达到最优。

  • 如何预测:给定字x,情境Z,我们得到模型后,就可以根据 x,Z,模型,得到在这种情况下x取各个类别的概率是多少,

由此可以预测出x的类别。

在上述回答中,有几个地方是没有定义的,例如,什么叫情境。在以字分词中,情境就是对一个字环境的描述,例如在句子我是 程序员中,如果我们将一个字的情境定义为:这个字前面的字和这个字后面的字。那么“程”这个字的情境为:“是”,以及“序”。

所以,所谓标注好的数据就是:{类别:情境}的集合,我们举例说明。

将C-1定义为字前的字,C0定义为当前字,C1定义为字后的字,那么如果我们有一句分好词的句子:我 是 一名 程序员 。

首先我们需要对每个字打个标签,表示类别:我/S 是/S 一/B 名/E 程/B 序/M 员/E 。/S

然后就可以转化为标注数据了,例如“程”字,可以得到一条标注数据为: B C-1=名 C0=序 C1=员

这条标注数据意思为当遇到C-1=名 C0=序 C1=员这种情境时,类别为B。

所以,由一堆分好词的数据,就可以得到许多条这样的标注数据。得到标注数据后,就可以使用机器学习包进行训练, 不同的机器学习包有不同的格式,但基本的思想都是这样的,我用的是张乐博士的最大熵工具包。

训练后可以得到相应的模型,预测时导入模型,然后给出相应情境(即C-1=? C0=? C1=?),就可以知道在此情境下各个类别的概率,在此可以简单地 认识哪个类别概率大,结果就是哪个类别,当然,也可以设计其它的方式。

在整个过程中,情境,机器学习方法,预测的方法都是可变的,但是以字分词大概的思想应该都是这样的。

3 实验及代码

 

3.1 数据来源

数据来自 Bakeoff2005 官方网站:http://sighan.cs.uchicago.edu/bakeoff2005/ 下载其中的 icwb2-data.tar.bz2 解压后取出以下文件:

  • 训练数据:icwb2-data/training/pku_ training.utf8
  • 测试数据:icwb2-data/testing/pku_ test.utf8
  • 正确分词结果:icwb2-data/gold/pku_ test_ gold.utf8
  • 评分工具:icwb2-data/script/socre

3.2 各部分数据示例

  1. 原始训练数据

    迈向  充满  希望  的  新  世纪
    
  2. 打标签后的训练数据
    迈/B向/E充/B满/E希/B望/E的/S新/S世/B纪/E
    
  3. 机器学习包可以接收的训练数据
    B C-1=b C0=迈 C1=向 C-1=bC0=迈 C0=迈C1=向 C-1=bC1=向 Num=0
    E C-1=迈 C0=向 C1=充 C-1=迈C0=向 C0=向C1=充 C-1=迈C1=充 Num=0
    B C-1=向 C0=充 C1=满 C-1=向C0=充 C0=充C1=满 C-1=向C1=满 Num=0
    E C-1=充 C0=满 C1=希 C-1=充C0=满 C0=满C1=希 C-1=充C1=希 Num=0
    B C-1=满 C0=希 C1=望 C-1=满C0=希 C0=希C1=望 C-1=满C1=望 Num=0
    E C-1=希 C0=望 C1=的 C-1=希C0=望 C0=望C1=的 C-1=希C1=的 Num=0
    S C-1=望 C0=的 C1=新 C-1=望C0=的 C0=的C1=新 C-1=望C1=新 Num=0
    S C-1=的 C0=新 C1=世 C-1=的C0=新 C0=新C1=世 C-1=的C1=世 Num=0
    B C-1=新 C0=世 C1=纪 C-1=新C0=世 C0=世C1=纪 C-1=新C1=纪 Num=0
    E C-1=世 C0=纪 C1=— C-1=世C0=纪 C0=纪C1=— C-1=世C1=— Num=0

    其中,Ci 表示与当前字偏移为i的字;Num表示是否为数字。

  4. 原始的测试数据
    共同创造美好的新世纪
    
  5. 可供模型预测的测试数据
    C-1=b C0=共 C1=同 C-1=bC0=共 C0=共C1=同 C-1=bC1=同 Num=0
    C-1=共 C0=同 C1=创 C-1=共C0=同 C0=同C1=创 C-1=共C1=创 Num=0
    C-1=同 C0=创 C1=造 C-1=同C0=创 C0=创C1=造 C-1=同C1=造 Num=0
    C-1=创 C0=造 C1=美 C-1=创C0=造 C0=造C1=美 C-1=创C1=美 Num=0
    C-1=造 C0=美 C1=好 C-1=造C0=美 C0=美C1=好 C-1=造C1=好 Num=0
    C-1=美 C0=好 C1=的 C-1=美C0=好 C0=好C1=的 C-1=美C1=的 Num=0
    C-1=好 C0=的 C1=新 C-1=好C0=的 C0=的C1=新 C-1=好C1=新 Num=0
    C-1=的 C0=新 C1=世 C-1=的C0=新 C0=新C1=世 C-1=的C1=世 Num=0
    C-1=新 C0=世 C1=纪 C-1=新C0=世 C0=世C1=纪 C-1=新C1=纪 Num=0
    C-1=世 C0=纪 C1=— C-1=世C0=纪 C0=纪C1=— C-1=世C1=— Num=0
  6. 预测结果
    共/B同/E创/B造/E美/B好/E的/S新/S世/B纪/E
    
  7. 分词结果
共同 创造 美好 的 新 世纪

注:上面展示的仅仅是数据示例,并非完整的数据

3.3 各部分代码示例

  1. 训练

    def training(feature_file_path, trained_model_file, times):
    m = MaxentModel()
    fr = codecs.open(feature_file_path, 'r', 'utf-8')
    all_list = []
    m.begin_add_event()
    for line in fr:
    line = line.rstrip()
    line_list = line.split(' ')
    str_list = []
    for item in line_list:
    str_list.append(item.encode('utf-8'))
    all_list.append(str_list)
    m.add_event(str_list[1:], str_list[0], 1)
    m.end_add_event()
    print 'begin training'
    m.train(times, "lbfgs")
    print 'end training'
    m.save(trained_model_file)
    return all_list

    这一部分使用了张乐博士的最大熵工具包提供的python接口,关键的代码是:

    m = MaxentModel()
    m.begin_add_event()
    m.add_event(str_list[1:], str_list[0], 1)
    m.end_add_event()
    m.train(times, "lbfgs")
    m.save(trained_model_file)
  2. 预测
def tag_test(test_feature_file, trained_model_file,  tag_test_set_file):
fr = codecs.open(test_feature_file, 'r', 'utf-8')
fw = codecs.open(tag_test_set_file, 'w', 'utf-8')
m = MaxentModel()
m.load(trained_model_file) for ...:
label_prob_list = m.eval_all(str_feature)
label = max_prob(label_prob_list)

这里只给出了部分代码,str_feature表示被测试的情境, label_prob_list表示各个类别的概率。

完整的代码可以参考我的Github主页上的分词工具: https://github.com/minixalpha/PyCWS/tree/master/src

参考文献:

1 黄昌宁,赵海.2007.中文分词十年回顾.中文信息学报,21(3): 8-19

2 Nianwen Xue, Suan P.Converse. 2002. Combining classifiers for Chinese word segmentation. Proceedings of the First SIGHAN workshop on Chinese language processing, 18:1-7.

3 Nianwen Xue, Libin Shen.2003. Chinese word segmentation as LMR tagging. Proceedings of the Second SIGHAN workshop on Chinese language processing, 17:176-179.

4 Richard Sproat, Thomas Emerson. 2003. The First international Chinese word segmentation Bakeoff. 17:133-143.

5 Thomas Emerson. 2005. The Second International Chinese Word Segmentation Bakeoff.

6 Jin Kiat Low, Hwee Tou Ng, and Wenyuan Guo. A Maximum Entropy Approach to Chinese Word Segmentation. 2005. Proceedings of the Fourth SIGHAN workshop on Chinese language processing.

7 Hai Zhao, Chang-Ning Huang and Mu Li. An Improved Chinese Word Segmentation System with Conditional Random Field. 2006. Proceedings of the Fifth SIGHAN workshop on Chinese language processing.

8 Adwait Ratnaparkhi. A maximum entropy model for part-of-speech tagging. 1996. Proceedings of the Empirical Methods in Natural Language Processing.

9 Le Zhang. Maximum Entropy Modeling Toolkit for Python and C++ . 2013,6. http://homepages.inf.ed.ac.uk/lzhang10/maxent_toolkit.html

使用Python,字标注及最大熵法进行中文分词的更多相关文章

  1. 基于Tire树和最大概率法的中文分词功能的Java实现

    对于分词系统的实现来说,主要应集中在两方面的考虑上:一是对语料库的组织,二是分词策略的制订. 1.   Tire树 Tire树,即字典树,是通过字串的公共前缀来对字串进行统计.排序及存储的一种树形结构 ...

  2. 用条件随机场CRF进行字标注中文分词(Python实现)

    http://www.tuicool.com/articles/zq2yyi   http://blog.csdn.net/u010189459/article/details/38546115 主题 ...

  3. Python 自然语言处理(1)中文分词技术

    中文分词技术 中文自动分词可主要归纳为“规则分词”“统计分词”和“混合分词”,规则分词主要是通过人工设立词库,按照一定方式进行匹配切分,实现简单高效,但对新词很难进行处理,统计分词能够较好应对新词发现 ...

  4. 【中文分词系列】 4. 基于双向LSTM的seq2seq字标注

    http://spaces.ac.cn/archives/3924/ 关于字标注法 上一篇文章谈到了分词的字标注法.要注意字标注法是很有潜力的,要不然它也不会在公开测试中取得最优的成绩了.在我看来,字 ...

  5. python排序之二冒泡排序法

    python排序之二冒泡排序法 如果你理解之前的插入排序法那冒泡排序法就很容易理解,冒泡排序是两个两个以向后位移的方式比较大小在互换的过程好了不多了先上代码吧如下: 首先还是一个无序列表lis,老规矩 ...

  6. Python的生成器进阶玩法

    Python的生成器进阶玩法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.yield的表达式形式 #!/usr/bin/env python #_*_coding:utf-8 ...

  7. Python实现客观赋权法

    本文从阐述Python实现客观赋权法的四种方式: 一. 熵权法 二. 因子分析权数法(FAM) 三. 主成分分析权数法(PCA) 四. 独立性权系数法 Python实现客观赋权法,在进行赋权前,先导入 ...

  8. Python函数标注

    Python函数标注 是关于用户自定义函数中使用的类型的完全可选元数据信息. 函数标注 以Python字典的形式存放在函数的 __annotations__ 属性中,并且不会影响函数的任何其他部分. ...

  9. 统计学习:《贝叶斯思维统计建模的Python学习法》中文PDF+英文PDF+代码

    用数学工具解决实际问题仅有的要求可能就是懂一点概率知识和程序设计.而贝叶斯方法是一种常见的利用概率学知识去解决不确定性问题的数学方法,对于一个计算机专业的人士,应当熟悉其应用在诸如机器翻译,语音识别, ...

随机推荐

  1. ORACLE STUDY NOTES 01

    [JSU]LJDragon's Oracle course notes In the first semester, junior year DML数据操纵语言 DML指:update,delete, ...

  2. pods 这两篇就够了

    http://www.cnblogs.com/gongyuhonglou/p/5801681.html http://blog.csdn.net/iunion/article/details/1701 ...

  3. 互联网程序设计c++

    地址:ftp.sist.stdu.edu.cn用户名:lzh_hlw20133密码:lzhstdftp端口:2014

  4. javax.management

    软件包 javax.management 的描述 提供 Java Management Extensions 的核心类. Java Management Extensions (JMXTM) API ...

  5. Android 中文 API (40) —— RatingBar

    Android 中文 API (40) —— RatingBar 前言 本章内容是 android.widget.RatingBar,译为"评分条",版本为Android 2.2 ...

  6. 作业三 ATM

    模拟实现一个ATM+购物商场程序 1.额度15000自定义 商城和银行两个帐户 2.实现购物商城,买东西加入购物车,调用信用卡接口结账 3.可以提现,手续费5%,提现额度不能超过50% 4.每月22日 ...

  7. Messager( 消息窗口) 组件

    一. 加载方式消息窗口提供了不同的消息框风格,包含 alert(警告框).confirm(确认框).prompt(提示框).progress(进度框)等.所有消息框都是异步的,用户可以在交互消息之后使 ...

  8. js中this的指向

    在js中this的指向对于新手来说一定是个难题,但是如果你真正理解了的话,也就没什么问题啦,下面就来讲讲this吧. JS中,this的值取决于调用的模式(调用对象),而JS中共有4种调用模式: 1. ...

  9. HTML、CSS、JS、PHP 的学习顺序~(零基础初学者)

    如果你有耐心坚持一年以上的话, 我会推荐HTML->CSS->JS->PHP的顺序来学习. 1. HTML学习:首先学习HTML,HTML作为标记语言是非常容易学的,把w3schoo ...

  10. C#list泛型集合

    //创建list泛型集合 List<int> ilist = new List<int>(); ilist.Add(); ilist.Add(); ilist.AddRange ...