赞
踩
word2vec是早期NLP的必要预处理过程,其用于生成词的向量表示(embeding)。
其将单词映射为固定长度的向量(embeding向量),而通过向量表示可以更好地表达不同词之间的相关性,因此会使得后续的分类、生成等NLP任务更好地学习训练。word2vec描述不同词之间的相关性,主要是指词同其上下文的其他词的共现性,主要有两种范式:
本文重点介绍跳元模型Skip-gram,为了求解上述式子,将上式求log转换为最小化下式:
其中上式中的词与词间的联合分布可以由词向量相似度衡量,word2vec为了方便计算,通过exp形式进行度量:
上式中的表示词向量,word2vec就是通过Embeding模块实现由单词到词向量的转换,从而上面的Loss最小化。Embeding模块实际上类似由于一个全连接网络层,其输入是N维的one-hot向量(N是指全量词的个数),输出是L维的向量(L是词向量的长度),其参数量总共为N*L。
word2vec主要是为求解上述Embeding模块的权重参数,其组成了中心词c的词向量
以下我们通过paddle代码实现word2vec网络结构的定义:
- class Word2Vec(nn.Layer):
- def __init__(self, num_embeddings, embedding_dim):
- super(Word2Vec, self).__init__()
- self.embed = nn.Embedding(num_embeddings, embedding_dim,
- weight_attr=paddle.ParamAttr(
- name="center_embed",
- initializer=paddle.nn.initializer.XavierUniform()))
-
- # 执行前向计算
- def forward(self, center, contexts_and_negatives=None):
- """Skip-Gram"""
- v = self.embed(center)
- if contexts_and_negatives is None:
- return v
- u = self.embed(contexts_and_negatives)
- pred = paddle.squeeze(paddle.bmm(v, u.transpose(perm=[0, 2, 1])), axis=1)
- return pred

上述定义中的pred用于表示
在训练时,我们将原来Loss转换为批量进行训练,另外的求解由于涉及到softmax计算,计算相对困难,因此一种我们将简化的方式进行训练(负采样)。
其首先定义共同出现时,定义词u在中心词窗口k内的概率为:
同理不在中心词窗口k内的概率为:
此时条件概率可以表示为:
此时batch内的loss可以表示为:
其中k表示正例的窗口大小,h表示负例数(即不在上下文窗口的词),上述loss函数可以用binary_cross_entropy_with_logits损失函数表示:
其中中label表示词是正或负例,logits即为
- class SigmoidBCELoss(nn.Layer):
- # 带掩码的二元交叉熵损失
- def __init__(self):
- super().__init__()
-
- def forward(self, inputs, label, mask):
- out = nn.functional.binary_cross_entropy_with_logits(
- logit=inputs, label=label, weight=mask, reduction="none")
- return out.mean(axis=1)
整体的paddle训练代码如下:
- # 中心词
- center_spec = paddle.static.InputSpec([None, 1], 'int64', 'center')
- # 上下文正例词及负例词
- context_spec = paddle.static.InputSpec([None, max_context_len], 'int64', 'contexts_and_negatives')
- # 正例及负例的标识
- label_spec = paddle.static.InputSpec([None, max_context_len], 'float32', 'label')
- # mask,正例及负例以外的填充为0不参与训练
- mask_spec = paddle.static.InputSpec([None, max_context_len], 'float32', 'mask')
-
- model = paddle.Model(Word2Vec(num_embeddings, embedding_dim), [center_spec, context_spec], [label_spec, mask_spec])
- model.prepare(
- optimizer=paddle.optimizer.Adam(learning_rate=learning_rate, parameters=model.parameters()),
- loss=SigmoidBCELoss()
- )
- model.fit(
- train_dataset,
- valid_dataset,
- batch_size=batch_size,
- epochs=num_epochs,
- eval_freq=1,
- shuffle=True,
- save_dir=save_model_dir,
- callbacks=[loss_print, vdl_record]
- )

GloVe主要在原来loss函数中引入了两点特性:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。