llm learning

Ethereal Lv4

1. LoRA

主要参考

Hoper-J/AI-Guide-and-Demos-zh_CN: 这是一份入门AI/LLM大模型的逐步指南,包含教程和演示代码,带你从API走进本地大模型部署和微调,代码文件会提供Kaggle或Colab在线版本,即便没有显卡也可以进行学习。项目中还开设了一个小型的代码游乐场🎡,你可以尝试在里面实验一些有意思的AI脚本。同时,包含李宏毅 (HUNG-YI LEE)2024生成式人工智能导论课程的完整中文镜像作业。

AI-Guide-and-Demos-zh_CN/Guide/16. 用 LoRA 微调 Stable Diffusion:拆开炼丹炉,动手实现你的第一次 AI 绘画.md at master · Hoper-J/AI-Guide-and-Demos-zh_CN

1.1 安装必要包

1
2
pip install torch torchvision transformers diffusers peft Pillow tqdm pyyaml accelerate
pip3 install torch==2.4.1 torchvision torchaudio -f https://mirrors.aliyun.com/pytorch-wheels/cu121/

1.2 设置huggingface镜像

1
# export HF_ENDPOINT=https://hf-mirror.com
1
2
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com/"

1.3 代码梳理

1.3.1 加载模型

  1. 加载噪声调度器:noise_scheduler = DDPMScheduler.from_pretrained

  2. 加载 Tokenizer:tokenizer = CLIPTokenizer.from_pretrained

  3. 加载 CLIP 文本编码器:text_encoder = CLIPTextModel.from_pretrained

  4. 加载 VAE 模型:vae = AutoencoderKL.from_pretrained

  5. 加载 UNet 模型:unet = UNet2DConditionModel.from_pretrained

  6. 转换为LoRA模型:get_peft_model(text_encoder, lora_config)PeftModel.from_pretrained(text_encoder, ...)

  7. 获取可训练LoRA参数:text_encoder.print_trainable_parameters()

  8. 冻结不需要训练模型的参数:vae.requires_grad_(False)

1.3.2 准备数据

  1. 自己定义数据类:Text2ImageDataset(定义__init____getitem____len__方法)

  2. 设定数据集预处理方法:transforms.Compose

  3. 加载数据集加载方法:torch.utils.data.DataLoadercollate_fn

1.3.3 准备学习器

prepare_optimizer使用AdamW学习器

1.3.4 准备学习率调节器

get_scheduler

1.3.5 切入训练模式

1
2
unet.train()
text_encoder.train()

1.3.6 计算损失

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 获取原图像向量
## 编码图像为潜在表示(latent)
latents = vae.encode(batch["pixel_values"].to(DEVICE, dtype=args.weight_dtype)).latent_dist.sample()
latents = latents * vae.config.scaling_factor ## 根据 VAE 的缩放因子调整潜在空间
## 加入噪声
noise = torch.randn_like(latents) # 生成与潜在表示相同形状的随机噪声
timesteps = torch.randint(0, noise_scheduler.config.num_train_timesteps, (latents.shape[0],), device=DEVICE).long()
noisy_latents = noise_scheduler.add_noise(latents, noise, timesteps)
## 获取文本编码
encoder_hidden_states = text_encoder(batch["input_ids"].to(DEVICE))[0]

## 预测噪声
model_pred = unet(noisy_latents, timesteps, encoder_hidden_states)[0]

## 计算损失
loss = F.mse_loss(model_pred.float(), target.float(), reduction="mean")

1.3.7 反向传播

1
2
3
loss.backward()
optimizer.step()
lr_scheduler.step()

其中,loss给可以调整的参数加上loss标记,做反向传播;optimizer根据学习率与计算方式将梯度应用到当前的参数上;lr_scheduler更新学习率

1.3.8 推理

  1. 切换为评估模式:text_encoder.eval()

  2. 创建SD执行流:DiffusionPipeline.from_pretrained

  3. 加载文本:load_validation_prompts

  4. 创建初始图像:采用随机数torch.Generator

  5. 推理

图文、代码详解BeamSearch - 知乎

产生预测的方式:全部搜索(不可能)、贪心(不一定全局最优)、多路(束搜索)

3. 采样

top-k:排序后直接取前k个

top-p:排序后取大于p的

4. DPO微调

可以同时对正向和反向的文本进行编码,并根据两者计算loss

5. 量化

  1. 对称量化

  2. 非对称量化

区别在于量化值区间是否限制了量化前后零点对应

6. token与embedding

  1. token:用于将文本映射成序列号

  2. embedding:用于丰富token含义

7. Transformer

  • Mask: KV Cache因为mask才可以进行。因为mask的缘故,使得计算只需要求和前面的即可。

  • 多级:更多层次地提取特征,相关性只是第一层通过注意力机制提取的特征。每级最终会经过FFN进一步归纳提取特征。

    • 为什么多级不会损失位置信息?提前在embedding时候将位置信息拼接到后面了

    • RoPE:旋转位置编码,引入的位置信息包含更多的相对位置信息

  • 计算权重:最终的经过FFN后的特征,再通过简单的线性层即可映射到词表空间,每个元素都是概率。通过搜索即可得到最大概率对应的词 。

  • 多头注意力:将输入经过embedding之后的切成多份。

  • 交叉注意力:Q与KV来自不同的样本,此时类似transformer经典的encode-decode架构

  • Multi-Head Latent Attention (MLA):通过低秩联合压缩技术,减少 K 和 V 矩阵的存储和计算开销

    • 对 K 和 V 矩阵进行低秩联合压缩

    • 对查询矩阵 Q 进行低秩压缩

    • 修改注意力计算方式

  • CacheBlend

    • 目标

      • 提前缓存KV Cache
    • 困难

      • KV Cache中携带位置信息

      • 交叉注意力

    • 解决方案

      • 使用RoPE,将绝对的位置信息改为通过矩阵旋转即可得到的位置信息

      • 观察到交叉注意力比较稀疏,因此只选取一些计算

  • 1850883-20250329150518961-375532481

8. 存储结合

8.1 LMCache

可以直接从源码安装

1
pip install -e .

例子都要求有GPU

8.2 llmperf

直接通过源码安装

1
pip install -e .

测试llm,可以指定地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export HF_ENDPOINT="https://hf-mirror.com"
export OPENAI_API_KEY=secret_abcdefg
export OPENAI_API_BASE="https://api.endpoints.anyscale.com/v1"

python token_benchmark_ray.py \
--model "meta-llama/Llama-2-7b-chat-hf" \
--mean-input-tokens 550 \
--stddev-input-tokens 150 \
--mean-output-tokens 150 \
--stddev-output-tokens 10 \
--max-num-completed-requests 2 \
--timeout 600 \
--num-concurrent-requests 1 \
--results-dir "result_outputs" \
--llm-api openai \
--additional-sampling-params '{}'

测试结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
\Results for token benchmark for gpt-4o queried with the openai api.

inter_token_latency_s
p25 = 0.02136684221360152
p50 = 0.02494121372332496
p75 = 0.0285155852330484
p90 = 0.030660208138882462
p95 = 0.03137508244082715
p99 = 0.0319469818823829
mean = 0.02494121372332496
min = 0.01779247070387808
max = 0.03208995674277184
stddev = 0.010109849332021768
ttft_s
p25 = 1.0939928072330076
p50 = 1.111728697491344
p75 = 1.1294645877496805
p90 = 1.1401061219046824
p95 = 1.1436532999563496
p99 = 1.1464910423976835
mean = 1.111728697491344
min = 1.0762569169746712
max = 1.147200478008017
stddev = 0.050164673088200495
end_to_end_latency_s
p25 = 3.1619555402430706
p50 = 3.7565545674879104
p75 = 4.35115359473275
p90 = 4.707913011079654
p95 = 4.826832816528622
p99 = 4.921968660887797
mean = 3.7565545674879104
min = 2.5673565129982308
max = 4.94575262197759
stddev = 1.6817800170070039
request_output_throughput_token_per_s
p25 = 43.90441006830381
p50 = 51.211761238901175
p75 = 58.51911240949853
p90 = 62.90352311185695
p95 = 64.36499334597642
p99 = 65.53416953327199
mean = 51.211761238901175
min = 36.597058897706454
max = 65.82646358009589
stddev = 20.668310260963395
number_input_tokens
p25 = 548.75
p50 = 559.5
p75 = 570.25
p90 = 576.7
p95 = 578.85
p99 = 580.57
mean = 559.5
min = 538
max = 581
stddev = 30.405591591021544
number_output_tokens
p25 = 172.0
p50 = 175.0
p75 = 178.0
p90 = 179.8
p95 = 180.4
p99 = 180.88
mean = 175.0
min = 169
max = 181
stddev = 8.48528137423857
Number Of Errored Requests: 0
Overall Output Throughput: 43.19723004741316
Number Of Completed Requests: 2
Completed Requests Per Minute: 14.810478873398797

8.3 部署配置要求

8.3.1 vllm

8.3.2 lmcache

9. 超长文本

9.1 位置编码

【位置编码速通】从ROPE到Yarn:通用公式解析长文本大模型的位置编码!_知识图谱_拥抱AGI-MCP技术社区

  • RoPE

  • Position Interpolation (PI):均匀拉伸的位置插值,也叫线性内插

  • NTK-Aware Interpolation:非均匀频率缩放,介于直接外推和线性内插之间的平滑方法

  • Dynamic Scaling:动态适配插值比例, NTK-Aware Interpolation升级版

  • NTK-by-parts Interpolation:基于波长局部分段插值

  • Yarn

9.2 分割

LLM - 长文本总结处理方案_当文档的长度过长时,llm怎样处理-CSDN博客

  • Map Reduce

  • Refine

  • Map Rerank

  • Binary Map

9.3 RAG

LLM大模型对超长文本处理的技术方案汇总(NBCE、Unlimiformer)_超长文档+大模型-CSDN博客

  • InfLLM:每次生成下一个token的时,Initial token和一个窗口内的token,Evicted token会分块,检索一部分token出来。(选取块中最具有特征的几个token)

    • 猜测:选取的token可以事先计算?具有特征是否可以使用当下注意力最高的token

    • 是否可以与位置编码融合?也就是说选取的token采用RoPE等方式计算:可能用处不大

  • NBCE:对长文本进行分段,对每段上文进行独立编码,在输出层对每一个Step预测token的概率矩阵进行融合

    • 猜测:可能损失块之间的位置信息
  • PCW:基本同NBCE

  • MemLong:类似RAG,只给大模型传递索引

  • Unlimiformer:将注意力计算外包给一个k-最近邻(kNN)索引来实现

  • AutoCompress:长文本上下文压缩成紧凑的摘要向量,这些向量随后可以作为软提示(soft prompts)供模型使用。

10. 算子

算子是Pytorch等框架与底层如cuda或openvino交互的方式

10.1 添加C++实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
at::Tensor mymuladd_cpu(at::Tensor a, const at::Tensor& b, double c) {
TORCH_CHECK(a.sizes() == b.sizes());
TORCH_CHECK(a.dtype() == at::kFloat);
TORCH_CHECK(b.dtype() == at::kFloat);
TORCH_INTERNAL_ASSERT(a.device().type() == at::DeviceType::CPU);
TORCH_INTERNAL_ASSERT(b.device().type() == at::DeviceType::CPU);
at::Tensor a_contig = a.contiguous();
at::Tensor b_contig = b.contiguous();
at::Tensor result = torch::empty(a_contig.sizes(), a_contig.options());
const float* a_ptr = a_contig.data_ptr<float>();
const float* b_ptr = b_contig.data_ptr<float>();
float* result_ptr = result.data_ptr<float>();
for (int64_t i = 0; i < result.numel(); i++) {
result_ptr[i] = a_ptr[i] * b_ptr[i] + c;
}
return result;
}

以下是softmax实现:

1
2
3
4
5
6
7
torch::Tensor softmax_impl(torch::Tensor input, int64_t dim) {
auto max_val = input.amax(dim, true); // 沿维度求最大值
auto shifted = input - max_val; // 减去最大值
auto exp_output = torch::exp(shifted); // 指数化
auto sum_exp = exp_output.sum(dim, true); // 计算分母
return exp_output / sum_exp; // 归一化
}

10.2 注册算子

声明

1
2
3
4
5
TORCH_LIBRARY(extension_cpp, m) {
// Note that "float" in the schema corresponds to the C++ double type
// and the Python float type.
m.def("mymuladd(Tensor a, Tensor b, float c) -> Tensor");
}

定义

1
2
3
TORCH_LIBRARY_IMPL(extension_cpp, CPU, m) {
m.impl("mymuladd", &mymuladd_cpu);
}

为算子添加 torch.compile 支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Important: the C++ custom operator definitions should be loaded first
# before calling ``torch.library`` APIs that add registrations for the
# C++ custom operator(s). The following import loads our
# C++ custom operator definitions.
# Note that if you are striving for Python agnosticism, you should use
# the ``load_library(...)`` API call instead. See the next section for
# more details.
from . import _C

@torch.library.register_fake("extension_cpp::mymuladd")
def _(a, b, c):
torch._check(a.shape == b.shape)
torch._check(a.dtype == torch.float)
torch._check(b.dtype == torch.float)
torch._check(a.device == b.device)
return torch.empty_like(a)

此外,也可以使用pybind方式注册算子。

10.3 添加训练支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def _backward(ctx, grad):
a, b = ctx.saved_tensors
grad_a, grad_b = None, None
if ctx.needs_input_grad[0]:
grad_a = grad * b
if ctx.needs_input_grad[1]:
grad_b = grad * a
return grad_a, grad_b, None

def _setup_context(ctx, inputs, output):
a, b, c = inputs
saved_a, saved_b = None, None
if ctx.needs_input_grad[0]:
saved_b = b
if ctx.needs_input_grad[1]:
saved_a = a
ctx.save_for_backward(saved_a, saved_b)

# This code adds training support for the operator. You must provide us
# the backward formula for the operator and a `setup_context` function
# to save values to be used in the backward.
torch.library.register_autograd(
"extension_cpp::mymuladd", _backward, setup_context=_setup_context)

参考

用 LoRA 微调 Stable Diffusion:拆开炼丹炉,动手实现你的第一次 AI 绘画_lora微调stable diffusion-CSDN博客

使用 Lora进行微调DeepSeek大模型_deepseek lora-CSDN博客

tloen/alpaca-lora: Instruct-tune LLaMA on consumer hardware

大模型轻量级微调(LoRA):训练速度、显存占用分析 - 知乎

Hoper-J/AI-Guide-and-Demos-zh_CN: 这是一份入门AI/LLM大模型的逐步指南,包含教程和演示代码,带你从API走进本地大模型部署和微调,代码文件会提供Kaggle或Colab在线版本,即便没有显卡也可以进行学习。项目中还开设了一个小型的代码游乐场🎡,你可以尝试在里面实验一些有意思的AI脚本。同时,包含李宏毅 (HUNG-YI LEE)2024生成式人工智能导论课程的完整中文镜像作业。

Stable Diffusion(SD)核心基础知识——(文生图、图生图)_sd模型-CSDN博客

如何快速下载huggingface模型——全方法总结 - 知乎

huggingface-cli下载数据(含国内镜像源方法)_huggingface-cli download-CSDN博客

理解Pytorch的loss.backward()和optimizer.step() - 知乎

OSError: Can‘t load tokenizer for ‘bert-base-chinese‘_oserror: can’t load tokenizer for ‘bert-base-chine-CSDN博客

ComfyUI:Stable Diffusion 及 LoRA、VAE 、ControlNet模型解析 - 知乎

AIGC-Stable Diffusion之VAE - 知乎

AI-Guide-and-Demos-zh_CN/Guide/17. 浅谈 RTN 模型量化:非对称 vs 对称.md at master · Hoper-J/AI-Guide-and-Demos-zh_CN

AI-Guide-and-Demos-zh_CN/Guide/g. 嵌入层 nn.Embedding() 详解和要点提醒(PyTorch).md at master · Hoper-J/AI-Guide-and-Demos-zh_CN

AI-Guide-and-Demos-zh_CN/Guide/18. 模型量化技术概述及 GGUF & GGML 文件格式解析.md at master · Hoper-J/AI-Guide-and-Demos-zh_CN

对称量化 VS 非对称量化 - 知乎

AI-Guide-and-Demos-zh_CN/Guide/11. DPO 微调示例:根据人类偏好优化 LLM 大语言模型.md at master · Hoper-J/AI-Guide-and-Demos-zh_CN

探秘Transformer系列之(20)— KV Cache - 罗西的思考 - 博客园

LLM 推理加速 - KV Cache - MartinLwx’s Blog

注意力机制到底在做什么,Q/K/V怎么来的?一文读懂Attention注意力机制

拆 Transformer 系列二:Multi- Head Attention 机制详解 - 知乎

神经网络算法 - 一文搞懂 Softmax 函数-CSDN博客

Transformer模型详解(图解最完整版) - 知乎

翻译: 详细图解Transformer多头自注意力机制 Attention Is All You Need-CSDN博客

(80 条消息) 为什么加速LLM推断有KV Cache而没有Q Cache? - 知乎

大模型推理加速:看图学KV Cache - 知乎

注意力机制到底在做什么,Q/K/V怎么来的?一文读懂Attention注意力机制

(80 条消息) Transformer中的Attention机制,注意力分布概率是如何求得的? - 知乎

Transformer 架构 « Leinux

十分钟读懂旋转编码(RoPE)

Multi-Head Latent Attention (MLA) 详细介绍(来自Deepseek V3的回答) - 知乎

举个例子讲下transformer的输入输出细节及其他 - 知乎

大模型百倍推理加速之KV cache篇 - 知乎

详解 CacheBlend:RAG 场景 KV 复用,打破前缀相同的限制 - 知乎

Welcome to LMCache! | LMCache

Installation | LMCache

ray-project/llmperf: LLMPerf is a library for validating and benchmarking LLMs

【踩坑】pip安装依赖卡在Installing build dependencies …-CSDN博客

Example: Offload KV cache to CPU | LMCache

Support for compute capability <7.0 · Issue #963 · vllm-project/vllm

1. CUDA 12.9 Release Notes — Release Notes 12.9 documentation

各 GPU 支持的 CUDA 版本 gpu cuda支持列表_mob64ca13ff28f1的技术博客_51CTO博客

NVIDIA GeForce 驱动程序 - N 卡驱动 | NVIDIA

CUDA GPU Compute Capability | NVIDIA Developer

Legacy CUDA GPU Compute Capability | NVIDIA Developer

【位置编码速通】从ROPE到Yarn:通用公式解析长文本大模型的位置编码!_知识图谱_拥抱AGI-MCP技术社区

清华NLP组发布InfLLM:无需额外训练,「1024K超长上下文」100%召回!-腾讯云开发者社区-腾讯云

PyTorch源码学习系列 - 3. 算子 - 知乎

PyTorch源码学习 - 知乎

自定义 C++ 和 CUDA 算子 — PyTorch 教程 2.7.0+cu126 文档 - PyTorch 深度学习库

自定义 Python 算子 — PyTorch 教程 2.7.0+cu126 文档 - PyTorch 深度学习库

PyTorch 自定义算子 — PyTorch 教程 2.7.0+cu126 文档 - PyTorch 深度学习库

深入浅出PyTorch(算子篇) - A君来了 - 博客园

PyTorch 源码解读之 :揭秘 C++/CUDA 算子实现和调用全流程-CSDN博客

PyTorch扩展自定义PyThon/C++(CUDA)算子的若干方法总结 - 知乎

pytorch自定义算子实现详解及反向传播梯度推导 - 知乎

【pytorch扩展】CUDA自定义pytorch算子(简单demo入手)_pytorch_木盏-AI编程社区

pytorch自定义算子并导出onnx计算图详细代码教程_pytorch输出模型的算子图结构-CSDN博客

Pytorch算子扩展详细例程(前向+反向) - BrianX - 博客园

【pytorch】解决pytorch:Torch not compiled with CUDA enabled-阿里云开发者社区

错误Torch not compiled with CUDA enabled解决方法附CUDA安装教程及Pytorch安装教程-CSDN博客

GPU版本pytorch(Cuda12.1)清华源快速安装一步一步教!小白教学~_pytorch清华源-CSDN博客

使用国内镜像加速安装 PyTorch | 无问芯穹文档

  • Title: llm learning
  • Author: Ethereal
  • Created at: 2025-04-06 17:07:30
  • Updated at: 2025-06-11 15:42:29
  • Link: https://ethereal-o.github.io/2025/04/06/llm-learning/
  • License: This work is licensed under CC BY-NC-SA 4.0.
 Comments