隐马尔科夫模型python实现简单拼音输入法
在网上看到一篇关于隐马尔科夫模型的介绍,觉得简直不能再神奇,又在网上找到大神的一篇关于如何用隐马尔可夫模型实现中文拼音输入的博客,无奈大神没给可以运行的代码,只能纯手动网上找到了结巴分词的词库,根据此训练得出隐马尔科夫模型,用维特比算法实现了一个简单的拼音输入法。githuh地址:https://github.com/LiuRoy/Pinyin_Demo
原理简介
隐马尔科夫模型
抄一段网上的定义:
隐马尔可夫模型 (Hidden Markov Model) 是一种统计模型,用来描述一个含有隐含未知参数的马尔可夫过程。其难点是从可观察的参数中确定该过程的隐含参数,然后利用这些参数来作进一步的分析。
拼音输入法中可观察的参数就是拼音,隐含的参数就是对应的汉字。
viterbi算法
参考https://zh.wikipedia.org/wiki/维特比算法,思想是动态规划,代码比较简单就不赘述。
代码解释
model定义
代码见model/table.py文件,针对隐马尔科夫的三个概率矩阵,分别设计了三个数据表存储。这样的好处很明显,汉字的转移概率矩阵是一个非常大的稀疏矩阵,直接文件存储占用空间很大,并且加载的时候也只能一次性读入内存,不仅内存占用高而且加载速度慢。此外数据库的join操作非常方便viterbi算法中的概率计算。
数据表定义如下:
class Transition(BaseModel):
__tablename__ = 'transition'
id = Column(Integer, primary_key=True)
previous = Column(String(1), nullable=False)
behind = Column(String(1), nullable=False)
probability = Column(Float, nullable=False)
class Emission(BaseModel):
__tablename__ = 'emission'
id = Column(Integer, primary_key=True)
character = Column(String(1), nullable=False)
pinyin = Column(String(7), nullable=False)
probability = Column(Float, nullable=False)
class Starting(BaseModel):
__tablename__ = 'starting'
id = Column(Integer, primary_key=True)
character = Column(String(1), nullable=False)
probability = Column(Float, nullable=False)
模型生成
代码见train/main.py文件,里面的initstarting,initemission,init_transition分别对应于生成隐马尔科夫模型中的初始概率矩阵,发射概率矩阵,转移概率矩阵,并把生成的结果写入sqlite文件中。训练用到的数据集是结巴分词里的词库,因为没有训练长句子,最后运行的结果也证明只能适用于短句输入。
初始概率矩阵
统计初始化概率矩阵,就是找出所有出现在词首的汉字,并统计它们出现在词首的次数,最后根据上述数据算出这些汉字出现在词首的概率,没统计的汉字就认为出现在词首的概率是0,不写入数据库。有一点注意的是为了防止概率计算的时候因为越算越小导致计算机无法比较,所有的概率都进行了自然对数运算。统计的结果如下:

转移概率矩阵
此处用到的是最简单的一阶隐马尔科夫模型,即认为在一个句子里,每个汉字的出现只和它前面的的一个汉字有关,虽然简单粗暴,但已经可以满足大部分情况。统计的过程就是找出字典中每个汉字后面出现的汉字集合,并统计概率。因为这个概率矩阵非常的大,逐条数据写入数据库过慢,后续可以优化为批量写入,提高训练效率。结果如下:

上图展示的一后面出现概率最高的十个字,也挺符合日常习惯。
发射概率矩阵
通俗点就是统计每个汉字对应的拼音以及在日常情况下的使用概率,已暴举例,它有两个读音:bao和pu,难点就是找bao和pu出现的概率。此处统计用到了pypinyin模块,把字典中的短语转换为拼音后进行概率统计,但是某些地方读音也不完全正确,最后运行的输入法会出现和拼音不匹配的结果。统计结果如下:

viterbi实现
代码建input_method/viterbi.py文件,此处会找到最多十个局部最优解,注意是十个局部最优解而不是十个全局最优解,但是这十个解中最优的那个是全局最优解,代码如下:
def viterbi(pinyin_list):
"""
viterbi算法实现输入法 Aargs:
pinyin_list (list): 拼音列表
"""
start_char = Emission.join_starting(pinyin_list[0])
V = {char: prob for char, prob in start_char} for i in range(1, len(pinyin_list)):
pinyin = pinyin_list[i] prob_map = {}
for phrase, prob in V.iteritems():
character = phrase[-1]
result = Transition.join_emission(pinyin, character)
if not result:
continue state, new_prob = result
prob_map[phrase + state] = new_prob + prob if prob_map:
V = prob_map
else:
return V
return V
结果展示
运行input_method/viterbi.py文件,简单的展示一下运行结果:

问题统计:
- 统计字典生成转移矩阵写入数据库的速度太慢,运行一次要将近十分钟。
- 发射概率矩阵数据不准确,总有一些汉字的拼音不匹配。
- 训练集太小,实现的输入法不适用于长句子。
隐马尔科夫模型python实现简单拼音输入法的更多相关文章
- 隐马尔科夫模型,第三种问题解法,维比特算法(biterbi) algorithm python代码
上篇介绍了隐马尔科夫模型 本文给出关于问题3解决方法,并给出一个例子的python代码 回顾上文,问题3是什么, 下面给出,维比特算法(biterbi) algorithm 下面通过一个具体例子,来说 ...
- HMM基本原理及其实现(隐马尔科夫模型)
HMM(隐马尔科夫模型)基本原理及其实现 HMM基本原理 Markov链:如果一个过程的“将来”仅依赖“现在”而不依赖“过去”,则此过程具有马尔可夫性,或称此过程为马尔可夫过程.马尔可夫链是时间和状态 ...
- HMM隐马尔科夫模型
这是一个非常重要的模型,凡是学统计学.机器学习.数据挖掘的人都应该彻底搞懂. python包: hmmlearn 0.2.0 https://github.com/hmmlearn/hmmlearn ...
- 用hmmlearn学习隐马尔科夫模型HMM
在之前的HMM系列中,我们对隐马尔科夫模型HMM的原理以及三个问题的求解方法做了总结.本文我们就从实践的角度用Python的hmmlearn库来学习HMM的使用.关于hmmlearn的更多资料在官方文 ...
- 隐马尔科夫模型(Hidden Markov Models)
链接汇总 http://www.csie.ntnu.edu.tw/~u91029/HiddenMarkovModel.html 演算法笔记 http://read.pudn.com/downloads ...
- 基于隐马尔科夫模型(HMM)的地图匹配(Map-Matching)算法
文章目录 1. 1. 摘要 2. 2. Map-Matching(MM)问题 3. 3. 隐马尔科夫模型(HMM) 3.1. 3.1. HMM简述 3.2. 3.2. 基于HMM的Map-Matchi ...
- 隐马尔科夫模型HMM学习最佳范例
谷歌路过这个专门介绍HMM及其相关算法的主页:http://rrurl.cn/vAgKhh 里面图文并茂动感十足,写得通俗易懂,可以说是介绍HMM很好的范例了.一个名为52nlp的博主(google ...
- HMM 自学教程(四)隐马尔科夫模型
本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在 HMM 学习最佳范例,这是针对 国外网站上一个 HMM 教程 的翻译,作者功底很深,翻译得很精彩 ...
- 隐马尔科夫模型(HMM)的概念
定义隐马尔科夫模型可以用一个三元组(π,A,B)来定义:π 表示初始状态概率的向量A =(aij)(隐藏状态的)转移矩阵 P(Xit|Xj(t-1)) t-1时刻是j而t时刻是i的概率B =(bij) ...
随机推荐
- Jenkins 安装的HTML Publisher Plugin 插件无法展示ant生成的JunitReport报告
最近在做基于jenkins ant junit 的测试持续集成,单独ant junit生成的junitreport报告打开正常,使用Jenkins的HTML Publisher Plugin 插件无 ...
- 【疯狂造轮子-iOS】JSON转Model系列之二
[疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...
- Socket聊天程序——客户端
写在前面: 上周末抽点时间把自己写的一个简单Socket聊天程序的初始设计和服务端细化设计记录了一下,周二终于等来毕业前考的软考证书,然后接下来就是在加班的日子度过了,今天正好周五,打算把客户端的详细 ...
- PHP验证用户登录例子-学习笔记
1.基本流程: 2.UML类图: 3.PHP代码: 3.1 index.php <?php /** * Created by PhpStorm. * User: andy * Date: 16- ...
- 学习ASP.NET Core,怎能不了解请求处理管道[1]: 中间件究竟是个什么东西?
ASP.NET Core管道虽然在结构组成上显得非常简单,但是在具体实现上却涉及到太多的对象,所以我们在 "通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流 ...
- XML技术之DOM4J解析器
由于DOM技术的解析,存在很多缺陷,比如内存溢出,解析速度慢等问题,所以就出现了DOM4J解析技术,DOM4J技术的出现大大改进了DOM解析技术的缺陷. 使用DOM4J技术解析XML文件的步骤? pu ...
- python 3.5 成功安装 scrapy 的步骤
http://www.cnblogs.com/hhh5460/p/5814275.html
- 游走 bzoj 3143
游走(2s 128MB)walk [问题描述] [输入格式] [输出格式] [样例输入] 3 3 2 3 1 2 1 3 [样例输出] 3.333 [样例说明] 题解: 主要算法:贪心:高斯消元: 题 ...
- ES6之let命令详解
let与块级作用域 { var foo='foo'; let bar='bar'; } console.log(foo,'var'); //foo varconsole.log(bar ,'bar') ...
- D3.js学习(六)
上节我们学习了如何绘制多条曲线, 以及给不同的曲线指定不同的坐标系.在这节当中,我们会对坐标轴标签相关的处理进行学习.首先,我们来想一个问题, 如何我们的x轴上的各个标签的距离比较近,但是标签名又比较 ...