微调6亿参数Qwen3 4B实现91.6%分类准确率


微调一个小到只有6亿参数的模型,让它在131道家庭问题测试里答对120道,把准确率从10%拉到92%。听起来像天方夜谭,但这事真有人干了。整个思路就是先把问题分类,再去找答案。过程挺折腾,但结局还挺香。

这个聊天机器人要先学会猜心思才能干活

哥们最近搞了个挺有意思的私人项目,整了个聊天机器人专门回答家里各种杂七杂八的问题。从游泳池维护到修车记录,从换暖气滤网到上次看牙医是啥时候,反正只要跟家里沾边的事,这机器人都得管。就跟我家那个啥都管的老妈子一样,只不过这玩意不会唠叨你。

这机器人干活的路数其实挺聪明,它用了RAG技术,就是从向量数据库里翻找家庭相关的知识。但光这样还不够,哥们更绝的是让向量搜索带上了元数据标签。换句话说,这机器人回答问题前,得先猜明白你在问什么领域的事。

比如你问“咱家游泳池水泵啥时候换的”,它得先明白这是“pool”类别的事,然后专门去池子相关的内容里翻答案。这就像你去图书馆找书,得先知道去哪个区域,不然就在整个图书馆里瞎转悠,那得找到猴年马月去。

分类这活拿个超大号模型去干实在太浪费了

哥们这边用了两个本地大模型来干活。主力是Qwen 3的4B参数版本,专门负责回答问题。而分类这种“脏活累活”,他居然扔给了一个只有6亿参数的超级迷你版Qwen 3 0.6B。这尺寸差距相当于让一个幼儿园小朋友去干专业分类的活,听着就离谱。

但这哥们偏不信邪。他琢磨着,这么小的模型虽然平时可能连“猫”和“狗”都分不利索,但要是专门训练它去认家里的东西呢?于是就有了这个实验的核心想法:把一个小模型专门训练成家庭问题的分类专家,让它能一眼看穿你问的是游泳池的事还是做饭的事。

这就好比你家那个连遥控器都玩不利索的老爸,你天天训练他认菜,最后他可能分不清空调和电视,但绝对能一眼认出韭菜和葱。

不训练就让这模型干活,那准确率简直没法看

哥们先试了试没训练的效果,就当看看这模型有多不靠谱。他准备了131道测试题,直接拿原始的Qwen 0.6B模型来分类。结果那叫一个惨不忍睹,131道题里只蒙对了13道,准确率只有区区9.92%。

json
{
  "scenario": "baseline-category",
  "model_kind": "baseline",
  "model_name": "qwen3:0.6b",
  "label_mode": "category",
  "total": 131,
  "correct": 13,
  "incorrect": 118,
  "accuracy": 0.0992
}

这数据意味着啥?就是你问它131个问题,它能答对的连十分之一都不到。这还不如我闭着眼睛瞎猜呢,瞎猜至少还能有百分之二三十的正确率,它倒好,连蒙都蒙不对。

仔细一扒拉失败案例,这模型的问题还挺有规律。第一,它逮着什么都往“electric”和“appliances”这俩标签上靠,好像家里除了电相关的东西就没别的了。第二,这家伙还特爱自创新词,根本不管你在列表里给它列了啥。

json
[
  {
    "case_id": 1,
    "question": "When was the lower air conditioning system swapped out?",
    "expected_category": "hvac",
    "scenario": "baseline-category",
    "model_kind": "baseline",
    "model_name": "qwen3:0.6b",
    "label_mode": "category",
    "predicted_category": "electric",
    "correct": false
  },
  {
    "case_id": 64,
    "question": "Which painter worked on Joe's room?",
    "expected_category": "painting",
    "scenario": "baseline-category",
    "model_kind": "baseline",
    "model_name": "qwen3:0.6b",
    "label_mode": "category",
    "predicted_category": null,
    "predicted_code": null,
    "correct": false,
    "status_code": 422,
    "error": "Ollama returned an unknown category name 'apartments' from response 'apartments'"
  }
]

你看第一个案例,问的是空调系统啥时候换的,明显该归到“hvac”类,模型硬给整成“electric”。第二个更绝,问的是油漆工的事,模型直接编了个“apartments”出来,这都哪跟哪啊。这就好比你让一个不懂行的人分类,他要么把所有东西都归到“杂七杂八”里,要么就发明一堆谁都听不懂的新词。说明光靠提示词,对这种超小模型来说完全不够用。

第一次微调之前先得准备好教材

哥们用的训练数据长什么样呢?就是一堆这种格式的问答对:

json
[
  { "question": "Who cleans our gutters at the house?", "category": "gutters" },
  { "question": "Who serviced the hot water heater for the home?", "category": "water heater" },
  { "question": "Who fixed the sprinkler system in the yard?", "category": "irrigation" },
  { "question": "Which store do we usually buy pinnekjott from?", "category": "cooking" },
  { "question": "What dimensions are the air filters for the home AC?", "category": "hvac" },
  { "question": "What year did we replace the downstairs AC unit?", "category": "hvac" }
]

每个样本就是一个问题加上它对应的正确分类。这就跟小学生做练习题似的,题目和答案都给你写好了,模型的任务就是照着学。整个数据集大概有850条这样的记录,哥们把它们拆成了三份:70%用来训练,15%用来验证,剩下15%留着最后考试用。

训练框架用的是Unsloth,这玩意在开源社区挺火的,专门用来调教Qwen和Llama这类本地模型。哥们用了QLoRA这种微调策略,说白了就是在不大动干戈的情况下,给模型做点定向培训,省时省力还省钱。

第一次微调之后,这家伙总算懂点人事了

微调之后再跑那131道题,结果直接起飞了。准确率从9.92%飙升到79.39%,104道题答对了。这进步幅度相当于一个考试永远不及格的学生,补了几天课直接冲到良好了。虽然还有些问题,但至少方向对了。

json
{
  "scenario": "finetuned-category",
  "model_kind": "finetuned",
  "model_name": "our-house-qwen3-0.6b-category-names",
  "label_mode": "category",
  "total": 131,
  "correct": 104,
  "incorrect": 27,
  "accuracy": 0.7939
}

不过仔细看那些答错的题,问题也挺明显。模型开始学会把“ac”、“air”这种词往“hvac”上靠了,说明它大概知道要归哪类,但就是记不住完整标签名。还有个更头疼的问题,就是跟水相关的几个类别,比如“fountain”、“water heater”和“pool”,它经常搞混。

这就好比你让它分“可乐”“雪碧”“芬达”,它可能知道都是汽水,但就是说不准具体是哪个牌子,还经常把这三个名字互相搞混。说明模型虽然学了个大概,但精细活还是干不利索。

第二次微调只改了一个小地方,结果就逆天了

哥们想了个歪招,既然模型记不住完整的类别名字,那就不让它记名字了呗。他把所有类别都换成了两个字母的代码,比如“hvac”变成“KK”,“pool”变成“OO”。这些代码没有任何语义上的关联,就是纯粹的代号。

然后重新训练模型,让它只输出两个字母的代码。这一改效果简直离谱,测试准确率直接飙到91.6%,131道题里答对了120道。一个6亿参数的小模型,经过这么一折腾,居然真能当个靠谱的分类器用了。

json
{
  "scenario": "finetuned-code",
  "model_kind": "finetuned",
  "model_name": "our-house-qwen3-0.6b",
  "label_mode": "code",
  "total": 131,
  "correct": 120,
  "incorrect": 11,
  "accuracy": 0.916
}

你细品这个逻辑,让模型去记“hvac”这个词,它可能跟“air”、“ac”搞混。但你让它记“KK”这个完全没意义的代码,它反而能学得倍儿清楚。这就像你让人记“苹果”这个词他可能跟“梨”搞混,但你让他记“A1”这个编号,他反而不会弄错。

虽然还有毛病但已经能当个靠谱的工具用了

当然91.6%的准确率也不是完美。哥们把剩下的11个错误都列出来了,发现最顽固的问题还是“water heater”跟“pool”搞混。看来只要跟水沾边,这模型就容易犯糊涂。

但话说回来,从9.92%到91.6%的提升,已经足够让这个模型在实际项目中派上用场了。毕竟哥们要的是聊天机器人能大概猜对你在问哪个领域,然后去对应的知识库里翻答案。只要猜对的概率够高,后面找答案的环节就能省不少事。

这也给我们提了个醒,有时候折腾大模型不一定非得追求什么超能力。像这种给家里用的聊天机器人,一个6亿参数的迷你模型,配合巧妙的训练方式,照样能把活干得漂漂亮亮。关键是你的思路要对,而不是一味堆算力。

训练的窍门在于让它学编号而不是学名字

回头看看整个实验,最关键的发现其实特别简单。别让模型去学那些有语义含义的类别名,给它换成没意义的代号,反而效果更好。因为模型越小,越容易在相近的意思上犯糊涂。

用“KK”代表“hvac”,用“OO”代表“pool”,模型只需要记住哪个代号对应哪种问题,根本不需要理解这些词是什么意思。这就像让你背电话号码比背人名简单,因为电话号码没含义,不容易搞混。

这招对那些超小模型特别管用。本来6亿参数的模型脑子就不太够用,你再让它去区分“water heater”和“pool”这种有重叠意思的词,那不是为难它嘛。直接给它抽象成代码,反而省事。

整个实验给我们的最大启示

从一个不靠谱的9.92%准确率,到能实际投入使用的91.6%准确率,这哥们用一个晚上估计就能把模型训好。他用的工具链也不复杂,就是Unsloth加Qwen 3 0.6B,再加几百条标注好的家庭问题数据。

这说明一件事,很多时候我们搞AI项目,不一定非要追着最新最大的模型跑。一个合适的模型加上聪明的训练策略,可能比砸钱买一堆显卡更管用。特别是做这种特定领域的分类任务,数据质量远比模型大小重要。

哥们已经把整个项目代码放GitHub上了,有兴趣的可以去翻翻。虽然这玩意是给美国人家里用的,分类都是什么“pool”“hvac”“gutters”这些,但换到中国家庭,改成“空调”“暖气”“做饭”“洗车”之类的,思路完全一样。

总结:
一个6亿参数的迷你模型,通过巧妙的训练策略,把分类准确率从9.92%拉到91.6%。核心窍门是让模型学无意义的代码而不是有语义的类别名,这说明小模型干精细活的关键在于降低它的认知负担。

作者单位背景:Torgeir Helgevold,个人开发者