开发者实践展示用Qwen 3:0.6B本地微调完成特定分类任务,证明小模型在边界场景的可行性。适合资源受限环境参考。
作为一个有趣的个人项目,我一直在开发一个聊天机器人,用来回答关于我家庭的一般性问题,从维护问题到医生的预约都涵盖。
总体想法是聊天机器人将通过 RAG 从向量数据库查询获取家庭知识,但为了获得更好的结果,我把向量搜索设计得支持元数据感知。
基本上,我通过一个预处理步骤来处理问题,将问题分类到已知的元数据类别中(例如 pool、car、hvac、cooking)。这样做的主要目的是缩小向量排序的搜索空间,只搜索与问题类别匹配的已索引条目。例如,问题"我们什么时候换的游泳池泵?"会在查询索引数据库前被映射到一个叫做 "pool" 的类别。
我想在这个实验中验证的假设是:一个非常小的本地 LLM 能否通过在家庭相关问题的数据集上进行微调来执行可靠的问题分类。
在这个项目中,我使用了两个不同的本地 LLM —— Qwen 3:4B 和 Qwen 3:0.6B。4B 参数版本用于通用问题回答,而超小型的 0.6B 版本用于问题分类。这个实验的整个前提是看一个只有 600M 参数的微型 LLM 能否被微调成家庭问题的可靠分类器。
对于微调,我使用了一个名叫 Unsloth 的流行开源框架,它似乎非常适合调整像 Qwen 和 Llama 这样的本地模型。
出于训练目的,我的初始数据集由约 ~850 条数据条目组成,我按照 70/15/15 的百分比将其分为训练数据、评估数据和测试数据。训练数据和评估数据用于训练期间,而测试数据集保留下来在训练后运行测试。详见下面的示例数据部分:
基本想法是在足够多的家庭问题集合上训练 LLM,使其成为可靠的问题分类器。
在进行任何微调之前,建立一个基线进行对比是很重要的。在这个实验中,基线是尝试"原样"使用原始的 Qwen 0.6B 模型,仅通过提示词。下面是用于基线的示例提示词:
作为我的离线评估方法之一,我创建了约 ~130 个集成测试,用来从第二个数据集的场景测试模型。对于基线模型,结果很差。在 131 个测试中,模型只正确分类了 13 个问题(约 10% 的正确响应)。详见下面的摘要:
在深入挖掘实际的失败时,出现了一些常见的模式:
模型大量过度使用 electric/appliances 这样的宽泛标签,错过了大多数其他类别(例如 pool、cooking、hvac)。
模型凭空捏造新类别(例如 apartments),并且不坚持提供的允许类别列表。
我在下面提供了测试报告的摘录:
基线的结果清楚地表明,像 Qwen 3 0.6B 这样的微型模型仅通过提示词无法提供可靠的性能。
对于下一个实验,我使用与之前相同的提示词,但进行模型微调来教导模型以更高的准确性进行分类。
我在这里包含了微调脚本,以防你有兴趣查看。在高层次上,我使用 Unsloth 和 QLora 作为微调策略。一个注意事项:Unsloth 提供的默认微调参数提供了非常好的起点。根据我的经验,花功夫整理一个好的数据集比担心调整 Unsloth 参数重要得多,至少在开始时是这样。
但有一个常见的陷阱要避免,那就是在训练数据上过拟合,这就是为什么在不在训练数据中的数据上测试模型很重要。除了静态的训练/测试数据,我还合并了一种方式来提供用户反馈以在未来重新训练期间作为第二个通道来修正训练数据。
在运行了集成测试套件后,我观察到预测精度有了明显的改进,如下面的报告所示:
预测精度从 10% 上升到 79%,但我仍然看到一些明确的不正确结果模式:
模型现在清楚地表现出朝着正确方向发展的迹象,但我看到一个模式是只输出允许列表中的正确类别的片段。一些例子是 ac/air 而不是 hvac。
模型被语义重叠的类别搞糊涂了,比如来自 fountain、water heater 和 pool 的基于水的混淆。
对第一次微调实验的一个简单改进是添加一个后处理步骤。这将允许我规范化预测语义正确但句法不正确的结果(例如 ac、air)。另一个调整是通过提供更多示例、告诉模型该做什么和不该做什么来在提示词本身中建立更多的强化。我会说两个想法都合理,但随着更多类别的增加,它导致更多的维护工作。
相反,我想看看我是否可以通过对我教导模型映射类别的方式做一些改变来稍微调整微调方法。
事实证明,我们可以对提示词进行一个小改动来获得比第 1 个实验更好的准确性改进。这个调整实际上只是对提示词的简单改变,我将类别映射到没有语义重叠的两个字符的不透明 ID,如下面的示例所示:
现在,我让模型输出固定格式的代码,而不是一个可能有重叠含义的可变类别字符串(例如基于水的类别)。
有趣的部分是我从这个简单的改变中看到了非常好的性能提升,如下面的摘要所示:
如你所见,预测精度现在约为 ~92%,这相当准确。看起来要求固定的、非重叠的输出能帮助微型 qwen 模型在生成响应时的表现。
虽然还有一些未命中。我在下面包含了具体的失败情况:
此时预测一般是可靠的,微调后的 LLM 作为我聊天机器人中的可用预测器运作,但仍有问题需要解决。一个突出的问题是 water heater -> pool,这可能仍然是由于这两个类别之间重叠的"watery"含义。为了解决这个问题,我可能需要重新访问训练数据并使其更加细致。
一个示例聊天交互可以在下面的截图中看到。特别注意蓝色问题气泡中的小类别标签(例如 "pool"),因为那是由微型 qwen 3:0.6B LLM 自动分类的部分。
我在这里包含了 Github 代码库,以防你有兴趣查看。
虽然这篇文章的主要重点是学习微型模型的微调,我确实从多个读者收到反馈,我应该考虑比 LLM 微调更简单的分类方法。这启发我使用 Logistic Regression 作为分类器来运行一个新实验。如果有兴趣,你可以在这里找到新文章。