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 进行词向量可视化
增加负采样,提升模型训练效率

相关推荐
纠结哥_Shrek12 分钟前
pytorch实现变分自编码器
人工智能·pytorch·python
程序喵;21 分钟前
Retrieval-Augmented Generation for Large Language Models: A Survey——(1)Overview
论文阅读·人工智能·语言模型·自然语言处理·rag
海思开发板总店33 分钟前
openRv1126 AI算法部署实战之——Tensorflow模型部署实战
人工智能·算法·tensorflow
zyhhsss37 分钟前
AI(计算机视觉)自学路线
人工智能·笔记·学习·计算机网络·机器学习·计算机视觉
AI浩1 小时前
【Block总结】SCSA,探索空间与通道注意力之间的协同效应|即插即用
人工智能·目标检测·计算机视觉
汤姆和佩琦1 小时前
2025-1-28-sklearn学习(47) & (48) 万家灯火亮年至,一声烟花开新来。
人工智能·python·学习·机器学习·sklearn
985小水博一枚呀1 小时前
【论文推荐|深度学习,滑坡检测,多光谱影像,自然灾害,遥感】2022年Landslide4Sense竞赛成果:基于多源卫星影像的先进滑坡检测算法研究(五)
大数据·人工智能·深度学习·算法·cnn
狗狗显卡1 小时前
ai翻唱入门
人工智能
上海迪士尼352 小时前
RRT_STAR路径规划代码
人工智能·算法·matlab