中文分词基础原理

工作这些年总会听到分词、字典、语义这些词,一直对分词这块不甚了解,最近正好公司在推行OKR,那么就给自己定了几个OKR,其中就有“了解业界两款java分词器并落地一份wiki“,目标相对来说比较容易达成,但是也要了解一些基本分词的原理,那么就有了这篇博客的原因。毕竟术业有专攻,平时的精力没有放在分词、NLP这些领域,这篇文章只描述一些基本的分词理论,用于备注。

什么是中文分词

一句话概括就是通过某种手段将一段字符串中的词提取出来

为什么中文分词比英文分词要难

  1. 与英文为代表的拉丁语系语言相比,英文以空格作为天然的分隔符,而中文由于继承自古代汉语的传统,词语之间没有分隔。 古代汉语中除了连绵词和人名地名等,词通常就是单个汉字,所以当时没有分词书写的必要。而现代汉语中双字或多字词居多,一个字不再等同于一个词。
  2. 现代汉语的基本表达单元虽然为“词”,且以双字或者多字词居多,但由于人们认识水平的不同,对词和短语的边界很难去区分。
    例如:“对随地吐痰者给予处罚”,“随地吐痰者”本身是一个词还是一个短语,不同的人会有不同的标准,同样的“海上”“酒厂”等等,即使是同一个人也可能做出不同判断,如果汉语真的要分词书写,必然会出现混乱,难度很大。
    中文分词的方法其实不局限于中文应用,也被应用到英文处理,如手写识别,单词之间的空格就不很清楚,中文分词方法可以帮助判别英文单词的边界。

常用分词算法

1、基于词典 (字符串匹配,机械 分词方法)

正向最大匹配法(MM)

正向最大匹配算法:从左到右将待分词文本中的几个连续字符与词表匹配,如果匹配上,则切分出一个词。但这里有一个问题:要做到最大匹配,并不是第一次匹配到就可以切分的 。我们来举个例子:

       待分词文本:   content[]={"中","华","民","族","从","此","站","起","来","了","。"}

       词表:   dict[]={"中华", "中华民族" , "从此","站起来"}

(1) 从content[1]开始,当扫描到content[2]的时候,发现"中华"已经在词表dict[]中了。但还不能切分出来,因为我们不知道后面的词语能不能组成更长的词(最大匹配)。

(2) 继续扫描content[3],发现"中华民"并不是dict[]中的词。但是我们还不能确定是否前面找到的"中华"已经是最大的词了。因为"中华民"是dict[2]的前缀。

(3) 扫描content[4],发现"中华民族"是dict[]中的词。继续扫描下去:

(4) 当扫描content[5]的时候,发现"中华民族从"并不是词表中的词,也不是词的前缀。因此可以切分出前面最大的词——“中华民族”。

由此可见,最大匹配出的词必须保证下一个扫描不是词表中的词或词,的前缀才可以结束

逆向最大匹配法

逆向匹配算法大致思路是从右往左开始切分,一般来说逆向最大匹配会比正向匹配更有效。

双向最大匹配法

因为不管是正向最大匹配法还是逆向最大匹配法,都是有一个缺点的,就是会将有歧义的。
如“我出生在中华人民共和国”,以最大匹配原则进行分词则分词结果为“我”、“出生”、“在”、“中华人民共和国”,而不是“我”、“出生”、“在”、“中华”、“人民”、“共和国”。

因为正向切分以及逆向切分的缺点(其实就是一个缺点),人们提出了双向切分算法。双相切分算法就是使用正向切分一次、逆向切分一次。如果两次切分结果一样的话就好说了,随便选一个结果就可以。但是如果切分不一样的话使用那一次的切分结果呢?这就涉及到了结果的选取原则问题。我以为切分词应该遵守以下原则:

   1:最大匹配原则:上面一直在说这个,我认为使用这个原则的原因是词的字数越多,表示的含义越丰富、对于一条语句分出来的词也就越少,相对的,准确性也就会越高。

   2:词库中没有的单字词越少越好。这个原则有点依赖于词库了,至少词库中应该有一些常用的单字成词的字吧,比如:“你”、“我”、“他”、“和”、“的”、“了”等。使用这个原则的原因可以从上面提到的“技术和服务”这个例子看出来:

正向结果:技术、和服、务
逆向结果:技术、和、服务
虽然分出来的结果单字词都是一个,但是,逆向的单字词”和“在词库中存在,所以我们选择返回逆向切分结果。

最少切分法

使每一句中切出的词最小,字典中的所有词都列出来

2、消除歧义

机械分词方法又叫基于字符串匹配的分词方法,它是按照一定的策略将待分析的字符串与一个“充分大的”机器词典中的词条进行匹配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。这是最简单的分词方法,但非常高效和常见。

(1) 匹配方法

机械分词方法按照扫描方向的不同,可以分为正向匹配和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;常用的几种机械分词方法如下:

l 正向最大匹配法(由左到右的方向);如以例句“达观数据是一家大数据公司”,使用正向最大匹配法分词的结果为“达观/数据/是一/家/大数据/公司”

l 逆向最大匹配法(由右到左的方向);同样以例句“达观数据是一家大数据公司”,使用逆向最大匹配法分词的结果为“达观/数据/是/一家/大数据/公司”

l 最少切分(使每一句中切出的词数最小)。例句“达观数据是一家大数据公司”被分为“达观数据/是/一家/大数据公司”。

(2) 消除歧义

因为同一个句子,在机械分词中经常会出现多种分词的组合,因此需要进行歧义消除,来得到最优的分词结果。

以很常见的MMSEG机械分词算法为例,MMSEG在搜索引擎Solr中经常使用到,是一种非常可靠高效的分词算法。MMSEG消除歧义的规则有四个,它在使用中依次用这四个规则进行过滤,直到只有一种结果或者第四个规则使用完毕。这个四个规则分别是:

  1. 最大匹配,选择“词组长度最大的”那个词组,然后选择这个词组的第一个词,作为切分出的第一个词,如对于“中国人民万岁”,匹配结果分别为:
    中/国/人
    中国/人/民
    中国/人民/万岁
    中国人/民/万岁
    在这个例子“词组长度最长的”词组为后两个,因此选择了“中国人/民/万岁”中的“中国人”,或者“中国/人民/万岁”中的“中国”。

  2. 最大平均词语长度。经过规则1过滤后,如果剩余的词组超过1个,那就选择平均词语长度最大的那个(平均词长=词组总字数/词语数量)。比如“生活水平”,可能得到如下词组:
    生/活水/平 (4/3=1.33)
    生活/水/平 (4/3=1.33)
    生活/水平 (4/2=2)
    根据此规则,就可以确定选择“生活/水平”这个词组

  3. 词语长度的最小变化率,这个变化率一般可以由标准差来决定。比如对于“中国人民万岁”这个短语,可以计算:
    中国/人民/万岁(标准差=sqrt(((2-2)2+(2-2)2+(2-2^2))/3)=0)
    中国人/民/万岁(标准差=sqrt(((2-3)2+(2-1)2+(2-2)^2)/3)=0.8165)
    于是选择“中国/人民/万岁”这个词组。
    计算词组中的所有单字词词频的自然对数,然后将得到的值相加,取总和最大的词组。比如:
    设施/和服/务
    设施/和/服务
    这两个词组中分别有“务”和“和”这两个单字词,假设“务”作为单字词时候的频率是5,“和”作为单字词时候的频率是10,对5和10取自然对数,然后取最大值者,所以取“和”字所在的词组,即“设施/和/服务”。

  4. 机械分词的缺陷
    机械分词方法是一种很简单高效的分词方法,它的速度很快,都是O(n)的时间复杂度,效果也可以。但缺点是对歧义和新词的处理不是很好,对词典中未出现的词没法进行处理,因此经常需要其他分词方法进行协作。

Java常用分词器

推荐几款分词器 主要依赖词库
1.words分词器,自己使用了一下api还是挺简单的
2. THULAC4j GitHub上目前star最多的Java分词项目,星多即正义https://github.com/yizhiru/thulac4j
鉴于本人不是该领域专业人士,只依靠google、baidu目前未了解到其他比较突出的分词器

//TODO NLP相关知识的了解

//TODO 编辑距离算法的了解

  • 23
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值