在上一篇博客里,简单的介绍了语言模型,其中举了一个例子,这里就用代码来实现实现目标句子出现概率的求值。
如果想再一次回顾语言模型的理论知识,可以直接点击语言模型(N-Gram)
研究生物很有意思。
他是研究应用。
踏实研究生物的。
他实验救生物的。
他大学时代是研究生物的。
生物专业是他的首选目标。
P(s) = P(他|<BOS>)P(是|他)P(研究|是)P(生物|研究)P(的|生物)P(<EOS>|的)
= 3/6 * 1/4 * 2/3 * 3/4 * 3/5 * 3/4
import jieba
import re
from zhon.hanzi import punctuation
from _overlapped import NULL
def Modify(s):
#将结尾标点符号截掉
if s[-1] in (r"[%s]+" %punctuation):
s = s[:-1] #截取字符串从开头到倒数一个字符的子串
#添加起始符BOS和终止符EOS
s_modify1 = re.sub(r"[%s]+" %punctuation, "EOSBOS", s) ## r'\w+'为正则表达式,匹配多个英文单词或者数字
s_modify2="BOS"+s_modify1+"EOS"
return s_modify2
输出:
‘BOS研究生物很有意思EOSBOS他是研究实物应用EOSBOS踏实研究生物的EOSBOS他实验救生物的EOSBOS他大学时代是研究生物的EOSBOS生物专业是他的首选目标吗EOS’
在下面函数里出现的NULL表示空,它不是一个值,这点不同于None。在python这类脚本语言中变量和值是绑定关系,但如果设置一个变量是NULL,实际就是说它没有与任何值绑定,也就是说该变量实际上并未被定义;
def Partition_Statistics(s, lists, dicts = NULL):
jieba.suggest_freq(("BOS", "EOS"), True)
s = jieba.cut(s, HMM = False) #精确模式,自动计算的词频在使用 HMM 新词发现功能时可能无效,所以设为False
format_s = ",".join(s)
#将词按","分割后依次填入数组
lists = format_s.split(",")
#统计词频
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’, ‘生物’, ‘专业’, ‘是’, ‘他’, ‘的’, ‘首选’, ‘目标’, ‘吗’, ‘EOS’]
def CompareList(ori_list,test_list):
#申请空间
count_list=[0]*(len(test_list)-1)
#遍历测试的字符串
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
输出:[3, 1, 2, 3, 3, 3]
def Probability(test_list,count_list,ori_dict):
flag=0
#概率值为p
p=1
for i in range(6):
p *=(float(count_list[flag])/float(ori_dict[test_list[i]]))
flag += 1
return p
if __name__ == "__main__":
#语料句子
s = "研究生物很有意思!他是研究实物应用。踏实研究生物的。他实验救生物的。他大学时代是研究生物的。生物专业是他的首选目标吗?"
ori_list=[]
ori_dict={}
#测试句子
s_test="他是研究生物的"
test_list=[]
count_list=[]
#分词并将结果存入一个list,词频统计结果存入字典
s_ori = Modify(s)
ori_list = Partition_Statistics(s_ori,ori_list,ori_dict)
s_test = Modify(s_test)
test_list = Partition_Statistics(s_test,test_list)
count_list = CompareList(ori_list, test_list)
p = Probability(test_list,count_list,ori_dict)
print(p)
输出:0.028124999999999997
这样就实现了以分词模式”<BOS> 他 是 研究 生物 的 <EOS>”计算出现句子“他是研究生物的”的概率,为0.028124999999999997。当然,这里只是简单处理了这个问题细节性问题和普遍适用性并没有考虑到,所以这里用到的方法对于可能并不适用于其他的问题,但具有一定的参考性,需要进行一些修改。