程序员转行学习AI大模型:位置编码

原理

在前面编码器-解码器介绍中,我们发现,模型并没有记录时序相关信息,即没有感知不同词汇的位置顺序。这会引起一个问题,针对"我喜欢你"这句话,经过前面的 Embedding 处理后,再进入编码器-解码器处理,最后生成的内容,是和输入"你喜欢我"最后生成的内容是一样的,但我们知道,这两句是含义完全不一样的语句。

加入位置编码,可以解决这个问题。位置编码,通过给每个位置添加一个向量,这个向量包含了位置信息,然后把这个向量加到词汇向量上。

python 复制代码
例如:
位置1向量:[0.1, 0.2,0.3, ...]
位置2向量:[0.4, 0.5,0.6, ...]
位置3向量:[0.7, 0.8,0.9, ...]

"我喜欢你",添加位置编码后:
"我"在位置1:"我"的词向量 + 位置1向量
"喜欢"在位置2:"喜欢"的词向量 + 位置2向量
"你"在位置3:"你"的词向量 + 位置3向量

经过这样处理,Transformer就可以区分词的位置了。

实现

在 Transformer 中,使用的正弦位置编码。

plain 复制代码
=== 正弦位置编码的详细解释 ===

1. 参数:
   d_model: 8
   max_len: 10

2. 位置索引:
   position: [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]

3. 分母项:
   div_term: [1.0, 0.3162, 0.1, 0.0316]
   
   解释:
   - div_term = 10000^(-2i/d_model)
   - i是维度索引(0, 2, 4, 6, ...)
   - 用于控制不同维度的频率

4. 位置编码矩阵:
   形状: torch.Size([10, 8])
   数据:
   位置0: [0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
   位置1: [0.8415, 0.5403, 0.3129, 0.9499, 0.0998, 0.9950, 0.0316, 0.9995]
   位置2: [0.9093, -0.4161, 0.5946, 0.8040, 0.1987, 0.9801, 0.0632, 0.9980]
   位置3: [0.1411, -0.9900, 0.8120, 0.5835, 0.2955, 0.9553, 0.0948, 0.9955]
   位置4: [-0.7568, -0.6536, 0.9516, 0.3073, 0.3894, 0.9211, 0.1263, 0.9920]
   ...

5. 解释:
   
   公式:
   PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
   PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
   
   含义:
   - pos: 位置索引(0, 1, 2, ...)
   - 2i: 偶数维度(0, 2, 4, ...)
   - 2i+1: 奇数维度(1, 3, 5, ...)
   
   特点:
   - 偶数维度用sin
   - 奇数维度用cos
   - 不同维度有不同的频率

6. 可视化:
   
   位置编码的每个维度:
   - 维度0: sin(pos * freq_0)
   - 维度1: cos(pos * freq_0)
   - 维度2: sin(pos * freq_1)
   - 维度3: cos(pos * freq_1)
   - ...
   
   不同维度的频率:
   - 低维度: 高频率(快速变化)
   - 高维度: 低频率(慢速变化)
   
   作用:
   - 不同维度捕捉不同粒度的位置信息
   - 低维度捕捉局部位置
   - 高维度捕捉全局位置
plain 复制代码
=== 逐步演示位置编码的添加过程 ===

1. 词向量:
   形状: torch.Size([1, 3, 8])
   数据:
   位置0: [0.1234, -0.5678, 0.9012, -0.3456, 0.7890, -0.1234, 0.5678, -0.9012]
   位置1: [0.2345, -0.6789, 0.0123, -0.4567, 0.8901, -0.2345, 0.6789, -0.0123]
   位置2: [0.3456, -0.7890, 0.1234, -0.5678, 0.9012, -0.3456, 0.7890, -0.1234]

2. 位置编码:
   形状: torch.Size([3, 8])
   数据:
   位置0: [0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
   位置1: [0.8415, 0.5403, 0.3129, 0.9499, 0.0998, 0.9950, 0.0316, 0.9995]
   位置2: [0.9093, -0.4161, 0.5946, 0.8040, 0.1987, 0.9801, 0.0632, 0.9980]

3. 添加位置编码后:
   形状: torch.Size([1, 3, 8])
   数据:
   位置0: [0.1234, 0.4322, 0.9012, 0.6544, 0.7890, 0.8766, 0.5678, 0.0988]
   位置1: [1.0760, -0.1386, 0.3252, 0.4932, 0.9899, 0.7605, 0.7105, 0.9872]
   位置2: [1.2549, -1.2051, 0.7180, 0.2362, 1.0999, 0.6345, 0.8532, 0.8746]
   
   计算:
   输出 = 词向量 + 位置编码

4. 总结:
   
   步骤:
   1. 获取词向量
   2. 获取位置编码
   3. 词向量 + 位置编码
   
   结果:
   - 每个词的向量包含了位置信息
   - Transformer可以区分不同位置的词
   
   数据流动:
   输入(1, 3, 8)
   ↓
   Embedding
   ↓
   词向量(1, 3, 8)
   ↓
   + 位置编码(1, 3, 8)
   ↓
   输出(1, 3, 8)
python 复制代码
class PositionalEncoding(nn.Module):
    '''位置编码模块'''

    def __init__(self, args):
        super(PositionalEncoding, self).__init__()
        # Dropout 层
        # self.dropout = nn.Dropout(p=args.dropout)

        # block size 是序列的最大长度
        pe = torch.zeros(args.block_size, args.n_embd)
        position = torch.arange(0, args.block_size).unsqueeze(1)
        # 计算 theta
        div_term = torch.exp(
            torch.arange(0, args.n_embd, 2) * -(math.log(10000.0) / args.n_embd)
        )
        # 分别计算 sin、cos 结果
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0)
        self.register_buffer("pe", pe)

    def forward(self, x):
        # 将位置编码加到 Embedding 结果上
        x = x + self.pe[:, : x.size(1)].requires_grad_(False)
        return x

位置编码类型

类型 特点 优点 缺点 使用模型
正弦位置编码 固定公式 不需要参数,可外推 不能学习 Transformer
可学习的位置编码 可以学习 效果可能更好 需要参数,不能外推 BERT、GPT
旋转位置编码 相对位置 适合长序列 实现复杂 LLaMA,GPT-NeoX

学习内容(Datawhale 开源学习项目 ):Happy-LLM

相关推荐
ZGIAI3 小时前
ZGI Workflow:条件分支走错时先查哪一层
人工智能·架构
X54先生(人文科技)3 小时前
《元创力》纪实录 · 桥段 《窑变纪元:一份来自星历2227年的深空考古笔记》
人工智能·开源·ai写作·零知识证明
ZGIAI3 小时前
ZGI 文件产物:生成报告后怎样交付
人工智能·架构
东方-教育技术博主3 小时前
自动编码在教育场景中的重要性:一项基于多源证据的深度综述
大数据·人工智能
骥龙4 小时前
模块二:Ollama本地模型部署与OpenCode代理配置
人工智能
阡之尘埃4 小时前
Python数据分析案例85——大模型微调全流程(SFT的LoRA微调)
人工智能·python·深度学习·语言模型·llm·微调·千问
Regentsoft丽晶软件4 小时前
品牌方新品上市促销政策无法实时同步经销商,有没有支持总部-经销商-终端一站式的分销解决方案?
人工智能·经验分享·数据库架构
liuqs3324 小时前
机器人产业加速发展,制造业正在迎来新的自动化探索
大数据·人工智能
腾讯云大数据4 小时前
DataBuddy数据语义驱动的企业Agent Runtime实践
大数据·人工智能·腾讯云·agent
裕晟资质规划4 小时前
武器装备科研生产单位保密资质申请方法论:条件模型与流程拆解
人工智能·算法