pytorch实现基于Word2Vec的词嵌入

PyTorch 实现 Word2Vec(Skip-gram 模型) 的完整代码,使用 中文语料 进行训练,包括数据预处理、模型定义、训练和测试。


1. 主要特点

支持中文数据 ,基于 jieba 进行分词
使用 Skip-gram 进行训练 ,适用于小数据集
支持负采样 ,提升训练效率
使用 cosine similarity 计算相似单词

完整代码:

复制代码
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import random
import jieba
from collections import Counter
from sklearn.metrics.pairwise import cosine_similarity

# ========== 1. 数据预处理 ==========
corpus = [
    "我们 喜欢 深度 学习",
    "自然 语言 处理 是 有趣 的",
    "人工智能 改变 了 世界",
    "深度 学习 是 人工智能 的 重要 组成部分"
]

# 超参数
window_size = 2      # 窗口大小
embedding_dim = 10   # 词向量维度
num_epochs = 100     # 训练轮数
learning_rate = 0.01 # 学习率
batch_size = 4       # 批大小
neg_samples = 5      # 负采样个数

# 分词 & 构建词汇表
tokenized_corpus = [list(jieba.cut(sentence)) for sentence in corpus]
vocab = set(word for sentence in tokenized_corpus for word in sentence)
word2idx = {word: idx for idx, word in enumerate(vocab)}
idx2word = {idx: word for word, idx in word2idx.items()}

# 统计词频
word_counts = Counter([word for sentence in tokenized_corpus for word in sentence])
total_words = sum(word_counts.values())

# 计算负采样概率
word_freqs = {word: count / total_words for word, count in word_counts.items()}
word_powers = {word: freq ** 0.75 for word, freq in word_freqs.items()}
Z = sum(word_powers.values())
word_distribution = {word: prob / Z for word, prob in word_powers.items()}

# 负采样函数
def negative_sampling(positive_word, num_samples=5):
    words = list(word_distribution.keys())
    probabilities = list(word_distribution.values())
    negatives = []
    while len(negatives) < num_samples:
        neg = np.random.choice(words, p=probabilities)
        if neg != positive_word:
            negatives.append(neg)
    return negatives

# 生成 Skip-gram 训练数据
data = []
for sentence in tokenized_corpus:
    indices = [word2idx[word] for word in sentence]
    for center_idx in range(len(indices)):
        center_word = indices[center_idx]
        for offset in range(-window_size, window_size + 1):
            context_idx = center_idx + offset
            if 0 <= context_idx < len(indices) and context_idx != center_idx:
                context_word = indices[context_idx]
                data.append((center_word, context_word))

# 转换为 PyTorch 张量
data = [(torch.tensor(center), torch.tensor(context)) for center, context in data]

# ========== 2. 定义 Word2Vec (Skip-gram) 模型 ==========
class Word2Vec(nn.Module):
    def __init__(self, vocab_size, embedding_dim):
        super(Word2Vec, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.output_layer = nn.Linear(embedding_dim, vocab_size)

    def forward(self, center_word):
        embed = self.embedding(center_word)  # 获取中心词向量
        out = self.output_layer(embed)       # 计算词分布
        return out

# 初始化模型
model = Word2Vec(len(vocab), embedding_dim)

# ========== 3. 训练 Word2Vec ==========
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

for epoch in range(num_epochs):
    total_loss = 0
    random.shuffle(data)  # 每轮打乱数据
    for center_word, context_word in data:
        optimizer.zero_grad()
        output = model(center_word.unsqueeze(0))  # 预测词分布
        loss = criterion(output, context_word.unsqueeze(0))  # 计算损失
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    
    if (epoch + 1) % 10 == 0:
        print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {total_loss:.4f}")

# ========== 4. 测试词向量 ==========
word_vectors = model.embedding.weight.data.numpy()

# 计算单词相似度
def most_similar(word, top_n=3):
    if word not in word2idx:
        return "单词不在词汇表中"
    
    word_vec = word_vectors[word2idx[word]].reshape(1, -1)
    similarities = cosine_similarity(word_vec, word_vectors)[0]
    
    # 获取相似度最高的 top_n 个单词(排除自身)
    similar_idx = similarities.argsort()[::-1][1:top_n+1]
    return [(idx2word[idx], similarities[idx]) for idx in similar_idx]

# 测试相似词
test_words = ["深度", "学习", "人工智能"]
for word in test_words:
    print(f"【{word}】的相似单词:", most_similar(word))
数据预处理
  • 使用 jieba.cut() 进行分词
  • 创建 word2idx 和 idx2word
  • 使用滑动窗口生成 (中心词, 上下文词) 训练样本
  • 实现 negative_sampling() 提高训练效率
模型
  • Embedding 层 学习词向量
  • Linear 层 计算单词的概率分布
  • CrossEntropyLoss 计算目标词与预测词的匹配度
  • 使用 Adam 进行梯度更新
计算词相似度
  • 使用 cosine_similarity 计算词向量相似度
  • 找出 top_n 个最相似的单词

5. 可优化点

使用更大的中文语料库 (如 THUCNews)

使用 t-SNE 进行词向量可视化
增加负采样,提升模型训练效率

相关推荐
回眸&啤酒鸭5 天前
【回眸】Minicart 电商购物车核心功能落地指南
人工智能
一隅论数智5 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
AI的探索之旅5 天前
97 个 OpenCV 实例(三十):双目立体,从标定到点云
人工智能·opencv·计算机视觉
AlbertZein5 天前
Step-5-Preview 上手实测:3D 游戏、金融分析、网页设计一次跑完
人工智能·aigc
LaughingZhu5 天前
Product Hunt 每日热榜 | 2026-09-19
人工智能·深度学习·神经网络·搜索引擎·百度
美狐美颜SDK开放平台6 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
wukangjupingbb6 天前
智能网联汽车安全能力框架
人工智能
风合星语6 天前
2026 具身智能技术实战(一):VLA 到底怎么控制机器人?——用 LeRobot 跑通 SmolVLA 推理
pytorch·机器人·具身智能·vla·lerobot·smolvla
龙亘川6 天前
明月照湾区,智启新赛道:从顶流文旅IP盛会看智慧文旅升级路径
人工智能·智慧城市·开源软件·数据可视化