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 文件读写操作实例详解
Mar 12 Python
Python Requests模拟登录实现图书馆座位自动预约
Apr 27 Python
python中利用h5py模块读取h5文件中的主键方法
Jun 05 Python
Python基本socket通信控制操作示例
Jan 30 Python
Python Excel处理库openpyxl使用详解
May 09 Python
一行python实现树形结构的方法
Aug 09 Python
python使用pip安装模块出现ReadTimeoutError: HTTPSConnectionPool的解决方法
Oct 04 Python
使用Python函数进行模块化的实现
Nov 15 Python
Win下PyInstaller 安装和使用教程
Dec 25 Python
Python日志logging模块功能与用法详解
Apr 09 Python
python实现代码审查自动回复消息
Feb 01 Python
opencv-python图像配准(匹配和叠加)的实现
Jun 23 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
如何做到多笔资料的同步
2006/10/09 PHP
php 删除目录下N分钟前创建的所有文件的实现代码
2013/08/10 PHP
PHP中Header使用的HTTP协议及常用方法小结
2014/11/04 PHP
php将HTML表格每行每列转为数组实现采集表格数据的方法
2015/04/03 PHP
Yii框架的布局文件实例分析
2019/09/04 PHP
些很实用且必用的小脚本代码
2006/06/26 Javascript
JavaScript 组件之旅(三):用 Ant 构建组件
2009/10/28 Javascript
JavaScript高级程序设计阅读笔记(十六) javascript检测浏览器和操作系统-detect.js
2012/08/14 Javascript
JS+CSS实现分类动态选择及移动功能效果代码
2015/10/19 Javascript
javascript数组遍历的方法实例分析
2016/09/13 Javascript
微信小程序 表单Form实例详解(附源码)
2016/12/22 Javascript
socket.io学习教程之深入学习篇(三)
2017/04/29 Javascript
jquery单击文字或图片内容放大并居中显示
2017/06/23 jQuery
NodeJS实现自定义流的方法
2018/08/01 NodeJs
深入分析element ScrollBar滚动组件源码
2019/01/22 Javascript
详解Vue-Router源码分析路由实现原理
2019/05/15 Javascript
react实现移动端下拉菜单的示例代码
2020/01/16 Javascript
js实现计算器功能
2020/08/10 Javascript
[00:47]TI7不朽珍藏III——沙王不朽展示
2017/07/15 DOTA
python中cPickle用法例子分享
2014/01/03 Python
Python中特殊函数集锦
2015/07/27 Python
网站渗透常用Python小脚本查询同ip网站
2017/05/08 Python
python中列表和元组的区别
2017/12/18 Python
python3.6使用pymysql连接Mysql数据库
2018/05/25 Python
python获取代码运行时间的实例代码
2018/06/11 Python
Python动态导入模块的方法实例分析
2018/06/28 Python
3个用于数据科学的顶级Python库
2018/09/29 Python
利用python GDAL库读写geotiff格式的遥感影像方法
2018/11/29 Python
python opencv读mp4视频的实例
2018/12/07 Python
python 堆和优先队列的使用详解
2019/03/05 Python
详解Python下载图片并保存本地的两种方式
2019/05/15 Python
matplotlib命令与格式之tick坐标轴日期格式(设置日期主副刻度)
2019/08/06 Python
Python CSS选择器爬取京东网商品信息过程解析
2020/06/01 Python
奥地利网上书店:Weltbild
2017/07/14 全球购物
亚洲最大旅游体验平台:KKday
2017/10/21 全球购物
pytorch 权重weight 与 梯度grad 可视化操作
2021/06/05 Python