AI-5-LLMs-from-scratch
1 Three main steps of construct a LLM
Step 1-1 Text analysis
1) Text split into individual word elements
2) Construct the word dictionary
3)BEP algorithm
4) Embedding Layer
在大模型(如GPT、BERT等)的训练过程中,将词元(Token)的ID转换为嵌入向量(Embedding Vector)是输入处理的核心步骤。这一过程通过嵌入层(Embedding Layer)实现,其核心思想是将离散的词元符号映射到连续的向量空间,从而能够被神经网络处理。以下是详细的原理和步骤:
【大模型靠啥理解文字?通俗解释:词嵌入embedding】 https://www.bilibili.com/video/BV1bfoQYCEHC/?share_source=copy_web&vd_source=4bbce1829495fde2f31b5349c79e3deb
1. 词元ID与词汇表
词元(Token):文本被分词后的最小单位(如单词、子词或字符)。
词汇表(Vocabulary):所有可能词元的集合,每个词元被分配一个唯一的整数ID。
例如,词汇表可能是{"the": 0, "cat": 1, "sat": 2, ...},词汇表大小记为V。词元ID:输入文本经过分词后,每个词元被替换为其在词汇表中的ID,形成一个整数序列。
例如,句子"the cat sat"转换为[0, 1, 2]。
2. 嵌入层(Embedding Layer)
嵌入层本质上是一个可学习的查找表(Lookup Table),其功能是将词元ID映射为稠密的连续向量。具体过程如下:
(1) 嵌入矩阵的初始化
嵌入矩阵(Embedding Matrix):
形状为(V, d),其中:V是词汇表大小(总词元数),d是嵌入向量的维度(如512、768等超参数)。
初始化方式:
嵌入矩阵通常通过随机初始化(如正态分布或均匀分布),并在训练过程中通过梯度下降更新参数。
(2) 查表操作(Lookup)
输入:一个形状为
(batch_size, sequence_length)的整数张量(每个元素是词元ID)。
例如,批量大小为3、序列长度为4的输入可能为:[[5, 23, 0, 42],
[17, 8, 102, 12],
[3, 64, 11, 9]]输出:一个形状为
(batch_size, sequence_length, d)的浮点数张量。
每个词元ID通过嵌入矩阵查表,替换为对应的d维向量。
例如,词元ID5被替换为嵌入矩阵第5行的向量。
3. 数学表示
- 假设词元ID为整数
i(满足0 ≤ i < V),嵌入矩阵为E ∈ R^(V×d),则对应的嵌入向量为:
[
\text{Embedding}(i) = E[i, :] \in R^d
] - 示例:
若E是10000×768的矩阵,词元ID42对应的嵌入向量是E[42](长度为768的向量)。
4. 为何需要嵌入向量?
- 从离散到连续:神经网络无法直接处理离散的符号(如整数ID),需转换为连续向量。
- 语义表示:嵌入向量可以捕捉词元的语义和语法特征(如相似词在向量空间中距离较近)。
- 降维:相比于One-Hot编码(维度为
V,稀疏且高维),嵌入向量维度d通常远小于V(稠密且低维)。
总结
- 核心步骤:词元ID → 嵌入矩阵查表 → 嵌入向量。
- 目的:将离散符号映射为连续向量,供神经网络处理。
- 关键特性:可学习性(通过训练优化)、低维稠密性、语义捕捉能力。
- 扩展应用:结合位置编码、多模态嵌入(如图像/文本联合嵌入)等。
这一过程是几乎所有现代NLP模型的基石,为后续的注意力机制、前馈网络等提供了可处理的输入形式。
Step 1-2 Attention mechansim
- Attention score: multiplying two vectors element-wise and then summing the products
- Normalization: to obtain attention weights that sum up to 1.
- attn_weights_2_tmp = attn_scores_2 / attn_scores_2.sum()
- torch.softmax: torch.exp(x) / torch.exp(x).sum(dim=0)
Bahdanau注意力机制是一种用于序列到序列(seq2seq)模型的关键技术,旨在解决传统编码器-解码器模型中固定长度上下文向量的信息瓶颈问题
- 传统seq2seq的局限性:传统模型将整个输入序列压缩为一个固定长度的上下文向量,导致长序列信息丢失。
- 注意力机制的引入:Bahdanau等人(2015)提出动态对齐机制,使解码器在每一步生成输出时,能自适应地关注输入序列的不同部分。
核心机制
编码器
- 双向RNN:输入序列通过双向RNN(如GRU/LSTM)处理,每个时间步的隐藏状态(前向+后向)拼接,形成包含全局上下文的编码器隐藏状态序列 {h_1, h_2, …, h_T}{h1,h2,…,h**T}。
解码器
动态上下文生成:解码器在时间步tt生成输出时,执行以下步骤:
计算注意力分数:通过加性注意力(Additive Attention)衡量解码器当前状态s_{t-1}s**t−1与每个编码器状态h_jh**j的相关性:
e_{tj} = v^T \tanh(W [s_{t-1}; h_j] + b)etj=v**Ttanh(W[s**t−1;h**j]+b)
其中v, W, bv,W,b为可学习参数,[;][;]表示拼接。
归一化为权重:通过Softmax将分数转换为权重:
\alpha_{tj} = \frac{\exp(e_{tj})}{\sum_{k=1}^T \exp(e_{tk})}αtj=∑k=1Texp(etk)exp(etj)
生成上下文向量:加权求和编码器状态:
c_t = \sum_{j=1}^T \alpha_{tj} h_jc**t=j=1∑Tαtjh**j
预测输出:将上下文向量c_tc**t与解码器当前状态s_{t-1}s**t−1拼接,通过全连接层和Softmax生成输出词的概率分布。
1)自注意力机制的内部工作原理
在自注意力机制中,“自”指的是该机制通过关联单个输入序列中的不同位置来计算注意力权重的能力。它可以评估并学习输入本身各个部分之间的关系和依赖,比如句子中的单词或图像中的像素。
2)带可训练权重的自注意力机制
引入了在模型训练期间更新的权重矩阵, 引入 3 个可训练的权重矩阵 Wq、Wk和 Wv,一步一步地实现自注意力机制.这 3个矩阵用于将嵌入的输入词元 x (i) 分别映射为查询向量、键向量和值向量,如图所示。
3)利用因果注意力隐藏未来词汇
因果机制的作用是调整注意力机制,防止模型访问序列中未来的信息,这在语言建模等任务中尤为重要,因为每个词的预测只能依赖之前出现的词。
对于许多大语言模型任务,你希望自注意力机制在预测序列中的下一个词元时仅考虑当前位置之前的词元。因果注意力(也称为掩码注意力)是一种特殊的自注意力形式。它限制模型在处理任何给定词元时,只能基于序列中的先前和当前输入来计算注意力分数,而标准的自注意力机制可以一次性访问整个输入序列。
4)将单头注意力扩展到多头注意力
多头机制涉及将注意力机制分成多个“头”。每个头会学习数据的不同特征,使模型能够在不同的位置同时关注来自不同表示子空间的信息。这能够提升模型在复杂任务中的性能。
“多头”这一术语指的是将注意力机制分成多个“头”,每个“头”独立工作。在这种情况下,单个因果注意力模块可以被看作单头注意力,因为它只有一组注意力权重按顺序处理输入。
多头注意力的主要思想是多次(并行)运行注意力机制,每次使用学到的不同的线性投影——这些投影是通过将输入数据(比如注意力机制中的查询向量、键向量和值向量)乘以权重矩阵得到的。
Chapter 4 Generate a GPT Model
非线性激活函数 ReLU(修正线性单元)
ReLU 是神经网络中的一种标准激活函数。如果你不熟悉 ReLU,可以这样来理解:它只是简单地将负输入值设为 0,从而确保层的输出值都是正值,这也解释了为什么结果层的输出中不包含负值。
具有 GELU 激活函数的前馈神经网络
GELU 和 SwiGLU 是更为复杂且平滑的激活函数,分别结合了高斯分布和 sigmoid 门控线性单元。与较为简单的 ReLU 激活函数相比,它们能够提升深度学习模型的性能。
GELU 激活函数可以通过多种方式实现,其精确的定义为 G LU( ) ( E x x x ) ,其中 ( ) x 是标准高斯分布的累积分布函数。然而,在实际操作中,通常我们会使用一种计算量较小的近似实现(原始的 GPT-2 模型也是使用这种通过曲线拟合得到的近似方法进行训练的)
GeLU vs ReLUGELU 的平滑特性可以在训练过程中带来更好的优化效果,因为它允许模型参数进行更细微的调整。相比之下,ReLU 在零点处有一个尖锐的拐角(参见图 4-8 的右图),有时会使得优化过程更加困难,特别是在深度或复杂的网络结构中。此外,ReLU 对负输入的输出为 0,而 GELU对负输入会输出一个小的非零值。这意味着在训练过程中,接收到负输入的神经元仍然可以参与学习,只是贡献程度不如正输入大。
FeedForward 模块在提升模型学习和泛化能力方面非常关键。虽然该模块的输入和输出维度保持一致,但它通过第一个线性层将嵌入维度扩展到了更高的维度,如图 4-10 所示。扩展之后,应用非线性 GELU 激活函数,然后通过第二个线性变换将维度缩回原始大小。这种设计允许模型探索更丰富的表示空间