分词是自然语言处理中最基本的任务之一,而词典分词是最简单、最常见的分词算法,仅需一部词典和一套查词典的规则即可。

利用词典分词,最主要的是定制合适的切分规则。规则主要有正向最长匹配、逆向最长匹配和双向最长匹配三种。本文主要介绍上述三种规则。

1、词典准备

既然是词典分词,那么我们首先需要找到一部字典,这里使用Hanlp提供的mini版本的中文词典:https://github.com/hankcs/HanLP/blob/master/data/dictionary/CoreNatureDictionary.mini.txt

下载下来之后保存在本地项目路径下,词典的内容如下:

可以看到第一列是我们需要的词,后面每两列代表一种词性以及词频。我们只需要得到所有的词即可:

with open('data/CoreNatureDictionary.mini.txt') as f:    dict_set = set([s.split('\t')[0] for s in f.readlines()])

dict_set

得到输出如下:

好了,词典准备完毕,接下来介绍几种词典分词方法。

2、切分规则

常用的切分规则有正向最长匹配、逆向最长匹配和双向最长匹配,它们都基于完全切分过程,因此本节先介绍完全切分过程,再介绍三种匹配规则。

2.1 完全切分

完全切分顾名思义,就是找出一段文本中所有在字典中的单词。假设我们要分词的句子是“自然语言处理入门实战”,完全切分的代码如下:

#完全切分def fully_segment(text,dic):    seg_list = []    for i in range(0,len(text)-1):        for j in range(i+1,len(text)):            word = text[i:j+1] # 注意这里是j+1            if word in dic:                seg_list.append(word)    return seg_list

print(','.join(fully_segment('自然语言处理入门实战',dict_set)))

输出为:

但完全切分不是真正意义上的分词,我们需要完善一下规则,考虑到越长的单词表达的意义越丰富,于是定义单词越长优先级越高。具体来说,在以某个字符为起点逐次向前或向后查找的过程中,优先输出更长的单词。这种规则统称为最长匹配算法。包括正向最长匹配、逆向最长匹配和双向最长匹配。

接下来,我们就来介绍下面这几种匹配算法。

2.2 正向最长匹配

正向匹配的过程示意图如下所示:

上图中,我们只给出了部分的分词过程,不过可以看到,它是一个从前向后匹配的过程,通过代码进一步理解下:

def forward_segment(text,dic):    seg_list = []    i = 0    while i < len(text):        longest_word = text[I]        for j in range(i+1,len(text)+1):            word = text[i:j]            if word in dic and len(word) > len(longest_word):                longest_word = word        seg_list.append(longest_word)        i += len(longest_word)    return seg_list

print(forward_segment("就读于中国人民大学",dict_set))

最终的分词结果如下:

可以看到,这样切分并不是我们想要的结果,因为中国人民大学切分为中国、人民和大学更加合理(或者当作一个专有名词,不进行切分),但在正向最长匹配中,因为中国人同样出现在了词典中,因此中国人便优先作为一个词输出了。

2.3 逆向最长匹配

接下来再看看逆向匹配的过程:

上图中,我们只给出了部分的分词过程,不过可以看到,它是一个从后向前匹配的过程,每次都认为从零位置到当前下标i位置的单词是最长的,然后基于词典不断往后移动j,直到切片对应的单词出现在词典中,通过代码进一步理解下:

def backward_segment(text,dic):    seg_list = []    i = len(text) - 1    while i >= 0:        longest_word = text[I]        for j in range(0,i):            word = text[j:i+1]            if word in dic and len(word) > len(longest_word):                longest_word = word        seg_list.append(longest_word)        i -= len(longest_word)    seg_list.reverse()    return seg_list

print(backward_segment("就读于中国人民大学",dict_set))

最终的切分结果如下:

可以看到切分结果符合我们的预期,但是从上面的流程图直观的就可以看到,逆向最长匹配的时间复杂度是明显高于正向匹配的,因为逆向匹配每次都需要从句子的最开始进行扫描。

2.4 双向最长匹配

对于同一个句子,正向最长匹配和逆向最长匹配带来的结果可能不同,那到底哪种更好呢?先看下面几个例子:

print(forward_segment("就读于中国人民大学",dict_set))print(forward_segment("电视上的电影节目",dict_set))print(forward_segment("项目的研究",dict_set))print(forward_segment("角色本人将会参与配音",dict_set))print(backward_segment("就读于中国人民大学",dict_set))print(backward_segment("电视上的电影节目",dict_set))print(backward_segment("项目的研究",dict_set))print(backward_segment("角色本人将会参与配音",dict_set))

分词结果如下:

可以看到,有时候正向匹配的效果更好,有时候逆向匹配的效果更好,但似乎逆向匹配的匹配成功次数更多。那能不能从两种结果中挑选一种比较好的呢?于是我们又有了双向最长匹配。规则如下:

1)同时执行正向和逆向最长匹配,若两者的词数不同,则返回词数更少的那一个;
2)否则,返回两者中单字更少的那一种;
3)当单子数量也相同时,优先返回逆向最长匹配的结果。

双向匹配的代码如下:

def count_single_word(word_list):    return sum(1 for word in word_list if len(word) == 1)

def bidiectional_segment(text,dic):    f = forward_segment(text,dic)    b = backward_segment(text,dic)    if len(f) < len(b):        return f    elif len(f) > len(b):        return b    else:        if count_single_word(f) < count_single_word(b):            return f        else:            return b

print(bidiectional_segment("就读于中国人民大学",dict_set))print(bidiectional_segment("电视上的电影节目",dict_set))print(bidiectional_segment("项目的研究",dict_set))print(bidiectional_segment("角色本人将会参与配音",dict_set))

最终的切分结果如下:

第三个句子还是没有获得正确的切分,因为在分词长度以及单字个数都一致的情况下,优先返回的是逆向匹配的结果。由此可见,基于词典匹配的规则分词方法,效果是比较差的。

好了,几种基于词典的规则分词方法就介绍道这里,下一篇我们将介绍如何对分词结果的精度进行评价,总不能一个个用肉眼去看吧,哈哈。

上述内容总结自《自然语言处理入门》:

NLP入门(1)-词典分词方法及实战相关推荐

  1. NLP入门学习1——分词和词性标注

    NLP入门学习1--分词和词性标注 0.简介 1.概念和工具 1.1 词性标注 1.2 NLTK 1.3 jieba 1.4 LAC 2.代码实现 2.1 分词 2.1.1 使用nltk进行分词: 2 ...

  2. 基于Python实现的词典分词方法或统计分词方法

    资源下载地址:https://download.csdn.net/download/sheziqiong/85787813 资源下载地址:https://download.csdn.net/downl ...

  3. NLP(2) | 中文分词分词的概念分词方法分类CRFHMM分词

    NLP(1) | 词向量one hot编码词向量编码思想 分词的概念 简单来说就是把词进行分开,分词的难点: 1.如何避免歧义,如:"白开水不如果汁甜".如何让机器避免将" ...

  4. NLP 《分词方法》

    在NLP中,最基础的处理的就是分词,不论是一个网页还是一片文章,还是一段话,都是需要先分词的才能去搞清楚这段话的意思的,这里介绍两个最经典的方法,都是基本的算法. 一:前向最大匹配(forward-m ...

  5. 中文分词算法—— 基于词典的方法

    1.基于词典的方法(字符串匹配,机械分词方法) 定义:按照一定策略将待分析的汉字串与一个"大机器词典"中的词条进行匹配,若在词典中找到某个字符串,则匹配成功. 按照扫描方向的不同: ...

  6. 【AI实战】大语言模型(LLM)有多强?还需要做传统NLP任务吗(分词、词性标注、NER、情感分类、知识图谱、多伦对话管理等)

    [AI实战]大语言模型(LLM)有多强?还需要做传统NLP任务吗(分词.词性标注.NER.情感分类.多伦对话管理等) 大语言模型 大语言模型有多强? 分词 词性标注 NER 情感分类 多伦对话管理 知 ...

  7. NLP入门之路及学习方法:从任务实践入手!

    Datawhale原创 作者:康兵兵,Datawhale成员 寄语:NLP入门,科学有效的方法是找到切入点,一个具体任务.从任务实践入手,做到既见树木也见森林. 笔者从2018年初开始接触机器学习,现 ...

  8. 【原创】NLP中的中文分词技术

     NLP中的中文分词技术 作者:mjs (360电商技术组) 随着需求的变化和技术的发展,互联网企业对数据的分析越来越深入,尤其是自然语言处理处理领域,近几年,在搜索引擎.数据挖掘.推荐系统等应用方 ...

  9. seg:NLP之正向最大匹配分词

    已迁移到我新博客,阅读体验更佳seg:NLP之正向最大匹配分词 完整代码实现放在我的github上:click me 一.任务要求 实现一个基于词典与规则的汉语自动分词系统. 二.技术路线 采用正向最 ...

最新文章

  1. ios 图片自动轮播
  2. 海思3559A上编译GDB源码操作步骤及简单使用
  3. java解析html的table
  4. vlan和如何建立vlan和vconifg
  5. 树莓4派开机动画_树莓派4+无屏幕安装系统+ssh远程+远程桌面
  6. matlabk大于等于0如何表示_【底层原理】浮点数在计算机中是如何表示
  7. LeetCode 1619. 删除某些元素后的数组均值
  8. 将机器学习模型部署为服务
  9. 论文阅读:Uncertainty-aware Joint Salient Object and Camouflaged Object Detection
  10. python request 库传送formdata_Python Requests库 form-data 上传文件操作
  11. DirectX (13) 粒子系统
  12. Video for linux 2 example (v4l2 demo)
  13. 下载debian老版本的链接
  14. java字符串数组排序
  15. 加权移动平均法 java_加权平均和移动平均
  16. ie 远程控制计算机,通过IE浏览器连接“远程桌面”方法详解
  17. WPS Office 2019文字组件插入和改写状态的切换
  18. 安装VC 6.0,出现 DOSX.EX must be in your AUTOEXEC.NT的信息
  19. 视频工厂:如何拍摄优质的餐饮宣传片之品牌植入篇
  20. 趋势:TypeScript - 一种思维方式

热门文章

  1. 安装或卸载Anaconda后Windows自带的cmd命令行窗口会闪退
  2. IDEA打jar包,如何跳过Test测试
  3. 高清:2口VGA分配器的使用与原理
  4. 在桥式结构中的注意事项 — 探头的CMRR
  5. iPhone十年的历程变化,你对未来的苹果手机抱有期待吗?
  6. dashboard android,dashboard下载-Dashboard 安卓版v1.2.12-PC6安卓网
  7. 金九银十简历石沉大海?别投了,软件测试岗位饱和了....
  8. spring循环依赖源码分析
  9. 关于视频中的速率问题,海思视频速率(高速信号与高频信号区分与解释)
  10. input file美化