语言模型串烧
语言模型的发展实在是太快了,怎么才赶上NLP快车呢?
注:为了更佳的阅读体验,欢迎访问我的博客:Write Down Something
Word2Vec(2013年1月)
CBOW用上下文训练目标词,而Skip-gram用目标词去预测上下文。Word2Vec采用三层神经网络就可以训练,最后一层的输出是Softmax,因为Softmax需要计算全局的token,因此速度慢。为了提高训练速度,衍生出用Huffman树和负采样代替最简单的Softmax的训练方法。
GloVe(2014年1月)
Global Vectors for Word Representation。
Word2Vec的目的是预测,而GloVe的目的是将共现矩阵降维。不过共现矩阵的维度太大不可能直接构造出来用传统方法降维,所以GloVe的工作实际上可以理解为重构共现矩阵。
假设词i的出现次数为 X i X_i Xi,词i和词j的共现次数为 x i , j x_{i,j} xi,j,那么词i和词j的共现频率就是 P i j = X i , j / X i P_{ij} = X_{i,j} / X_i Pij=Xi,j/Xi。作者认为 两个词的相关程度是可以通过共现次数做比较的,就行下面这个表格:
P i k / P j k P_{ik}/P_{jk} Pik/Pjk | 单词j和单词k相关 | 单词j和单词k不相关 |
---|---|---|
单词i和单词k相关 | 趋近于1 | 很大 |
单词i和单词k不相关 | 很小 | 趋近于1 |
而用词向量表示词义的时候,衡量两者近似程度就是用内积。用 v i v_i vi、 v j v_j vj、 v k v_k vk分别表示词i、j、k的词向量,并用函数g(i,j,k)表示词向量i和词向量j谁更接近于词向量k,那么结合共现次数,就可以推知:
P i , k P j , k = g ( i , j , k ) \frac{P_{i,k}}{P_{j,k}} = g(i,j,k) Pj,kPi,k=g(i,j,k)
代价函数为
J = ∑ i , j , k ( P i , k / P j , k − g ( i , j , k ) ) 2 J = \sum_{i,j,k}(P_{i,k}/P_{j,k} − g(i,j,k))^2 J=i,j,k∑(Pi,k/Pj,k−g(i,j,k))2
不过目前,计算所有g的代价是 O ( n 3 ) O(n^3) O(n3),作者将函数g展开,并最终得到了函数g的等价形式。首先是定义函数g,
g ( i , j , k ) = e x p ( v i T v k − v j T v k ) = e x p ( v i T v k ) e x p ( v j T v k ) g(i,j,k) = exp(v_i^T v_k − v_j^T v_k) = \frac{exp(v_i^T v_k)}{exp(v_j^T v_k)} g(i,j,k)=exp(viTvk−vjTvk)=exp(vjTvk)exp(viTvk)
因此
P i , k P j , k = e x p ( v i T v k ) e x p ( v j T v k ) \frac{P_{i,k}}{P_{j,k}} = \frac{exp(v_i^T v_k)}{exp(v_j^T v_k)} Pj,kPi,k=exp(vjTvk)exp(viTvk)
那么只要等式上下对应相等,整个等式就成立了
P i , k = e x p ( v i T v k ) P_{i,k} = exp(v_i^T v_k) Pi,k=exp(viTvk)
进一步,两边同时取对数
l o g ( P i , k ) = v i T v k log(P_{i,k}) = v_i^T v_k log(Pi,k)=viTvk
这样代价函数化简为时间复杂度为 O ( n 2 ) O(n^2) O(n2)的
J = ∑ i , k ( l o g ( P i , k ) − v i T v k ) 2 J = \sum_{i,k}(log(P_{i,k}) − v_i^T v_k)^2 J=i,k∑(log(Pi,k)−viTvk)2
但是实际上这里存在一个bug: l o g ( P i , k ) log(P_{i,k}) log(Pi,k)不具备对称性,而 v i