用python实现NLP中的二元语法模型
来源:互联网 发布:安卓内核优化修改 编辑:程序博客网 时间:2024/06/03 16:18
最近刚接触NLP,使用的书是宗成庆的《统计自然语言处理》,看到n元语法模型这一章节,于是用python写了出来。
而一切的起源,则是一个简单的问题。
1 基于以下语料建立语言模型
研究生物很有意思。
他大学时代是研究生物的。
生物专业是他的首选目标。
他是研究生。
尝试以“词”作为基元计算出现句子“他是研究生物的”的概率
让我们一起带着问题来逐步解决它吧 …………
乍一看,我是一脸懵逼的。(这都是些什么?!!)
遂翻书~
哦,全概率公式啊,好简单(微笑脸)。可是有了它,有什么用?
现在出现了一个严峻的问题,在这一项
举个栗子,
莎士比亚说:“我的妈呀,咋这么多”
但是你细细一想,并不是这样的,今儿的天气和20年前某一天的天气有啥关系?
所以,二元语法模型就诞生了。。意思是,今儿的天气只和昨儿的天气有关系。
以此类推,一元语法模型就是,今儿的天气好坏是今儿的事,跟昨天半毛钱关系也没有。
这就是用二元语法模型改进后的全概率公式~【哦,对了,二元语法模型又叫一阶马尔科夫链】
既然知道了二元语法模型的内幕,那我们就正式开始建模之旅吧~
首先,我们遇到的第一座大山是:
1)这些词都是有意义的吗?
实现起来是这个样子的:
#将句子变为"BOSxxxxxEOS"这种形式def reform(sentence): #如果是以“。”结束的则将“。”删掉 if sentence.endswith("。"): sentence=sentence[:-1] #添加起始符BOS和终止符EOS sentence_modify1=sentence.replace("。", "EOSBOS") sentence_modify2="BOS"+sentence_modify1+"EOS" return sentence_modify2
用语料测试后的结果是这样子的:
哇哦,第一座大山就这么轻松翻越~
好吧,一山过后还有一山:
2)分词咋分?还有需不需要统计词频?
分词我们采用了Python的一个分词包,叫jieba分词。
统计词频这个想法不错,毕竟我们最后一定是要算概率的,统计一下呗。
import jiebafrom _overlapped import NULL#分词并统计词频def segmentation(sentence,lists,dicts=NULL): jieba.suggest_freq("BOS", True) jieba.suggest_freq("EOS", True) #分词 sentence = jieba.cut(sentence,HMM=False) #组合 format_sentence=",".join(sentence) #将词按","分割后依次填入数组word_list[] lists=format_sentence.split(",") #统计词频,如果词在字典word_dir{}中出现过则+1,未出现则=1 if dicts!=NULL: for word in lists: if word not in dicts: dicts[word]=1 else: dicts[word]+=1 return lists
分词后的结果是这样的:
语料字符串:
[‘BOS’, ‘研究’, ‘生物’, ‘很’, ‘有意思’, ‘EOS’, ‘BOS’, ‘他’, ‘大学’, ‘时代’, ‘是’, ‘研究’, ‘生物’, ‘的’, ‘EOS’, ‘BOS’, ‘生物’, ‘专业’, ‘是’, ‘他’, ‘的’, ‘首选’, ‘目标’, ‘EOS’, ‘BOS’, ‘他’, ‘是’, ‘研究生’, ‘EOS’]
测试字符串:
[‘BOS’, ‘他’, ‘是’, ‘研究’, ‘生物’, ‘的’, ‘EOS’]
统计以后的字典是这样的:
{‘BOS’: 4, ‘研究’: 2, ‘生物’: 3, ‘很’: 1, ‘有意思’: 1, ‘EOS’: 4, ‘他’: 3, ‘大学’: 1, ‘时代’: 1, ‘是’: 3, ‘的’: 2, ‘专业’: 1, ‘首选’: 1, ‘目标’: 1, ‘研究生’: 1}
现在映入眼帘的是第三座大山,天哪,怎么除了山就没有别的了?
3)我的条件概率
先来个消消乐,让两个列表(语料字符串和待比较字符串)相互比较比较,在语料字符串里看见和待比较字符串相同的就+1
#比较两个数列,二元语法def compareList(ori_list,test_list): #申请空间 count_list=[0]*(len(test_list)) #遍历测试的字符串 for i in range(0,len(test_list)-1): #遍历语料字符串,且因为是二元语法,不用比较语料字符串的最后一个字符 for j in range(0,len(ori_list)-2): #如果测试的第一个词和语料的第一个词相等则比较第二个词 if test_list[i]==ori_list[j]: if test_list[i+1]==ori_list[j+1]: count_list[i]+=1 return count_list
执行的结果如下:
[2, 1, 1, 2, 1, 1, 0]
然后你看这个公式怎么说的。。
公式如下:
这个好办,要计算
实现起来是这样:
#计算概率 def probability(test_list,count_list,ori_dict): flag=0 #概率值为p p=1 for key in test_list: #数据平滑处理:加1法 p*=(float(count_list[flag]+1)/float(ori_dict[key]+1)) flag+=1 return p
计算结果如下:
0.01
哎呦?
怎么,完了?就这么简单?
简直不敢相信自己的眼睛 ☺
把整个程序贴在后边,快让它跑起来吧~
'''Created on 2017年1月15日@author: 薛沛雷'''import jiebafrom _overlapped import NULL#将句子变为"BOSxxxxxEOS"这种形式def reform(sentence): #如果是以“。”结束的则将“。”删掉 if sentence.endswith("。"): sentence=sentence[:-1] #添加起始符BOS和终止符EOS sentence_modify1=sentence.replace("。", "EOSBOS") sentence_modify2="BOS"+sentence_modify1+"EOS" return sentence_modify2#分词并统计词频def segmentation(sentence,lists,dicts=NULL): jieba.suggest_freq("BOS", True) jieba.suggest_freq("EOS", True) sentence = jieba.cut(sentence,HMM=False) format_sentence=",".join(sentence) #将词按","分割后依次填入数组word_list[] lists=format_sentence.split(",") #统计词频,如果词在字典word_dir{}中出现过则+1,未出现则=1 if dicts!=NULL: for word in lists: if word not in dicts: dicts[word]=1 else: dicts[word]+=1 return lists#比较两个数列,二元语法def compareList(ori_list,test_list): #申请空间 count_list=[0]*(len(test_list)) #遍历测试的字符串 for i in range(0,len(test_list)-1): #遍历语料字符串,且因为是二元语法,不用比较语料字符串的最后一个字符 for j in range(0,len(ori_list)-2): #如果测试的第一个词和语料的第一个词相等则比较第二个词 if test_list[i]==ori_list[j]: if test_list[i+1]==ori_list[j+1]: count_list[i]+=1 return count_list#计算概率 def probability(test_list,count_list,ori_dict): flag=0 #概率值为p p=1 for key in test_list: #数据平滑处理:加1法 p*=(float(count_list[flag]+1)/float(ori_dict[key]+1)) flag+=1 return pif __name__ == "__main__": #语料句子 sentence_ori="研究生物很有意思。他大学时代是研究生物的。生物专业是他的首选目标。他是研究生。" ori_list=[] ori_dict={} sentence_ori_temp="" #测试句子 sentence_test="他是研究生物的" sentence_test_temp="" test_list=[] count_list=[] p=0 #分词并将结果存入一个list,词频统计结果存入字典 sentence_ori_temp=reform(sentence_ori) ori_list=segmentation(sentence_ori_temp,ori_list,ori_dict) sentence_test_temp=reform(sentence_test) test_list=segmentation(sentence_test_temp,test_list) count_list=compareList(ori_list, test_list) p=probability(test_list,count_list,ori_dict) print(p)
忽然想起几句话,也是我写这篇文章的初衷,愿能与诸君共勉:
学习不要跟猴子掰玉米一样,不要好大喜功,要及时巩固已有基础
完!
- 用python实现NLP中的二元语法模型
- 二元语法模型与viterbi算法分词
- 基于二元语法模型的中文分词
- NLP中的语言模型(language model)
- CRF模型在NLP中的运用
- 采用二元语法模型与viterbi算法分词
- 【python 走进NLP】NLP WordEmbedding的概念和实现
- 二元语法(2-gram)分词中的平滑算法
- 《NLP汉语自然语言处理原理与实践》第四章 NLP中的概率图模型
- NLP汉语自然语言处理原理与实践 4 NLP中的概率图模型
- NLP中的语言模型及文本特征提取算法
- NLP处理-Spark中的HashTF与CountVectorizer模型
- rails模型中的资料库语法
- NLP语言模型
- c#4.0中的dynamic还是真好用啊,可以实现二元分派
- 【python】SIR模型实现
- Python 使用nltk对特定词汇进行双连词处理 (二元语法)
- NLP with Python
- PCA的数学原理(非常值得阅读)
- html——img标签的使用
- Slor 简介
- 表单验证学习
- 人见人爱A^B
- 用python实现NLP中的二元语法模型
- poj Heavy Transportation(dijkstra,spfa)
- myeclipse 配置struts出现 Unable to load configuration.
- hdu 3987 Harry Potter and the Forbidden Forest (最小割)
- Docker 总结
- 自定义控件—自定义的ExpandableTextView
- QProcess 启动win第三方程序
- ROS入门_1.18 接下来做什么?
- CSS3之转换 、过渡 、动画