本文摘要 · 理论来源:【统计自然语言处理】第七章 自动分词;【统计学习方法】第十章 隐马尔可夫模型
· 代码目的:手写HMM进行中文分词
作者:CSDN 征途黯然.

一、数据集

  数据集的形式如下:

新    B
华   M
社   E
北   B
京   E
二   B
月   E
十   B
二   M
日   E
电   S中  B
国   E
十   B
四   E
……

  数据集已经标注好了四种状态(B、M、E、S),每个句子之间用换行分割。

  获取本数据集或者代码工程,可以关注公众号‘三黄工作室’回复‘中文分词’。

二、代码介绍

  1. 定义一个类,HmmModel

  2. 类中定义属性,分词状态self.STATE,状态转移矩阵self.A_dict,发射矩阵self.B_dict,初始矩阵self.Pi_dict

  3. 类中函数load,先加载序列化的中间模型,如果中间模型数据不存在,则去加载语料库,重新训练,训练好了之后,把中间数据序列化保存成.pkl文件。
  这里的中间模型,指的是状态转移矩阵self.A_dict,发射矩阵self.B_dict,初始矩阵self.Pi_dict这3个矩阵的数据。
  把中间数据序列化保存成.pkl文件,需要调用第4步的save方法。

  4. 类中函数save,保存状态转移矩阵self.A_dict,发射矩阵self.B_dict,初始矩阵self.Pi_dict这3个矩阵的数据到.pkl文件。

  5. 类中函数viterbi,维特比算法。根据输入的句子text,进行索引,返回最优的状态序列。

  6. 类中函数cut,把维特比算法中返回最优的状态序列进行识别切分。

三、代码

import pickleclass HmmModel:def __init__(self):# 分词状态self.STATE = {'B', 'M', 'E', 'S'}# 状态转移矩阵self.A_dict = {}# 发射矩阵self.B_dict = {}# 初始矩阵self.Pi_dict = {}# 加载数据 先加载模型数据,没有就读取语料库重新训练def load(self, model_file='../dataset/hmm/model.pkl', train_file='../dataset/hmm/train.txt'):# 加载模型数据try:with open(model_file, 'rb') as f:self.A_dict = pickle.load(f)self.B_dict = pickle.load(f)self.Pi_dict = pickle.load(f)returnexcept FileNotFoundError:pass# 统计状态出现次数 方便求发射矩阵Count_dict = {}# 存放初始语料所有数据data = []# 存放初始语料中的一个句子sentence = []# 初始化模型参数def init_params():for state in self.STATE:self.A_dict[state] = {s: 0.0 for s in self.STATE}self.Pi_dict[state] = 0.0self.B_dict[state] = {}Count_dict[state] = 0init_params()# 读取语料库with open(train_file, encoding='utf8') as f:# 每句按元组存在data中for line in f:line = line.strip()word_list = [i for i in line if i != '\t']if not line:data.append(sentence)sentence = []else:sentence.append((word_list[0], word_list[1]))# 统计次数for s in data:for k, v in enumerate(s):Count_dict[v[1]] += 1if k == 0:self.Pi_dict[v[1]] += 1  # 每个句子的第一个字的状态,用于计算初始状态概率else:self.A_dict[s[k - 1][1]][v[1]] += 1  # 计算转移概率self.B_dict[s[k][1]][v[0]] = self.B_dict[s[k][1]].get(v[0], 0) + 1.0  # 计算发射概率# 计算频率self.Pi_dict = {k: v * 1.0 / len(data) for k, v in self.Pi_dict.items()}self.A_dict = {k: {k1: v1 / Count_dict[k] for k1, v1 in v.items()} for k, v in self.A_dict.items()}# 加1平滑self.B_dict = {k: {k1: (v1 + 1) / Count_dict[k] for k1, v1 in v.items()} for k, v in self.B_dict.items()}# 把中间模型数据保存下来self.save()# 保存中间模型数据def save(self, model_file='../dataset/hmm/model.pkl'):# 序列化import picklewith open(model_file, 'wb') as f:pickle.dump(self.A_dict, f)pickle.dump(self.B_dict, f)pickle.dump(self.Pi_dict, f)# 维特比算法def viterbi(self, text):# 加载数据self.load()# 赋别名states, start_p, trans_p, emit_p = self.STATE, self.Pi_dict, self.A_dict, self.B_dict# 初始化顶点集、路径集V = [{}]path = {}# 初始化第一个状态for y in states:V[0][y] = start_p[y] * emit_p[y].get(text[0], 0)path[y] = [y]# 遍历剩下的状态for t in range(1, len(text)):V.append({})newpath = {}# 检验训练的发射概率矩阵中是否有该字neverSeen = text[t] not in emit_p['S'].keys() and \text[t] not in emit_p['M'].keys() and \text[t] not in emit_p['E'].keys() and \text[t] not in emit_p['B'].keys()for y in states:# 生词值为1,发射矩阵一行内词找不到为0(发射矩阵有4行)emitP = emit_p[y].get(text[t], 0) if not neverSeen else 1.0  # 设置未知字单独成词# 在当前状态为y下,计算前一个时刻的四种状态的代价乘积,取max(prob, state) = max([(V[t - 1][y0] * trans_p[y0].get(y, 0) *emitP, y0)for y0 in states if V[t - 1][y0] > 0])V[t][y] = probnewpath[y] = path[state] + [y]path = newpathif emit_p['M'].get(text[-1], 0) > emit_p['S'].get(text[-1], 0):(prob, state) = max([(V[len(text) - 1][y], y) for y in ('E', 'M')])else:(prob, state) = max([(V[len(text) - 1][y], y) for y in states])return (prob, path[state])def cut(self, text):prob, pos_list = self.viterbi(text)begin, next = 0, 0for i, char in enumerate(text):pos = pos_list[i]if pos == 'B':begin = ielif pos == 'E':yield text[begin: i + 1]next = i + 1elif pos == 'S':yield charnext = i + 1if next < len(text):yield text[next:]hmm = HmmModel()
text = '人类社会前进的航船就要驶入21世纪的新航程。'
res = hmm.cut(text)
print(str(list(res)))

  测试结果:

['人类', '社会', '前进', '的', '航船', '就', '要', '驶入', '21', '世纪', '的', '新', '航程', '。']

获取本项目的源代码

如果需要本组件的源代码,请扫描关注我的公众号,回复“中文分词”即可。

【自然语言处理】hmm隐马尔可夫模型进行中文分词 代码相关推荐

  1. HMM隐马尔科夫模型(附维特比代码)

    背景知识:马尔科夫模型 1 马尔科夫的局限性 在一些情况下,我们并不能直接得到观测的结果,比如在天气系统中,我们不能直接得到天气的状态,但是我们有一堆蚂蚁,可以从蚂蚁的行为状态找到天气变化的关系规律. ...

  2. HMM隐马尔可夫模型进行中文文本分词

    文章目录 一.HMM简述 1.引入 2.隐马尔科夫模型 (1)定义(Definition of a hidden Markov model) (2)应用 3.前向算法(了解) 4. 维特比算法 5.前 ...

  3. 李航《统计学习方法》之HMM隐马尔可夫模型

    李航<统计学习方法>之HMM隐马尔可夫模型 文章目录 前言 一.基本概念 1.语言描述: 2.符号表示 3.基本假设 4.例子 5.隐马尔可夫模型解决的三个基本问题 二.概率计算算法 1. ...

  4. NLP基础 : HMM 隐马尔可夫模型

    Hidden Markov Model, HMM 隐马尔可夫模型,是一种描述隐性变量(状态)和显性变量(观测状态)之间关系的模型.该模型遵循两个假设,隐性状态i只取决于前一个隐性状态i-1,而与其他先 ...

  5. 【自然语言处理】隐马尔可夫模型【Ⅰ】马尔可夫模型

    有任何的书写错误.排版错误.概念错误等,希望大家包含指正. 由于字数限制,分成六篇博客. [自然语言处理]隐马尔可夫模型[Ⅰ]马尔可夫模型 [自然语言处理]隐马尔科夫模型[Ⅱ]隐马尔科夫模型概述 [自 ...

  6. 视频教程-隐马尔科夫算法:中文分词神器-深度学习

    隐马尔科夫算法:中文分词神器 在中国知网从事自然语言处理和知识图谱的开发,并负责带领团队完成项目,对深度学习和机器学习算法有深入研究. 吕强 ¥49.00 立即订阅 扫码下载「CSDN程序员学院APP ...

  7. HMM(隐马尔科夫)用于中文分词

    什么是熵(Entropy) 简单来说,熵是表示物质系统状态的一种度量,用它老表征系统的无序程度.熵越大,系统越无序,意味着系统结构和运动的不确定和无规则:反之,,熵越小,系统越有序,意味着具有确定和有 ...

  8. HMM隐马尔可夫模型(HMM)攻略

    隐马尔可夫模型 (Hidden Markov Model,HMM) 最初由 L. E. Baum 和其它一些学者发表在一系列的统计学论文中,随后在语言识别,自然语言处理以及生物信息等领域体现了很大的价 ...

  9. HMM隐马尔科夫模型 学习总结

    隐马尔可夫模型(Hidden Markov Model,简称HMM)是结构最简单的动态贝叶斯网(dynamic Bayesian network),这是一种著名的有向图模型,主要用于时序数据建模,在语 ...

最新文章

  1. TCP/IP、 IPX/SPX、 NetBEUI、 AppleTalk协议
  2. C语言 将程序运行的时间记录在记事本中,下次运行进行读取
  3. c# 因其保护级别而不可访问。只能处理公共类型。
  4. python 对象创建_从Python中的基类对象创建对象
  5. 我们来聊点成年人的话题!
  6. Bootstrap 图片
  7. Ruby On Rails --环境搭建之回眸一笑
  8. 怎样修改美国的服务器节点,美国云服务器节点怎么
  9. jmeter的HTTP请求
  10. Netty权威指南(第2版) pdf百度网盘下载
  11. 使用cmd命令 关机
  12. 青少年软件编程(Python)等级考试试卷一级(判断题)2021-9
  13. win10开始菜单打不开_win10开始菜单没反应的解决方法教程
  14. 群体遗传分析—LD连锁不平衡
  15. npm安装慢 ,卡在sill idealTree buildDeps不动
  16. 《深入理解计算机系统》漫游指南
  17. 超级计算机欧冠军尤文,超级计算机预测欧冠结局:尤文决赛2-1巴萨 C罗赢梅西捧第6冠...
  18. 瞎想-电信IPTV如何做到真高清真4K直播
  19. Python写游戏,我上我也行 - Flappy Bird 03
  20. Django 数据库连接使用

热门文章

  1. SpringBoot BasicService
  2. Oracle如何代码编辑,配置UltraEdit为Oracle PL/SQL代码编辑器
  3. 病从口入:土壤菌群如何影响肠道健康
  4. NAR:UNITE真菌鉴定ITS数据库——处理未分类和并行分类
  5. NBT:人类微生物组千万基因的参考基因集
  6. 2019微生物组—宏基因组分析技术研讨会第五期
  7. DADA2中文教程v1.8
  8. linux shell编程时报:bad substitution错误的解决办法
  9. android scrollview 布局,Android scrollview实现底部继续拖动查看图文详情
  10. python使用numpy包编写自定义函数计算MAPE(平均绝对百分比误差)指标mean absolute percentage error (MAPE)、MAPE指标解读、MAPE指标使用的注意事项