Transformer_PositionalEncoding学习

这篇文章,主要是自己学习的一个记录,如果不自己写下来,之前搞懂的东西,很快也会忘掉。还是得踏踏实实的慢慢来啊(🐷)

下面的是transformer中的encoding的代码的一部分,这部分代码加上了位置编码,利用sin和cos来巧妙的表示位置信息。

这里为什么说是巧妙呢?

因为位置信息可以随着输入文本的长度变得很长,如果只用1234这样的顺序,很难有效表示位置关系。

而利用sin和cos,可以表示非常多的位置关系。为了能表示更多的位置关系,这里将sin和cos中除以10000。

torch.squeeze()详解

代码如下

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, dropout=0.1, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)
		
        pe = torch.zeros(max_len, d_model)
        #生成0向量,生成矩阵pe[max_len, d_model]
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        #torch.arange(0, max_len)生成张量维度为(max_len,),可以看作是一个包含max_len个元素的行向量,
        #unsqueeze(1)表示在维度=1的地方插入一个新的维度
        #torch.squeeze()表示对数据维度进行压缩,去掉维数为1的维度,比如一行或者一列这种。squeeze(a)表示将
        #a中所有为1的维度删除,不为1的维度没有影响
        #torch.unsqueeze(a,N)表示在a中指定位置N加上一个维数为1的维度
        print(torch.arange(0, max_len, dtype=torch.float))
        
        print(position)
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
        #torch.arange(0, d_model, 2)这一步表示生成一个0-d_model维度的张量,然后以步长为2递增赋值
        print(position.shape)
        print(div_term.shape)
        pe[:, 0::2] = torch.sin(position * div_term)
        #对pe[:, 0::2]用法做出解释。:在切片中表示对整个轴进行选择,[:,...]表示对所有行进行选择
        #...表示可以有任意数量的维度;0::2是对列进行选择的部分,0表示从第0行开始,2表示以步长为2进行选择
        pe[:, 1::2] = torch.cos(position * div_term)
        #这里position[max_len,1],div_term[model/2,]这里利用广播机制
        #(即每个张量复制之前存在的元素然后进行维度扩展),position*div_term.shape=[max_len,model/2]
        pe = pe.unsqueeze(0).transpose(0, 1)
        #这里,给第0维加入维度,然后将0和1维进行交换
        self.register_buffer('pe', pe)
        #将pe注册为模型的缓冲区

    def forward(self, x):
        """
        x: [seq_len, batch_size, d_model]
        """
        x = x + self.pe[:x.size(0), :]
		#将张量和位置编码相加,即加入位置信息
		
        return self.dropout(x)

将 pe 注册为模型的缓冲区有以下作用:

  1. 保持状态:通过将 pe 注册为模型的缓冲区,它会被保存在模型的状态中。这意味着在训练过程中,每次前向传播时都可以使用相同的位置编码,而不必重新计算或传递它。
  2. 共享内存:注册为缓冲区后,pe 可以在模型的不同方法之间共享内存。这对于需要在多个方法中使用的常量、权重或其他参数非常有用。
  3. 参数持久化:当保存和加载模型时,注册为缓冲区的内容也会被自动保存和加载。这确保了在重新加载模型后,缓冲区的内容仍然是一致的。
    总之,通过将 pe 注册为模型的缓冲区,我们可以方便地使用和管理位置编码,并使其成为模型的一部分,而不必手动传递它或重新计算它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值