Python自然语言处理之切分算法详解


Posted in Python onApril 25, 2021

一、前言

我们需要分析某句话,就必须检测该条语句中的词语。

一般来说,一句话肯定包含多个词语,它们互相重叠,具体输出哪一个由自然语言的切分算法决定。常用的切分算法有完全切分、正向最长匹配、逆向最长匹配以及双向最长匹配。

本篇博文将一一介绍这些常用的切分算法。

二、完全切分

完全切分是指,找出一段文本中的所有单词。

不考虑效率的话,完全切分算法其实非常简单。只要遍历文本中的连续序列,查询该序列是否在词典中即可。上一篇我们获取了词典的所有词语dic,这里我们直接用代码遍历某段文本,完全切分出所有的词语。代码如下:

from pyhanlp import *


def load_dictionary():
    IOUtil = JClass('com.hankcs.hanlp.corpus.io.IOUtil')
    path = HanLP.Config.CoreDictionaryPath.replace('.txt', '.mini.txt')
    dic = IOUtil.loadDictionary([path])
    return set(dic.keySet())


def fully_segment(text, dic):
    list = []
    for i in range(len(text)):
        for j in range(i + 1, len(text) + 1):
            temp = text[i:j]
            if temp in dic:
                list.append(temp)
    return list


if __name__ == "__main__":
    dic = load_dictionary()
    print(fully_segment("在绝对实力面前,一切的说辞都是枉然", dic))

Python自然语言处理之切分算法详解

可以看到,完全切分算法输出了文本中所有的单字与词汇。
这里的算法原理是:开始遍历单个字,以该字为首,将后面每个字依次组合到单个字中,分析出这些组合字句是否在词典中。第二次,从第二个字开始,组合后面的字,以此类推。不懂的看下图就明白了。

Python自然语言处理之切分算法详解

三、正向最长匹配

虽然说完全切分能获取到所有出现在字典中的单词,单字,但是我们获取语句中单字一般来说没有任何意义,我们更希望获取的是中文分词,那种具有意义的词语序列。

比如,上面我们希望“绝对实力”成为一整个词,而不是“绝对”+“实力”之类的碎片。为了达到这个目的,我们需要完善一下我们的算法。考虑到越长的单词表达的意义更加的丰富,于是我们定义单词越长优先级越高。

具体来说,就是在某个下标为起点递增查词的过程中,优先输出更长的单词,这种规则被称为最长匹配算法。该下标的扫描顺序如果从前往后,则称为正向最长匹配,反之则为逆向最长匹配。

下面,我们来实现正向最长匹配,代码如下:

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

算法的原理:首先通过while循环判断i是否超出了字符串的大小,如果没有,获取当前第一个字符串为第一个最长匹配结果,接着遍历第一个字符串的所有可能组合结尾,如果在字典中,判断当前词语是否大于前面的最长匹配结果,如果是替换掉最长。遍历完成之后,将最长的结果添加到列表中,然后再获取第二字符,遍历所有结尾组合,获取最长匹配。以此类推。

四、逆向最长匹配

既然了解了正向如何匹配,那么逆向算法应该也很好写。代码如下:

def backward_segment(text, dic):
    list = []
    i = len(text) - 1
    while i >= 0:
        long_word = text[i]
        for j in range(0, i):
            word = text[j:i + 1]
            if word in dic:
                if len(word) > len(long_word):
                    long_word = word
                    break
        list.append(long_word)
        i -= len(long_word)
    return list

算法的原理:就是上面的正向反过来,但是这里并不是倒推文字,文字还是按语句的顺序,但是长度是从最长到最短,也就是遇到第一个就可以返回了添加了。比正向最长匹配算法节约时间。

五、双向最长匹配

虽然逆向比正向节约时间,但本身有一个很大的漏洞。假如我现在的句子中有一段“项目的”字符串,那么正向会出现“项目”,“的”两个词汇,而逆向会出现:“项”,“目的”两个词汇。

为此,我们的算法工程师提出了新的匹配规则,双向最长匹配。这是一种融合两种匹配方法的复杂规则,流程如下:

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

具体代码如下:

#统计单字个数
def count_single_char(list):
    return sum(1 for word in list if len(word) == 1)

#双向匹配算法
def bidirectional_segment():
    f = forward_segment("在绝对实力面前,一切的说辞都是枉然", dic)
    b = backward_segment("在绝对实力面前,一切的说辞都是枉然", dic)
    if len(f) < len(b):
        return f
    elif len(f) > len(b):
        return b
    else:
        if count_single_char(f)<count_single_char(b):
            return f
        else:
            return b

到此这篇关于Python自然语言处理之切分算法详解的文章就介绍到这了,更多相关python切分算法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
跟老齐学Python之玩转字符串(2)
Sep 14 Python
深入理解Python中命名空间的查找规则LEGB
Aug 06 Python
Python处理PDF及生成多层PDF实例代码
Apr 24 Python
详解Python pygame安装过程笔记
Jun 05 Python
浅谈Django自定义模板标签template_tags的用处
Dec 20 Python
浅谈Python实现2种文件复制的方法
Jan 19 Python
Ubuntu+python将nii图像保存成png格式
Jul 18 Python
django和vue实现数据交互的方法
Aug 21 Python
解决Keras 与 Tensorflow 版本之间的兼容性问题
Feb 07 Python
pytorch锁死在dataloader(训练时卡死)
May 28 Python
Python实现日志实时监测的示例详解
Apr 06 Python
使用Django框架创建项目
Jun 10 Python
Python网络编程之ZeroMQ知识总结
Python 文本滚动播放器的实现代码
Apr 25 #Python
Python基于Opencv识别两张相似图片
matplotlib之pyplot模块实现添加子图subplot的使用
python实现简单区块链结构
python实现图片九宫格分割的示例
详解python中[-1]、[:-1]、[::-1]、[n::-1]使用方法
Apr 25 #Python
You might like
使用MaxMind 根据IP地址对访问者定位
2006/10/09 PHP
我用php+mysql写的留言本
2006/10/09 PHP
PHP动态规划解决0-1背包问题实例分析
2015/03/23 PHP
php文件操作之小型留言本实例
2015/06/20 PHP
PHP实现负载均衡session共享redis缓存操作示例
2018/08/22 PHP
laravel config文件配置全局变量的例子
2019/10/13 PHP
json 定义
2008/06/10 Javascript
JavaScript中实现块作用域的方法
2010/04/01 Javascript
如何消除inline-block属性带来的标签间间隙
2016/03/31 Javascript
JS实现星星评分功能实例代码(两种方法)
2016/06/09 Javascript
Map.vue基于百度地图组件重构笔记分享
2017/04/17 Javascript
解决angularjs WdatePicker ng-model的问题
2018/09/13 Javascript
Vue页面跳转动画效果的实现方法
2018/09/23 Javascript
小程序实现五星点评效果
2018/11/03 Javascript
vue-cli中使用高德地图的方法示例
2019/03/28 Javascript
elementUI select组件value值注意事项详解
2019/05/29 Javascript
[05:28]刀塔密之一:团结则存
2014/07/03 DOTA
python fabric使用笔记
2015/05/09 Python
Python中二维列表如何获取子区域元素的组成
2017/01/19 Python
Python实现完整的事务操作示例
2017/06/20 Python
python实现基于SVM手写数字识别功能
2020/05/27 Python
Python中的默认参数实例分析
2018/01/29 Python
python实现k-means聚类算法
2018/02/23 Python
Python中的集合介绍
2019/01/28 Python
解决tensorflow由于未初始化变量而导致的错误问题
2020/01/06 Python
django执行原始查询sql,并返回Dict字典例子
2020/04/01 Python
python中可以声明变量类型吗
2020/06/18 Python
超级实用的8个Python列表技巧
2020/08/24 Python
Python 实现PS滤镜的旋涡特效
2020/12/03 Python
移动端Html5页面生成图片解决方案
2018/08/07 HTML / CSS
C语言笔试题回忆
2015/04/02 面试题
买卖合同协议书范本
2014/10/18 职场文书
售后前台接待岗位职责
2015/04/03 职场文书
演讲比赛通讯稿
2015/07/18 职场文书
详细分析PHP7与PHP5区别
2021/06/26 PHP
Nginx配置之实现多台服务器负载均衡
2021/08/02 Servers