大模型入门:训练、微调、量化精度与模型选型

📅 发布时间:2026/9/27 17:58:27
大模型入门:训练、微调、量化精度与模型选型
一、训练把随机数字变成有用的数字先分清两件常被混为一谈的事。训练是造模型推理是用模型。训练拿海量文本反复做文字接龙——预测下一个 token猜错了就把内部参数往「让正确答案概率更高」的方向调一点。这个循环要转很多很多遍。推理则是拿这堆已经固定下来的数字对你的输入算一遍得到下一个 token每调用一次 API就是一次推理。分界线只有一条参数动不动。训练时参数一直在被修改推理时参数是只读的。这条推论的用处比看上去大模型不会因为跟你聊过什么而改变。对话历史是每次请求重新打包发给它的不是它记住了。想让它变只能回去改文件里的数字——那又是训练。训练留下了什么产物是一大堆固定下来的数字词表、embedding 矩阵、每一层的权重打包成你能下载到的模型文件。以 Qwen3-0.6B 为例model.safetensors里是 311 块张量model.embed_tokens.weight [151936, 1024] model.layers.0.self_attn.q_proj.weight [2048, 1024] model.layers.0.mlp.gate_proj.weight [3072, 1024] ... model.layers.27.mlp.down_proj.weight [1024, 3072]模型「学到的东西」就是这样一堆二维矩阵没有一个是人写的。embedding 那张表最能说明训练在干什么。刚建表时里面全是随机数训练过程中经常出现在相似位置的词——比如「我养了一只 ___」里的「猫」和「狗」——它们的向量会被推到相近的位置。所谓「语义相近的向量也相近」不是设计出来的是海量接龙的副产品。151,936 × 1,024 ≈ 1.56 亿个数每个数 2 byteBF16光这一张表就占 311MB。训练存档checkpoint训练要持续调整大量参数中途断了不能从头再来所以训练程序会定期把当时的状态存下来当前权重、优化器状态、已完成的步数。这份存档叫 checkpoint仓库里的checkpoint-1000、checkpoint-2000就是不同步数的版本。普通使用者应该挑作者明确发布的最终版本。中间存档可能还没训到位效果不理想。训练之前先切数据这块是我笔记里最完整、也最容易被跳过的一段。模型学规律用训练集调参和选模型用验证集最终评估用测试集。三件事由三批互斥的数据来做。集合干什么关键约束训练集更新模型参数也是预处理唯一能拟合的地方验证集调参、早停、选模型不更新参数但反复用很多轮也会被用脏测试集最终评估训练和调参阶段必须隔离不能拿来调参三条最容易踩的线不能有样本重叠。哪怕只有一条样本同时出现在两个集合里评估隔离就已经破了。预处理只在训练集上拟合。标准化、归一化、特征选择、PCA——这些步骤如果提前看见了全量数据就是预处理泄漏分数会虚高。时间序列不能随机打乱。按时间顺序切否则未来信息会漏到过去。数据量不足以切固定验证集时可以先留出测试集再在训练集内部做 K 折交叉验证fromsklearn.model_selectionimporttrain_test_split,KFold# 测试集先独立留出之后不再碰X_train_all,X_test,y_train_all,y_testtrain_test_split(X,y,test_size0.2,random_state42,stratifyy)# 剩下的在训练集内部轮流当训练/验证kfKFold(n_splits5,shuffleTrue,random_state42)fortr_idx,va_idxinkf.split(X_train_all):X_tr,X_vaX_train_all[tr_idx],X_train_all[va_idx]# 每一折都要重新拟合预处理器再 transform 验证部分要注意的是交叉验证给出的是「某套超参数或方法」的平均泛化能力不是某一个最终模型的分数——每一折训练出来的都是独立模型。二、微调从只会接话到会答话这一节短因为笔记里就这么多。Base 模型是纯粹的文本补全模型只会「接话」。你把问题丢给它它可能顺着续写更多问题——因为它学的是「下一段文字长什么样」不是「怎么回答问题」。Instruct 模型是在 Base 基础上做过指令对齐的会把你的输入当成问题来回答。Chat 模型同类。于是选择很直接日常聊天、写代码、当助手 → 选Instruct或Chat版本想继续预训练、或者自己微调 → 才需要 Base 版本作起点模型卡上通常会标清楚这是 Base、Instruct 还是 Chat。另外微调后的权重通常仍存成 Safetensors和原始权重是同一套文件格式只是里面的数字变了。还有一句值得单独拎出来同规模的不同模型、同模型的不同微调版本实际表现差距可能很大。别看到 7B 就当它们是同一个水平。三、量化与精度每个数占几个字节字母 B 在模型语境里有两个毫不相干的含义。出现在哪B 的全称含义例子GB/MB/KB/TBByte字节存储大小权重文件 1.50GB显存 28GB14B/0.6B/70BBillion十亿参数量14B ≈ 140 亿个参数最典型的误读是把qwen3:0.6b里的0.6b当成 0.6GB。这个模型的实际磁盘占用是 522MB——看着「碰巧接近」但两者毫无关系参数量 6 亿是「有多少个数字」522MB 是「这些数字存下来占多大」。一句话记法看到 G/M/K 打头的容量单位B 是字节问的是「占多大」看到光秃秃的 N B 当模型名B 是十亿问的是「多少个参数」。一条估算公式占用 ≈ 参数量 × 每个参数占用的字节数参数量定「有多少个数」数值格式定「每个数占几个字节」两者相乘才是文件大小 / 显存占用。字节数的算法很直白位数 ÷ 8FP32 就是 32 ÷ 8 4。精度每个参数占用FP324 字节FP16 / BF162 字节INT81 字节INT40.5 字节2-bit0.25 字节代入 14B约 140 亿参数精度估算占用FP32约 56 GBFP16约 28 GBINT8约 14 GBINT4约 7 GB2-bit约 3.5 GB这个式公式是我平时计算「我这台机器跑不跑得动」用的。FP 和 INT 是两个家族格式族全称特点常见档位FPFloating Point浮点数能表示小数数值范围广FP324 字节、FP16 / BF162 字节INTInteger整数更省空间计算更快INT81 字节、INT40.5 字节容易混的一点FP / INT 说的是「哪一族」FP16 / INT4 这类说的是「哪一族 多少位」。同一族内部的比较FP32 → FP16 → BF16是精度问题跨族的转换FP16 → INT8 → INT4通常就是量化训练几乎都用 FP 家族因为梯度更新需要足够的动态范围INT 家族省空间、算得快代价是能表示的值的粒度变粗。精度是名词量化是动词精度量化回答的问题用多少位表示一个数怎么从高精度转到低精度性质状态 / 格式动作 / 过程词性感觉名词「这是 FP16」动词「把它量化成 INT4」精度是「用什么格式」量化是「从高格式转到低格式」。中文里两者都常被说成「降低精度」但降低精度是量化的结果不是量化本身。精度是静态属性——一个模型文件存下来是什么格式就一直是什么格式量化是一次性操作——跑完得到一个全新的、低精度的文件。收益、代价和真实数字收益很直接权重文件更小加载权重所需的内存更少笔记本也能跑起来。代价是「降智」推理的本质是大量的矩阵运算如果权重矩阵中数字的精度降低那么计算结果难免有偏差体现出来的就是模型的回答质量下降。注意速度不一定会提升——要看硬件和推理引擎的支持情况。4 bit 量化不一定比 8 bit 量化快。实测数字Qwen3-0.6BHugging Face 官方仓库的 BF16 权重1.50GBOllama 的Q4_K_M模型包523MB理论上 4 bit 应该是 16 bit 的 1/4约 375MB但实际是 523MB。差异来自三处量化要额外记录缩放数据scale 等辅助信息部分张量会保留更高精度有的参数量按「不重复」算有的按「实际存了多少个数」算。Q4_0、Q4_K_M、Q8_0是不同的量化方案名字里能看出大致位数和算法。具体好不好用要看发布者的说明最好在自己的任务和硬件上实测。四、选型把模型跑起来同一套权重四个角度问四件事刚开始看这些词会以为是一堆并列的模型类型其实不是。术语它解决的问题例子checkpoint保存的是哪个训练时刻的模型或训练状态checkpoint-2000、最终权重精度和量化权重里的数字如何表示BF16、FP16、Q4_0、Q4_K_M文件格式权重参数和元数据如何保存Safetensors、GGUFHugging Face Hub模型发布和版本管理模型页、Model Card、License这四层可以自由组合所以同一条链能一路走到底BF16 权重→存成 Safetensors→转成 GGUF→量化成 Q4_K_M→本地引擎加载于是看到7B · Q4_K_M · GGUF这种标签就能读懂了约 70 亿参数4 bit 为主的量化方案组织成适合本地推理工具读取的 GGUF 单文件。两种文件格式的差别Safetensors只装张量 一份描述清单加载时不会执行任何东西。早年.bin权重用 pickle 序列化加载时可能执行文件里夹带的代码这是它被换掉的原因。模型结构和 tokenizer 通常仍放在单独的 JSON 文件里。GGUF把架构、tokenizer、量化类型全打包进一个文件面向本地推理工具。llama.cpp、LM Studio、Ollama 直接加载它。下载模型到底是下载什么从 Hugging Face 下载模型往往不是下载一个能双击运行的程序而是下载一组文件交给推理框架共同解释。文件类别对应文件作用权重文件model.safetensors保存模型学到的所有参数配置文件config.json、generation_config.json说明模型结构和默认生成配置tokenizer 文件tokenizer.json、tokenizer_config.json、merges.txt、vocab.json定义文字和 token 如何互相转换config.json里每个字段都和原理一一对应字段值Qwen3-0.6B对应概念vocab_size151,936embedding 矩阵的行数hidden_size1,024embedding 矩阵的列数num_attention_heads16多头头数num_hidden_layers28层要叠的遍数max_position_embeddings40,960上下文长度上限这两个 JSON 文件都很小但少了它们权重就只是一堆没法组装的数字。选型时先看模型卡别只看参数量模型卡README.md通常写清楚这是 Base / Instruct / Chat、支持的语言和任务、训练数据、评测结果、已知限制、许可证、推荐推理框架和提示词格式。但模型名称和参数量不能完整说明能力同规模的不同模型、同模型的不同微调版本实际表现差距可能很大同一个名字里的数字数法可能不同Qwen3 的0.6B按模型逻辑上不重复的参数算Hugging Face 页面统计的0.8B按权重文件里实际存了多少个数算——两个数都没错小模型在模型卡上宣传的推理、Agent 能力够不够用得拿自己的任务实测本机跑先算内存账ollama pull qwen3:0.6b ollama run qwen3:0.6b ollama list# 磁盘上有什么包ollama show qwen3:0.6b# 模型的能力上限ollamaps# 这一次占了多少内存ollama stop qwen3:0.6b# 卸内存不删模型ollamarmqwen3:0.6b# 才删磁盘关键是别把这三个数混起来命令看什么ollama list磁盘包。qwen3:0.6b → 522 MBollama show架构上限context length 40960、量化 Q4_K_Mollama ps本次加载后的 RAMSIZE / PROCESSOR / CONTEXT / UNTILollama ps的 SIZE 公式是SIZE ≈ 权重文件大小 按 CONTEXT 预分配的 KV cache注意「预分配」三个字。Ollama 在加载模型时按 CONTEXT 一次性划一整块 KV 内存之后只说一句 “hi” 或者聊 300 轮这块地都已经占着SIZE 不会因为对话变长而增长。实测qwen3:0.6b的 KV cache 约 115KB/tokenFP16--ctx-size 32768时115KB × 32768 ≈ 3.7GB KV 522MB 权重 ≈ 4.2GB加上开销对上 SIZE4.4 GB这里有两个「上下文」要分清ollama show的 40960 是能力上限——这块地理论上能划多少车位ollama ps的 CONTEXT 是这一次实际划了几格Ollama 默认往往只给 2048 或 4096要长窗口得显式说ollama run qwen3:0.6b --ctx-size 32768。本机 HTTP 接口curlhttp://localhost:11434/v1/chat/completions\-HContent-Type: application/json\-d{model:qwen3:0.6b,messages:[{role:user,content:你好}],stream:false}基址是http://localhost:11434/v1字段名和云端兼容reasoning_effort: none关思考。默认无鉴权——不要把 11434 暴露到公网。一个现实的门槛接口通了不等于能用它干活。要接 Coding Agent官方文档建议上下文 ≥64Kqwen3:0.6b的上限是 40960连门槛都不到。笔记本级硬件能跑本地模型的通常都是小模型很难真正驱动 Coding Agent。小结环节总结训练改参数把随机数变成有用的数产物是模型文件推理只读参数每次 API 调用都是一次推理微调Base 会接话Instruct 会答话微调从 Base 出发精度每个参数用多少位是状态量化从高精度转到低精度是动作体积参数量 × 每参数字节数另外加 KV cache选型看模型卡、看上下文、实测参数量不等于能力