语言模型:在NLP中,把 x 看作一个句子里的一个词语,y 是这个词语的上下文词语,那么f就是语言模型,模型的目的,是判断(x,y)这个样本,是否符合自然语言的法则,即词语x和词语y放在一起,是不是人话。
统计语言模型(statistical language model)是建立在一段序列(比如一句话)上联合概率分布。skip-gram 模型是尝试用w_t预测context(w),具体是最大化“均值对数似然概率”,两个次之间的skip-gram概率p(w_t+j|w_t)可以这样定义,分子是把w对应的的词向量和context(w)里的某个词对应的词向量做点乘/内积,分母是把w对应的词向量和和词汇表中的所有词向量做点乘。最后得到的结果经过一个softmax,得到真正的概率。点乘后经过softmax 复杂度高,才有了两种改进方法,softmax和负采样。
示例讲解的时候,用的是onehot作为输入,实际使用的时候并不是,而是随机生成的,但是并不影响理解。onehot更加有利于理解整个word2vec,随机生成相当于初始化时,将input->hidden的参数随机化处理,
这是符合神经网络参数初始化的要求的,因为如果全置0或者全置1,会出现所有的参数学到的是一样的。如何参数初始化,参见深度学习中的参数初始化
softmax:原始的 cbow 和 skip-gram 更新一次参数,需要计算词典里的所有单词的预测和预测误差,使用每个word的预测误差去更新输出向量。计算太耗资源。
hierarchical softmax
[copy] output vector,只有非叶子节点有 vector 表示,叶子节点没有 vector 表示。具体的过程为:要预测的目标词不再是用onehot表示,而是用huffman编码,先接一个输出节点,即只有一个权重 w1 ,输出节点输出 1/1+exp(-w*x),变成一个二分类的 LR,输出一个概率值 P1,然后根据目标词的 huffman tree 编码,将 x 再输出到下一个 LR,对应权重 w2,输出 P2,总共遇到的 LR 个数(或者说权重个数)跟 huffman tree 编码长度一致,大概有 log(V) 个,最后将这 log(V) 个 P 相乘,得到属于目标词的概率/
[自述] softmax作为多分类,其实是词典大小个数的类别数的多分类。每次计算, 分母要把词典内的所有词都参与计算。计算量确实很大,且计算时所有的类别是拍平在同一层的。多分类的另一个思路就是进行多次二分类,很自然的就转化为二分类问题,之前我们见到的
多分类转化成多个二分类问题,大多是从平面的角度看的,且多分类的类目其实也不多。而这里多分类的类目非常huge,重在描述这个多个二分类的过程,就变成了二叉树构建构成。[带层级关系的二分类实现多分类]这个说法不准,且是错误的,因为 huffman 树本身没有节点间的物理属性层级关系,huffman 树的构造原则只有一个,那就是根据出现频率使得路径的构造最短。所以,也可以说,这种层级关系,只指频率这这一种物理属性。不包含其他属性。
负采样
多分类转化为一个正例和多个负例的方式来学习每个二分类的分类器。如skipgram时,context为1,随机抽词置0,loss为交叉熵。cbow时,目标词为1,随机抽词置0,loss为交叉熵。
J
(
θ
)
=
1
T
∑
t
=
1
T
J
t
(
θ
)
J(\theta)=\frac{1}{T}\sum_{t=1}^{T}{J_t(\theta)}
J(θ)=T1∑t=1TJt(θ)
J
t
(
θ
)
=
l
o
g
σ
(
u
o
T
v
c
)
+
∑
i
=
1
k
E
j
P
(
w
)
[
l
o
g
σ
(
−
u
j
T
v
c
)
]
J_t(\theta)=log\sigma(u_o^Tv_c)+\sum_{i=1}^{k}E_{jP(w)}[log\sigma(-u_j^Tv_c)]
Jt(θ)=logσ(uoTvc)+∑i=1kEjP(w)[logσ(−ujTvc)]
负采样处理:
设词汇表大小为V,每个词的等概率为1/V,按词频计算词汇概率为
p
(
w
)
=
c
o
u
n
t
(
w
)
3
/
4
∑
u
b
e
l
o
n
g
t
o
v
o
c
a
b
u
l
a
r
y
c
o
u
n
t
(
u
)
3
/
4
p(w)=\frac{count(w)^{3/4}}{\sum_{u belong to vocabulary} count(u)^{3/4}}
p(w)=∑ubelongtovocabularycount(u)3/4count(w)3/4
参见word2vec原理(三) 基于Negative Sampling的模型
CBOW
每次gd,调整周围词的向量,对周围词的调整是统一的,求出的gradient的值会同样的作用到每个周围词的词向量中。
Skipgram
每次gd,调整中心词的词向量。
- cbow 比skipgram 训练快些,cbow每次都更新context,skipgram每次只更新目标词
- skipgram 效果要好些,因为output是多个,相当于把普通一次训练的多次执行。
- skipgram 对低频词更友好些,cbow 相当于完形填空,选择低频词的概率较低。
- 负采样相比较于哈夫曼树更快一些,特别是当词表较大的时候。
谈谈多标签分类
多标签分类的转化成传统分类问题的一些处理方案
- 随机抽标签,会丢掉样本,一般不推荐使用。比如,fasttext 支持二分类,如果用来实现多分类,底层就是这种实现机制。
- 将样本按标签构造训练集,样本属于/不属于某个标签,对每个标签训练单独分类器,最后将多个分类结果合成。比如,word2vec 训练的 trick 负采样,就类似于这种,构造多种属于/不属于标签样本,只是word2vec不需要最终的预测结果,只是要模型参数,所以可以不进行最后一步,将多个分类结果合起来这一步。
- 将多标签看成是一个新标签,在一个更多的标签集上做分类。
- 每个有多标签的样本,复制该样本,每个样本对应于单标签。
谈谈降维作用
词向量的维度(与隐含层节点数一致)一般情况下要远远小于词语总数 V 的大小,所以 Word2vec 本质上是一种降维操作——把词语从 one-hot encoder 形式的表示降维到 Word2vec 形式的表示。
word2vec 的降维和 autoencoder 降维的差异:
- word2vec input和output 分别是 word 和 context,而 autoencoder 的 input 和 output 分别是word和word本身。
- word2vec 用的是分类,最后一步是softmax,loss是交叉熵。而autoencoder用的是自建损失函数。
- word2vec的原理是使用语言模型最大化均值对数似然概率,autoencoder的原理是无监督的用NN学习数据编码的方式。