word2vec详解

def skip_gram(center, contexts_and_negatives, embed_v, embed_u):
    v = embed_v(center)
    u = embed_u(contexts_and_negatives)
    pred = torch.bmm(v, u.permute(0, 2, 1))
    return pred
net = nn.Sequential(nn.Embedding(num_embeddings=len(idx_to_token), embedding_dim=embed_size),
                    nn.Embedding(num_embeddings=len(idx_to_token), embedding_dim=embed_size))
pred = skip_gram(center, context_negative, net[0], net[1])

len(idx_to_token) = 512
embed_size = 100
那么v.shape = [512, 1, 100], u.shape = [512, 60, 100]

问题: 为啥skip_gram的前向传播直接是 vuTvu^TvuT
为了便于说明,我们从vvv和uuu中直接拿一个"矩阵"来说明:
vvv中拿一个batch, 假设为v1v_1v1​,且shape=[1, 100]; 从uuu中拿一个batch, 假设为u1u_1u1​,且shape=[60,100]; 为了方便举例,我们将两者的形状再次缩小,设v1v_1v1​.shape=[1, 3], u1u_1u1​.shape=[2, 3], 即设 v1=[0.5, 1,0.1] v_1=\left[ \text{0.5, 1,}-0.1 \right] v1​=[0.5, 1,−0.1]u1=[0.1, 0.5, 0.20.5, 0.3, 0.8] u_1=\left[ \begin{array}{c} \text{0.1, 0.5, }0.2\\ -\text{0.5, 0.3, }0.8\\ \end{array} \right] u1​=[0.1, 0.5, 0.2−0.5, 0.3, 0.8​]
其中v1v_1v1​的一行代表一个中心词的向量;u1u_1u1​的每一行代表中心词上下文及噪声词的向量,所以v1u1Tv_1u_1^Tv1​u1T​就表示中心词与每个上下文的词或噪声词的内积,假设u1u_1u1​的第一行是上下文词, 第二行是噪声词的向量,那么v1v_1v1​与u1u_1u1​第一行做内积结果应该趋向(上下文之间的词相似性更高), v1v_1v1​与u1u_1u1​第二行做内积结果应该趋向0(噪声词和中心词没啥关联),正好我们设置的label = [1, 0]这种格式, 通过交叉熵损失函数,迭代优化后会调整u1u_1u1​和v1v_1v1​的值(实际上是调整embed_v和embed_u),使得内积结果趋向label; 最终的词向量是embed_v,它每一行代表一个词的向量, 每个词的索引和行数对应

未完,待更新…
完整程序见:word2vec.py

word2vec详解word2vec详解 orangerfun 发布了9 篇原创文章 · 获赞 0 · 访问量 83 私信 关注
上一篇:java-轻松将python导出到没有解释器的人


下一篇:为用户生成JavaScript嵌入代码