您的位置:首页 > 编程语言 > Python开发

python实现三元语言模型与输入法推荐

2017-05-21 11:39 1311 查看
语言模型的作用是在大量的训练样例中,给出一个句子求出概率,其中应用的技术有平滑、 统计语言模型。

假设S表示某一个有意义的句子,由一连串特定顺序排列的词w1、w2、w3、...、wn组成,利用条件概率公式,能够得到:

P(S)=P(W1,W2,W3,...,Wn)

=P(W1)P(W2|W1)P(W3|W1,W2)…P(Wn|W1,W2,…,Wn-1)

P(W1)    —— 第一个词W1出现的概率

P(W2|W1)—— 已知第一个词W1的前提下,第二个词W2出现的概率

根据马尔科夫模型,

    任意一个词出现的概率只与它前面出现的有限的1个或着i个词有关。

如句子,“我爱打篮球”的概率:

二元模型:P(我) * P(爱|我) * P(打|爱) * P(篮球|打)

三元模型:P(我,爱) * P(打|我,爱) * P(篮球|爱,打)

P(我,爱) = P(我) * (爱|我)

 

•     Goal:compute the probability of a sentence or sequence of words:

     P(W) = P(w1,w2,w3,w4,w5…wn)

•     Related task: probability of an upcoming word:

      P(w5|w1,w2,w3,w4)

•     Amodel that computes either of these:

          P(W)     or    P(wn|w1,w2…wn-1)          is called alanguage model.

•     Better:the grammar       But languagemodel
or LM is standard



根据语言模型和统计结果确定候选集,完成推荐下一个词的任务。

 

实践步骤:

1、获取语料库资料

2、分词统计

3、以一定格式输出到文本中

4、读入文本

5、分词

6、查找文本中的资料

7、排序

8、输出前5个结果

 

主要的问题包括:

1、需要大量的多领域语料库。

2、运行效率和存储空间,是时间和空间的折衷处理。

3、可以加入词性考虑。

 

代码:

 获取一个文件夹下全部文件:

#读取目录内所有文件,返回文件路径列表
def readAllFiles(baseDir, fileList):
filelist=os.listdir(baseDir)
for dir in filelist:
if os.path.isdir(baseDir+'/'+dir):
readAllFiles(baseDir+'/'+dir, fileList)
else:
fileList.append(baseDir+'/'+dir)


读取文件:

def readFile(url):
dataset = open(url, 'r+', encoding='utf-8').read()


核心统计词频,其中包含去除文件中的词性标注:

#统计词频,三个单词
def frequency(sentence, dicts, N=2, replace=True, split_string='  '):
#排除词性标注
if replace==True:
sentence = sentence.replace('\n', '').replace('/', '')
for alp in alp_table:
sentence=sentence.replace(alp, '')
lists=sentence.split('  ')
preword_list=[]
total_word=0
#list是当前的sentence词语集合的列表
for word in lists:
#代表句子的结尾
if word in symbol_table:
temp = dicts
for preword in preword_list:
temp = temp[pre·	word]
if preword_list!=[]:
temp[' '] += 1
preword_list = []
continue

#去除词语中的无意义标注,如胖子&#中的&,#
for ch in forbidden_table:
if ch in word:
word.replace(ch, '')

if word not in word_dict:
word_dict[word]=1
else:
word_dict[word]+=1

total_word+=1
if le
b8ff
n(preword_list)==N:
temp=dicts
for preword in preword_list:
temp=temp[preword]
temp[' ']+=1
preword_list.pop(0)

temp=dicts
for preword in preword_list:
if preword not in temp:
temp[preword]={' ':0}
temp=temp[preword]
if word not in temp:
temp[word]={' ':0}
preword_list.append(word)
return total_word


把字典转换为格式化字符串,把字典转换为方便排序的列表:

def dict2str(dicts):
result=""
for dic in dicts:
if dic==' ':
continue
#result+=dic+' '+str(dicts[dic])+'\n'
else:
temp=dicts[dic]
for dic2 in temp:
if dic2 == ' ':
result+=dic+' '+str(temp[dic2])+'\n'
else:
temp2=temp[dic2]
for dic3 in temp2:
if dic3==' ':
result+=dic+' '+dic2+' '+str(temp2[dic3])+'\n'
else:
result+=dic+' '+dic2+' '+dic3+' '+str(temp2[dic3][' '])+'\n'
return result

def dict2list(dic:dict):
''' 将字典转化为列表 '''
keys = dic.keys()
vals = dic.values()
lst = [(key, val) for key, val in zip(keys, vals)]
return lst


运行函数:

import os
alp_table = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u','v',
'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_']
symbol_table = [',', '。', '!', '?', ';', '、', '/', '(', ')', '《', '》', '——', '\'', '\"']+alp_table
num_table = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']

forbidden_table = ['&','#',',', '。', '!', '?', ';', '、', '/', '(', ')', '《', '》', '——', '\'', '“', '”', '【', '】']+symbol_table+alp_table+num_table
dataset=""
word_dict={}
if __name__=='__main__':
dicts = {}
files_list = []
# 读取全部文件
readAllFiles('./corpus2/corpus', files_list)
# 对每个文件进行识别单词操作
for file in files_list:
fp = open(file, 'r+')
frequency(fp.read(), dicts, N=3)
fp.close()

fp = open('dict.txt', 'a')
word_dict=sorted(word_dict.items(), key=lambda x:x[1],reverse=True)
for k in word_dict:
fp.write(k[0]+' '+str(k[1])+'\n')
#print(len(lst))
fp.close()


预处理结束后,进行第二步查询结果:

核心函数,预测,功能是读入文件,进行统计排序:

fp=open('result3.txt', 'r')
dataset=fp.read().split('\n')
fp.close()
#输入词组列表后预测
def Predict2(sentence, urlPath='result3.txt'):
word_list=" ".join(jieba.cut(sentence, HMM=False)).split(' ')
if (len(word_list) <= 0):
return False
result_dict={}
start=False
if len(word_list)==1:
for data in dataset:
words = data.split(' ')
if len(words)<3:
continue
if word_list[0]==words[0]:
start=True
if words[1] not in result_dict:
if len(words) == 3:
result_dict[words[1]] = int(words[2])
else:
result_dict[words[1]] = int(words[3])
else:
if len(words) == 3:
result_dict[words[1]] += int(words[2])
else:
result_dict[words[1]] += int(words[3])
'''else:
if start==True:
break'''
else:
for data in dataset:
words = data.split(' ')
if len(words)!=4:
continue
if word_list[-2]==words[0] and word_list[-1]==words[1]:
#start=True
result_dict[words[2]] =int(words[3])
'''else:
if start==True:
break'''
result_list = dict2list(result_dict)
result_list.sort(key=lambda item:item[1], reverse=True)
return result_list


最后,输入句子,利用jieba分词,可以得到最终结果:

alp_table = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u','v',
'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_']
symbol_table = [',', '。', '!', '?', ';', '、', '/', '(', ')', '《', '》', '——', '\'', '\"', ';']+alp_table
num_table = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']

forbidden_table = ['&','#',',', '。', '!', '?', ';', '、', '/', '(', ')', '《', '》', '——', '\'', '“', '”', '【', '】']+symbol_table+alp_table+num_table

#begin = datetime.datetime.now()
#list=Predict('坐')
#end = datetime.datetime.now()
#print(end-begin)
if __name__=='__main__':
print('按q退出程序')
while True:
s = input('输入句子:')
if (s == 'q'):
break
word_list = " ".join(jieba.cut(s, HMM=False)).split(' ')
start=datetime.datetime.now()
lkk = Predict2(s)
lst=[]
for word in lkk:
ok=True
for ch in forbidden_table:
if ch in word[0]:
ok=False
break
if(ok==True):
lst.append(word)
if(len(lst)==5):
break

length=len(lst)
if length < 5:
length = 5
fp = open('dict.txt', 'r')
lines = fp.readlines()
for line in lines:
templst = line.split(' ')
word=templst[0]
templst[1] = templst[1].split('\n')[0]
if (word in lst) or (word in word_list):
continue
ok = True
for ch in forbidden_table:
if ch in word:
ok = False
break
if (ok == True):
lst.append(templst)
if (len(lst) == 5):
break
fp.close()
result = "推荐: "
for i in range(length):
result += lst[i][0] + str(lst[i][1]) + '  '
print(result + '\n')
end = datetime.datetime.now()
print(end - start)


实现效果:



文件保存形式:



到此完成推荐词语的任务,记得安装jieba分词,可以免去输入分词。

有需要语料库的朋友可以留言告知。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: