ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

微调前先测基线:用SST-2 64条样本摸清小模型真实水平

微调前先测基线:用SST-2 64条样本摸清小模型真实水平 在你正式跑起微调脚本之前先花二十分钟做一件看起来有点反直觉的事不要急着把整理好的数据丢进训练循环而是先拿一小撮开发样本把模型当前的真实水平摸清楚。我说的就是给模型建立“微调前基线”——用一个像 SST-2 这样的经典任务从开发集里抽 64 条样本就能把能力基线和格式基线一次性测明白。为什么要做这件事因为微调小模型的绝大多数翻车现场都不是训练没跑完而是你根本不知道模型在任务上的起点在哪里。是压根不会做这道题还是会做但输出格式乱成一团还是已经会了只是边界判断差一点——这三类问题对应的微调策略完全不同。先测基线再决定要不要调、怎么调、数据怎么构造这才是正常的流程。这篇文章我就拿 SST-2 的 64 条开发样本为例把基线测试的完整思路、实操步骤、结果解读以及从基线到微调参数决策的整个链路讲清楚。不管你是准备给 Qwen、Llama 这类小模型做 LoRA 微调还是想把某个领域数据灌进去让模型更听话这套方法都直接能用。1. 微调前先建立基线到底在测什么1.1 能力基线模型到底会不会这道题能力基线回答的问题很朴素在完全不微调的情况下模型拿这个任务能得多少分。比如 SST-2任务是给一句电影评论判情感极性正面或负面。零样本情况下一个 1.5B 参数的指令微调模型直接拿这段评论去问它“正还是负”它大概率能答对一部分。这部分“不需要训练就有的能力”就是模型自带的任务理解力。这个数字非常重要但它通常被忽略。很多人拿到任务后的第一反应是“先微调”好像微调是把一个完全不会的模型教会。实际不是这样的——小模型经过指令微调后对很多常见任务已经有一定程度的理解只是稳定性和边界控制不好。你先测出这个起点才能判断微调是“在已有能力上做校准”还是“从零开始教它一个新能力”。举个具体例子。我用 Qwen2.5-1.5B-Instruct 在 SST-2 的 64 条开发样本上做过一次零样本摸底准确率在 70% 上下。这意味着它已经懂“电影评论情感分类”这件事了只是有大概三成样本判断不稳。这种情况下微调的重点就不是“教会它分类”而是“让它在你的数据分布上更准、更稳定”。反过来如果你测出来的准确率接近随机50%那说明模型对任务完全没有概念这时候再往下微调你就得重新考虑任务设计、标签定义、样本量甚至是不是该换更大的底座模型。同样的训练预算用在这两种不同起点上结果会差非常多。1.2 格式基线模型能不能“好好说话”第二个维度是格式基线。这个经常被低估但它在实际工程里比能力基线更容易坑人。格式基线回答的问题是模型输出的东西你的下游能不能直接消费拿 SST-2 来说你期望的答案就是 “Positive” 或 “Negative” 二选一。但真实模型会怎么输出我见过花式百出的情况输出 “Positive.” 带个英文句号输出 “The sentiment of this review is positive.” 一整句话输出 “正面的” 中文混杂输出 “Positive, with high confidence” 还带附加说明输出一段分析最后才给出结论甚至有时候温度稍高它会换着花样输出 “Positive / Negative” 都给你列出来如果你的微调训练数据是严格按 “输入 标签” 构造的而模型在推理阶段延续这种发散输出的习惯那你的评估脚本、后处理解析、上下游系统全部都要跟着遭殃。更麻烦的是格式问题会在微调之后被放大——训练数据如果格式统一模型会学到统一格式训练数据如果不统一模型输出会更乱。所以格式基线一定要测而且要带着明确的“可解析率”指标来测64 条样本里有多少条输出能精确匹配到你预定义的答案集这个数字如果连 80% 都不到你首要解决的不是能力问题而是格式对齐问题。1.3 为什么偏偏是 64 条开发样本你可能想问为什么不用更多样本或者为什么不用训练集三个理由。第一开发集是模型没见过的数据用它测出来的结果才代表模型的真实泛化能力。用训练集测基线等于开卷考试没有参考价值。第二SST-2 的开发集总共 872 条抽 64 条出来只占 7.3%跑一轮推理在 1.5B 到 3B 的小模型上不过几十秒成本几乎可以忽略。第三64 条这个量级在统计上刚好能支撑你做分层分析——按正负标签均衡抽样每类 32 条再看模型在不同类型样本上的表现差异这个信息密度在一两百条样本范围内就已经很充足了。再补一句64 条不是一个神圣的数字。你完全可以用 32 条或者 128 条原则只有一条正负样本均衡且能覆盖你关心的样本类型。我之所以锁定 64是因为它在“快速”和“可靠”之间是个很舒服的中间值——比 32 条稳定比 128 条更快。2. 搭建能力基线SST-2 探测实验怎么做2.1 数据准备与模型加载先准备数据。Hugging Face 的 datasets 库可以直接加载 GLUE 里的 SST-2from datasets import load_dataset dev load_dataset(glue, sst2, splitvalidation) print(len(dev)) # 872 # 按标签均衡抽样各有 32 条 pos dev.filter(lambda x: x[label] 1).select(range(32)) neg dev.filter(lambda x: x[label] 0).select(range(32)) sample pos.concatenate(neg).shuffle(seed42)注意 shuffle 时固定一个随机种子这样你后续微调、复测用的都是同一批样本结果才可对比。如果你后续要拿这 64 条做微调后的回归测试最好保存一份快照到本地。模型加载不用多说按你手头资源选。如果是纯 CPU 推理1.5B 级别的小模型也扛得住就是慢一点。有 GPU 更好batch size 开大点一次性跑完。2.2 推理参数与提示模板提示模板是基线测试里最影响结果的一环。我常用的模板很简单Review: {sentence} Question: What is the sentiment of this review? Options: Positive, Negative Answer:这里有两个细节。第一输出约束尽量写清楚把候选答案直接列出来让模型在限定集合里做选择这能显著降低格式混乱的概率。第二推理温度设成 0或使用贪婪解码保证输出是确定性的——基线测试要的是可复现不是多样性。max_new_tokens 给 16 就够不用多给多了反而容易引出附加解释。from transformers import pipeline pipe pipeline(text-generation, modelQwen/Qwen2.5-1.5B-Instruct, device0) prompt_template ( Review: {sentence}\n Question: What is the sentiment of this review?\n Options: Positive, Negative\n Answer: ) # 跑完 64 条收集原始输出先别急着判对错 outputs [] for ex in sample: p prompt_template.format(sentenceex[sentence]) out pipe(p, max_new_tokens16, temperature0.0, do_sampleFalse)[0][generated_text] outputs.append(out)收集原始输出后先把“判断对错”和“解析格式”分开这是基线测试里一个重要的原则。你先把所有输出原样存下来然后两步走先看格式可解析率再看解析后的准确率。这两个指标分开统计才能定位问题到底出在哪一层。2.3 指标设计与结果解读能力基线的主指标是准确率和宏平均 F1。因为抽样是均衡的精确率和召回率也都能算但宏平均 F1 更有参考价值——它能反映出模型对正负两类是否对称。我实测时发现一个典型现象模型往往对 Negative 类别的召回率偏低。很多带否定词、转折结构的评论模型容易误判成 Positive。比如 “good cast, but a bad script” 这种句子前半段是正面词后半段才是真正的负面标签模型很容易被前半段带偏。这种 64 条样本里的规律往后大概率会在你的业务数据里重演。所以务必做分层分析按句子长度分桶短句 10 词、中句 10-20 词、长句 20 词按是否含否定词分桶按是否含强烈情感词分桶。这个分析不用写复杂代码pandas 分组统计一下就行。每一层都记录准确率你就能得到一张“模型的优劣势地图”。这张地图直接作用在微调数据构造上如果长句容易错你的训练数据里就要多放长句如果否定句容易错就要加强这类样本的占比。没有基线测试你根本不知道往哪个方向加重采样。3. 格式基线的全面体检3.1 输出可解析性测试格式基线的第一个指标是“可解析率”64 条原始输出里有多少条能解析成我们预定义的答案标签。这里我给一个简单的判定逻辑去掉首尾空白、去掉句号、统一小写之后判断输出是否属于 {positive, negative, positive., negative.} 这个集合。属于就算可解析不属于就记成一次格式失败。我用 Qwen2.5-1.5B-Instruct 跑出来的可解析率一般在 90% 以上主要失败模式是输出 “Positive, with high confidence” 或 “The sentiment is positive”。这些小尾巴会让严格匹配失败。但注意不同模型的格式习惯差异很大有些小模型特别爱“解释性输出”解析率可能直接掉到 70% 以下。可解析率的统计逻辑类似这样def is_parseable(text): t text.strip().lower().rstrip(.) return t in {positive, negative} parseable sum(is_parseable(t) for t in outputs) print(fParseable rate: {parseable / 64:.2%})这个数字很诚实。它直接告诉你如果现在立刻接一个自动化下游系统有多少样本会被卡在解析环节。3.2 温度敏感性与指令遵循确定性的贪婪解码只是第一步。微调后的模型在真实推理时往往使用采样temperature 0所以格式基线还要测一件事温度对输出稳定性的影响。同一批 64 条样本跑一遍 temperature0.7 的采样看答案漂移有多严重。我的经验是好的微调模型在同一 prompt 下温度升高后应该保持主答案稳定只是措辞略有变化。如果模型在温度 0.7 下频繁在 Positive 和 Negative 之间横跳甚至开始输出大段分析文本说明模型对这个任务的内在置信度很低微调时要通过大量强化格式的样本来纠偏。还有一个更容易被忽略的测试指令遵循反向测试。你把模板里的 Options 从 “Positive, Negative” 改成 “Negative, Positive”看模型是跟着选项顺序走还是坚持“它觉得对”的答案。如果模型完全无视选项顺序说明它对这个任务有自己的内隐判断而这种判断有时反而是噪音。这个测试不用跑满 64 条抽 10 条看看趋势就够了。3.3 定位格式问题的根因格式基线不合格时先别急着骂模型。大部分格式问题有三个来源第一种是提示模板本身太弱。模板里没有明确说“只输出一个词”模型就默认按对话习惯补一句解释。这时候先用 prompt 工程解决往模板里加一行 “Output only the selected option, no explanation.”格式就稳很多。第二种是底座模型本身偏好附加解释。有些模型在指令微调阶段就被训成了“话痨”它的输出习惯很难靠 prompt 压制。这种只能靠微调来纠正——训练数据里全部用严格的“输入到标签”格式模型见过足够多的干净样本后会逐步收敛输出风格。第三种是解码参数问题。max_new_tokens 给太多、温度给太高都会诱发冗余输出。基线测试时先把这些变量固定成“最严格模式”后续再逐步放宽。所以格式基线的完整结论应该是这样一句话“在我用的这个提示模板、这个解码参数下模型的输出可解析率是多少失败模式长什么样以及我把模板改成什么之后能优化到多少。”带着这个结论去设计微调数据你就不会盲目堆样本量了。4. 从基线到微调参数与策略的决策参考4.1 能力基线决定 LoRA 配置基线测试做完你就会面对一个最直接的问题这个模型到底值不值得微调以及用多大的力气去调。我把结果分为三档。第一档零样本准确率已经有 70% 以上说明任务能力基本在线缺的是分布对齐和稳定性。这种场景用 LoRA 就很轻量rank 设 8 到 16学习率 1e-4 到 2e-4训练 1 到 3 轮就够。不需要大动干戈重点是把数据质量和格式统一性做好。第二档准确率在 55% 到 65% 之间模型对任务半懂不懂。这种场景建议 rank 设 16 左右学习率 2e-4训练轮数放到 3 到 5 轮。同时注意训练数据里要保证足够的“关键样本”覆盖——把基线下层分析中表现差的那几类样本加大比重。第三档准确率贴着随机线50% 上下甚至低于随机。这种情况我建议你先停下来别急着烧算力。重新检查任务定义——标签设计是不是合理prompt 是不是产生了歧义数据抽样本身有没有出问题如果这些都排除了模型还是不会那可能需要换一个更大的底座模型或者通过继续预训练去补基础能力。LoRA 微调不是万能的它对“模型已经会但还不够好”的任务增益最大对“从零掌握复杂语义规律”的任务增益很有限。下面是实际项目里常用的配置参考表基线准确率建议数据量LoRA rank学习率训练轮数微调目标70% 以上数百到数千条8-161e-41-3 轮分布校准与格式对齐55%-65%数千条162e-43-5 轮能力提升与稳定接近随机重新审视任务不建议直接调--先解决任务定义这个表不是金科玉律每个底座模型的脾气不一样只是一个经过多次验证的起点。但从基线结果出发做决策总比拍脑袋定参数靠谱得多。4.2 格式基线决定数据构造方式格式基线直接决定了你的训练数据长什么样。这是我反复强调的一点微调数据的构造方式不应该照抄别人的模板而应该根据你基线测试里看到的失败模式来定制。如果你的基线可解析率低失败模式是“输出整句解释”那你的训练数据里就要大量使用“输入到标签”的严格格式让模型反复看到“看到模板就只吐标签”的样例。你甚至可以在每个样本的 instruction 部分写明 “Answer with the label only.”让格式约束成为任务的一部分。如果你的失败模式是“多标签输出”把 Positive 和 Negative 都列出来则在数据构造时要刻意避免任何带多个候选标签的文本同时可以在 loss 计算时只对答案部分做监督忽略 prompt 部分的 loss。这样做能让模型把注意力集中在学习输出的尾端。另外标签词汇本身也要统一。SST-2 可以有两个版本英文标签 “Positive / Negative” 或中文标签 “正面 / 负面”。基线测试时试一下哪种标签词模型输出更稳定微调时就用哪个。这个小实验花不了两分钟但能省掉很多后续解析的麻烦。4.3 微调后的回归验证基线测试的最后一个用途是给微调效果提供对照坐标。微调跑完之后把同一批 64 条开发样本原样跑一遍对比前后的准确率和可解析率。如果准确率上升、可解析率保持高位说明微调方向正确。如果准确率上升但可解析率崩了说明训练数据格式不统一模型学到了坏习惯。如果两个都原地踏步说明这次微调基本无效需要回查数据质量、学习率、训练轮数。这里有个经验提醒不要只看微调后的绝对准确率要看和基线的差值。如果你零样本基线准确率是 72%微调后变成 75%虽然数字不算高但三个点的提升可能就是数据质量的真实信号。如果你基线只有 55%微调后跳到 68%那这次微调效果就很显著。没有基线对照你连“效果显著”这种基本判断都做不出来。回归测试用同一批样本还有一个额外好处你能看到每条样本的前后变化。模型从错变对是进步从对变错则是退化。把退化样本单独拉出来看往往能发现有意思的现象——比如模型因为微调数据里某种表述过多学会了过度偏向某一类。5. 实操中的常见陷阱与排查实录5.1 常见问题速查表我在多个微调项目里反复遇到一些典型问题整理成一张速查表方便你对照排查。现象可能原因排查方法建议处理零样本准确率远低于随机提示模板有误导标签映射错误数据抽样不均衡换个模板重测检查抽样代码修正模板重新抽样可解析率偏低输出带解释模型习惯附加输出prompt 约束不足看输出的完整文本跑一次带强约束的模板对比修改模板加入明确限制微调时用严格格式同一批样本两次测试结果不一致推理未固定种子温度非 0模型量化波动确认 do_sampleFalse固定随机种子基线测试统一用贪婪解码正负类准确率差距很大模型对某一类有系统性偏见数据分布不均查看混淆矩阵和分层分析微调时加重弱势类采样微调后准确率提升但格式崩坏训练数据格式不统一标签词汇不一致检查训练数据的 output 字段是否有噪声清洗训练数据统一标签词微调后出现明显退化样本训练数据与开发样本冲突过度拟合对比前后答案变化检查训练集是否有重复样本查重降低学习率或轮数这里面最常踩的坑其实是“数据泄漏”。SST-2 这类公开数据集语料已经存在很多年了模型的预训练语料里很可能已经包含部分相关文本。所以零样本准确率会显得偏高但这不是模型真实任务能力的体现。如果你做的是业务场景一定要用自己业务场景里真实的开发样本做基线而不是拿公开数据集的结果当作模型真实水平的全部证据。顺带一提这类“先测后调”的思路并不只适用于文本分类。无论是让大模型输出结构化 JSON还是做信息抽取、问答、知识库问答的结构化回答都需要微调前先跑一遍基线把输出的形状摸清楚再做数据构造的决策。5.2 三个值得长期坚持的习惯最后分享三个我在实操中沉淀下来的习惯它们帮我躲过了不少坑。第一个习惯基线测试永远保留原始输出。不要只记录准确率就完事把 64 条原始输出保存成一个 JSON 文件后续做格式分析、找失败模式要用。哪怕当时看完整输出很费眼这些原始痕迹所有后续决策都离不开。第二个习惯抽样的种子号也写进实验记录。哪怕只是微调一个小模型也要有基本的实验管理意识。模型版本、抽样种子、prompt 版本、温度参数、测试日期这些一条都不能少。我发现很多团队复现问题不是复现不了而是根本没记录当初是怎么抽的样。第三个习惯在业务数据上也要建“固定回归集”。从你的真实业务数据里挑 50 到 100 条多样性足够强的样本固定下来每次微调前后都跑一遍。公开数据集测的是模型常识推理能力回归集测的才是你的业务落地指标。这两个分数结合着看对模型整体状态的判断就立体多了。这套 64 条开发样本的基线方法我自己在 Qwen、Llama 这些常见小模型上都验证过改动最小、见效最快。微调开始前花二十分钟把能力基线和格式基线都摸透再回头调整数据构造和训练参数你会明显感觉到整个微调过程踏实很多——因为你做的每一步都有了依据。
返回列表