一文读懂词向量Word2Vec及Python实现
Word2Vec 简介
Word2Vec 是一个流行的词嵌入算法,由 Tomas Mikolov 和他的团队在 2013 年提出。它的主要目的是将每个单词映射到固定大小的向量,这些向量能够捕捉单词之间的语义关系。
我们通过一个简单的例子来解释这句话。
假设你有以下句子:
"狗喜欢玩球。" "猫喜欢爬树。" "狗和猫都是宠物。" "足球是一种流行的运动。"
现在,当我们使用 Word2Vec 算法训练这些句子时,我们会得到每个单词的向量表示。这些向量不是随机的数字,而是捕捉了单词之间的语义关系。例如:
“狗”和“猫”的向量可能会很接近,因为它们都被描述为“宠物”。 而“玩球”和“足球”之间也可能有某种关系,因为它们都与“球”这个概念有关。 同时,“玩球”和“爬树”之间的关系可能就不那么紧密,因为它们描述的是完全不同的活动。这意味着,如果我们查看“狗”的向量与其他所有单词的向量之间的相似性,我们可能会发现“猫”是最相似的,而“爬树”可能是最不相似的。
在数学上,这种“相似性”通常通过计算向量之间的余弦相似度来量化。
余弦相似度用于度量两个向量的夹角的余弦值,以此作为两个向量之间的相似度。公式如下:
其中:
和 是两个向量。 表示 和 的点积。 和 分别表示 和 的模长(也叫做范数),它们的计算方法是取向量的每个元 素的平方,然后求和,再取平方根。余弦相似度的值范围在 之间,其中 1 表示两个向量完全相似,0 表示两个向量完全不 相关,而 - 1 表示两个向量完全相反。
具有高余弦相似度的两个向量表示它们在语义上很接近。
这正是 Word2Vec 能够实现的:通过学习文本中的上下文,为每个单词生成一个向量,这个向量能够捕捉与其他单词的语义关系。
Word2Vec 的工作原理
Word2Vec 的训练基于两种主要的架构:CBOW (Continuous Bag of Words) 和 Skip-Gram。
CBOW (连续词袋模型):
它预测目标单词 (中心词) 基于其上下文 (周围的词) 。换句话说,它使用上下文来预测 目标单词。 输入层: 上下文词的 one-hot 编码。 输出层: 目标单词的概率分布。
在 CBOW 中,根据上下文词(例如 ) 预测目标 词 的概率。给定一个上下文 , 目标词 的概率为:
其中:
是目标词 的输出向量。 是上下文的嵌入向量,通常是上下文词嵌入向量的平均值。 是词汇表大小。
Skip-Gram:
它的工作方式与 CBOW 相反。它试图使用目标单词来预测其上下文。 输入层: 目标单词的 one-hot 编码。 输出层: 上下文词的概率分布。
与 CBOW 相反,Skip-Gram 试图从目标词预测上下文。对于每个上下文词 (其中 的概率为:
其中:
是上下文词 的输出向量。 是目标词 的输入向量。 是词汇表大小。
神经网络架构:
Word2Vec 使用浅层的神经网络,通常只有一层隐藏层。该网络可以是基于上述两种架构之一进行训练的。在训练过程结束后,权重从输入层到隐藏层被用作单词的向量表示。
训统过程:
初始值: 开始时,模型的权重是随机的,每个单词都有一个随机的向量表示。 滑动窗口:选择一个窗口大小,然后在文本中滑动这个窗口,每次滑动都提取目标词和其上 下文词,并基于选择的架构(CBOW 或Skip-Gram)进行训练。 优化: 使用 softmax 函数来计算输出词的概率分布,并使用反向传播和梯度下降来优化权重,使误差最小化。 抽取词向量:训练结束后,从输入到隐藏层的权重被用作词的向量表示。
负采样:
由于 softmax 函数需要考虑词汇表中的每个单词,因此计算成本会非常高。为了解决这个问题,Word2Vec 使用了一种称为 "负采样" 的技术。在这种方法中,而不是更新所有单词的权 重,它只更新正样本和一小部分随机选择的负样本的权重。
让我们定义一个正样本为 ,其对应的损失为:
其中:
是 Sigmoid 函数。 是词 被选为负样本的概率。
经过训练,语义上相似或相关的词在向量空间中会靠得很近。例如,"king" 和 "queen" 之间的关系可以通过向量算术来捕获,如:king - man + woman ≈ queen。
Word2Vec 使用上下文信息,通过浅层神经网络训练,为每个单词提供了一个密集的向量表示,这些向量能够捕捉单词的语义和句法关系。
Python实现
gensim 库可以非常简便地训练 Word2Vec 模型。以下是使用 gensim 训练 Word2Vec Skip-Gram 模型的步骤:
安装 gensim:
pip install gensim
使用 gensim 训练 Word2Vec:
from gensim.models import Word2Vec
import logging
# 为了显示训练日志
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
# 示例句子
sentences = [
"I love machine learning",
"Machine learning is fascinating",
"Deep learning and machine learning are both subsets of AI"
]
# Tokenization
sentences = [sentence.split() for sentence in sentences]
# 训练 Word2Vec 模型
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, workers=4, sg=1) # sg=1 表示使用 Skip-Gram; 若为0则使用 CBOW
# 保存模型
model.save("word2vec_example.model")
使用模型: 加载模型并查询相似的词:
# 加载模型
model = Word2Vec.load("word2vec_example.model")
# 查找与 "machine" 最相似的词
similar_words = model.wv.most_similar("machine", topn=5)
print(similar_words)
你也可以直接获取某个词的向量:
vector = model.wv['machine']
print(vector)
以上就是使用 gensim 进行 Word2Vec 训练的简化示例。请注意,为了得到有意义的词向量,你需要一个大型的语料库。这里只是为了展示如何使用库而提供的小型示例,感兴趣的朋友可以使用自己的或公开的语料库进行训练。