CBOW
基本思路是:用上下文预测目标词汇。输入层由目标词汇 y y y的上下文单词 { x 1 , . . . , x c } \{{{x}_{1}},...,{{x}_{c}}\} {x1,...,xc}组成, x i {x}_{i} xi是被onehot编码过的V维向量,其中V是词汇量;隐含层是N维向量h;输出层是被onehot编码过的目标词y。输入向量通过 V ∗ N V*N V∗N维的权重矩阵 W ′ {W}' W′连接到输出层。因为词库 V V V往往非常大,使用标准的softmax计算相当耗时,于是CBOW的输出层采用的是上文提到的分层Softmax
前向传播
假设已经获得权重矩阵 W W W和 W ′ {W}' W′,隐含层h的输出计算公式: h = 1 C W ⋅ ( ∑ i = 1 c x i ) h=\frac{1}{C}W\cdot (\sum\limits_{i=1}^{c}{{{x}_{i}}}) h=C1W⋅(i=1∑cxi)
即:隐含层的输出是C个上下文单词 向量的加权平均,权重为 W W W。接着我们计算输出层的每个节点: u j = v ’ w j T ⋅ h {{u}_{j}}={v’}_{{{w}_{j}}}^{T}\cdot h uj=v’wjT⋅h此处 v ’ w j {v’}_{{w}_{j}} v’wj是矩阵 W ′ {W}' W′的第j列,最后将 u j {{u}_{j}} uj作为softmax函数的输入,得到 y j {{y}_{j}} yj:
y j = p ( w y j ∣ w 1 , . . . , w c ) = exp ( u j ) ∑ j ′ = 1 V exp ( u ′ j ) {{y}_{j}}=p({{w}_{yj}}|{{w}_{1}},...,{{w}_{c}})=\frac{\exp ({{u}_{j}})}{\sum\nolimits_{j'=1}^{V}{\exp (u{{'}_{j}})}} yj=p(wyj∣w1,...,wc)=∑j′=1Vexp(u′j)exp(uj)
反向传播学习权重矩阵
在学习权重矩阵的过程中,首先随机产生初始值,然后feed训练样本到模型中并观测期望输出和真实输出的误差。接着,我们计算误差关于权重矩阵的梯度,并在梯度的方向纠正它们。
首先定义随时函数,objective是最大化给定输入上下文,target单词的条件概率。因此,损失函数为:
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ & E=-\log p(…
此处 j ∗ {{j}^{*}} j∗表示目标单词在词库V中的索引。
如何更新权重 W ′ {W}' W′? 先对E关于 W i j ′ W_{ij}^{'} Wij′求导: ∂ E ∂ W i j ′ = ∂ E ∂ u j ⋅ ∂ u j ∂ W i j ′ = ( y j − [ [ j = j ∗ ] ] ) ⋅ h i \frac{\partial E}{\partial W_{ij}^{'}}=\frac{\partial E}{\partial {{u}_{j}}}\cdot \frac{\partial {{u}_{j}}}{\partial W_{ij}^{'}}=({{y}_{j}}-\left[\!\left[ j={{j}^{*}} \right]\!\right])\cdot {{h}_{i}} ∂Wij′∂E=∂uj∂E⋅∂Wij′∂uj=(yj−[[j=j∗]])⋅hi
[ [ j = j ∗ ] ] \left[\!\left[ j={{j}^{*}} \right]\!\right] [[j=j∗]]函数表示: [ [ j = j ∗ ] ] = { 1 i f : j = = j ∗ − 1 o t h e r w i s e \left[\!\left[ j={{j}^{*}} \right]\!\right]=\left\{ \begin{matrix} 1 & if:j=={{j}^{*}} \\ -1 & otherwise \\ \end{matrix} \right. [[j=j∗]]={1−1if:j==j∗otherwise
于是, W i j ′ W_{ij}^{'} Wij′的更新公式:
W i j ′ ( n e w ) = W i j ′ ( o l d ) − η ⋅ ( y j − [ [ j = j ∗ ] ] ) ⋅ h W_{ij}^{'(new)}=W_{ij}^{'(old)}-\eta \cdot ({{y}_{j}}-\left[\!\left[ j={{j}^{*}} \right]\!\right])\cdot h Wij′(new)=Wij′(old)−η⋅(yj−[[j=j∗]])⋅h
如何更新权重W?
我们首先计算E关于隐藏层节点的导数:
∂ E ∂ h i = ∑ j = 1 V ∂ E ∂ u j ⋅ ∂ u j ∂ h i = ∑ j = 1 V ( y j − [ [ j = j ∗ ] ] ) ⋅ W i j ′ \frac{\partial E}{\partial {{h}_{i}}}=\sum\limits_{j=1}^{V}{\frac{\partial E}{\partial {{u}_{j}}}\cdot \frac{\partial {{u}_{j}}}{\partial {{h}_{i}}}}=\sum\limits_{j=1}^{V}{({{y}_{j}}-\left[\!\left[ j={{j}^{*}} \right]\!\right])}\cdot W_{ij}^{'} ∂hi∂E=j=1∑V∂uj∂E⋅∂hi∂uj=j=1∑V(yj−[[j=j∗]])⋅Wij′
然后,E关于权重的导数为:
∂ E ∂ w k i = ∂ E ∂ h i ⋅ ∂ h i ∂ w k i = ∑ j = 1 V ( y j − [ [ j = j ∗ ] ] ) ⋅ W i j ′ ⋅ 1 C ⋅ x k \frac{\partial E}{\partial {{w}_{ki}}}=\frac{\partial E}{\partial {{h}_{i}}}\cdot \frac{\partial {{h}_{i}}}{\partial {{w}_{ki}}}=\sum\limits_{j=1}^{V}{({{y}_{j}}-\left[\!\left[ j={{j}^{*}} \right]\!\right])}\cdot W_{ij}^{'}\cdot \frac{1}{C}\cdot {{x}_{k}} ∂wki∂E=∂hi∂E⋅∂wki∂hi=j=1∑V(yj−[[j=j∗]])⋅Wij′⋅C1⋅xk
于是, w k i {{w}_{ki}} wki的更新公式:
W k i ( n e w ) = W k i ( o l d ) − η ⋅ ∑ j = 1 V ( y j − [ [ j = j ∗ ] ] ) ⋅ W i j ′ ⋅ 1 C ⋅ x k W_{ki}^{(new)}=W_{ki}^{(old)}-\eta \cdot \sum\limits_{j=1}^{V}{({{y}_{j}}-\left[\!\left[ j={{j}^{*}} \right]\!\right])}\cdot W_{ij}^{'}\cdot \frac{1}{C}\cdot {{x}_{k}} Wki(new)=Wki(old)−η⋅j=1∑V(yj−[[j=j∗]])⋅Wij′⋅C1⋅xk
GloVe
Global Vectors for Word Representation,它是一个基于全局词频统计的词表征工具,它可以把一个单词表达成一个由实数组成的向量,这些向量捕捉到了单词之间的一些语义特征,比如相似性(similarity)、类比性(analogy)等。我们通过对向量的运算,比如欧几里得距离或者cosine相似度来计算出两个单词之间的语义相似性。
GloVe的共现矩阵:
根据语料库(corpus)构建一个共现矩阵X,矩阵中的每一个元素 X i j {{X}_{ij}} Xij代表单词 i i i和上下文单词 j j j在特定大小的上下文窗口中共同出现的次数。一般而言,这个次数的最小单位是1,但是GloVe不这么认为:它根据两个单词在上下文窗口的距离d,提出了一个衰减函数:decay=1/d用于计算权重,也就是说,距离越远的两个单词所占总计数的权重越小。
词向量与共现矩阵的近似关系
构建词向量和共现矩阵之间的近似关系,公式如下: w i T w ~ j + b i + b ~ j = log ( X i j ) w_{i}^{T}{{{\tilde{w}}}_{j}}+{{b}_{i}}+{{{\tilde{b}}}_{j}}=\log ({{X}_{ij}}) wiTw~j+bi+b~j=log(Xij)
构造损失函数
J = ∑ i j = 1 V f ( X i j ) ( w i T w ~ j + b i + b ~ j − log ( X i j ) ) 2 J=\sum\nolimits_{ij=1}^{V}{f({{X}_{ij}})}{{(w_{i}^{T}{{{\tilde{w}}}_{j}}+{{b}_{i}}+{{{\tilde{b}}}_{j}}-\log ({{X}_{ij}}))}^{2}} J=∑ij=1Vf(Xij)(wiTw~j+bi+b~j−log(Xij))2
此损失函数的基本形式就是最简单的均方误差,只不过在此基础上加了一个权重函数 f ( X i j ) f({{X}_{ij}}) f(Xij)。在一个语料库中,会存在许多同时出现的单词组合,我们希望:
- 这些词的组合之间的权重要大于那些很少出现在一起的单词间的权重,故,这个函数应该是非递减函数
- 但我们不希望此权重过大,当达到一定程度后应该不再增加;
- 如果两个单词没有在一起出现,也就是 X i j = 0 {{X}_{ij}=0} Xij=0,那么它们应该不参与到损失函数的计算当中去,也就是 f ( x ) f(x) f(x)要满足 f ( 0 ) = 0 f(0)=0 f(0)=0。
因此定义权重函数为如下形式的分段函数:
f ( x ) = { ( x / x max ) α i f : x < x max 1 o t h e r w i s e f(x)=\left\{ \begin{matrix} {{(x/{{x}_{\max }})}^{\alpha }} & if:x<{{x}_{\max }} \\ 1 & otherwise \\ \end{matrix} \right. f(x)={(x/xmax)α1if:x<xmaxotherwise.
函数图像如下所示:
训练GloVe模型
很多人称GloVe是一种无监督的学习方式(确实不需人工标注label),但它还是有label的,这个label就是以上公式中的 log ( X i j ) \log ({{X}_{ij}}) log(Xij),而公式中的 w w w和 w ~ {\tilde{w}} w~就是要不断更新/学习的参数,所以本质上它的训练方式跟监督学习的训练方法没什么区别都是基于梯度下降的。
具体训练过程如下:==采用AdaGrad的梯度下降算法,对矩阵X中的所有非零元素进行随机采样,学习曲率(learning rate)设置为0.05,在vector size 小于300的情况下迭代了50次,其他大小的vectors上迭代了100次,直至收敛。==最终学习得到的是两个vector是 w w w和 w ~ {\tilde{w}} w~因为X是对称的(symmetric),所以从原理上讲 w w w和 w ~ {\tilde{w}} w~也是对称的,他们唯一的区别就是初始化的值不一样,而导致最终的值不一样。
所以这两者其实是等价的,都可以当作最终的结果来使用。但,为了提高鲁棒性,我们最终会选择两者之和 w + w ~ w+{\tilde{w}} w+w~作为最终的vector(两者的初始化不同相当于加了不同的随机噪声,所以能提高鲁棒性)。在训练400亿个token后,得到的实验结果如下图:
改图共采用三个指标:语义精确度、语法准确度以及总体准确度。不难发现,Vector Dimension在300时性能达到最佳,而context Windows size大致在6-10的区间。
inner join
多表连接建立记录集。某些情况下,需要把数字数据类型显示为相应的文本名称这样就遇到了多表联接建立记录集的问题。
#连接俩数据表
FROM Member INNER JOIN MemberSort ON Member.MemberSort = MemberSort.MemberSort
FROM 表1 INNER JOIN 表2 ON 表1.字段号 = 表2.字段号
#连接仨数据表
FROM(Member INNER JOIN MenberSort ON Member.MemberSort = MemberSort.MemberSort) INNER JOIN MemberLevel ON Member.MemberLevel = MemberLevel.MemberLevel
FROM (表1 INNER JOIN 表2 ON 表1.字段号 = 表2.字段号) INNER JOIN 表3 ON 表1.字段号 = 表3.字段号
#连接四个数据表
FROM((表1 INNER JOIN 表2 ON 表1.字段号 = 表2.字段号)INNER JOIN 表3 ON 表1.字段号 = 表3.字段号) INNER JOIN 表4 ON Member.字段号 = 表4.字段号
left join
左连接,把左边的全部查出来,右边有的则匹配,没有则为null
select * from temp1 t1 left join temp2 t2 on t1.aid=t2.bid;
#若是三张表,通过两个left join来连接,则把前面两张表先left join之后当作一张表,然后再与第三张表left join,同理多表以此类推。
select * from temp1 t1 left join temp2 t2 on t1.aid=t2.bid left join temp3 t3 on t2.bid=t3.cid;
第三张表left join,同理多表以此类推。
select * from temp1 t1 left join temp2 t2 on t1.aid=t2.bid left join temp3 t3 on t2.bid=t3.cid;