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 02 Python
python中map()函数的使用方法示例
Sep 29 Python
Python中字典的浅拷贝与深拷贝用法实例分析
Jan 02 Python
Python实现计算字符串中出现次数最多的字符示例
Jan 21 Python
Python中使用pypdf2合并、分割、加密pdf文件的代码详解
May 21 Python
Python 装饰器原理、定义与用法详解
Dec 07 Python
浅谈Python线程的同步互斥与死锁
Mar 22 Python
使用jupyter notebook直接打开.md格式的文件
Apr 10 Python
Python Flask框架实现简单加法工具过程解析
Jun 03 Python
python如何支持并发方法详解
Jul 25 Python
解决Python 函数声明先后顺序出现的问题
Sep 02 Python
Python函数对象与闭包函数
Apr 13 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
为了这两部电子管收音机,买了6套全新电子管和10粒刻度盘灯泡
2021/03/02 无线电
如何正确理解PHP的错误信息
2006/10/09 PHP
给apache2.2加上mod_encoding模块後 php5.2.0 处理url出现bug
2007/04/12 PHP
深入php中var_dump方法的使用详解
2013/06/24 PHP
php常用hash加密函数
2014/11/22 PHP
php实现的mongodb操作类实例
2015/04/03 PHP
适合PHP初学者阅读的4本经典书籍
2016/09/23 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
php设计模式之工厂方法模式分析【星际争霸游戏案例】
2020/01/23 PHP
document.write()及其输出内容的样式、位置控制
2013/08/12 Javascript
非html5实现js版弹球游戏示例代码
2013/09/22 Javascript
JS+CSS设置img在DIV中只显示Img垂直居中的部分
2013/10/24 Javascript
php+js实现倒计时功能
2014/06/02 Javascript
Internet Explorer 11 浏览器介绍:别叫我IE
2014/09/28 Javascript
jQuery Form表单取值的方法
2017/01/11 Javascript
详解 vue better-scroll滚动插件排坑
2018/02/08 Javascript
jQuery+vue.js实现的多选下拉列表功能示例
2019/01/15 jQuery
微信公众平台 发送模板消息(Java接口开发)
2019/04/17 Javascript
Vue+Django项目部署详解
2019/05/30 Javascript
解决vue单页面修改样式无法覆盖问题
2019/08/05 Javascript
react组件基本用法示例小结
2020/04/27 Javascript
Python连接mysql数据库的正确姿势
2016/02/03 Python
python图像常规操作
2017/11/11 Python
Flask框架Jinjia模板常用语法总结
2018/07/19 Python
Python txt文件加入字典并查询的方法
2019/01/15 Python
如何利用python给图片添加半透明水印
2019/09/06 Python
纯CSS3实现地球自转实现代码(图文教程附送源码)
2012/12/26 HTML / CSS
HTML5 Blob对象的具体使用
2020/05/22 HTML / CSS
美国最古老的精致书写工具制造商:A.T. Cross(高仕)
2018/01/30 全球购物
L’AGENCE官网:加州女装品牌
2018/06/03 全球购物
园林施工员岗位职责
2013/12/11 职场文书
幼儿园教师培训制度
2014/01/16 职场文书
爱心捐款倡议书范文
2014/05/12 职场文书
青年教师听课心得体会
2016/01/15 职场文书
技术转让协议书
2016/03/19 职场文书
MySQL中几种插入和批量语句实例详解
2021/09/14 MySQL