Pytorch中的torch.nn.Embedding()

本文详细介绍了PyTorch中的torch.nn.Embedding模块,这是一个用于存储固定大小词嵌入的查找表。该模块接受词索引作为输入,返回对应的词嵌入向量。在示例中展示了如何创建和使用Embedding层,并解释了padding_idx参数的作用,即不更新指定索引的嵌入向量。此外,文章还提及Transformer中词向量乘以平方根的模型维度的原因,但作者认为这一操作的实际效果有待商榷。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Pytorch中的torch.nn.Embedding()

torch.nn.Embedding

介绍:

  1. 一个简单的查找表(lookup table),存储固定字典和大小的词嵌入。当然,Embedding()的作用不一定是针对单词嵌入,也可以应付推荐系统中用户和商品的嵌入。
  2. 此模块通常用于存储单词嵌入并使用索引检索它们(类似数组)。模块的输入是一个索引列表,输出是相应的词嵌入

例子代码1

import torch
import torch.nn as nn
# 创建10个维度大小为3的嵌入向量
embedding=nn.Embedding(10,3)
input=torch.LongTensor([[1,2,4],[4,3,2]])  # 索引列表
print(embedding(input))   # 通过索引列表获取相应索引的嵌入向量
tensor([[[-0.5383,  0.0499, -0.7475],
         [ 0.9555,  0.2302, -0.1948],
         [-0.9377, -0.2700,  0.1331]],

        [[-0.9377, -0.2700,  0.1331],
         [ 0.3063, -0.8556, -0.1219],
         [ 0.9555,  0.2302, -0.1948]]], grad_fn=<EmbeddingBackward>)

如果从词向量的角度来看可以有下面解释:

第一个参数是字的总数,第二个参数是字的向量表示的维度。

我们的输入input是两个句子,每个句子都是由四个字组成的,使用每个字的索引来表示,于是使用nn.Embedding对输入进行编码,每个字都会编码成长度为3的向量。

例子代码2

"""
padding_idx(int,可选):如果指定,则 `padding_idx` 处的条目对梯度没有贡献;
因此,在训练期间不会更新`padding_idx`索引的嵌入向量,即它仍然是一个固定的“pad”(填充)。
一般设置为0,因为这样就可以使索引从1开始计算了
"""

padding_idx = 0
embedding = nn.Embedding(10, 3, padding_idx=padding_idx)  #

input = torch.LongTensor([0, 0, 1, 1, 2, 2, 5])
print(embedding(input))
tensor([[ 0.0000,  0.0000,  0.0000],
        [ 0.0000,  0.0000,  0.0000],
        [ 0.3913,  0.1981, -0.4038],
        [ 0.3913,  0.1981, -0.4038],
        [-1.0189,  0.3309,  0.2123],
        [-1.0189,  0.3309,  0.2123],
        [ 1.1989, -0.4495, -0.6550]], grad_fn=<EmbeddingBackward>)
# 索引0的向量全是0, 不参与训练

我是因为看了一下Transformer的代码才查询了这个API,下面是他的Embeddings

我是看到Transformer 的词向量后面还要乘以math.sqrt(self.d_model)感到很奇怪,所以查询了一下

class Embeddings(nn.Module):
  def __init__(self,d_model,vocab):
    #d_model=512 嵌入维度, vocab=当前语言的词表大小
    super(Embeddings,self).__init__()
    self.lut=nn.Embedding(vocab,d_model) 
    # one-hot转词嵌入,这里有一个待训练的矩阵E,大小是vocab*d_model
    self.d_model=d_model # 512
  def forward(self,x): 
     # x ~ (batch.size, sequence.length, one-hot), 
     #one-hot大小=vocab,当前语言的词表大小
     return self.lut(x)*math.sqrt(self.d_model) 
     # 得到的10*512词嵌入矩阵,主动乘以sqrt(512)=22.6,
     #这里我做了一些对比,感觉这个乘以sqrt(512)没啥用… 求反驳。
     #这里的输出的tensor大小类似于(batch.size, sequence.length, 512)
### 如何在PyTorch中使用`nn.Embedding` #### 创建嵌入层 为了创建一个嵌入层,在 PyTorch 中可以利用 `torch.nn.Embedding` 类。此方法允许指定词汇表大小以及每个词所需的维度数,即嵌入尺寸。这有助于将离散的数据转换成稠密的向量形式[^1]。 ```python import torch from torch import nn vocab_size = 1000 # 假设词汇表中有1000个不同的词语 embedding_dim = 32 # 设定每个词被表示为长度为32的向量 embedding_layer = nn.Embedding(vocab_size, embedding_dim) ``` #### 输入与输出形状 当给定了索引列表作为输入时,这些整数值代表了来自预定义词汇表的位置。通过调用上述构建好的嵌入对象,并传入张量形式的一批索引,即可获得相应位置上词项所对应的学习到的向量表达。值得注意的是,输入应该是一维或多维 LongTensor 或者是自动转换为此类型的其他类型;而输出将会保持相同的前置维度结构不变,仅在其最后增加了一个由设定参数决定的新轴——也就是所谓的“通道”,其大小等于之前设置过的嵌入维度[^3]。 ```python input_indices = torch.LongTensor([1, 2, 4, 5]) # 示例性的四个词的索引 embedded_output = embedding_layer(input_indices) print(f"Input shape: {input_indices.shape}") print(f"Output shape after embedding: {embedded_output.shape}") ``` #### 训练过程中的更新机制 默认情况下,`nn.Embedding` 的权重矩阵是可以参与反向传播过程中梯度计算并随之调整优化的一部分。这意味着随着模型整体性能提升的同时也会不断改进对于各个具体类别/单词的最佳低维空间定位方式[^4]。 ```python criterion = nn.MSELoss() optimizer = torch.optim.SGD(embedding_layer.parameters(), lr=0.01) target = torch.randn(4, embedding_dim) # 随机生成目标值用于演示目的 output = embedding_layer(input_indices) loss = criterion(output, target) loss.backward() optimizer.step() # 更新参数 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值