【NLP】2.1 统计语言模型

文章介绍了语言模型的基本概念,包括对句子分配概率的任务,以及如何使用贝叶斯公式和条件概率进行数学建模。重点讨论了n元语法(N-Gram)作为改进方法,用来缓解数据稀疏性和计算复杂性的问题。通过案例展示了如何实现N-Gram模型,计算句子概率,并生成排列组合。最后指出传统模型在处理长距离依赖和泛化能力上的局限性。
摘要由CSDN通过智能技术生成

2.1 统计语言模型简介

2.1.1 语言模型任务

原始语句:南京市长江大桥

Sentence_1:南京;市长;江大桥

Sentence_2:南京市;长江大桥

很明显,第二种更合理。

模型指的是对事物的数学抽象,那么语言模型指的就是对语言现象的数学抽象

定义:语言模型任务是给句子一个分配概率的任务,也就是计算 P ( w ) P(w) P(w) w w w 是一句话。此外,语言模型也对给定单词在多个单词也就是一个词序列之后的可能性进行分析,并分配概率。

语料库:采样世界语句集合,得到的子集,就是样本空间。

贝叶斯公式 P ( A B ) = P ( A ∣ B ) P ( B ) = P ( B ∣ A ) P ( A ) P(AB) = P(A|B)P(B)=P(B|A)P(A) P(AB)=P(AB)P(B)=P(BA)P(A)

定义的数学解释:分配一个词在序列之后的概率(条件概率),给任意词序列分配概率。

语言模型就是给任何词序列分配一个概率
P ( w i ∣ w 1 , w 2 , . . . , w i − 1 ) = P ( w 1 , w 2 , . . . , w i − 1 , w i ) P ( w 1 , w 2 , . . . , w i − 1 ) (2.1.1) P(w_i|w_1,w_2,...,w_{i-1})=\frac{P(w_1,w_2,...,w_{i-1},w_i)}{P(w_1,w_2,...,w_{i-1})}\tag{2.1.1} P(wiw1,w2,...,wi1)=P(w1,w2,...,wi1)P(w1,w2,...,wi1,wi)(2.1.1)
我们定义一个统计模型如下:
P ( w 1 ; n ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 1 : 2 ) P ( w 4 ∣ w 1 : 3 ) . . . P ( w n ∣ w 1 : n − 1 ) (2.1.2) P(w_{1;n})=P(w_1)P(w_2|w_1)P(w_3|w_{1:2})P(w_4|w_{1:3})...P(w_n|w_{1:n-1})\tag{2.1.2} P(w1;n)=P(w1)P(w2w1)P(w3w1:2)P(w4w1:3)...P(wnw1:n1)(2.1.2)

总结:语言模型任务的完美表现是预测序列中的下一个单词具有与人类参与者所需的相同或更低的猜测数目,这是人类智能的体现。此外,语言模型还可以用于对机器翻译和语音识别的结果进行打分。语言模型是NLP、人工智能、机器学习研究的主要角色。

缺点

  1. 数据稀疏,越长的句子概率越低。
  2. 计算代价大,句子越长,要根据句子来索引计算和储存的 p 就越多。
  3. 最后一个词取决于这句话前面的所有词,是的高效建模整句话的难度大。

2.1.2 改进方法

最经典和传统的改进方法,就是n阶马尔可夫模型,也叫n元语法或者N-Gram

一个k阶马尔可夫假设,假设序列中下一个词的概率只依赖于其前k个词。用公式表示如下( $i $ 为要预测的词的位置或索引, w w w 代表词):
P ( w i + 1 ∣ w 1 , i ) ≈ P ( w i + 1 ∣ w i − k i i ) (2.1.3) P(w_{i+1}|w_{1,i}) \approx P(w_{i+1}|w_{i-k_ii})\tag{2.1.3} P(wi+1w1,i)P(wi+1wikii)(2.1.3)
那句子的概率估计就变为:
P ( w 1 : n ) ≈ ∏ i = 1 n P ( w i ∣ w i − k : i − 1 ) (2.1.4) P(w_{1:n}) \approx \prod_{i=1}^{n} P(w_i|w_{i-k:i-1})\tag{2.1.4} P(w1:n)i=1nP(wiwik:i1)(2.1.4)

2.1.3 案例实现

【1】语料预处理

from collections import Counter
import numpy as np


"""语料"""
corpus = '''她的菜很好 她的菜很香 她的他很好 他的菜很香 他的她很好
很香的菜 很好的她 很菜的他 她的好 菜的香 他的菜 她很好 他很菜 菜很好'''.split() # 以空格为分隔符,将语料分开


"""语料预处理"""
counter = Counter()  # 词频统计
for sentence in corpus:
    for word in sentence:
        counter[word] += 1
counter = counter.most_common()
lec = len(counter)
word2id = {counter[i][0]: i for i in range(lec)}
id2word = {i: w for w, i in word2id.items()}
print(word2id)
print(id2word)

image-20230613163255350

【2】N-Gram建模训练

"""N-gram建模训练"""
unigram = np.array([i[1] for i in counter]) / sum(i[1] for i in counter)
print(unigram)

print("-------------------字到序号的转变-------------------")
bigram = np.zeros((lec, lec))   # + 1e-8
for sentence in corpus:
    sentence = [word2id[w] for w in sentence]
    print(sentence)
    for i in range(1, len(sentence)):
        bigram[[sentence[i - 1]], [sentence[i]]] += 1  # 对应词表位置词频加一(第一个词是3并且第二个词是0的情况词频加一)

print("-------------------相邻两个词出现的数量-------------------")
print(bigram)

print("-------------------相邻两个词出现的数量归一化-------------------")
for i in range(lec):
    bigram[i] /= bigram[i].sum()  # 对词频归一化,变为概率
print(bigram)

image-20230613164944138

注意

image-20230613164514306

【3】句子概率

P ( w 1 : n ) ≈ ∏ i = 1 n P ( w i ∣ w i − k : i − 1 ) P(w_{1:n}) \approx \prod_{i=1}^{n} P(w_i|w_{i-k:i-1}) P(w1:n)i=1nP(wiwik:i1)

"""句子概率"""
def prob(sentence):
    s = [word2id[w] for w in sentence]
    les = len(s)
    if les < 1:
        return 0
    p = unigram[s[0]]
    if les < 2:
        return p
    for i in range(1, les):
        p *= bigram[s[i - 1], s[i]] #根据上边的概率矩阵计算得到
    return p

print('很好的菜', prob('很好的菜'))
print('菜很好的', prob('菜很好的'))
print('菜好的很', prob('菜好的很'))

image-20230613165304020

是根据上边的概率矩阵计算得到的, P ( w 1 , w 2 , w 3 , w 4 ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 2 ) P ( w 4 ∣ w 3 ) P(w_1,w_2,w_3,w_4) = P(w_1)P(w_2|w_1)P(w_3|w_2)P(w_4|w_3) P(w1,w2,w3,w4)=P(w1)P(w2w1)P(w3w2)P(w4w3) ,是基于2-Gram计算的。

【4】生成排列组合

"""排列组合"""
def permutation_and_combination(ls_ori, ls_all=None):
    ls_all = ls_all or [[]]
    le = len(ls_ori)
    if le == 1:
        ls_all[-1].append(ls_ori[0])
        ls_all.append(ls_all[-1][: -2])
        return ls_all
    for i in range(le):
        ls, lsi = ls_ori[:i] + ls_ori[i + 1:], ls_ori[i]
        ls_all[-1].append(lsi)
        ls_all = permutation_and_combination(ls, ls_all)
    if ls_all[-1]:
        ls_all[-1].pop()
    else:
        ls_all.pop()
    return ls_all

print('123排列组合', permutation_and_combination([1, 2, 3]))


"""给定词组,返回最大概率组合的句子"""
def max_prob(words):
    pc = permutation_and_combination(words)  # 生成排列组合
    p, w = max((prob(s), s) for s in pc)
    return p, ''.join(w)

print(*max_prob(list('香很的菜')))
print(*max_prob(list('她的菜香很')))
print(*max_prob(list('好很的他菜')))
print(*max_prob(list('好很的的她菜')))

image-20230613170108129

传统语言模型的限制:

  1. 如果采用n元语法,长距离依赖无法解决
  2. 最大似然估计应用于n元语法,稀疏性无法解决
  3. 泛化性差,black car, blue car的出现,并不能有助于我们预测red car
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值