NLP初学-Word Segmentation(分词)
最近在看一些NLP相关的内容,用博客记录整理一下。
无论是CV还是NLP,说到底是将图像和文本转化为数据的方式,在计算机中进行用不同算法进行处理。
对文本处理的第一步一般都是分词。现在有很多现成的分词工具:Jieba分词、SnowNLP、哈工大LTP、HanNLP等。
具体算法方面主要是最大匹配(Max Matching)和考虑语义(lncorporate Semantic)。
1. 前向最大匹配算法
1.1 前向最大匹配算法的原理
首先,我们分词的目的是将一段中文分成若干个词语,前向最大匹配就是从前向后寻找在词典中存在的词。
废话不多说,直接上例子:
首先我们假设Max_len = 5,即假设单词的最大长度为5。
再假设我们现在词典中存在的词有:
[“我们”, “经常”,“常有”, “有意见”,“有意”, “意见”, “分歧”,
“我”,“们”,“经”,“常”,“有”,“意”,“见”]
现在,我们用前向最大匹配算法来划分 我们经常有意见分歧 这句话。
例:我们经常有意见分歧(max_len = 5)
第一轮:取子串 “我们经常有”,正向取词,如果匹配失败,每次去掉匹配字段最后面的一个字。
“我们经常有”,扫描词典中的5字单词,没有匹配,子串长度减 1 变为“我们经常”。
“我们经常”,扫描词典中的4字单词,没有匹配,变为“我们经”。
“我们经”,扫描词典中的3字单词,没有匹配, 变为“我们”。
“我们”,扫描词典中的2字单词,匹配成功,输出“我们”,输入变为“经常有意见分歧”。
第二轮:取子串“经常有意见”
“经常有意见”,扫描词典中的5字单词,没有匹配,子串长度减 1 变为“经常有意”。
“经常有意”,扫描词典中的4字单词,没有匹配,子串长度减 1 变为“经常有”。
“经常有”,扫描词典中的3字单词,没有匹配,子串长度减 1 变为“经常”。
“经常”,扫描词典中的2字单词,有匹配,输出“经常”,输入变为“有意见分歧”。
以此类推,直到输入长度为0时,扫描终止。
最终,前向最大匹配算法得出的结果为:
我们 / 经常 / 有意见 / 分歧
1.2 前向最大匹配算法的Python实现
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 19 08:57:56 2018@author: Lenovo
"""test_file = 'train/train.txt'#训练语料
test_file2 = 'test/test.txt'#测试语料
test_file3 = 'test_sc/test_sc_zhengxiang.txt'#生成结果def get_dic(test_file): #读取文本返回列表with open(test_file,'r',encoding='utf-8',) as f:try:file_content = f.read().split()finally:f.close()chars = list(set(file_content))return charsdic = get_dic(test_file)
def readfile(test_file2):max_length = 5 h = open(test_file3,'w',encoding='utf-8',) with open(test_file2,'r',encoding='utf-8',) as f:lines = f.readlines()for line in lines:#分别对每行进行正向最大匹配处理max_length = 5 my_list = []len_hang = len(line)while len_hang>0 :tryWord = line[0:max_length]while tryWord not in dic:if len(tryWord)==1:breaktryWord=tryWord[0:len(tryWord)-1]my_list.append(tryWord)line = line[len(tryWord):]len_hang = len(line)for t in my_list:#将分词结果写入生成文件if t == '\n' :h.write('\n')else:h.write(t + " ")h.close()readfile(test_file2)
代码摘录于https://www.cnblogs.com/Jm-15/p/9403352.html
2. 后向最大匹配算法
2.1 后向最大匹配算法的原理
与前向最大匹配算法类似,只是方向相反,即从后向前寻找词典中存在的词并输出。
例:我们经常有意见分歧(max_len = 5)
第一轮:取子串 “有意见分歧”,后向取词,如果匹配失败,每次去掉匹配字段最前面的一个字。
“有意见分歧”,扫描词典中的5字单词,没有匹配,子串长度减 1 变为“意见分歧”。
“意见分歧”,扫描词典中的4字单词,没有匹配,变为“见分歧”。
“见分歧”,扫描词典中的3字单词,没有匹配, 变为“分歧”。
“分歧”,扫描词典中的2字单词,匹配成功,输出“分歧”,输入变为“我们经常有意见”。
第二轮:取子串“经常有意见”
“经常有意见”,扫描词典中的5字单词,没有匹配,子串长度减 1 变为“常有意见”。
“常有意见”,扫描词典中的4字单词,没有匹配,子串长度减 1 变为“有意见”。
“有意见”,有匹配,输出“有意见”,输入变为“我们经常”。
以此类推,直到输入长度为0时,扫描终止。
最终,后向最大匹配算法得出的结果为:
我们 / 经常 / 有意见 / 分歧
可见,在此例子中,前向和后向最大匹配算法得到的结果相同。
但是,如果我们去掉词典中的[有意见]一词,
我们使用前向所得到的结果是: 我们 / 经常 / 有意 / 见 / 分歧
我们使用后向所得到的结果是: 我们 / 经 / 常有 / 意见 / 分歧
可以看到,前向和后向最大匹配算法得到得结果不一样了,一般来说,80%的情况是一样的,20%的可能不一样。同时可以看出,词典或者叫做词库 对于分词结果的质量的影响非常大!
2.2 后向最大匹配算法的python实现
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 19 08:57:56 2018@author: Lenovo
"""
test_file = 'train/train.txt'
test_file2 = 'test/test.txt'
test_file3 = 'test_sc/test_sc.txt'def get_dic(test_file): with open(test_file,'r',encoding='utf-8',) as f:try:file_content = f.read().split()finally:f.close()chars = list(set(file_content))return charsdic = get_dic(test_file)
def readfile(test_file2):max_length = 5 h = open(test_file3,'w',encoding='utf-8',) with open(test_file2,'r',encoding='utf-8',) as f:lines = f.readlines()for line in lines:my_stack = []len_hang = len(line)while len_hang>0 :tryWord = line[-max_length:]while tryWord not in dic:if len(tryWord)==1:breaktryWord=tryWord[1:]my_stack.append(tryWord)line = line[0:len(line)-len(tryWord)]len_hang = len(line)while len(my_stack):t = my_stack.pop()if t == '\n' :h.write('\n')else:h.write(t + " ")h.close()readfile(test_file2)
代码摘录于https://www.cnblogs.com/Jm-15/p/9403352.html
训练语料和测试语料库:
链接: https://pan.baidu.com/s/1X0coEznut6_s0jsDG9_9Dg 密码: b393
3. 双向最大匹配算法
3.1 双向最大匹配算法的原理
双向最大匹配算法的原理就是将正向最大匹配算法和逆向最大匹配算法进行比较,从而确定正确的分词方法。
步骤如下:
比较正向最大匹配和逆向最大匹配结果。
如果分词数量结果不同,那么取分词数量较少的那个。
如果分词数量结果相同:
1.分词结果相同,可以返回任何一个。
2.分词结果不同,返回单字数比较少的那个,
如果单字数个数也相同,则任意返回一个。
3.2 双向最大匹配算法的python实现
-- coding: utf-8 --class MM():def init(self):self.window_size = 3def cut(self,text):result = []index = 0text_length = len(text)dic = ['研究','研究生','生命','命','的','起源']while text_length > index:for size in range(self.window_size+index,index,-1):piece = text[index:size]if piece in dic:index = size - 1breakindex = index + 1result.append(piece+'----')return(result)
class RMM():def init(self):self.window_size = 3def cut(self,text):result = []index = 0index = len(text)dic = ['研究','研究生','生命','命','的','起源']while index > 0:for size in range(index - self.window_size,index,):piece = text[size:index]if piece in dic:index = size + 1breakindex = index - 1result.append(piece+'----')result.reverse()return(result)
if __name__ == '__main__':text = '研究生命的起源'count1 = 0count2 = 0First = MM()Second = RMM()a = First.cut(text)b = Second.cut(text)if a == b:print(a)lena = len(a)lenb = len(b)if lena == lenb:for DY1 in a:if len(DY1) == 5:count1 = count1 + 1for DY2 in b:if len(DY2) == 5:count2 = count2 + 1if count1 > count2:print(b)else:print(a)if lena > lenb:print(b)if lena < lenb: print(a)
代码摘录于https://blog.csdn.net/weixin_43256799/article/details/86098695
4.维特比算法(Viterbi)
维特比算法实际是用动态规划解隐马尔可夫模型预测问题,就是用动态规划(dynamic programming)求概率最大路径(最优路径)。 这时一条路径对应着一个状态序列。类似有向图(转移概率为权重)找最优路径。
小白给小白详解维特比算法(一)
小白给小白详解维特比算法(二)
viterbi-algorithm 维特比算法的例子解析
Python词性标注HMM+viterbi实现
# -*- coding: utf-8 -*-
"""
@author: 蔚蓝的天空tom
Aim:实现隐马尔科夫模型的维特比算法(Viterbi Algorithm)
"""import numpy as np#隐马尔可夫模型λ=(A, B, pai)
#A是状态转移概率分布,状态集合Q的大小N=np.shape(A)[0]
#从下给定A可知:Q={盒1, 盒2, 盒3}, N=3
A = np.array([[0.5, 0.2, 0.3],[0.3, 0.5, 0.2],[0.2, 0.3, 0.5]])
#B是观测概率分布,观测集合V的大小T=np.shape(B)[1]
#从下面给定的B可知:V={红,白},T=2
B = np.array([[0.5, 0.5],[0.4, 0.6],[0.7, 0.3]])
#pai是初始状态概率分布,初始状态个数=np.shape(pai)[0]
pai = np.array([[0.2],[0.4],[0.4]])#观测序列
O = np.array([[0],[1],[0]]) #0表示红色,1表示白,就是(红,白,红)观测序列def viterbi_algorithm(A, B, pai, O):N = np.shape(A)[0] #隐马尔科夫模型状态个数T = np.shape(O)[0] #观测序列的观测个数,即时刻个数print('N=%d, T=%d'%(N,T))#每个时刻每个状态对应的局部最优状态序列的概率数组delta = np.zeros((T,N)) #最终shape=(T,N)#[[0.10, 0.16, 0.28], #时刻0每个状态对应的局部最优状态序列的概率# [0.028, 0.0504, 0.042], #时刻1每个状态对应的局部最优状态序列的概率# [0.00756, 0.01008, 0.0147]] #时刻2每个状态对应的局部最优状态序列的概率#每个时刻每个状态对应的局部最优状态序列的前导状态索引数组psi = np.zeros((T,N)) #最终shape=(T,N)#[[0, 0, 0], #时刻0的前导状态索引# [2, 2, 2], #时刻1的前导状态索引# [1, 1, 2]] #时刻2的前导状态索引#(1)viterbi algorithmfor t in range(T):#[0,1,...,T-1]print('\n===================time t=%d'%t)if 0 == t:#计算初值print('a0:', pai.reshape((1, N)), 'b0:', np.array(B[:,O[t]]).reshape((1, N)))delta[t] = np.multiply(pai.reshape((1, N)), np.array(B[:,O[t]]).reshape((1, N)))print('delta_t0:', delta[t])continuefor i in range(N):print('\n*****i=%d'%i)print('delta[t%d-1]:'%t, delta[t-1], 'A[:,i%d]'%i, A[:,i])delta_t_i = np.multiply(delta[t-1], A[:,i])print('delta_t%d_i%d step1:'%(t,i), delta_t_i)delta_t_i = np.multiply(delta_t_i, B[i, O[t]])print('delta_t%d_i%d result:'%(t,i), delta_t_i)delta[t,i] = max(delta_t_i)psi[t][i] = np.argmax(delta_t_i)print('delta:\n', delta)print('psi:\n', psi)states = np.zeros((T,))t_range = -1 * np.array(sorted(-1*np.arange(T)))for t in t_range:if T-1 == t:print('time %d'%t, np.argmax(delta[t]))states[t] = np.argmax(delta[t])else:print('psi shape:', np.shape(psi))print('states shape:', np.shape(states))states[t] = psi[t+1, states[t+1]]print('best state queue:', states)return if __name__=='__main__':viterbi_algorithm(A,B,pai,O)
NLP初学-Word Segmentation(分词)相关推荐
- Intro to CRF Chinese Word Segmentation
Intro to CRF Chinese Word Segmentation How to handle this problem 朋友送给你一卷胶卷底片,这些底片上标着拍摄日期,但是底片有一些磨损了 ...
- 【NLP learning】Tokenizer分词技术概述
[NLP learning]Tokenizer分词技术概述 目录 [NLP learning]Tokenizer分词技术概述 极简方法--空格分词(Space) 预训练模型的分词方法--子词分解/子标 ...
- seg:NLP之正向最大匹配分词
已迁移到我新博客,阅读体验更佳seg:NLP之正向最大匹配分词 完整代码实现放在我的github上:click me 一.任务要求 实现一个基于词典与规则的汉语自动分词系统. 二.技术路线 采用正向最 ...
- 深度学习将会变革NLP中的中文分词
深度学习将会变革NLP中的中文分词 2016-08-08 19:03 转载 陈圳 0条评论 雷锋网按:本文转自ResysChina高翔,文章主要介绍了1)区分中文分词的方法:2)用深度学习的方法来解决 ...
- Tokenisation word segmentation sentence segmentation
David D. Palmer Chapter 2: Tokenisation and SentenceSegmentation.2000 https://scholar.google.com/cit ...
- NLP:Word Embedding词嵌入/word2vec词向量思想方法(一种主流的分布式表示)的简介、使用方法、案例应用之详细攻略
NLP:Word Embedding词嵌入/word2vec词向量思想方法(一种主流的分布式表示)的简介.使用方法.案例应用之详细攻略 目录 词嵌入(一种主流的分布式表示)的简介 词嵌入的案例理解
- word中文分词 一
前言:这篇笔记算是 word中文分词 java库的入门笔记,记录下word分词的基本配置,和一个由于经验浅而踩的坑. 感谢word分词 的作者,word分词的github地址:http ...
- 【原创】NLP中的中文分词技术
NLP中的中文分词技术 作者:mjs (360电商技术组) 随着需求的变化和技术的发展,互联网企业对数据的分析越来越深入,尤其是自然语言处理处理领域,近几年,在搜索引擎.数据挖掘.推荐系统等应用方 ...
- NLP入门学习1——分词和词性标注
NLP入门学习1--分词和词性标注 0.简介 1.概念和工具 1.1 词性标注 1.2 NLTK 1.3 jieba 1.4 LAC 2.代码实现 2.1 分词 2.1.1 使用nltk进行分词: 2 ...
最新文章
- java字体颜色编程_java Applet 程序设计讲解2 字体,颜色的使用
- 【 C 】初识函数指针
- unix修改ip和计算机名,UNIX shell获取IP和修改IP
- ML之sklearn:sklearn.linear_mode中的LogisticRegression函数的简介、使用方法之详细攻略
- Phython 3 笔记2 —— 基础语法
- php 模拟 cas,PHP discuz3.2 cas
- linux 查询 lib信息,怎么查看linux是否使用 libarchive
- 笑郭网络验证3.8研究笔记(内有视频教程)
- 在读博士练成健身达人,女大学生在宿舍练出八块腹肌……
- 我如何开始学习Web开发
- VB为MSHFlexGrid添加表格编辑功能
- 用户登录自动注销问题
- classloader隔离练习
- 关于禁用html中a标签的思考
- jsp内置对象与四种作用域
- 使用golang实现对请求签名和验签
- 实验|三层交换机配置实例
- django学习日记2017-10-20: 登录界面
- 请你估算一下学校门口卖煎饼商贩的收入,使用哪些方式可以增加收入?
- Mac下安装DBeaver