语言模型可以说是自然语言处理中最重要的模型。语言模型可以看做是一个函数,用于计算一个句子出现的概率,即语言模型可以判断某一句话从语法上是否通顺(是不是人话),从语义上是否有歧义。在很多时候,我们都要度量一句话的出现概率,一句话的出现概率等同于一句话语法的流畅程度。通过语言模型,我们可以知道:
P
L
M
(
今
天
天
气
真
不
错
)
>
P
L
M
(
真
不
错
天
气
今
天
)
P
L
M
(
全
民
A
I
是
趋
势
)
>
P
L
M
(
全
民
趋
势
是
A
I
)
P_{LM}(今天天气真不错)>P_{LM}(真不错天气今天)\\P_{LM}(全民AI是趋势)>P_{LM}(全民趋势是AI)
PLM(今天天气真不错)>PLM(真不错天气今天)PLM(全民AI是趋势)>PLM(全民趋势是AI)
语言模型可以用于语音识别,机器翻译。
那么,如何计算每句话出现的概率?每句话出现的概率等于单词序列出现的概率。
P
L
M
(
s
)
=
P
L
M
(
w
1
,
w
2
,
.
.
.
,
w
n
)
P_{LM}(s)=P_{LM}(w_1,w_2,...,w_n)
PLM(s)=PLM(w1,w2,...,wn)
根据链式法则,可以表示为
P
L
M
(
s
)
=
P
L
M
(
w
1
,
w
2
,
.
.
.
,
w
n
)
=
P
L
M
(
w
1
)
P
L
M
(
w
2
∣
w
1
)
.
.
.
P
L
M
(
w
n
∣
w
1
w
2
.
.
.
w
n
−
1
)
P_{LM}(s)=P_{LM}(w_1,w_2,...,w_n)=P_{LM}(w_1)P_{LM}(w_2|w_1)...P_{LM}(w_n|w_1w_2...w_{n-1})
PLM(s)=PLM(w1,w2,...,wn)=PLM(w1)PLM(w2∣w1)...PLM(wn∣w1w2...wn−1)
因此,语言模型是一个概率模型,所谓的通顺,就是出现的概率高。比如:今天天气真不错应该怎样建模呢?
P
L
M
(
今
天
天
气
真
不
错
)
=
P
L
M
(
今
天
,
天
气
,
真
,
不
错
)
=
P
L
M
(
今
天
)
P
L
M
(
天
气
∣
今
天
)
P
L
M
(
真
∣
今
天
,
天
气
)
P
L
M
(
不
错
∣
今
天
,
天
气
,
真
)
P_{LM}(今天天气真不错)=P_{LM}(今天,天气,真,不错)=P_{LM}(今天)P_{LM}(天气|今天)P_{LM}(真|今天,天气)P_{LM}(不错|今天,天气,真)
PLM(今天天气真不错)=PLM(今天,天气,真,不错)=PLM(今天)PLM(天气∣今天)PLM(真∣今天,天气)PLM(不错∣今天,天气,真)
然而,对于长序列来说,当前条件很长的时候,许多条件概率也非常稀疏(概率值很小)。前面的条件(单词)都需要考虑进来嘛?如果假设每个词的出现概率是独立的,那样,就可以将上面的条件概率分布简化为如下一元语言模型(Unigram Model):
P
L
M
(
w
)
=
∏
i
=
1
n
P
L
M
(
w
i
)
P_{LM}(w)=\prod_{i=1}^nP_{LM}(w_i)
PLM(w)=i=1∏nPLM(wi)
但是很明显每个词出现的概率不可能是独立的,所以我们可以放宽假设,这就涉及到NLP领域最重要的假设:马尔科夫假设,假设任意一个词,它的出现概率只与前面出现的一个词(或者几个词)有关,那么,基于这个假设就可以将上面的条件概率分布简化为如下二元语言模型(Bigram Model):
P
L
M
(
s
)
=
P
L
M
(
w
1
)
P
L
M
(
w
2
∣
w
1
)
P
L
M
(
w
3
∣
w
2
)
.
.
.
P
L
M
(
w
n
∣
w
n
−
1
)
P_{LM}(s)=P_{LM}(w_1)P_{LM}(w_2|w_1)P_{LM}(w_3|w_2)...P_{LM}(w_n|w_{n-1})
PLM(s)=PLM(w1)PLM(w2∣w1)PLM(w3∣w2)...PLM(wn∣wn−1)
依次类推,还有三元语言模型(Trigram Model):
P
L
M
(
s
)
=
P
L
M
(
w
1
)
P
L
M
(
w
2
∣
w
1
)
P
L
M
(
w
3
∣
w
2
,
w
1
)
.
.
.
P
L
M
(
w
n
∣
w
n
−
1
,
w
n
−
2
)
P_{LM}(s)=P_{LM}(w_1)P_{LM}(w_2|w_1)P_{LM}(w_3|w_2,w_1)...P_{LM}(w_n|w_{n-1},w_{n-2})
PLM(s)=PLM(w1)PLM(w2∣w1)PLM(w3∣w2,w1)...PLM(wn∣wn−1,wn−2)
这类模型统称为N-gram Model。
使用神经网络构建语言模型与使用N-gram Model的思路是一样的,使用神经网络构建语言模型时,仍然会使用条件概率分解的形式,唯一的不同是在N-gram 语言模型中使用的是基于统计的方法估计每一个条件概率分布,而在神经网络中,我们使用的是神经网络近似每一个条件概率。
理想情况下,
下面介绍一种新的评价指标—perplexity(困惑度)
perplexity越低,表明语言模型认为这句话出现的概率越高,这句话越有可能出现。困惑度最小是1,perplexity越小,确定性越高,perplexity越低越好。
平滑概念指的是试图给没有出现的N-gram分配一个比较合理的数值出来,不至于直接为0。下面介绍多种平滑策略:
OOV问题
OOV= out of vocab,没有出现在词典中的单词
拼写错误在英语中比汉语中更加常见。拼写纠错的前提是你所要输入的词是在词典中的,所使用的词典是非常完备的。我们可以将拼写错误分成两种情况:一种是错别字错误;另一种是语法错误。
- 输入(用户输入)
- 从词典中寻找编辑距离最小的候选(生成编辑距离为1,2的字符串)
- 过滤
我们如何进行过滤呢?
这里要用到noisy channel model
贝叶斯公式:
其中, P ( c ) P(c) P(c)就是一个语言模型,P(s|c)就是在字符串c出现的前提下,字符串s出现的概率。这样处理相当于将一个复杂问题划分成两个子问题乘积的形式来考虑。- 返回
最小编辑距离Minimum Edit Distance(MED)
:
两个字符串之间的最小编辑距离可以定义为将字符串1转化为字符串2的最小的[插入/删除/替换]的操作数。
字符串"ABC"到字符串“BC”的操作数为1。
字符串“INTENTION”转变成字符串“EXECUTION”的操作数为5。
最小编辑距离有如下应用:拼写纠错,基因序列对齐;评估机器翻译与语音识别中的错误。
那么,如何计算两个字符串的最小编辑距离?
这是一个DP问题,需要使用动态规划算法,两个字符串的最小编辑距离可以划分成计算两个子串的最小编辑距离。
如果两个子串Am == Bn
,则两个字符串的最小编辑距离等于去掉这个子串的最小编辑距离。
如果两个子串Am != Bn
,则分别计算三种操作的最小编辑距离,选择编辑距离最小的,即为最小编辑距离。
词集模型是指基于词典的句子的one-hot编码。词集模型只能统计这句话是否出现过这个词,而不能记录词之间的顺序,词出现的个数。one-hot编码表达方式有如下缺点:不能捕捉词之间的意思;新词不容易泛化,无法利用现有的词典解决新词编码。举个例子:词典:[今天,天气,真,不错]
- 每个单词的表示:
今天:[1,0,0,0]
天气:[0,1,0,0]
真:[0,0,1,0]
不错:[0,0,0,1]- 每个句子表示:
今天真不错:[1,0,1,1]
鉴于词集模型只能统计这句话是否出现过这个词,而不能记录词之间的顺序,词出现的个数;词袋模型进行了改进,可以记录词出现的个数。当然,并不是词出现的次数越多就越重要,也并不是词出现的越少就越不重要。此时,就需要分别从本句子与全局角度来查看这个词重不重要,这也就是TF-IDF的核心思想。
词袋模型是最基础的文本表示模型。词袋模型是将每篇文章看成一袋子词,并忽略每个词出现的顺序。具体来说,就是将整段文本以词为单位切分开,然后每篇文章可以表示成一个长向量,向量中的每一维代表一个单词,而该维对应的权重则反映这个词在原文章中的重要程度。常用TF-IDF来计算权重,公式为:
T
F
−
I
D
F
(
t
,
d
)
=
T
F
(
t
,
d
)
×
I
D
F
(
t
)
TF-IDF(t,d)=TF(t,d)×IDF(t)
TF−IDF(t,d)=TF(t,d)×IDF(t)
其中,
T
F
(
t
,
d
)
TF(t,d)
TF(t,d)为单词
t
t
t在文档
d
d
d中出现的频率;
I
D
F
(
t
)
IDF(t)
IDF(t)是逆文档频率,用来衡量单词
t
t
t对表达语义所起的重要性,表示为
I
D
F
(
t
)
=
l
o
g
N
N
(
w
)
+
1
IDF(t)=log\frac{N}{N(w)+1}
IDF(t)=logN(w)+1N
其中,N表示语料库中的文章总数,N(w)表示词语w出现在多少个文档中
逆文档频率最直观的解释是:如果一个单词在非常多的文章里面出现,那么它很可能是一个通用词汇,对于区分某篇文章特殊语义的贡献越小,因此对权重做一定惩罚。
什么才算是一个好的文本表示?相似词的表征之间的相似度要比不相似词的表征之间的相似度大。显然,不管是词集模型还是词袋模型,都不能满足这个要求。并且,不管是词集模型还是词袋模型,文本表示都是非常稀疏的,占用内存大,有用信息少。所以,我们想要更少的维度,更合理的表达方式来表达文本。研究者们利用词向量模型来进行词向量表示。传统的词向量模型有:SkipGram,Glove,CBOW;考虑上下文的词向量模型有ELmo,Bert,XLNet。
分布式词表示能够很好的表示新词,提升模型的泛化性能;更容易表示语义信息。分布式词表示基于假设:利用上下文的统计信息来表示这个词的意思。分布式词表示介绍两种形式:Counting Based, Prediction Based。
Counting Based:统计共现矩阵得到不同词的表现信息(共现关系)。
利用共现矩阵得到词的表现信息有如下问题:
增加词汇量
高维
稀疏
有如下解决方法:
- SVD的高计算代价
- 难以合并新的单词或者新文档,泛化性能比较低
- 难以与深度学习(DL)模型集成
CBOW是预测中间单词,这个模型涉及window size,如果window size=2,那么用前两个单词与后两个单词来预测中间的词。如上图中的CBOW,
输入:前后两个单词的onehot向量表示,如果词集大小为10000,则输入向量为(4×10000)
隐藏层大小为(10000×100)
输出:输出向量为(1×10000)
权重W:权重W的大小为(10000×100)
权重 W ′ W' W′:权重$W’的大小为(100×10000)输入乘以权重W得到分布式向量表示再乘 W ′ W' W′后进行累加(或者平均)得到向量表征,通过向量表征softmax,依据概率值最大,从词集中找出最应该出现的单词。
skip-gram是利用中心词预测上下文的单词。下面我们介绍这个模型是如何优化与预测的?我们要优化的是根据语料得到的条件概率分布,即优化给定中心词
w
w
w,上下文中的词
c
c
c出现的概率。
m
a
x
θ
∏
w
∈
T
e
x
t
∏
c
∈
C
o
n
t
e
x
t
P
(
c
∣
w
,
θ
)
\underset {\theta}{max}\prod_{w∈Text}\prod_{c∈Context}P(c|w,θ)
θmaxw∈Text∏c∈Context∏P(c∣w,θ)
用softmax形式参数化条件概率:
P
(
c
∣
w
,
θ
)
=
e
u
c
⋅
v
w
∑
c
′
e
u
c
′
v
w
P(c|w,θ)=\frac{e^{u_c·v_w}}{\sum_{c'}{e^{u_{c'}v_w}}}
P(c∣w,θ)=∑c′euc′vweuc⋅vw
∑
c
′
∈
C
o
n
t
e
x
t
P
(
c
′
∣
w
,
θ
)
\sum_{c'∈Context}P(c'|w,θ)
∑c′∈ContextP(c′∣w,θ) = 1,表示
w
,
c
w,c
w,c的语义相似性概率。我们在skip-Gram Model中需要维护两个词向量矩阵,这两个词向量矩阵一个是中心词Text矩阵
v
v
v,一个是上下文词Context矩阵
u
u
u。优化这个目标函数,就是优化
θ
\theta
θ,也就是固定
u
i
u_i
ui,基于梯度,更新中心词
v
v
v。
为什么中心词矩阵与Context矩阵要区分出来?事实上,完全可以使用同样的矩阵,不过,在使用中心词预测两侧的词时,中心词与两侧的词所扮演的角色是不同的。如果使用同样的分布,一定程度上削减模型的表达性能,如果使用不同的分布,一定程度上会增强模型的性能。
由于log函数是递增函数,因此两个最优化目标是等价的,这样转化会给计算带来便利。
针对求和是基于整个词表进行的,它的时间复杂度非常大,是与词表大小呈线性关系的,出现了两个
t
r
i
c
k
trick
trick:
Negative sampling(负采样)
采样得到一个上下文词和一个目标词,生成一个正样本(positive example),生成一个负样本(negative example),则是用与正样本相同的上下文词,再在字典中随机选择一个单词,这就是负采样(negative sampling)。
现在我们来看看如何进行负采样,得到neg个负例。word2vec采样的方法并不复杂, 如果词汇表的大小为
V
V
V,那么我们就将一段长度为1的线段分成
V
V
V份,每份对应词汇表中的一个词。 当然每个词对应的线段长度是不一样的,高频词对应的线段长,低频词对应的线段短。 每个词
w
w
w的线段长度由下式决定:
Hierarchical Softmax
原先的softmax是从字典大小的词中预测属于哪个词。Hierarchical Softmax采用树的结构,减少搜索路径。
回到基于Hierarchical Softmax的word2vec本身,我们的目标是找到合适的所有节点的词向量和所有内部节点
θ
\theta
θ,使训练样本达到最大似然。
更新流程:
1.基于语料训练样本建立霍夫曼树,会倾向于将词频比较大的放在树的前面。
2. 随机初始化所有的模型参数 θ \theta θ,所有的词向量 w w w
3. 进行梯度上升迭代过程,对于训练集中的每一个样本做梯度更新,更新: θ \theta θ和 w
4. 如果梯度收敛,则结束梯度迭代,否则回到步骤3继续迭代
这一部分没有理解的可以参考:https://www.cnblogs.com/pinard/p/7243513.html
如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!