文章目录
-
- 1. transformer 介绍
- 2 Position Encoding
-
- 2.1 位置编码原理
- 2.2 代码实现
- 3 Self-attention
- 4 前馈层FFN
- 5 残差连接与层归一化
- 6 编码器和解码器结构
1. transformer 介绍
Transformer 模型是由谷歌在 2017 年提出并
首先
应用于机器翻译
的神经网络模型结构。机器翻译的目标是从源语言(Source Language)转换到目标语言(Target Language)。Transformer 结构完全通过注意力机制
完成对源语言序列和目标语言序列全局依赖的建模
。当前几乎全部大语言模型
都是基于Transformer 结构
,本节以应用于机器翻译的基于 Transformer 的编码器和解码器介绍该模型。
Transformer它的提出最开始是针对NLP领域
的,在次之前大家主要用的是RNN,LSTM这类时序网络。像RNN
这类网络其实它是有些问题的,首先它的记忆的长度
是有限的,特别像RNN它的记忆长度就比较短,所以后面就有提出LSTM
。但是他们还有另外一个问题就是无法并行化
,也就是说我们必须先计算 t 0 t_0 t0时刻的输出,计算完之后我们才能进一步计算 t 1 t_1 t1时刻的数据。由于无法并行化,训练效率就比较低.
针对这一问题,Google提出了Transformer来替代之前的时序网络,
- Transformer不受硬件限制的情况下,理论上
记忆是可以无限长
的。 - 其次,它是可以做
并行化
的,这是一个非常大的优点
基于 Transformer 结构主要分两部分
:编码器Encoder
和解码器Decoder
,它们均由若干个基本的 Transformer 块
(Block)组成(对应着图中的灰色框)。每个 Transformer 块都接收一个向量序列 { x i } i = 1 t \{x_i\}_{i=1}^t {
xi}i=1t作为输入,并输出一个等长
的向量序列作为输出 { y i } i = 1 t \{y_i\}_{i=1}^t {
yi}i=1t, 而 y i y_i yi是当前 Transformer 块对输入 x i x_i xi进一步整合其上下文语义后对应的输出。
主要涉及到如下几个模块:
-
Position Encoding
: 使用位置编码来理解文本的顺序 -
注意力层
:使用多头注意力(Multi-Head Attention
)机制 整合上下文语义
,它使得序列中任意两个token
之间的依赖关系可以直接被建模而不基于传统的循环结构,从而更好地解决文本的长程依赖
。 -
位置感知前馈层(Position-wise FFN)
:通过全连接层对输入文本序列中的每个单词表示进行更复杂的变换 -
残差连接:
对应图中的 Add 部分。它是一条分别作用在上述两个子层当中的直连通路,被用于连接它们的输入与输出。从而使得信息流动更加高效,有利于模型的优化
。 -
层归一化:
对应图中的 Norm 部分。作用于上述两个子层的输出表示序列中,对表示序列进行层归一化操作,同样起到稳定优化的作用。
2 Position Encoding
2.1 位置编码原理
由于Transformer模型没有循环神经网络的迭代操作,所以我们必须提供每个token位置信息给Transformer, 这样它才能识别出语言中的顺序关系。
Positional Encoding(位置嵌入)
, 它的维度为[num_token,embedding_dimension]
, 位置嵌入的维度与词向量token的维度是相同的,都是embedding_dimension
。其中max_sequence_length
属于超参数,指的是限定每个句子最长由多少个词组成。
注意,我们一般以字
为单位训练Transformer模型,首先初始化字编码大小为[vocab_size,embedding_dimension]
, vocab_size 为字库中所有字的数量,embedding_dimension为字向量的维度,对应pytorch中,其实就是 nn.Embedding(vocab_size,embedding_dimension)
论文中使用了 s i n sin sin 和 c o s cos cos函数的线性变换来提供给模型位置信息:
其中pos
指的是一句话中某个字的位置,取值范围为[0,max_sequence_length]
, i i i指的是字向量的序号,取值范围是[0,embedding_dimension/2]
, d m o d e l d_{model} dmodel指的是embedding_dimension的值。
通过sin
和cos
处理,从而使得位置编码产生不同对的周期性变化,使得每个位置在embedding_dimension
维度上都会得到不同周期的sin
和cos
函数的取值组合,从而产生独一的位置信息,最终使得模型学到位置之间的依赖关系和自然语言的时序特效
2.2 代码实现
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import math
def get_positional_encoding(max_seq_len,embed_dim):
# 初始化一个positional encoding
# embed_dim: 字嵌入的维度
# max_seq_len: 最大的序列长度
positional_encoding = np.array([
[pos/np.power(1000,2*i/ embed_dim) for i in range(embed_dim)] if pos !=0 else \
np.zeros(embed_dim) for pos in range(max_seq_len)
])
positional_encoding[1:,0::2] = np.sin(positional_encoding[1:,0::2]) #dim 2i 偶数
positional_encoding[1:,1::2] = np.cos(positional_encoding[1:,1::2]) #dim 2i+1 奇数
return positional_encoding
positional_encoding = get_positional_encoding(max_seq_len=100,embed_dim=16)
plt.figure(figsize=(10,10))
sns.heatmap(positional_encoding)
plt.title('Sinusoidal Function')
plt.xlabel('hidden dimension')
plt.figure(figsize=(8,5))
plt.plot(positional_encoding[1:,1],label="dimension 1")
plt.plot(positional_encoding[1:,2],label="dimension 2")
plt.plot(positional_encoding[1:,3],label="dimension 3")
plt.legend()
plt.xlabel("Sequence length")
plt.ylabel("Period of Positional Encoding")
3 Self-attention
自注意力(Self-Attention)操作是基于 Transformer 的机器翻译模型的基本操作,在源语言的编码和目标语言的生成中频繁地被使用以建模源语言、目标语言任意两个单词之间的依赖关系。给定由单词语义嵌入及其位置编码叠加得到的输入表示 { x i ∈ R d } i t \{x_i \in R^d\}_i^t { xi∈Rd}it, 为了实现对上下文语义依赖的建模,进一步引入在自注意力机制中涉及到的三个元素:查询 q i q_i qi