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() 进行分词
  • 创建 word2idxidx2word
  • 使用滑动窗口生成 (中心词, 上下文词) 训练样本
  • 实现 negative_sampling() 提高训练效率
模型
  • Embedding 学习词向量
  • Linear 计算单词的概率分布
  • CrossEntropyLoss 计算目标词与预测词的匹配度
  • 使用 Adam 进行梯度更新
计算词相似度
  • 使用 cosine_similarity 计算词向量相似度
  • 找出 top_n 个最相似的单词

5. 可优化点

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

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

相关推荐
AIGC方案25 分钟前
deepseek热度已过?
人工智能·大模型
88号技师26 分钟前
模糊斜率熵Fuzzy Slope entropy+状态分类识别!2024年11月新作登上IEEE Trans顶刊
人工智能·机器学习·分类·数据挖掘·信号处理·故障诊断·信息熵
死磕代码程序媛1 小时前
谷歌25年春季新课:15小时速成机器学习
人工智能·机器学习
有Li1 小时前
弥合多层次差距:用于超声心动图中基于文本引导的标签高效分割的双向循环框架|文献速递-深度学习医疗AI最新文献
人工智能
橙色小博1 小时前
Transformer模型解析与实例:搭建一个自己的预测语言模型
人工智能·深度学习·神经网络·机器学习·transformer
意.远2 小时前
PyTorch实现二维卷积与边缘检测:从原理到实战
人工智能·pytorch·python·深度学习·神经网络·计算机视觉
电报号dapp1192 小时前
2025年智能合约玩法创新白皮书:九大核心模块与收益模型重构Web3经济范式
人工智能·重构·web3·去中心化·区块链·智能合约
三道杠卷胡3 小时前
【AI News | 20250411】每日AI进展
人工智能·python·计算机视觉·语言模型·aigc
汪子熙3 小时前
利用 Trae 开发平面直角坐标系的教学动画
人工智能·trae
区块链蓝海3 小时前
Cables 现已正式启动积分计划 Alpha 阶段,开放早期白名单申请
人工智能·区块链