欢迎来到本 Repo!这里是一个专注于大语言模型学习的仓库,旨在为大语言模型学习入门者和大语言模型研发岗位的面试准备者提供全面的基础知识。
我们涵盖了多个主题,包括深度学习基础知识、自然语言处理基础知识、大语言模型基础知识以及大语言模型推理和应用等内容。你将在这里找到丰富的学习资料,帮助你构建对大语言模型的全面理解和应用能力。
除了基础知识,我们还会推荐一些大语言模型领域的前沿论文,帮助你跟上最新的研究进展,掌握最先进的技术。
无论你是新手还是有经验的从业者,本 Repo 都会为你提供有价值的学习资源。欢迎一起探索大语言模型的奥秘,让我们一同进步和成长!如果你有任何问题或建议,欢迎提出,我们将尽力完善这个仓库,为大家提供更好的学习体验。谢谢你的参与!
Transformer 模型的自注意力(Self Attention)机制涉及三种线性变换:查询(Q)、键(K)、值(V),以及通过计算注意力权重和加权求和来生成最终的输出。以下是自注意力机制的公式:
假设输入序列为 $X \in \mathbb{R}^{L \times d}$,其中 $L$ 是序列长度, $d$ 是特征维度。自注意力层中的线性变换矩阵为 $W_q \in \mathbb{R}^{d \times d_k}$、 $W_k \in \mathbb{R}^{d \times d_k}$ 和 $W_v \in \mathbb{R}^{d \times d_v}$,其中 $d_k$ 和 $d_v$ 是分割查询、键和值时的维度。
查询(Q)、键(K)和值(V)的线性变换:
多头拆分:
注意力得分计算:
注意力加权求和:
上述公式涵盖了Transformer模型中自注意力层的基本计算步骤。在实际应用中,通常还会考虑添加缩放(scaling)、掩码(masking)等操作来优化注意力机制的计算过程。多头自注意力则在每个头上分别进行这些计算,然后将多个头的输出拼接或串联起来,进一步提取序列中的信息
一个多头 Self Attention 代码实现如下:
import torch
import torch.nn.functional as F
class SelfAttentionLayer(torch.nn.Module):
def __init__(self, d_model, num_heads):
super(SelfAttentionLayer, self).__init__()
self.d_model = d_model
self.num_heads = num_heads
self.d_k = d_model // num_heads
# 线性变换矩阵
self.W_q = torch.nn.Linear(d_model, d_model, bias=False)
self.W_k = torch.nn.Linear(d_model, d_model, bias=False)
self.W_v = torch.nn.Linear(d_model, d_model, bias=False)
def split_heads(self, x, batch_size):
x = x.view(batch_size, -1, self.num_heads, self.d_k)
return x.permute(0, 2, 1, 3)
def forward(self, x):
batch_size, seq_len, d_model = x.size()
q = self.W_q(x)
k = self.W_k(x)
v = self.W_v(x)
q = self.split_heads(q, batch_size)
k = self.split_heads(k, batch_size)
v = self.split_heads(v, batch_size)
# Scaled Dot-Product Attention
attn_scores = torch.matmul(q, k.transpose(-2, -1)) / (self.d_k ** 0.5)
attn_weights = F.softmax(attn_scores, dim=-1)
# Attention加权求和
output = torch.matmul(attn_weights, v)
output = output.permute(0, 2, 1, 3).contiguous().view(batch_size, seq_len, -1)
return output
# 测试自注意力层
d_model = 512
num_heads = 8
seq_len = 10
batch_size = 16
input_data = torch.randn(batch_size, seq_len, d_model)
self_attention = SelfAttentionLayer(d_model, num_heads)
output = self_attention(input_data)
print(output.size()) # 输出: torch.Size([16, 10, 512])
上面 Transformer 代码中有使用 $\sqrt{d_{k}}$ 来对 softmax 之后的结果进行 scale,解释如下:
We suspect that for large values of $d_{k}$, the dot products grow large in magnitude, pushing the softmax function into regions where it has extremely small gradients. To counteract this effect, we scale the dot products by $\frac{1}{d_{k}}$. To illustrate why the dot products get large, assume that the components of q and k are independent random variables with mean 0 and variance 1. Then their dot product $q ⋅ k=\sum_{i=1}^{d_{k}}(q_{i}k_{i})$, has mean 0 and variance $d_{k}$.
对于任何一门语言,单词在句子中的位置以及排列顺序是非常重要的,它们不仅是一个句子的语法结构的组成部分,更是表达语义的重要概念。一个单词在句子的位置或排列顺序不同,可能整个句子的意思就发生了偏差。
I do not like the story of the movie, but I do like the cast. I do like the story of the movie, but I do not like the cast. 上面两句话所使用的的单词完全一样,但是所表达的句意却截然相反。那么,引入词序信息有助于区别这两句话的意思。
Transformer 模型抛弃了 RNN、CNN 作为序列学习的基本模型。我们知道,循环神经网络本身就是一种顺序结构,天生就包含了词在序列中的位置信息。当抛弃循环神经网络结构,完全采用 Attention 取而代之,这些词序信息就会丢失,模型就没有办法知道每个词在句子中的相对和绝对的位置信息。因此,有必要把词序信号加到词向量上帮助模型学习这些信息,位置编码(Positional Encoding)就是用来解决这种问题的方法。

根据复数乘法的几何意义,该变换实际上对应着向量的旋转,所以我们称之为“旋转式位置编码”

- 左半部分为预训练阶段的位置向量范围[0,2048]
- 右上角为长度外推的部分(2048,4096]
- 左下角为位置插值法,将[0,4096]的值降采样到[0,2048]预训练阶段支持的范围
参考:为什么 Pre Norm 的效果不如 Post Norm?

对于一个NCHW(批次大小,通道数,高度,宽度)格式的输入张量,Batch Normalization(BN)层通常包含两组可学习参数:缩放因子(scale)和偏移(shift)。
基于 pytorch 的 BN 示例代码
# CV Example
import torch
import torch.nn as nn
batch, channel, height, width = 20, 100, 35, 45
input = torch.randn(batch, channel, height, width)
m = nn.BatchNorm2d(channel)
output = m(input)
for k, v in m.named_parameters():
print(k, v.shape)
# -> weight torch.Size([100])
# -> bias torch.Size([100])
# NLP Example
import torch
import torch.nn as nn
batch, sentence_length, embedding_dim = 20, 5, 10
embedding = torch.randn(batch, sentence_length, embedding_dim)
layer_norm = nn.LayerNorm(embedding_dim)
output = layer_norm(embedding)
for k, v in layer_norm.named_parameters():
print(k, v.shape)
# -> weight torch.Size([10])
# -> bias torch.Size([10])
import torch
import torch.nn as nn
N, C, H, W = 20, 5, 10, 15
input = torch.randn(N, C, H, W)
layer_norm = nn.LayerNorm([C, H, W])
output = layer_norm(input)
for k, v in layer_norm.named_parameters():
print(k, v.shape)
# -> weight torch.Size([5, 10, 15])
# -> bias torch.Size([5, 10, 15])
语言模型是对文本进行推理。由于文本是字符串,但对模型来说,输入只能是数字,所以就需要将文本转成用数字来表达。最直接的想法,就是类似查字典,构造一个字典,包含文本中所有出现的词汇,比如中文,可以每个字作为词典的一个元素,构成一个列表;一个句子就可以转换成由每个词的编号(词在词典中的序号)组成的数字表达。分词就是将连续的字序列按照一定的规范重新组合成语义独立词序列的过程,一个分词示例流程如下:
古典分词方法
拆分为单个字符(Character embedding)
基于子词的分词方法(Subword Tokenization)
字节对编码(BPE, Byte Pair Encoder),又称 digram coding 双字母组合编码,是一种数据压缩 算法,用来在固定大小的词表中实现可变⻓度的子词。该算法简单有效,因而目前它是最流行的方法。
WordPiece:WordPiece算法和BPE类似,区别在于WordPiece是基于概率生成新的subword而不是下一最高频字节对。- Unigram:它和 BPE 等一个不同就是,bpe是初始化一个小词表,然后一个个增加到限定的词汇量,而 Unigram 是先初始一个大词表,接着通过语言模型评估不断减少词表,直到限定词汇量。


NVIDIA 出品的 Megatron-LM 是一个基于 PyTorch 的分布式训练框架,用来训练基于 Transformer 的大型语言模型。Megatron-LM 综合应用了数据并行(Data Parallelism),张量并行(Tensor Parallelism)和流水线并行(Pipeline Parallelism)来复现 GPT-3.
【背景】
并行策略介绍:其中张量并行和流水线并行属于模型并行范畴




DeepSpeed的核心是ZeRO(Zero Redundancy Optimizer),简单来说,它是一种显存优化的数据并行(data parallelism, DP)方案。在过去两年DeepSpeed团队发表了三篇ZeRO相关的论文,提出了去除冗余参数、引入CPU和内存、引入NVMe等方法,从始至终都围绕着一个目标:将显存优化进行到底。
ZeRO将模型训练阶段,每张卡中显存内容分为两类:


【背景】之前的 PEFT 方法是 adapter/prefix/promp/P-tuning,但是Adapter会引入很强的推理延迟(只能串行),prefix/prompt/P-tuning很难练,而且要占用context length,变相的降低模型能力
【详解】具体来说,就是考虑到语言模型(LLM 尤其如此)的参数的低秩属性(low intrinsic dimension),或者说过参数化,在做 finetune 的时候不做 full-finetune,而是用一个降维矩阵 A 和一个升维矩阵 B 去做 finetune。如果我们认为原来的模型的某个参数矩阵为 $W_{0}$,那么可以认为原来经过全微调的参数矩阵为 $W_{0} + \Delta(W)$ ,但考虑到前面的低秩属性,在 lora 中我们可以简单认为 $\Delta(W)=BA$ (B 是升维矩阵,A 是降维矩阵,其中 A 正常随机数初始化,B 全 0 初始化,从而保证训练初期的稳定性),其中 BA 的秩相当于是你认为的模型实际的秩。这样的话在做推理的时候, $h=W_{0}x + BAx$ ,根本不会引入推理延迟,因为你只需要把训好的 lora 参数 $AB$ 加进模型初始权重 $W_{0}$ 中就可以了。在 Transformer 中 self-attention 和 mlp 模块都有对应的 params 矩阵,对应加上 lora 即可。
虽然理论上可以将 A 矩阵设置为 0(即 B 矩阵随机初始化),但研究表明这会导致次优性能。在论文 The Impact of Initialization on LoRA Finetuning Dynamics 中,作者比较了两种初始化方案:
研究发现:

预训练
后训练:包括监督微调(SFT)、在线强化学习(RL)和直接偏好优化(DPO),特别针对推理、编码和数学问题进行优化。SFT 和 DPO 使用小规模训练的原因是发现 SFT 和 DPO 会过度约束模型,限制了在线 RL 阶段的探索。后训练分为三个阶段:
Llama4 的三个不同规模大小的模型
| 模型 | 活跃参数 | 总参数 | 专家数 | 上下文窗口 | 备注 |
|---|---|---|---|---|---|
| Scout | 17B | 109B | 16 | 10M | 适合单 GPU 运行,性能优于 Gemini 2.0 Flash-Lite |
| Maverick | 17B | 400B | 128 | 未指定 | 性能优于 GPT-4o,成本效益高 |
| Behemoth | 288B | ~2T | 16 | 未指定 | 仍在训练中,预计超越 GPT-4.5 等模型 |



背景
DPO 实现方式


其中 $y_w$ 的被人类喜好程度大于 $y_l$,DPO loss 的梯度如下

可以看出该 loss 的作用主要是增加喜好数据的 likelihood,降低非喜好数据的 likelihood,同时会基于隐私 reward 估计的错误程度进行加权。本文的实验表明了这种加权的重要性,因为没有加权系数的这种方法的简单版本可能会导致语言模型退化

Let's think step by step"





MoE 的优势:速度与效率
预训练速度:由于具有稀疏层,它们的预训练速度比密集模型快得多。
推理速度:尽管规模较大,但它们提供更快的推理速度,在任何给定时间内仅使用其参数的一小部分。
低成本:与具有相同总参数数量的密集模型相比,由于前两点,MoE 模型在训练和推理上要便宜得多。
回答质量:通过为不同主题使用专家,它创建了一个表现更好的整体模型。能够记住更多信息并解决更多的特定场景。
MoE 的缺点:GPU 需求和难以训练
GPU VRAM 需求:一个问题是它们对 VRAM 的高需求,因为所有专家都需要加载到内存中,即使在某个特定时间只使用了 1 或 2 个。
微调困难:历史上,MoEs 在微调方面存在困难,经常导致过拟合。尽管现在在这方面已经取得了许多进展,并且变得更容易。
训练和推理的权衡:尽管提供了更快的推理,但它们需要对 VRAM 和计算资源进行谨慎管理。
参考:What is Temperature in NLP / LLMs?, NLP / LLMs中的Temperature 是什么?
温度系数直观解释
温度系数数学解释
参考:Huggingface 的 generate 方法介绍:top_p sampling、top_k sampling、greedy_search、beam_search
基于以下参数能避免重复样本生成
repetition_penalty
repetition_penalty 来降低重复序列的权重,具体代码如下,对于小于 0 的部分乘以 penalty 参数,大于 0 的部分乘以 penalty 参数,这里 penalty 一般设置为 1~2 之间,所以能够降低重复序列的值。核心代码如下:
score = torch.where(score < 0, score * self.penalty, score / self.penalty)
no_repeat_ngram_size
no_repeat_ngram_size=n 能够促使 n-gram 不会重复出现for i, banned_tokens in enumerate(banned_batch_tokens):
scores[i, banned_tokens] = -float("inf")
注意这里将 logits 置为负无穷后,经过 softmax 函数后就实现将概率置 0 了。参考: 为什么 output token 的价格比 input token 更贵?, 大模型output token为什么比input token贵?, 为什么使用大模型API时,output token 的价格比 input token 更贵?

在 KV cache(键值缓存)的支持下,大模型生成 token 分为两个阶段:
计算量和内存角度来看 input token 与 output token 差异不大
input token 与 output token 成本差异原因是资源利用率不同
46 commits
TypeScript
44.8%
CSS
31.1%
Python
23.7%
欢迎来到本 Repo!这里是一个专注于大语言模型学习的仓库,旨在为大语言模型学习入门者和大语言模型研发岗位的面试准备者提供全面的基础知识。
我们涵盖了多个主题,包括深度学习基础知识、自然语言处理基础知识、大语言模型基础知识以及大语言模型推理和应用等内容。你将在这里找到丰富的学习资料,帮助你构建对大语言模型的全面理解和应用能力。
除了基础知识,我们还会推荐一些大语言模型领域的前沿论文,帮助你跟上最新的研究进展,掌握最先进的技术。
无论你是新手还是有经验的从业者,本 Repo 都会为你提供有价值的学习资源。欢迎一起探索大语言模型的奥秘,让我们一同进步和成长!如果你有任何问题或建议,欢迎提出,我们将尽力完善这个仓库,为大家提供更好的学习体验。谢谢你的参与!
Transformer 模型的自注意力(Self Attention)机制涉及三种线性变换:查询(Q)、键(K)、值(V),以及通过计算注意力权重和加权求和来生成最终的输出。以下是自注意力机制的公式:
假设输入序列为 $X \in \mathbb{R}^{L \times d}$,其中 $L$ 是序列长度, $d$ 是特征维度。自注意力层中的线性变换矩阵为 $W_q \in \mathbb{R}^{d \times d_k}$、 $W_k \in \mathbb{R}^{d \times d_k}$ 和 $W_v \in \mathbb{R}^{d \times d_v}$,其中 $d_k$ 和 $d_v$ 是分割查询、键和值时的维度。
查询(Q)、键(K)和值(V)的线性变换:
多头拆分:
注意力得分计算:
注意力加权求和:
上述公式涵盖了Transformer模型中自注意力层的基本计算步骤。在实际应用中,通常还会考虑添加缩放(scaling)、掩码(masking)等操作来优化注意力机制的计算过程。多头自注意力则在每个头上分别进行这些计算,然后将多个头的输出拼接或串联起来,进一步提取序列中的信息
一个多头 Self Attention 代码实现如下:
import torch
import torch.nn.functional as F
class SelfAttentionLayer(torch.nn.Module):
def __init__(self, d_model, num_heads):
super(SelfAttentionLayer, self).__init__()
self.d_model = d_model
self.num_heads = num_heads
self.d_k = d_model // num_heads
# 线性变换矩阵
self.W_q = torch.nn.Linear(d_model, d_model, bias=False)
self.W_k = torch.nn.Linear(d_model, d_model, bias=False)
self.W_v = torch.nn.Linear(d_model, d_model, bias=False)
def split_heads(self, x, batch_size):
x = x.view(batch_size, -1, self.num_heads, self.d_k)
return x.permute(0, 2, 1, 3)
def forward(self, x):
batch_size, seq_len, d_model = x.size()
q = self.W_q(x)
k = self.W_k(x)
v = self.W_v(x)
q = self.split_heads(q, batch_size)
k = self.split_heads(k, batch_size)
v = self.split_heads(v, batch_size)
# Scaled Dot-Product Attention
attn_scores = torch.matmul(q, k.transpose(-2, -1)) / (self.d_k ** 0.5)
attn_weights = F.softmax(attn_scores, dim=-1)
# Attention加权求和
output = torch.matmul(attn_weights, v)
output = output.permute(0, 2, 1, 3).contiguous().view(batch_size, seq_len, -1)
return output
# 测试自注意力层
d_model = 512
num_heads = 8
seq_len = 10
batch_size = 16
input_data = torch.randn(batch_size, seq_len, d_model)
self_attention = SelfAttentionLayer(d_model, num_heads)
output = self_attention(input_data)
print(output.size()) # 输出: torch.Size([16, 10, 512])
上面 Transformer 代码中有使用 $\sqrt{d_{k}}$ 来对 softmax 之后的结果进行 scale,解释如下:
We suspect that for large values of $d_{k}$, the dot products grow large in magnitude, pushing the softmax function into regions where it has extremely small gradients. To counteract this effect, we scale the dot products by $\frac{1}{d_{k}}$. To illustrate why the dot products get large, assume that the components of q and k are independent random variables with mean 0 and variance 1. Then their dot product $q ⋅ k=\sum_{i=1}^{d_{k}}(q_{i}k_{i})$, has mean 0 and variance $d_{k}$.
对于任何一门语言,单词在句子中的位置以及排列顺序是非常重要的,它们不仅是一个句子的语法结构的组成部分,更是表达语义的重要概念。一个单词在句子的位置或排列顺序不同,可能整个句子的意思就发生了偏差。
I do not like the story of the movie, but I do like the cast. I do like the story of the movie, but I do not like the cast. 上面两句话所使用的的单词完全一样,但是所表达的句意却截然相反。那么,引入词序信息有助于区别这两句话的意思。
Transformer 模型抛弃了 RNN、CNN 作为序列学习的基本模型。我们知道,循环神经网络本身就是一种顺序结构,天生就包含了词在序列中的位置信息。当抛弃循环神经网络结构,完全采用 Attention 取而代之,这些词序信息就会丢失,模型就没有办法知道每个词在句子中的相对和绝对的位置信息。因此,有必要把词序信号加到词向量上帮助模型学习这些信息,位置编码(Positional Encoding)就是用来解决这种问题的方法。

根据复数乘法的几何意义,该变换实际上对应着向量的旋转,所以我们称之为“旋转式位置编码”

- 左半部分为预训练阶段的位置向量范围[0,2048]
- 右上角为长度外推的部分(2048,4096]
- 左下角为位置插值法,将[0,4096]的值降采样到[0,2048]预训练阶段支持的范围
参考:为什么 Pre Norm 的效果不如 Post Norm?

对于一个NCHW(批次大小,通道数,高度,宽度)格式的输入张量,Batch Normalization(BN)层通常包含两组可学习参数:缩放因子(scale)和偏移(shift)。
基于 pytorch 的 BN 示例代码
# CV Example
import torch
import torch.nn as nn
batch, channel, height, width = 20, 100, 35, 45
input = torch.randn(batch, channel, height, width)
m = nn.BatchNorm2d(channel)
output = m(input)
for k, v in m.named_parameters():
print(k, v.shape)
# -> weight torch.Size([100])
# -> bias torch.Size([100])
# NLP Example
import torch
import torch.nn as nn
batch, sentence_length, embedding_dim = 20, 5, 10
embedding = torch.randn(batch, sentence_length, embedding_dim)
layer_norm = nn.LayerNorm(embedding_dim)
output = layer_norm(embedding)
for k, v in layer_norm.named_parameters():
print(k, v.shape)
# -> weight torch.Size([10])
# -> bias torch.Size([10])
import torch
import torch.nn as nn
N, C, H, W = 20, 5, 10, 15
input = torch.randn(N, C, H, W)
layer_norm = nn.LayerNorm([C, H, W])
output = layer_norm(input)
for k, v in layer_norm.named_parameters():
print(k, v.shape)
# -> weight torch.Size([5, 10, 15])
# -> bias torch.Size([5, 10, 15])
语言模型是对文本进行推理。由于文本是字符串,但对模型来说,输入只能是数字,所以就需要将文本转成用数字来表达。最直接的想法,就是类似查字典,构造一个字典,包含文本中所有出现的词汇,比如中文,可以每个字作为词典的一个元素,构成一个列表;一个句子就可以转换成由每个词的编号(词在词典中的序号)组成的数字表达。分词就是将连续的字序列按照一定的规范重新组合成语义独立词序列的过程,一个分词示例流程如下:
古典分词方法
拆分为单个字符(Character embedding)
基于子词的分词方法(Subword Tokenization)
字节对编码(BPE, Byte Pair Encoder),又称 digram coding 双字母组合编码,是一种数据压缩 算法,用来在固定大小的词表中实现可变⻓度的子词。该算法简单有效,因而目前它是最流行的方法。
WordPiece:WordPiece算法和BPE类似,区别在于WordPiece是基于概率生成新的subword而不是下一最高频字节对。- Unigram:它和 BPE 等一个不同就是,bpe是初始化一个小词表,然后一个个增加到限定的词汇量,而 Unigram 是先初始一个大词表,接着通过语言模型评估不断减少词表,直到限定词汇量。


NVIDIA 出品的 Megatron-LM 是一个基于 PyTorch 的分布式训练框架,用来训练基于 Transformer 的大型语言模型。Megatron-LM 综合应用了数据并行(Data Parallelism),张量并行(Tensor Parallelism)和流水线并行(Pipeline Parallelism)来复现 GPT-3.
【背景】
并行策略介绍:其中张量并行和流水线并行属于模型并行范畴




DeepSpeed的核心是ZeRO(Zero Redundancy Optimizer),简单来说,它是一种显存优化的数据并行(data parallelism, DP)方案。在过去两年DeepSpeed团队发表了三篇ZeRO相关的论文,提出了去除冗余参数、引入CPU和内存、引入NVMe等方法,从始至终都围绕着一个目标:将显存优化进行到底。
ZeRO将模型训练阶段,每张卡中显存内容分为两类:


【背景】之前的 PEFT 方法是 adapter/prefix/promp/P-tuning,但是Adapter会引入很强的推理延迟(只能串行),prefix/prompt/P-tuning很难练,而且要占用context length,变相的降低模型能力
【详解】具体来说,就是考虑到语言模型(LLM 尤其如此)的参数的低秩属性(low intrinsic dimension),或者说过参数化,在做 finetune 的时候不做 full-finetune,而是用一个降维矩阵 A 和一个升维矩阵 B 去做 finetune。如果我们认为原来的模型的某个参数矩阵为 $W_{0}$,那么可以认为原来经过全微调的参数矩阵为 $W_{0} + \Delta(W)$ ,但考虑到前面的低秩属性,在 lora 中我们可以简单认为 $\Delta(W)=BA$ (B 是升维矩阵,A 是降维矩阵,其中 A 正常随机数初始化,B 全 0 初始化,从而保证训练初期的稳定性),其中 BA 的秩相当于是你认为的模型实际的秩。这样的话在做推理的时候, $h=W_{0}x + BAx$ ,根本不会引入推理延迟,因为你只需要把训好的 lora 参数 $AB$ 加进模型初始权重 $W_{0}$ 中就可以了。在 Transformer 中 self-attention 和 mlp 模块都有对应的 params 矩阵,对应加上 lora 即可。
虽然理论上可以将 A 矩阵设置为 0(即 B 矩阵随机初始化),但研究表明这会导致次优性能。在论文 The Impact of Initialization on LoRA Finetuning Dynamics 中,作者比较了两种初始化方案:
研究发现:

预训练
后训练:包括监督微调(SFT)、在线强化学习(RL)和直接偏好优化(DPO),特别针对推理、编码和数学问题进行优化。SFT 和 DPO 使用小规模训练的原因是发现 SFT 和 DPO 会过度约束模型,限制了在线 RL 阶段的探索。后训练分为三个阶段:
Llama4 的三个不同规模大小的模型
| 模型 | 活跃参数 | 总参数 | 专家数 | 上下文窗口 | 备注 |
|---|---|---|---|---|---|
| Scout | 17B | 109B | 16 | 10M | 适合单 GPU 运行,性能优于 Gemini 2.0 Flash-Lite |
| Maverick | 17B | 400B | 128 | 未指定 | 性能优于 GPT-4o,成本效益高 |
| Behemoth | 288B | ~2T | 16 | 未指定 | 仍在训练中,预计超越 GPT-4.5 等模型 |



背景
DPO 实现方式


其中 $y_w$ 的被人类喜好程度大于 $y_l$,DPO loss 的梯度如下

可以看出该 loss 的作用主要是增加喜好数据的 likelihood,降低非喜好数据的 likelihood,同时会基于隐私 reward 估计的错误程度进行加权。本文的实验表明了这种加权的重要性,因为没有加权系数的这种方法的简单版本可能会导致语言模型退化

Let's think step by step"





MoE 的优势:速度与效率
预训练速度:由于具有稀疏层,它们的预训练速度比密集模型快得多。
推理速度:尽管规模较大,但它们提供更快的推理速度,在任何给定时间内仅使用其参数的一小部分。
低成本:与具有相同总参数数量的密集模型相比,由于前两点,MoE 模型在训练和推理上要便宜得多。
回答质量:通过为不同主题使用专家,它创建了一个表现更好的整体模型。能够记住更多信息并解决更多的特定场景。
MoE 的缺点:GPU 需求和难以训练
GPU VRAM 需求:一个问题是它们对 VRAM 的高需求,因为所有专家都需要加载到内存中,即使在某个特定时间只使用了 1 或 2 个。
微调困难:历史上,MoEs 在微调方面存在困难,经常导致过拟合。尽管现在在这方面已经取得了许多进展,并且变得更容易。
训练和推理的权衡:尽管提供了更快的推理,但它们需要对 VRAM 和计算资源进行谨慎管理。
参考:What is Temperature in NLP / LLMs?, NLP / LLMs中的Temperature 是什么?
温度系数直观解释
温度系数数学解释
参考:Huggingface 的 generate 方法介绍:top_p sampling、top_k sampling、greedy_search、beam_search
基于以下参数能避免重复样本生成
repetition_penalty
repetition_penalty 来降低重复序列的权重,具体代码如下,对于小于 0 的部分乘以 penalty 参数,大于 0 的部分乘以 penalty 参数,这里 penalty 一般设置为 1~2 之间,所以能够降低重复序列的值。核心代码如下:
score = torch.where(score < 0, score * self.penalty, score / self.penalty)
no_repeat_ngram_size
no_repeat_ngram_size=n 能够促使 n-gram 不会重复出现for i, banned_tokens in enumerate(banned_batch_tokens):
scores[i, banned_tokens] = -float("inf")
注意这里将 logits 置为负无穷后,经过 softmax 函数后就实现将概率置 0 了。参考: 为什么 output token 的价格比 input token 更贵?, 大模型output token为什么比input token贵?, 为什么使用大模型API时,output token 的价格比 input token 更贵?

在 KV cache(键值缓存)的支持下,大模型生成 token 分为两个阶段:
计算量和内存角度来看 input token 与 output token 差异不大
input token 与 output token 成本差异原因是资源利用率不同
46 commits
TypeScript
44.8%
CSS
31.1%
Python
23.7%