Transformer理解

部署运行你感兴趣的模型镜像

什么是Transformer

一句话: Seq2seq model with self-attention

Seq2seq model

是什么

Seq2Seq(Sequence to Sequence) 指的是一种模型结构,用于 将一个序列映射为另一个序列
它最初被提出是为了解决 机器翻译 任务,例如:

输入序列(英文句子):“I love cats”
输出序列(中文句子):“我喜欢猫”

基本结构

典型代表:RNN

适合处理输入为序列信息(sequence)

模块作用举例
Encoder(编码器)读取输入序列,并把它压缩成一个上下文向量(context vector)把英文句子编码为语义表示
Decoder(解码器)逐步生成输出序列,每次根据之前已生成的词和上下文向量预测下一个词根据语义表示生成中文句子
1️⃣ Encoder 阶段:
  • 输入一个序列 x=[x1,x2,…,xn]x = [x_1, x_2, …, x_n]x=[x1,x2,…,xn]
  • 经过循环神经网络(RNN、LSTM、GRU)逐步更新隐藏状态(其实就是模型内部“记忆”,即 内部向量)
  • 最后一个隐藏状态 hn 被认为是整个句子的语义表示(context vector)
2️⃣ Decoder 阶段:
  • Decoder 也是一个 RNN,它在每个时间步根据上一个词和 context vector 生成下一个词
  • 不断迭代,直到生成结束符 <EOS>

缺陷

  • **难以并行->**训练速度慢、难以利用 GPU 的并行计算优势
  • **长程依赖问题->**梯度衰减(遗忘信息)、爆炸(不稳定):改进 LSTM、GRU
  • **信息压缩瓶颈->**Encoder 的最后一个隐藏状态 hn要作为整句的语义总结(context vector)传给 Decoder,面向长句不佳

基础知识解析

1 文字转向量(X to a)

Transformer 接收的输入不是文字,而是一个二维矩阵。
X ∈ R n × d model X \in \mathbb{R}^{n \times d_{\text{model}}} XRn×dmodel
所以第一步要把句子拆分成一个个 Token(最小单位)

# 句子转Token:分词方式有很多,如 字级分词、词级分词、子词分词(Transformer标准做法)
今天天气不错->[今, 天, 天, 气, 不, 错]	# 字级分词

第二步就是将这些Token转为数字。每个 token 都会被查到一个整数 ID(索引),对应词表(vocab)里的位置,于是就可以用数字序列代替句子。

# Token转ID:
vocab:
今 → 1012
天 → 1035
气 → 2345
不 → 765
错 → 990

[,,,,,]->[1012, 1035, 1035, 2345, 765, 990]

但是上面得到的数字序列只是一个标签,并没有实际的含义,于是第三步通过 embedding 层 把它们映射到语义空间(高维向量)。

Embedding 是一个可学习矩阵:(语义是在训练过程中理解浮现的,即是经过大量数据喂出来的)
E ∈ R ∣ V ∣ × d model E \in \mathbb{R}^{|V| \times d_{\text{model}}} ERV×dmodel

  • ∣V∣:词表大小(如 50,000)
  • d_modeld:每个词向量维度(如 512 或 768)

这样就可以把 token转向量

# 索引转向量
今 → [0.12, -0.34, 0.56, ..., 0.87]  # 如,一共 512 维
天 → [0.22, -0.15, 0.78, ..., -0.33]
...

[1012, 1035, 1035, 2345, 765, 990]->[[...512...], [...512...], ...]	# shape=[6,512]

因为 Transformer 没有循环结构(不像 RNN),它本身不知道词的先后顺序(eg. “今天天气不错” 和 “天气今天不错” 对模型来说可能是同一个序列(不区分顺序))。

所以第四步就是要额外入一个 位置编码(Positional Encoding)(本质上是一个和转向量后的数据相同shape的向量,比如这里的PE矩阵就是 [6,512],然后让两个矩阵相加),让模型知道“第几个词”。

在这里插入图片描述

而这个PE矩阵每个项的值是通过公式算出来的(公式已知且确定,和哈希类似),所以模型想要知道当前分词的位置只需要逆向公式即可。

总流程如下:

“今天天气不错。”
      ↓ 分词
[,,,,,]
      ↓ 转索引
[1012, 1035, 1035, 2345, 765, 990] → 形状 [6, 1]
      ↓ 词嵌入
[[...512...], [...512...], ...] → 形状 [6, 512]
      ↓ 加上位置编码PE矩阵
X = [[x1], [x2], ..., [x6]]  → 形状 [6, 512]

这个 X 就是送入 Transformer Encoder 的输入矩阵。接下来模型才会对它进行 Q,K,V 映射注意力计算等步骤。

2 Self-attention(a to b)

setp 1 QKV映射

所谓的QKV映射,就是将输入的向量,乘上Wq Wk Wv权重矩阵(都是 可学习参数
(下面的例子中,4其实就代表上面例子的512)

  • ( Q, K, V ):分别是 Query(查询)、Key(键)、Value(值)

在 Transformer 里:

  • 每个词都会生成自己的 Q、K、V 向量
  • Q 决定它要“查询什么
  • K 决定它“提供什么信息
  • V 是它“具体携带的信息

step 2 q对k做attention

首先是获取一个中间值 α

在这里插入图片描述

然后是做一个 softmax,得到第二个中间值 α`

在这里插入图片描述

最后再将 α` 和 v 相乘,将结果相加,得到 bi

在这里插入图片描述

这样其实就可以通过调节 v 的参数,调整模型对任意Token的注意力(比如如果让v3=0,那对x3这个字的关注就会变少)

而且上述过程可以并行:

在这里插入图片描述

为什么可以并行?因为可以化作矩阵同时计算

在这里插入图片描述

在这里插入图片描述

总结:self-attention层 的 Input 到 Output,其实就是一堆矩阵乘法

在这里插入图片描述

3 Multi-Head Self-Attention(多角度理解一句话)

类似卷积核,不同卷积核关注同一图片的不同特征信息,多头注意力机制 的目的也是为了多个角度理解语义。

对比维度CNN 卷积核Multi-Head Attention
参数多样性多个卷积核权重多组 (W_Q, W_K, W_V)
特征提取视角每个卷积核提取不同局部模式(边缘、角点等)每个注意力头学习不同语义关系(主谓、修饰、时态等)
结果融合多个 feature map 拼接多个 head 的输出拼接
最终目标获取更丰富的空间特征获取更全面的语义依赖

区别在于:

  • CNN 的卷积核是局部感受野(看邻近像素);
  • Attention 的每个头是全局感受野(能看整个序列)。

比如:我爱北京天安门,3个头

注意力头关注的语义
Head 1主语 → 动作(我 → 爱)
Head 2动作 → 宾语(爱 → 北京)
Head 3实体连接(北京 → 天安门)

实际的矩阵计算也很方便:
在这里插入图片描述

Masked Multi-Head Self-Attention

掩码多头注意力机制 相对于多头注意力机制,其 真正的区别只在于:是否“遮住未来的信息”

如下图所示,圈出的粉色框,正是**“第 2 个 token 的 masked self-attention 可见区域”**。它表示在生成第 2 个输出时,模型只使用自己和之前的内容,不会看未来的内容。

在这里插入图片描述

即,b2 的运算是:

在这里插入图片描述

Transformer框架

【NLP】Transformer详解 - 知乎

在之前的基础知识讲解中,我们其实已经攻克的最难的部分,也解决了模型的输入问题,Encoder 部分也差不多了。下面再来系统讲解一下:

Embedding-句转vec

略(见 基础知识解析 1)

Encoder-理解语义

功能

理解输入序列的语义,并把这种理解转化为高维向量表示,供解码器或下游任务使用。

框架

在这里插入图片描述

  • **Add:**表示残差网络,是为了保证模型学习稳定性的(不退步)
  • Norm:表示归一化,为了稳定训练、加快收敛、防止梯度爆炸/消失(Transformer 使用 LayerNorm
  • Feed Forward:表示前馈神经网络,是进行非线性加工和语义升华的模块(激活函数 Relu)

这里对比一下 LayerNorm 和 BatchNorm 的区别:

对比项Batch NormalizationLayer Normalization
归一化维度跨样本(对 batch 维度取均值)样本内(对特征维度取均值)
是否依赖 batch size✅ 是❌ 否
适用场景CNN、小批量图像训练RNN、Transformer(序列任务)

Decoder-输出句子(vec形式)

功能

根据语义生成输出

框架

在这里插入图片描述

注意:这里解码器的输入有两个,一个是Encoder的结果 R1,一个是当前生成序列的结果 R2瞻前顾后

其中,R1直接送往多头自注意力机制R2需要经过掩码多头自注意力机制进行加工,再和R1一起去。

Encoder和Decoder的总结表:

模块功能输入输出类比
Encoder理解输入内容,提取语义特征Token向量序列上下文语义表示序列“阅读理解器”
Decoder根据语义生成输出Encoder结果 + 已生成的词预测下一个词“语言生成器”

Output-vec转句子

在这里插入图片描述

step 1 线性变换(Linear Projection)

通过一个线性层(即矩阵乘法 + 偏置项)映射到词表维度

公式:yi=zi·Wo+bo

其中,Wo 是线性层权重矩阵,bo 是偏置项,每个 yi 表示该位置上所有词的置信度分数。

step 2 Softmax 转为概率分布

Softmax 将所有 logit 转换成概率分布
于是:

  • 每个位置上,模型会给出“下一个词是哪个”的概率;
  • 概率最大的那个词(Argmax)就是模型预测的输出。
step 3 查表输出文本

根据概率分布选择概率最大的那个索引对应的字输出

总结

针对具体例子来说,我们已知:

  1. 词表里有5个词

    索引
    1
    2
    3
    4
    5
  2. 线性权重矩阵

    Wo.shape=4x5 (4:表示一个字的向量dim,5:词表长度)

# Decoder 输出
Z=[[0.2,0.1,0.5,0.7],[...],[...]]	# Z1=[0.2,−0.1,0.5,0.7]
			⬇️线性层	# y=z·Wo+bo,
y=[[0.82,0.52,0.39,0.47,0.68],	#  z1对应在词表中的置信度 logit
   [...],
   [...]]
			⬇️softmax	# 转概率
o=[[0.26,0.19,0.17,0.18,0.20],[...],[...]]
			⬇️查表
o1概率最高的是 0.26 这项,对应索引1,表示 “我”,输出
o2...

推荐大家看看:李宏毅老师讲的Transformer

您可能感兴趣的与本文相关的镜像

Seed-Coder-8B-Base

Seed-Coder-8B-Base

文本生成
Seed-Coder

Seed-Coder是一个功能强大、透明、参数高效的 8B 级开源代码模型系列,包括基础变体、指导变体和推理变体,由字节团队开源

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值