突破词向量困境:从One-Hot到分布式表示的进化之路

突破词向量困境:从One-Hot到分布式表示的进化之路

【免费下载链接】nn-zero-to-hero Neural Networks: Zero to Hero 【免费下载链接】nn-zero-to-hero 项目地址: https://gitcode.com/GitHub_Trending/nn/nn-zero-to-hero

你是否还在为文本数据难以被计算机理解而烦恼?是否遇到过One-Hot编码(独热编码)导致的维度灾难问题?本文将通过GitHub_Trending/nn/nn-zero-to-hero项目中的实践案例,带你一步步掌握词嵌入(Word Embedding)技术,彻底解决文本表示难题。读完本文后,你将能够:理解One-Hot编码的局限性、掌握分布式表示的核心原理、通过PyTorch实现简单的词嵌入模型、运用lectures/makemore/makemore_part2_mlp.ipynb中的方法优化嵌入效果。

One-Hot编码:简单却低效的文本表示

在自然语言处理(NLP)领域,计算机无法直接理解文本字符,需要将其转换为数值形式。One-Hot编码是最基础的方法之一,它为每个字符分配一个唯一的索引,并用只有一个1其余全0的向量表示该字符。

lectures/makemore/makemore_part1_bigrams.ipynb中,我们可以看到这种编码方式的实现:

# 构建字符到索引的映射
chars = sorted(list(set(''.join(words))))
stoi = {s:i+1 for i,s in enumerate(chars)}
stoi['.'] = 0  # 句点作为特殊字符表示起始和结束
itos = {i:s for s,i in stoi.items()}

这种方法的优点是简单直观,但存在严重缺陷:假设词汇表大小为V,每个向量的维度就是V,当V很大时(如包含上万个单词),会导致维度灾难。同时,One-Hot向量之间是正交的,无法表示词语间的语义关联,例如"君主"和"女性君主"在One-Hot表示中没有任何相似性。

分布式表示:让词语拥有语义

分布式表示(Distributed Representation)通过低维稠密向量来表示词语,向量的每个维度都承载了一定的语义信息。这种方法能够:大幅降低维度、捕捉词语间的语义相似性、通过向量运算实现语义推理(如"君主-男性+女性=女性君主")。

lectures/makemore/makemore_part2_mlp.ipynb中,项目使用了一个27×2的嵌入矩阵将字符映射到2维空间:

# 初始化嵌入矩阵:27个字符,每个字符用2维向量表示
C = torch.randn((27, 2))

这个嵌入矩阵就是分布式表示的核心。通过训练,相似的字符会在向量空间中聚集在一起。例如,元音字母可能会被映射到空间的某一区域,而辅音字母则聚集在另一区域。

从理论到实践:实现简易词嵌入模型

下面我们将通过lectures/makemore/makemore_part2_mlp.ipynb中的代码,一步步实现从字符到嵌入向量的转换过程。

1. 数据准备

首先需要构建训练数据集,将文本转换为模型可接受的输入格式:

block_size = 3  # 上下文长度:用前3个字符预测下一个字符
X, Y = [], []
for w in words:
    context = [0] * block_size  # 初始上下文用0填充(对应'.'字符)
    for ch in w + '.':
        ix = stoi[ch]
        X.append(context)
        Y.append(ix)
        context = context[1:] + [ix]  # 滑动窗口更新上下文

X = torch.tensor(X)
Y = torch.tensor(Y)

2. 嵌入层实现

使用PyTorch的张量索引实现嵌入层,这是整个模型中最关键的部分:

# 初始化嵌入矩阵:27个字符,每个字符用10维向量表示
g = torch.Generator().manual_seed(2147483647)  # 固定随机种子以确保可复现性
C = torch.randn((27, 10), generator=g)

# 将输入的字符索引转换为嵌入向量
emb = C[X]  # 形状:(样本数, block_size, 嵌入维度) -> (32, 3, 10)

3. 构建神经网络

添加简单的神经网络层来学习字符间的依赖关系,从而优化嵌入向量:

# 第一层:线性变换 + tanh激活函数
W1 = torch.randn((30, 200), generator=g)  # 30 = 3*10 (block_size * embedding_dim)
b1 = torch.randn(200, generator=g)
h = torch.tanh(emb.view(-1, 30) @ W1 + b1)  # (32, 200)

# 输出层:预测下一个字符的概率分布
W2 = torch.randn((200, 27), generator=g)
b2 = torch.randn(27, generator=g)
logits = h @ W2 + b2  # (32, 27)
loss = F.cross_entropy(logits, Y)  # 计算交叉熵损失

4. 模型训练与嵌入优化

通过反向传播更新嵌入矩阵,使相似语义的字符在向量空间中距离更近:

# 训练循环
for i in range(200000):
    # 随机采样小批量数据
    ix = torch.randint(0, Xtr.shape[0], (32,))
    
    # 前向传播
    emb = C[Xtr[ix]]  # (32, 3, 10)
    h = torch.tanh(emb.view(-1, 30) @ W1 + b1)  # (32, 200)
    logits = h @ W2 + b2  # (32, 27)
    loss = F.cross_entropy(logits, Ytr[ix])
    
    # 反向传播更新参数
    for p in parameters:
        p.grad = None
    loss.backward()
    
    # 参数更新
    lr = 0.1 if i < 100000 else 0.01  # 学习率调度
    for p in parameters:
        p.data += -lr * p.grad

可视化嵌入空间:直观理解语义关联

训练完成后,我们可以将高维嵌入向量降维到2D空间并可视化,直观地观察字符间的语义关联:

# 可视化嵌入矩阵的前两个维度
plt.figure(figsize=(8,8))
plt.scatter(C[:,0].data, C[:,1].data, s=200)
for i in range(C.shape[0]):
    plt.text(C[i,0].item(), C[i,1].item(), itos[i], ha="center", va="center", color='white')
plt.grid('minor')

通过这个可视化,你会发现语义相似的字符(如元音字母a、e、i、o、u)在空间中会聚集在一起,而这种聚集是模型通过数据自动学习到的,无需人工标注。

进阶探索:优化嵌入质量的实用技巧

要进一步提升嵌入质量,可以尝试以下方法,这些技巧在lectures/makemore/makemore_part3_bn.ipynblectures/makemore/makemore_part4_backprop.ipynblectures/makemore/makemore_part5_cnn1.ipynb中都有详细探讨:

  1. 增加嵌入维度:将嵌入维度从10增加到更高维度(如24维)可以捕捉更丰富的语义信息:
n_embd = 24  # 字符嵌入向量的维度
C = torch.randn((27, n_embd), generator=g)
  1. 使用批归一化:在网络层之间添加批归一化可以加速训练并提高稳定性:
# 在隐藏层后添加批归一化层
h = torch.tanh(emb.view(-1, 30) @ W1 + b1)
h = bn(h)  # 批归一化
  1. 深度神经网络:增加网络层数可以学习更复杂的语义模式:
# 添加额外的隐藏层
W3 = torch.randn((200, 100), generator=g)
b3 = torch.randn(100, generator=g)
h = torch.tanh(h @ W3 + b3)
  1. 卷积神经网络:对于序列数据,卷积层可以有效捕捉局部特征:
# 使用卷积层处理嵌入序列
conv = torch.nn.Conv1d(in_channels=10, out_channels=32, kernel_size=3)
h = conv(emb.permute(0, 2, 1))  # 调整维度以适应卷积操作

总结与展望

本文通过GitHub_Trending/nn/nn-zero-to-hero项目中的lectures/makemore/系列教程,详细介绍了词嵌入技术从理论到实践的完整过程。我们从One-Hot编码的局限性出发,逐步过渡到分布式表示的核心思想,最终通过PyTorch实现了一个简易但有效的词嵌入模型。

词嵌入技术是现代NLP的基础,它不仅解决了文本表示问题,更为后续的文本分类、情感分析、机器翻译等任务提供了高质量的输入特征。随着深度学习的发展,词嵌入技术也在不断进化,从Word2Vec、GloVe到BERT等预训练语言模型的词嵌入,模型的表达能力越来越强。

建议读者进一步深入学习lectures/makemore/makemore_part3_bn.ipynb中的批归一化技术和lectures/makemore/makemore_part5_cnn1.ipynb中的卷积神经网络应用,探索如何将词嵌入与更复杂的网络结构结合,以获得更好的文本表示效果。

希望本文能够帮助你彻底理解词嵌入技术,并在实际项目中灵活应用。如果你对文章内容有任何疑问或建议,欢迎在项目仓库中提交issue,让我们一起完善这个教程。记住,好的文本表示是NLP任务成功的关键第一步,掌握词嵌入技术将为你的NLP之旅打下坚实基础。

【免费下载链接】nn-zero-to-hero Neural Networks: Zero to Hero 【免费下载链接】nn-zero-to-hero 项目地址: https://gitcode.com/GitHub_Trending/nn/nn-zero-to-hero

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值