[{"data":1,"prerenderedAt":399},["ShallowReactive",2],{"article:column:/column/llm-to-agent-learning/14":3},{"id":4,"title":5,"body":6,"description":391,"extension":392,"meta":393,"navigation":394,"path":395,"seo":396,"stem":397,"__hash__":398},"column/column/llm-to-agent-learning/14.md","14｜微调为什么不必重练整个模型：从SFT到LoRA",{"type":7,"value":8,"toc":372},"minimark",[9,14,18,21,24,27,30,34,44,47,50,54,57,60,68,71,75,78,81,87,90,98,101,108,112,115,118,121,124,131,134,137,140,143,149,152,155,158,166,170,173,176,184,187,193,196,200,208,211,219,222,230,233,237,240,243,246,249,252,281,284,288,293,296,301,304,309,312,315,320,323,328,331,336,339,342,347,350,355,358,363,366,369],[10,11,13],"h2",{"id":12},"_1会回答还要每次都按同一种要求回答","1．会回答，还要每次都按同一种要求回答",[15,16,17],"p",{},"假设你每天处理会议通知，希望模型统一提取“时间、地点”两项。原文没写地点，就填“未提供”，不要热心地补一个会议室。",[15,19,20],{},"用一段提示词加两个示例，模型可能已经做得不错。可当通知写法变复杂、任务量变大时，它偶尔仍会加解释、漏掉条件。我们能不能让这种行为更稳定地成为模型的习惯？",[15,22,23],{},"这就引出了微调：从一个已有模型出发，再用针对性的数据训练，改变其中可训练的参数。以后遇到新通知，模型会使用训练后的参数来计算。这里的“习惯”只是便于理解的说法，具体发生的是数值更新，不是给程序写下一条永不违反的规章。",[15,25,26],{},"先做一个位置判断。同一份示例，可以走两条路。放进本次输入，它改变当前上下文；拿来计算训练损失、更新参数，它才参与微调。聊天中纠正一次答案，并不能单凭这一点断定底层模型当场重新训练了。",[15,28,29],{},"还有两个经常被并排念出的名字：**SFT说明我们用什么监督信号来训练；LoRA说明我们让哪些数怎样参与更新。**它们回答的是不同问题，因此可以合在一起使用。",[10,31,33],{"id":32},"_2先分清训练目标与更新空间","2．先分清训练目标与更新空间",[15,35,36,37],{},"第13章已经把示范回答变成逐token负对数损失：模型给目标token的概率由0.25升到0.5，损失便从约1.386降到0.693。SFT继续使用这种监督信号；常见设置只对回答位置算损失，请求及示范前缀提供条件，具体范围以训练配置为准。",[38,39,43],"a",{"href":40,"rel":41},"https://huggingface.co/docs/trl/sft_trainer",[42],"nofollow","TRL：SFT训练目标与损失范围",[15,45,46],{},"本章固定这个目标，改变的是“损失可以通过哪些参数下降”。全参数微调允许整座模型一起调整；LoRA则限制可训练增量的形式。同一份SFT数据因此可以配合两种更新方式，也都需要完整生成评测。",[15,48,49],{},"会议数据仍须明确教会缺失字段规则。如果训练通知总有地点，或标注员总凭经验补齐，换一种省资源的更新方法也不会凭空产生“未提供”这一标准。先说明要学什么，再选择允许它怎样学。",[10,51,53],{"id":52},"_3全参数微调到底贵在哪里","3．全参数微调，到底贵在哪里",[15,55,56],{},"Transformer里有许多权重矩阵。矩阵可以看成排列整齐的数字表：它把输入向量的各项加权组合，形成新的表示。全参数微调允许更新模型的全部参数，通常也意味着要为大量参数保存梯度和优化器状态。",[15,58,59],{},"梯度告诉更新方法当前该往哪里调整；优化器还可能记录过去的变化，帮助决定下一步。训练途中产生的中间结果叫激活，也常需要保留或重新计算，以便反向传播。显存因此不只装着那份下载来的模型权重。",[15,61,62,63],{},"直观地说，仓库里除了原材料，还要放加工中的半成品、工具和记录。只看模型文件有多大，无法直接推断训练要多少显存。序列长度、批次大小、数值精度和实现方式都会改变这笔账。",[38,64,67],{"href":65,"rel":66},"https://huggingface.co/docs/transformers/model_memory_anatomy",[42],"Transformers：训练显存构成",[15,69,70],{},"如果原模型已经学会了大量通用模式，新任务只需要对其中一些计算作调整，能否保留它的大部分权重，把可训练部分做得更小？参数高效微调沿着这个问题探索，LoRA就是其中一种重要方法。",[10,72,74],{"id":73},"_4lora给原计算加了一条窄支路","4．LoRA给原计算加了一条窄支路",[15,76,77],{},"设某个原权重矩阵叫W₀，输入向量叫x。原计算可以简写为W₀x，意思是让这张数字表对输入做一次加权变换。",[15,79,80],{},"LoRA把W₀冻结，再增加两个较小的可训练矩阵A和B。输入除了走原来的主路，也先经过A，再经过B；两条路的结果相加：",[15,82,83],{},[84,85,86],"strong",{},"新输出＝W₀x＋B(Ax)",[15,88,89],{},"这里把单个输入x写成列向量，所以先算Ax，再算B(Ax)。第03、06章使用行向量，只是记法约定不同；把相关向量和矩阵一起转置，计算可以对应，不能只交换乘法顺序。下面的4×4数字都按列向量约定解释。",[15,91,92,93],{},"真实实现通常还会给支路乘一个缩放系数，后面的选读会解释。这里先忽略它，只看结构。冻结只代表W₀不被优化器更新，模型仍要使用这张矩阵计算；在多层网络里，训练信号也仍要经过相关计算路径，才能更新适配器。",[38,94,97],{"href":95,"rel":96},"https://arxiv.org/abs/2106.09685",[42],"LoRA原论文",[15,99,100],{},"如果原矩阵有d行、k列，它包含d×k个参数。A有r行、k列，B有d行、r列，新增可训练参数就是r×k＋d×r。只要r比d和k小得多，这条支路就窄得多。r称为秩参数，可以先理解成中间通道数。",[15,102,103,104,107],{},"为什么叫“低秩”？想象一张很大的更新表，其中每一列本可以独立变化；经过r条窄通道后，更新只能由有限的共同方向组合出来。它限制的是",[84,105,106],{},"本次增量的表达方式","，不是把原模型的所有知识压成r个数字，也没有删除原来的大矩阵。",[10,109,111],{"id":110},"_5拿四个数字亲手走完一次lora","5．拿四个数字，亲手走完一次LoRA",[15,113,114],{},"我们选一组故意很小的数字。原矩阵W₀取4×4单位矩阵，它会原样保留输入。输入x＝［1，2，0，0］，主路输出也是［1，2，0，0］。",[15,116,117],{},"支路只留一个中间通道，即r＝1。令A＝［1，0，1，0］，先计算Ax：1×1＋0×2＋1×0＋0×0＝1。",[15,119,120],{},"再令B为竖排的［1，2，0，−1］。把刚才的1送进去，支路得到［1，2，0，−1］。加到主路后，新输出就是［2，4，0，−1］。",[15,122,123],{},"这次只展示前向计算，A和B都是手填的，不能当成训练效果。它至少证明了：原矩阵一个数都没变，新增的小矩阵仍能改变输出。看图1时，分别跟住主路的四个数和支路的那个中间数，再在右侧逐项相加。",[15,125,126],{},[127,128],"img",{"alt":129,"src":130},"14｜微调为什么不必重练整个模型：从SFT到LoRA：图1","/collections-assets/llm-to-agent-learning/2a3f99a387c87c23c35df25a568341c44cbaf20a0622cba2cee919565d6b50b6.png",[15,132,133],{},"图1｜本例W₀为4×4单位矩阵，A为1×4，B为4×1；暂把缩放设为1。输入分两路，主路给出［1，2，0，0］，支路给出［1，2，0，－1］，相加为［2，4，0，－1］。",[15,135,136],{},"再把两个小矩阵先乘起来，得到增量矩阵BA。由于A是［1，0，1，0］，BA的四列依次是B、零向量、B、零向量。也就是说，输入第一项和第三项只能沿同一个B方向影响输出；第二项和第四项在这条特定支路上暂不起作用。",[15,138,139],{},"换成任意输入［x₁，x₂，x₃，x₄］，支路输出就是（x₁＋x₃）B。无论输入怎样变，输出增量都在B这条直线上：系数为2时是2B，为－1时是－B，为0时没有增量。它无法同时做到“第一项只改第一个输出，第三项只改第二个输出”这两个独立方向。",[15,141,142],{},"训练能改变A和B，因此B的方向本身也能改变；受限的是一套已选定参数下，所有输入共享的更新方向数量。r＝1只提供一个方向，r条通道则提供B的r列所张成的组合空间，所以rank(BA)≤r。方向还可能彼此重复，因此是“小于或等于”。原矩阵W₀仍可以满秩，最后的W₀＋BA也可以满秩。",[15,144,145],{},[127,146],{"alt":147,"src":148},"14｜微调为什么不必重练整个模型：从SFT到LoRA：图2","/collections-assets/llm-to-agent-learning/c753a2c767b5f96f54c5a0637a43e569f458475771a0cbc4966afbd132729664.png",[15,150,151],{},"图2｜BA的列全部由B组合而成。右下的二维投影只取B的前两项［1，2］，2B与－B仍共线；完整四维结论来自矩阵乘法，不依赖这幅投影。一个任意4×4增量可有四个独立方向，本例只能有一个。",[15,153,154],{},"原矩阵有16个数，A和B合计8个。在真实尺度的教学算例里，4096×4096矩阵有16,777,216个数；若r＝8，两张小矩阵合计65,536个，仅为前者的1/256，也就是约0.39%。",[15,156,157],{},"原模型已经提供丰富表示，特定任务的有效更新可能近似落在少数方向上，这是LoRA原论文研究的经验现象，不是所有任务都满足的定理。省下来的自由度，也带来限制。若任务需要的更新难以由这些少数方向表达，较小的r可能不够。提高r通常增加可训练参数与资源开销，却不保证效果一定提高；数据太少时，更多自由度也可能更容易拟合偶然模式。",[15,159,160,161],{},"LoRA可以加在注意力的投影矩阵，也可以覆盖前馈网络等模块。放在哪里、覆盖多少层、秩取多大，都会改变能力与开销。仅比较“都用了LoRA”，远远不够。",[38,162,165],{"href":163,"rel":164},"https://huggingface.co/docs/peft/developer_guides/lora",[42],"PEFT：LoRA目标层与配置",[10,167,169],{"id":168},"_6qlora为什么还能再省一块","6．QLoRA为什么还能再省一块",[15,171,172],{},"LoRA减少了需要训练的参数，但冻结基座仍然可能占据大量显存。QLoRA进一步让基座以低位表示存储，并训练LoRA适配器。",[15,174,175],{},"“位”可以先理解成记录一个数允许使用多少二进制格子。格子越少，可表示的精细程度越受限制，存储也越小。这类似把测量结果从很多位小数压到较少档位，会引入近似误差。",[15,177,178,179],{},"QLoRA原研究把冻结基座做成4-bit表示，并结合适合相应权重分布的NF4、量化常数的进一步压缩和分页优化器等方法。计算时通常需要把存储值转换到较高精度参与运算；4-bit存储不等于每一步乘法、梯度和激活都用4-bit。",[38,180,183],{"href":181,"rel":182},"https://arxiv.org/abs/2305.14314",[42],"QLoRA原论文",[15,185,186],{},"现在可以逐项看资源账：LoRA主要缩小可训练参数对应的梯度和优化器状态；QLoRA进一步减少基座权重的存储。激活、临时计算、量化附加信息和运行时开销仍然存在。长输入仍可能很占显存，不能拿单个矩阵的参数比例承诺整机节省比例。",[15,188,189],{},[127,190],{"alt":191,"src":192},"14｜微调为什么不必重练整个模型：从SFT到LoRA：图3","/collections-assets/llm-to-agent-learning/0829299091c1cc9384e29835a5d906f18a63f5a0a6c3fab04b3397a6431adb46.png",[15,194,195],{},"图3｜按同一目标矩阵比较全参、LoRA与QLoRA的资源类别。LoRA把该矩阵的可训练参数从16,777,216个减到65,536个；QLoRA再缩小冻结基座的存储。符号与文字标明哪些项改变，图中布局不代表显存占比。",[10,197,199],{"id":198},"_7把这些名字放回一个真实模型配置","7．把这些名字放回一个真实模型配置",[15,201,202,203],{},"这些方法已经体现在可检查的开源训练配置里。Qwen团队的官方微调说明提供Qwen3的Axolotl使用路线，链接了Qwen3-32B的QLoRA SFT配置，并说明可将基座改为Qwen3-8B。",[38,204,207],{"href":205,"rel":206},"https://github.com/QwenLM/Qwen3/blob/main/docs/source/training/axolotl.md",[42],"Qwen：Axolotl微调说明",[15,209,210],{},"读到这里，我们就不必把它们当成四个神秘按钮：Qwen3指所选基座，SFT指利用示范回答构造训练目标，LoRA指增量更新方式，4-bit量化主要描述基座存储。它们组合起来，才构成一种具体训练设置。",[15,212,213,214],{},"固定在Axolotl v0.9.2的示例里，还能看到rank设为16、alpha设为32、序列长度设为2048。它的验证集比例设为0，所以拿来做教学实验时，应另行留出验证和测试数据。示例可运行的配置，并不自动等于完整的效果评估方案。",[38,215,218],{"href":216,"rel":217},"https://github.com/axolotl-ai-cloud/axolotl/blob/v0.9.2/examples/qwen3/32b-qlora.yaml",[42],"固定版本配置",[15,220,221],{},"这个配置说明方法怎样落到实际模型，不能证明我们的会议任务一定会改善，也不能照搬出一个硬件或效果承诺。还需要检查模型版本、许可证、数据格式、训练模板和评测条件。",[15,223,224,225],{},"为什么基座版本也是这份结果的一部分？沿用第5节同一组A、B和输入x，只把基座换成2倍单位矩阵：主路变为［2，4，0，0］，支路仍为［1，2，0，−1］，最终输出便从［2，4，0，−1］变成［3，6，0，−1］。所有矩阵尺寸都兼容，结果仍然改变了。因此，单独保存适配器时，还应记录它对应的基座版本、挂载位置和缩放设置。PEFT通常把适配器参数保存为单独文件，配套配置记录基座与目标模块等信息；加载时仍需要相应基座。",[38,226,229],{"href":227,"rel":228},"https://huggingface.co/docs/peft/developer_guides/checkpoint",[42],"PEFT的适配器保存格式",[15,231,232],{},"这与软件交付中核对依赖版本、保留可复查的修改有共同之处。区别在于，LoRA交付的是通过数据学出的参数增量，它沿共享计算影响许多输入，并没有把“地点缺失就填未提供”写成一条保证执行的程序规则。能正确加载说明结构接通了；行为是否改善、其他能力是否退步，还要进入下面的回归与独立评测。",[10,234,236],{"id":235},"_8什么时候值得微调怎样判断没有白忙","8．什么时候值得微调，怎样判断没有白忙",[15,238,239],{},"回到会议通知。如果只是偶尔提取几条，先把提示词和示例写清楚，成本通常更低。如果问题是“今天的规定变了”，优先让模型拿到现行资料；把新规定微调进去，不会自动获得更新、删除和逐句引用能力。",[15,241,242],{},"当任务长期稳定、数量较大、已有可靠示范，而且提示词基线仍达不到要求时，SFT与LoRA才更值得进入比较。它们也可以与检索组合：训练模型更稳定地遵循“依据资料回答”，每次再提供最新资料。",[15,244,245],{},"先把评测题留出来，再训练。至少覆盖四类通知：普通写法、同义改写、缺失地点、包含两场不同会议。对最后一类，先把任务规范补清楚：分别输出两组时间、地点，不把两场的信息混在一起。把同一通知轻微改写后同时放进训练集和测试集，会让成绩显得过于乐观。",[15,247,248],{},"分别检查字段正确率、无依据补全率、格式符合率，也检查原有能力是否退步。再与“原模型＋同样提示词”比较。如果微调只记住了训练通知，或者格式更整齐却更爱编地点，就还没有达到目标。不要编造一个漂亮提升数字替代这次测试。",[15,250,251],{},"可以先做一个不需要电脑的小练习：把十条通知分成训练示范和留出题；写清“没提供地点”时的标准答案；交换一条表达方式，看看评分规则是否仍然明确。它不会训练出模型，却能提前暴露训练目标不清和数据泄漏。",[253,254,255,259,262,265,268],"details",{},[256,257,258],"summary",{},"选读｜缩放、初始化与合并，没有高数也能读懂",[15,260,261],{},"常见LoRA写作W＝W₀＋(α/r)BA。α控制支路影响的尺度；r也出现在参数数量中，两者作用不同。变更r时不能只盯着“容量”，还应看实际缩放方式。部分变体使用不同缩放规则。",[15,263,264],{},"常见初始化让A随机、B为零，这样一开始BA为零，模型先保留原来的计算；如果两个矩阵都为零，在普通设置下可能让这条双矩阵支路无法得到有效起步梯度。更新B的信号要经过Ax，更新A的信号要经过B。A和B同时为零时，两边的普通一阶梯度都为零；A随机、B为零时，初始增量仍为零，但Ax可以非零，让B先获得更新信号。这仅针对基本BA支路，初始化细节应以所用实现为准。",[15,266,267],{},"对普通线性层，训练完成后可把增量加回兼容的基座权重，省掉独立支路的推理计算。量化基座涉及反量化、合并、重新量化等额外取舍，不能笼统承诺“任何适配器都能无损合并”。保留独立适配器，则方便为同一兼容基座切换不同任务配置。",[15,269,270,271,275,276],{},"延伸阅读：",[38,272,274],{"href":163,"rel":273},[42],"PEFT LoRA开发指南","、",[38,277,280],{"href":278,"rel":279},"https://huggingface.co/docs/peft/developer_guides/quantization",[42],"PEFT量化训练",[10,282,283],{"id":283},"本章练习",[285,286,287],"h3",{"id":287},"题目",[15,289,290],{},[84,291,292],{},"问题1｜上下文还是训练",[15,294,295],{},"把三条会议示例放进请求，底层参数固定；另一次用同样示例计算损失并更新LoRA的A、B。哪次属于微调？两次都应遵守怎样的缺失地点规则？",[15,297,298],{},[84,299,300],{},"问题2｜低秩限制在哪里",[15,302,303],{},"沿用第5节的单位矩阵基座W₀及A、B，缩放为1，输入改为［2，0，1，0］。计算Ax、支路输出与最终输出；再说明这条支路能否产生［0，1，0，0］这个增量。",[15,305,306],{},[84,307,308],{},"问题3｜参数账与显存账",[15,310,311],{},"4096×4096矩阵使用r＝8的LoRA，新增多少可训练参数、占原矩阵多少？再把冻结基座改为4-bit存储，哪些资源会缩小，哪些还须另算？",[285,313,314],{"id":314},"思考提示",[15,316,317],{},[84,318,319],{},"提示1｜对应问题1",[15,321,322],{},"看示例有没有参与参数更新；再把学习方式与任务规范分开。",[15,324,325],{},[84,326,327],{},"提示2｜对应问题2",[15,329,330],{},"先把输入压成一个数，再乘B。比较目标增量是否是B的某个倍数。",[15,332,333],{},[84,334,335],{},"提示3｜对应问题3",[15,337,338],{},"A和B分别计数；把基座、梯度、优化器状态与激活分开。",[285,340,341],{"id":341},"参考答案与解析",[15,343,344],{},[84,345,346],{},"答案1｜对应问题1",[15,348,349],{},"第二次属于微调，第一次只改变当前上下文。两次都应在原文缺失地点时输出“未提供”；是否微调不会改变这条任务规范，也不保证规则已经被可靠学会。",[15,351,352],{},[84,353,354],{},"答案2｜对应问题2",[15,356,357],{},"Ax＝3，支路为［3，6，0，－3］，与单位矩阵主路［2，0，1，0］相加，得到［5，6，1，－3］。支路不能产生［0，1，0，0］：若倍数为0，第二项也为0；若非0，第一项就非0。这是一个方向的表示限制。",[15,359,360],{},[84,361,362],{},"答案3｜对应问题3",[15,364,365],{},"新增8×4096＋4096×8＝65,536个，占16,777,216的1/256，即0.390625%。LoRA主要减少可训练参数所需的梯度和优化器状态；4-bit基座再减少权重存储。适配器、激活、临时计算、量化尺度和运行开销还须另算，不能把参数比例当总显存比例。",[10,367,368],{"id":368},"下一章",[15,370,371],{},"SFT让模型学习示范答案，LoRA限制更新的参数空间。但同一道题常常有多个合理回答，哪一个更清楚、更忠实，并不总能由唯一标准文本表达。下一章转向RLHF与DPO：当训练信号变成“这份回答比另一份好”，参数更新又怎样发生？",{"title":373,"searchDepth":374,"depth":374,"links":375},"",3,[376,378,379,380,381,382,383,384,385,390],{"id":12,"depth":377,"text":13},2,{"id":32,"depth":377,"text":33},{"id":52,"depth":377,"text":53},{"id":73,"depth":377,"text":74},{"id":110,"depth":377,"text":111},{"id":168,"depth":377,"text":169},{"id":198,"depth":377,"text":199},{"id":235,"depth":377,"text":236},{"id":283,"depth":377,"text":283,"children":386},[387,388,389],{"id":287,"depth":374,"text":287},{"id":314,"depth":374,"text":314},{"id":341,"depth":374,"text":341},{"id":368,"depth":377,"text":368},"从信息表示和学习出发，用可核算的例子与白板图逐步理解大模型、后训练、推理和Agent系统。","md",{},true,"/column/llm-to-agent-learning/14",{"title":5,"description":391},"column/llm-to-agent-learning/14","OP-_X0UGQdcDN-HZc_KX99Yw-EXnNd_FsnVpC6frWu4",1791935828763]