PyTorch深度学习实战 |词嵌入和位置编码

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 本文介绍了PyTorch中词嵌入(Embedding)和位置编码(Positional Encoding)的实现与应用。词嵌入通过Word2Vec、GloVe等技术将单词转换为连续向量,其中使用nn.Embedding层加载预训练词向量,并展示如何可视化词向量间的语义关系(如"king-man≈queen-woman")。位置编码部分详细解释了如何通过正弦/余弦函数为词向量添加位置信息,包含公式推导和代码实现(PositionalEncoding类)。文章提供了完整的PyTorch代码示

 词嵌入

 引入    

   只要是使用深度学习模型处理 NLP 问题:在模型中就需要添加,Embedding 层。比如在

Transformers 中的左下角和右下角就有两个词嵌入层。

image.gif

Embedding层负责将离散的单词数据转换称连续且固定长度的向量,简单来说:

词向量:用一个d维空间的向量表示一个词

词嵌入:就是将一个词嵌入到一个特定的向量空间

image.gif

如果我们想把一句话,作为神经网络的输入,比如Are you OK? 神经网络是没有办法直接处理这个

文本的,我们需要先将Are you OK?基于词表vocab转换称整数索引序列的形式,例如转换称【1,

2,3,4】,然后再基于Embedding层,将整数索引序列转换成单词向量的序列,这里假设每个单

词用4维的向量表示,那么4个词的句子Are you OK? 就会被转换为 4×4 的词向量矩阵。每行对应

一个单词。得到输入文本的向量矩阵后,才可以使用神经网络对文本进行特征提取和处理。

image.gif

下面我们会从3个方面解释词嵌入 (Embedding) 技术

(1)词嵌入的作用 (2)嵌入矩阵的计算 (3)Embedding 层的使用

词嵌入的作用

      词嵌入是一种将词汇表中的词或短语映射为固定长度向量的技术我们可以将高维且稀疏的单词

索引转为低维且连续的向量转换后的连续向量可以表示出单词与单词之间的语义关系。此时我们使

用词嵌入技术,就可以把4个高纬稀疏的的向量,转换成4个低纬连续的向量,转换后的向量,每个

维度都是一个浮点数,这里我们就把向量映射到一个7维的空间中。

image.gif

为了进一步表示词与词之间的关系,我们可以把词向量,基于降维算法,降成2维,从而使单词向

量在平面上绘制出来。此时就会发现语义相近的词语在向量空间中距离相近。词嵌入可通过向量的

数学运算体现词语的语义关联,例如:向量(“king”) - 向量(“man”) ≈ 向量(“queen”) - 向量

(“woman”)。词嵌入技术的核心价值:将自然语言中的词语转换为数值向量,并通过向量体现词

语间的语义关系;为机器翻译、文本分类、语义检索等高级 NLP 任务提供基础支撑。

image.gif

嵌入矩阵

为了实现词嵌入,我们会使用特定的词嵌入算法,例如通过 Word2Vec、FastText、GloVe 等词嵌

入算法,训练得到一个通用的嵌入矩阵,该矩阵即为模型中的 Embedding 层。具体来说嵌入矩阵

的行就是语料库中词语的个数,嵌入矩阵的列表示词语的维度。设词表中包括5000个单词,每个

单词用一个128维的向量表示。我们将嵌入矩阵用E来表示。

image.gif

嵌入矩阵的使用方法有两种形式:

基于矩阵相乘:将单词的独热编码向量与嵌入矩阵相乘,得到对应的词向量(本质是矩阵乘法实现

的映射)。

基于索引查找:直接通过单词在词汇表中的索引,从嵌入矩阵中提取对应的行向量(是实际工程中

更高效的常用方式)。

比如我们对Are you OK? 这句话进行编码,每个词是一个5000维的向量,整个句子是一个4*5000

矩阵我们将该矩阵记作V。然后我们把独热编码矩阵和嵌入矩阵相乘,就得到句子的嵌入向量矩

阵。

image.gif

另一种方式是索引查找,句子中的每个词都对应着,词表中的一个整数索引,然后我们直接获取索

引在嵌入句子对应的行就好了。

image.gif

Embedding 层的使用

下面我们会使用torch.nn来创建一个Embedding 层,并使用这个Embedding 层计算单词的词向

量,并实现可视化。

from torchtext.vocab import import GloVe  # 导入GloVe词向量
# 简单介绍
# GloVe词向量,它是斯坦福大学的研究者在2014年开发和发布的
# GloVe和word2vec与fasttext,是当前最常用的3个词向量版本
# 6B表示了模型是基于60 亿个单词的语料库训练的
# 300表示一个单词,使用300维的向量表示
glove = GloVe(name='6B', dim=300)

image.gif

import torch
from torch import nn
# 使用nn.Embedding创建词嵌入层
# 将glove.vectors,通过from_pretrained接口,导入到Embedding层中
# 此时的embedding层,就载入了GloVe词向量数据
embedding = nn.Embedding.from_pretrained(glove.vectors)
# 打印embedding层中的weight的尺寸
print(f"embedding.shape: {embedding.weight.shape}")

image.gif

程序输出:embedding.shape: torch.Size([400000, 300])表示 Embedding 层的权重矩阵尺寸为

“400000 个单词 × 300 维向量”,对应 GloVe 预训练词向量的词汇量与维度。

# 将man、woman、king、queen等8个词语的词向量,绘制到二维平面上
words = ['man', 'woman', 'king', 'queen', 'cat', 'dog', 'mother', 'father']
indices = []
for word in words:
    # 将单词word,通过glove的词汇表,转换为单词的索引
    index = glove.stoi[word]
    # 将这些索引保存到indices数组中
    indices.append(index)
    # 打印单词word和索引index的对应关系
    print(f"{word} -> {index}")

image.gif

程序输出:man -> 300 woman -> 787 king -> 691 queen -> 2060 cat -> 5450 dog -> 2926 mother

-> 808 father -> 629

# 将索引列表,使用torch.tensor,转为张量的形式
indices = torch.tensor(indices)
# 将索引列表转换为,词向量的矩阵
vectors = embedding(indices).detach().numpy()
# 打印vector的尺寸
print(f"vectors.shape: {vectors.shape}")

image.gif

程序输出:vectors.shape: (8, 300)这段代码的核心是从 Embedding 层中提取目标单词的词向量:

(8, 300)表示词向量矩阵的尺寸为 “8 个单词 × 300 维向量”,对应 8 个目标单词各自的 300 维

GloVe 词向量。

from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# 使用PCA降维算法,将向量vectors进行降维
pca = PCA(n_components=2)
vectors_2d = pca.fit_transform(vectors)
# 将单词和向量,绘制到二维平面上
plt.scatter(vectors_2d[:, 0], vectors_2d[:, 1])
for i, word in enumerate(words):
    plt.annotate(word,
                 xy=(vectors_2d[i, 0], vectors_2d[i, 1]),
                 xytext=(-10, 10),
                 textcoords='offset points')
plt.show()

image.gif

用 PCA 算法将 300 维的词向量降维至 2 维(适配二维平面展示);

通过 matplotlib 绘制降维后的向量散点图,并为每个点标注对应的单词;

完整代码

from torchtext.vocab import GloVe  # 导入GloVe词向量
# 简单介绍
# GloVe词向量,它是斯坦福大学的研究者在2014年开发和发布的
# GloVe和word2vec与fasttext,是当前最常用的3个词向量版本
# 6B表示了模型是基于60 亿个单词的语料库训练的
# 300表示一个单词,使用300维的向量表示
glove = GloVe(name='6B', dim=300)
import torch
from torch import nn
# 使用nn.Embedding创建词嵌入层
# 将glove.vectors,通过from_pretrained接口,导入到Embedding层中
# 此时的embedding层,就载入了GloVe词向量数据
embedding = nn.Embedding.from_pretrained(glove.vectors)
# 打印embedding层中的weight的尺寸
print(f"embedding.shape: {embedding.weight.shape}")
# 将man、woman、king、queen等8个词语的词向量,绘制到二维平面上
words = ['man', 'woman', 'king', 'queen', 'cat', 'dog', 'mother', 'father']
indices = []
for word in words:
    # 将单词word,通过glove的词汇表,转换为单词的索引
    index = glove.stoi[word]
    # 将这些索引保存到indices数组中
    indices.append(index)
    # 打印单词word和索引index的对应关系
    print(f"{word} -> {index}")
# 将索引列表,使用torch.tensor,转为张量的形式
indices = torch.tensor(indices)
# 将索引列表转换为,词向量的矩阵
vectors = embedding(indices).detach().numpy()
# 打印vector的尺寸
print(f"vectors.shape: {vectors.shape}")
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# 使用PCA降维算法,将向量vectors进行降维
pca = PCA(n_components=2)
vectors_2d = pca.fit_transform(vectors)
# 将单词和向量,绘制到二维平面上
plt.scatter(vectors_2d[:, 0], vectors_2d[:, 1])
for i, word in enumerate(words):
    plt.annotate(word,
                 xy=(vectors_2d[i, 0], vectors_2d[i, 1]),
                 xytext=(-10, 10),
                 textcoords='offset points')
plt.show()

image.gif


位置编码 (PositionalEncoding)

     为什么给词向量的每个维度,加上位置编码,就能给这个词向量加上位置信息呐?为什么可以

直接将词向量和位置编码相加?为什么这样的操作就是有实际意义?将正弦和余弦的常量信息,直

接加到词向量上,不会破坏词向量本身的信息吗?

image.gif

下面我们将从4个方面详细介绍位置编码,位置编码 (PositionalEncoding):(1)什么是位置编码

(2) 如何计算位置编码(3)位置编码的真正意义(4)位置编码的代码实现

什么是位置编码

     下面我们用机器翻译为例说明位置编码,待翻译英文Are you OK?会从下方的左侧位置输入,

中文标注 你好吗?会从下方的右侧位置输入,当Are you OK?和你好吗?进入到Transformer中,

会被第一个组件,词向量层处理,词向量层把单词变成词向量,“位置编码的目的是,将位置信

息‘附加’到原始的信息上。

如何计算位置编码?

d表示位置编码向量的维度,这里我们举出的例子中维度是4。

pos表示序列中的位置,比如,Are--->0,you--->1,OK--->2,?--->3

image.gif

i表示位置编码向量维度索引的一半,比如:

第0维维度,2*0=0,所以i=0,2i=0

第1维维度,2*0+1=1,所以i=1,2i=0

第2维维度,2*1=1,所以i=1,2i=2

第3维维度,2*1+1=2,所以i=1.2i=2

image.gif

        在 Transformer 模型中,词向量(Word Embeddings)的表示是通过将输入的词嵌入

(Embedding)词向量矩阵和位置编码(Positional Encoding)矩阵相加得到的。

image.gif

位置编码的意义

   位置编码 (PositionalEncoding):     增加额外的位置信息帮助模型更好地理解语言的顺序性

质,通过绝对足够充分的训练数据:使模型能够学会理解 “词向量”+“位置编码” 的复合特征最终完

成对文本的整体理解。

代码实现

(1)定义词向量矩阵

词向量矩阵(形状:[5, 4]),word_embeds

word_embeds = torch.tensor([
    [0.4002, 0.9882, 0.6261, 0.1502],  # Are
    [0.3413, 0.9284, 0.9349, 0.8958],  # you
    [0.5347, 0.2969, 0.7019, 0.6293],  # OK
    [0.8704, 0.4956, 0.3794, 0.5646]   # ?
])
print("图片中的词向量矩阵:")
print(word_embeds)

image.gif

(2)初始化位置编码模块(embed_dim=4,max_pos=5)

     [5, 4]的矩阵(5 个位置,每个位置 4 维),pos的大小是5*1的代表,位置索引,计算

embed_dim=4
max_pos=5
# 1. 生成位置索引(0到max_pos-1)
pos = torch.arange(max_pos).unsqueeze(1)  # 形状:[max_pos, 1]
print(pos)
# 2. 计算正余弦编码的频率项(公式中的10000^(2i/d_model)的倒数)
div_term = torch.exp(torch.arange(0, embed_dim, 2) * (-math.log(10000.0) / embed_dim))
print(div_term)
# 3. 初始化位置编码矩阵(全零)
pe = torch.zeros(max_pos, embed_dim)  # 形状:[max_pos, embed_dim]
print(pe)
# 4. 填充偶数维度(用正弦函数)
pe[:, 0::2] = torch.sin(pos * div_term)  # 0::2表示从0开始,步长为2的列(偶数维)
print(pe[:, 0::2])
# 5. 填充奇数维度(用余弦函数)
pe[:, 1::2] = torch.cos(pos * div_term)  # 1::2表示从1开始,步长为2的列(奇数维)
print(pe[:, 1::2])
print(pos_encoder.pe[:4])  # 取前4个位置的编码

image.gif

image.gif

(3)完整代码

import torch
import torch.nn as nn
import math
# 1. 定义位置编码模块(复用之前的实现)
class PositionalEncoding(nn.Module):
    def __init__(self, embed_dim: int, max_pos: int = 10):
        super().__init__()
        pos = torch.arange(max_pos).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, embed_dim, 2) * (-math.log(10000.0) / embed_dim))
        pe = torch.zeros(max_pos, embed_dim)
        pe[:, 0::2] = torch.sin(pos * div_term)
        pe[:, 1::2] = torch.cos(pos * div_term)
        self.register_buffer('pe', pe)
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        seq_len = x.size(0)
        return x + self.pe[:seq_len]  # 这里x是[序列长度, 词向量维度],无需批次维度
# 2. 构造图片中的词向量矩阵(形状:[5, 4])
word_embeds = torch.tensor([
    [0.4002, 0.9882, 0.6261, 0.1502],  # Are
    [0.3413, 0.9284, 0.9349, 0.8958],  # you
    [0.5347, 0.2969, 0.7019, 0.6293],  # OK
    [0.8704, 0.4956, 0.3794, 0.5646]   # ?
])
print("图片中的词向量矩阵:")
print(word_embeds)
# 3. 初始化位置编码模块(embed_dim=4,max_pos=5)
pos_encoder = PositionalEncoding(embed_dim=4, max_pos=5)
print("\n图片对应的位置编码矩阵:")
print(pos_encoder.pe[:4])  # 取前4个位置的编码
# 4. 计算“词向量 + 位置编码”的结果
output = pos_encoder(word_embeds)
print("\n最终相加结果:")
print(output)

image.gif

【1】参考:小黑黑讲AI

目录
相关文章
|
1月前
|
机器学习/深度学习 存储 人工智能
图解人工智能的数学基础(线性代数)
本文系统讲解线性代数核心概念,涵盖向量(定义、几何/坐标表示、内积)、矩阵(含义、运算、秩、逆、相似、分解)、行列式(几何意义与变换关系)、线性方程组、特征值与特征向量、二次型、向量空间及范数等,强调其在AI与神经网络中的实际应用。
283 7
|
1月前
|
机器学习/深度学习 数据挖掘 PyTorch
PyTorch深度学习实战 |手算​​FCN全卷积神经网络
本文介绍了FCN-8s语义分割网络的实现细节。首先解释了语义分割的概念及其与图像分类的区别,重点分析了FCN网络结构中的全卷积化、上采样和跳跃连接三个关键技术。全卷积化将传统CNN的全连接层改为卷积层,实现像素级分类;上采样通过双线性插值恢复特征图尺寸;跳跃连接则融合高低层特征以提升细节表现。文章详细推导了损失函数的计算过程,并提供了完整的PyTorch实现代码,包括双线性插值权重初始化、VGG16骨干网络和FCN-8s主体结构。最后通过测试验证了模型能正确输出与输入尺寸匹配的预测结果。
274 3
|
1月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch深度学习实战 |层归一化层和FeedForward
本文介绍了PyTorch深度学习中Add&Norm层和FeedForward层的实现原理。Add&Norm层由残差连接(Add)和层归一化(Norm)组成,能加速模型收敛并稳定训练。层归一化会对神经网络每层的输出进行归一化处理,文中详细展示了其计算方法和PyTorch实现代码。FeedForward层是一个两层的全连接网络,通过线性变换提取更深层次特征。文章还分析了Transformer模型中使用层归一化的原因,并提供了完整的代码实现,包括参数初始化和前向传播过程。
136 0
|
2月前
|
SQL 运维 监控
生产环境改了个配置,半小时后业务挂了——变更管理到底管什么
统计过去半年的P1/P2故障,接近4成是配置变更引发的。本文从一次连接池参数误改导致的生产事故出发,拆解最小可用的变更管理4个动作——分级、记录、通知、关联,不搞ITIL全套流程,先让变更可追溯、可关联、出了事能3分钟定位。
364 1
生产环境改了个配置,半小时后业务挂了——变更管理到底管什么
|
2月前
|
存储 人工智能 监控
Nacos Skill Registry:面向个人场景的 Skill 中心实践
构建个人 Skill 技能中心,实现多 Agent 复用与协作。
376 26
|
1月前
|
机器学习/深度学习 存储 编解码
PyTorch深度学习实战 | 手算卷积网络(Resnet-18)
ResNet-18是解决深层网络梯度消失与退化问题的经典模型,核心在于残差连接(Shortcut):让输入X直接跳跃传递,与卷积学习的残差F(X)相加(F(X)+X),实现恒等映射。其含4个stage、18层可训练层,每个BasicBlock由两个3×3卷积+BN+ReLU构成,并通过1×1卷积适配尺寸/通道差异,显著提升深层网络训练稳定性与性能。(239字)
215 2
|
1月前
|
机器学习/深度学习 算法 自动驾驶
图解强化学习 |手算DDPG
DDPG(深度确定性策略梯度)是一种面向连续动作空间的Actor-Critic强化学习算法。它采用4网络结构(Actor/Critic及其对应目标网络),结合经验回放与软更新,通过确定性策略梯度优化策略,广泛应用于机器人控制、自动驾驶等场景。(239字)
272 1
|
1月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch深度学习实战 |常见层 layer结构的实现和代码实战
本文介绍了PyTorch中常见的7种神经网络层结构及其输入输出逻辑。通过代码示例演示了全连接层(nn.Linear)、卷积层(nn.Conv2d)、LSTM层、GCN图卷积层和Transformer层的使用方法,重点讲解了各层的输入输出维度变换规则。文章以一张海绵宝宝图片为例,详细展示了图像数据的预处理流程,包括使用PIL和OpenCV两种方法读取图片并转换为PyTorch张量的过程。通过"代码+实战"的方式帮助读者理解神经网络层如何对特征进行维度变换,最终实现从原始输入到目标输出的映射
175 0
|
1月前
|
机器学习/深度学习 数据可视化 PyTorch
PyTorch深度学习实战 |语义分割基础知识
《PyTorch语义分割实战解析》摘要:本文深入探讨语义分割中的标签处理技术,对比P模式与L模式的本质区别。P模式通过调色板实现人机双重视觉效果,底层存储类别索引(0,1,2等),表面呈现彩色可视化效果。针对边缘模糊问题,提出使用255作为忽略标签(IgnoreLabel)的解决方案。文章系统梳理7大评价指标:从基础的像素准确率(PA)到综合性的mIoU和mF1,特别强调mIoU作为核心指标的重要性,其平衡各类别的特性使其成为模型性能评估的黄金标准。通过技术原理与实战经验的结合,为深度学习从业者提供了语义分
168 0
|
1月前
|
机器学习/深度学习 自然语言处理 算法
PyTorch深度学习实战 | Transformer模型初识
本文介绍了Transformer模型在机器翻译任务中的工作原理。主要内容包括:1)模型分为编码器(处理英文输入)和解码器(生成中文输出)两部分;2)推理时采用自回归模式,逐步生成翻译结果;3)训练时使用教师强制模式,始终以真实标签指导模型学习。文章详细阐述了编码器-解码器结构的工作流程,包括词嵌入、多头注意力机制等核心组件,以及如何通过残差连接和层标准化优化模型性能。最后解释了编码器和解码器三个关键计算步骤的张量维度变化过程。
190 0

热门文章

最新文章