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

 

语言模型的作用是在大量的训练样例中,给出一个句子求出概率,其中应用的技术有平滑、 统计语言模型。

 

假设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 len(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分词,可以免去输入分词。

有大规模中文语料推荐的朋友可以搜索“搜狗实验室”中的全网新闻数据,训练模型效果更好!

//有需要语料库的朋友可以留言告知。

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值