Word2Vec 学习

举报
九年义务漏网鲨鱼 发表于 2025/09/15 15:18:47 2025/09/15
【摘要】 Word2Vec How achieve Lookup table Coding Pre-dataing Model Negative sameple Word2Vec单词与单词之间的向量往往不在同一个向量空间,例如,传统的编码方式:one-hot编码,不同单词[1, 0, 0]和[0, 1, 0]之间的余弦相似度为0。因此,Word2Vec希望能够通过训练得到一个新的词向量表达方式,从而...

Word2Vec

单词与单词之间的向量往往不在同一个向量空间,例如,传统的编码方式:one-hot编码,不同单词[1, 0, 0][0, 1, 0]之间的余弦相似度为0。因此,Word2Vec希望能够通过训练得到一个新的词向量表达方式,从而丰富向量的语义信息。主要目标如图所示,从一个稀疏的one-hot向量通过训练得到一个丰富稠密的新向量。

image.png

How achieve

word2vec通过神经网络模型训练新的词向量表达

image.png

  • 模型中参数的定义:

    one-hot:[1, 7] 表示一共有七个单词;

Embedding:表示输入层到隐藏层的权重矩阵,是从one-hot向量到Embedding向量的关键,[7, 3]表示训练完成的每一个embedding向量维度为3;

WeightLogits:表示隐藏层到输出层的权重矩阵,是模型损失计算的关键;

Logits:表示最后每个单词输出的概率,与目标标签做损失进行模型训练;

Lookup table

语料库十分巨大,每个单词都采用one-hot输入训练会大大增加存储和计算开销,因此,在输入的过程,仅仅输入单词的索引值,例如在上述例子中,直接采用索引4进行输入,同样也可以得到相同的词向量。

image.png

Coding

Word2Vec有两种模型结构:CBOW和Skip-gram,本质上的模型架构的不同:输入和输出一对多(Skip-gram)和多对一(CBOW)。

CBOW:通过前t个单词预测后一个单词

Skip-gram:通过周围的单词预测中间的单词 (一般来说,效果较好

Pre-dataing

  • 构建词汇表(Lookup-table)
def build_vocab(corpus):
    word_counts = Counter(chain(*corpus))
    vocab = {word: i for i, (word, _) in enumerate(word_counts.items())}
    return vocab
  • 构建不同模型的输入、输出
# Skip-gram 数据集生成
def generate_skipgram_data(corpus, vocab, window_size):
    data = []
    for sentence in corpus:
        for i in range(len(sentence)):
            target = sentence[i]
            context = [sentence[j] for j in range(max(0, i - window_size), min(len(sentence), i + window_size + 1)) if j != i]
            for context_word in context:
                data.append((vocab[target], vocab[context_word]))
    return data

# cbow 数据集生成
def generate_cbow_data(corpus, vocab, window_size):
    data = []
    for sentence in corpus:
        for i in range(len(sentence)):
            target = sentence[i]
            context = [sentence[j] for j in range(max(0, i - window_size), min(len(sentence), i + window_size + 1)) if j != i]
            data.append(([vocab[word] for word in context], vocab[target]))
    return data

Model

可以发现两个结构的代码只有输入和输出的大小不同,其他类似

  • CBOW
class CBOW(nn.Module):
    def __init__(self, vocab_size, embedding_dim):
        super(CBOW, self).__init__()
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)
        self.linear = nn.Linear(embedding_dim, vocab_size)

    def forward(self, context_words):
        embedded = self.embeddings(context_words).mean(dim=1)  # 平均上下文词向量
        logits = self.linear(embedded)
        return logits
  • Skip-gram
class SkipGram(nn.Module):
    def __init__(self, vocab_size, embedding_dim):
        super(SkipGram, self).__init__()
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)
        self.linear = nn.Linear(embedding_dim, vocab_size)

    def forward(self, target_word):
        embedded = self.embeddings(target_word)  # (Batch, embedding_dim)
        logits = self.linear(embedded)
        return logits 

Negative sameple

提出动机:每次模型训练都需要计算所有词向量的损失,通过只更新负样本的权重,避免整个词汇表的计算

​ Word2Vec模型本质是一个多分类问题,最后需要通过softmax激活函数判断哪一个单词的概率最大,因此需要计算所有单词的概率大小。而负采样优化是指将原来的任务退化为二分类问题,只对正负样本进行判断,在词汇表随机选取NnegN_{neg}个样本作为负样本集合。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。