Python预测分词的实现


Posted in Python onJune 18, 2021

前言

在机器学习中,我们有了训练集的话,就开始预测。预测是指利用模型对句子进行推断的过程。在中文分词任务中也就是利用模型推断分词序列,同时也叫解码。

在HanLP库中,二元语法的解码由ViterbiSegment分词器提供。本篇将详细介绍ViterbiSegment的使用方式

 

加载模型

在前篇博文中,我们已经得到了训练的一元,二元语法模型。后续的处理肯定会基于这几个文件来处理。所以,我们首先要做的就是加载这些模型到程序中:

if __name__ == "__main__":
    MODEL_PATH = "123"
    HanLP.Config.CoreDictionaryPath = MODEL_PATH + ".txt"
    HanLP.Config.BiGramDictionaryPath = MODEL_PATH + ".ngram.txt"
    CoreDictionary = SafeJClass("com.hankcs.hanlp.dictionary.CoreDictionary")
    CoreBiGramTableDictionary = SafeJClass('com.hankcs.hanlp.dictionary.CoreBiGramTableDictionary')
    print(CoreDictionary.getTermFrequency("秦机"))
    print(CoreBiGramTableDictionary.getBiFrequency("秦机","的"))

运行之后,效果如下:

Python预测分词的实现

这里我们使用CoreDictionary.getTermFrequency()方法获取”秦机“的频次。使用CoreBiGramTableDictionary.getBiFrequency()方法获取“秦机 的”的二元语法频次。

 

构建词网

在前文中我们介绍了符号“末##末“,代表句子结尾,”始##始“代表句子开头。而词网指的是句子中所有一元语法构成的网状结构。比如MSR词典中的“秦机和科技”这个句子,是给定的一元词典。我们将句子中所有单词找出来。得到如下词网:

[始##始]
[秦机]
[]
[和,和科]
[科技]
[技]
[末##末]

对应的此图如下所示:

Python预测分词的实现

当然,这里博主只是举例说明词网的概念,“和科”并不是一个单词。

下面,我们来通过方法构建词网。具体代码如下:

def build_wordnet(sent, trie):
    JString = JClass('java.lang.String')
    Vertex = JClass('com.hankcs.hanlp.seg.common.Vertex')
    WordNet = JClass('com.hankcs.hanlp.seg.common.WordNet')
    searcher = trie.getSearcher(JString(sent), 0)
    wordnet = WordNet(sent)
    while searcher.next():
        wordnet.add(searcher.begin + 1,
                    Vertex(sent[searcher.begin:searcher.begin + searcher.length], searcher.value, searcher.index))
    # 原子分词,保证图连通
    vertexes = wordnet.getVertexes()
    i = 0
    while i < len(vertexes):
        if len(vertexes[i]) == 0:  # 空白行
            j = i + 1
            for j in range(i + 1, len(vertexes) - 1):  # 寻找第一个非空行 j
                if len(vertexes[j]):
                    break
            wordnet.add(i, Vertex.newPunctuationInstance(sent[i - 1: j - 1]))  # 填充[i, j)之间的空白行
            i = j
        else:
            i += len(vertexes[i][-1].realWord)

    return wordnet


if __name__ == "__main__":
    MODEL_PATH = "123"
    HanLP.Config.CoreDictionaryPath = MODEL_PATH + ".txt"
    HanLP.Config.BiGramDictionaryPath = MODEL_PATH + ".ngram.txt"
    CoreDictionary = SafeJClass("com.hankcs.hanlp.dictionary.CoreDictionary")
    CoreBiGramTableDictionary = SafeJClass('com.hankcs.hanlp.dictionary.CoreBiGramTableDictionary')
    print(build_wordnet("秦机和科技", CoreDictionary.trie))

运行之后,我们会得到与上图归纳差不多的内容:

Python预测分词的实现

 

维特比算法

如果现在我们赋予上述词图每条边以二元语法的概率作为距离,那么如何求解词图上的最短路径就是一个关键问题。

假设文本长度为n,则一共有2(n-1次方)种切分方式,因为每2个字符间都有2种选择:切或者不切,时间复杂度就为O(2(n-1次方))。显然不切实际,这里我们考虑使用维特比算法。

维特比算法原理:它分为前向和后向两个步骤。

  • 前向:由起点出发从前往后遍历节点,更新从起点到该节点的最下花费以及前驱指针
  • 后向:由终点出发从后往前回溯前驱指针,取得最短路径

维特比算法用python代码的实现如下:

def viterbi(wordnet):
    nodes = wordnet.getVertexes()
    # 前向遍历
    for i in range(0, len(nodes) - 1):
        for node in nodes[i]:
            for to in nodes[i + len(node.realWord)]:
                # 根据距离公式计算节点距离,并维护最短路径上的前驱指针from
                to.updateFrom(node)
    # 后向回溯
    # 最短路径
    path = []
    # 从终点回溯
    f = nodes[len(nodes) - 1].getFirst()
    while f:
        path.insert(0, f)
        # 按前驱指针from回溯
        f = f.getFrom()
    return [v.realWord for v in path]

 

实战

现在我们来做个测试,我们在msr_test_gold.utf8上训练模型,为秦机和科技常见词图,最后运行维特比算法。详细代码如下所示:

if __name__ == "__main__":
    MODEL_PATH = "123"
    corpus_path = r"E:\ProgramData\Anaconda3\Lib\site-packages\pyhanlp\static\data\test\icwb2-data\gold\msr_test_gold.utf8"
    train_model(corpus_path, MODEL_PATH)
    HanLP.Config.CoreDictionaryPath = MODEL_PATH + ".txt"
    HanLP.Config.BiGramDictionaryPath = MODEL_PATH + ".ngram.txt"
    CoreDictionary = SafeJClass("com.hankcs.hanlp.dictionary.CoreDictionary")
    CoreBiGramTableDictionary = SafeJClass('com.hankcs.hanlp.dictionary.CoreBiGramTableDictionary')
    ViterbiSegment = JClass('com.hankcs.hanlp.seg.Viterbi.ViterbiSegment')
    MODEL_PATH = "123"
    HanLP.Config.CoreDictionaryPath = MODEL_PATH + ".txt"
    HanLP.Config.BiGramDictionaryPath = MODEL_PATH + ".ngram.txt"
    sent = "秦机和科技"
    wordnet = build_wordnet(sent, CoreDictionary.trie)
    print(viterbi(wordnet))

Python预测分词的实现

有的人可能有疑问,因为二元模型里,本身就存在秦机 和
科技这个样本。这么做不是多此一举吗?那好,我们替换sent的文本内容为“北京和广州”,这个样本可不在模型中。运行之后,效果如下:

Python预测分词的实现

我们发现依然能正确的分词为[北京 和 广州],这就是二元语法模型的泛化能力。至此我们走通了语料标注,训练模型,预测分词结果的完整步骤。

到此这篇关于Python预测分词的实现的文章就介绍到这了,更多相关Python预测分词内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python学习笔记:字典的使用示例详解
Jun 13 Python
Python+Selenium自动化实现分页(pagination)处理
Mar 31 Python
python调用系统ffmpeg实现视频截图、http发送
Mar 06 Python
Python3导入CSV文件的实例(跟Python2有些许的不同)
Jun 22 Python
numpy下的flatten()函数用法详解
May 27 Python
pyqt5 禁止窗口最大化和禁止窗口拉伸的方法
Jun 18 Python
pyqt5实现绘制ui,列表窗口,滚动窗口显示图片的方法
Jun 20 Python
python单例模式原理与创建方法实例分析
Oct 26 Python
10个Python面试常问的问题(小结)
Nov 20 Python
用Python写一个简易版弹球游戏
Apr 13 Python
Python pandas求方差和标准差的方法实例
Aug 04 Python
Python可视化动图组件ipyvizzu绘制惊艳的可视化动图
Apr 21 Python
学会Python数据可视化必须尝试这7个库
python tqdm用法及实例详解
Jun 16 #Python
python使用pymysql模块操作MySQL
分析Python感知线程状态的解决方案之Event与信号量
Jun 16 #Python
Python中else的三种使用场景
Jun 16 #Python
Python基础之条件语句详解
教你怎么用Python实现GIF动图的提取及合成
You might like
php数组声明、遍历、数组全局变量使用小结
2013/06/05 PHP
php foreach正序倒序输出示例代码
2014/07/01 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
2020/02/21 PHP
javascript Prototype 对象扩展
2009/05/15 Javascript
Javascript 文件夹选择框的两种解决方案
2009/07/01 Javascript
Extjs NumberField后面加单位实现思路
2013/07/30 Javascript
将json当数据库一样操作的javascript lib
2013/10/28 Javascript
jquery 检测元素是否存在的实例代码
2013/11/19 Javascript
JS实现div居中示例
2014/04/17 Javascript
JS实现队列与堆栈的方法
2016/04/21 Javascript
React Native之TextInput组件解析示例
2017/08/22 Javascript
微信公众号平台接口开发 获取access_token过程解析
2019/08/14 Javascript
VUE的history模式下除了index外其他路由404报错解决办法
2019/08/21 Javascript
vue实现图片上传预览功能
2019/12/23 Javascript
ES6中的类(Class)示例详解
2020/12/09 Javascript
python执行外部程序的常用方法小结
2015/03/21 Python
Python读取一个目录下所有目录和文件的方法
2016/07/15 Python
PyCharm 常用快捷键和设置方法
2017/12/20 Python
浅谈dataframe中更改列属性的方法
2018/07/10 Python
详解PyTorch手写数字识别(MNIST数据集)
2019/08/16 Python
PyTorch使用cpu加载模型运算方式
2020/01/13 Python
Python爬虫爬取有道实现翻译功能
2020/11/27 Python
python通用数据库操作工具 pydbclib的使用简介
2020/12/21 Python
python Scrapy爬虫框架的使用
2021/01/21 Python
python网络爬虫实现发送短信验证码的方法
2021/02/25 Python
HTML5地理定位_动力节点Java学院整理
2017/07/12 HTML / CSS
学习党课思想汇报
2013/12/29 职场文书
教师申诉制度
2014/01/29 职场文书
中专毕业生自我鉴定
2014/02/02 职场文书
答谢会策划方案
2014/05/12 职场文书
超市优秀员工获奖感言
2014/08/15 职场文书
课外科技活动总结
2014/08/27 职场文书
裁员通知
2015/04/25 职场文书
新郎父母婚礼致辞
2015/07/27 职场文书
来探秘“德国中小企业”的成功之道
2019/07/26 职场文书
Nginx 安装SSL证书完成HTTPS部署
2022/04/28 Servers