跳到主要内容
AI教程

使用 Tiny Classifiers 和 Ettin-17M 训练快速、低成本的文本分类器

了解如何准备分类数据、使用更大型的 AI 模型生成标签、微调 Ettin-17M、评估准确率、估算盈亏平衡量,并使用 tiny-classifiers 配方在本地运行预测。

使用 Tiny Classifiers 和 Ettin-17M 训练快速、低成本的文本分类器

Tiny Classifiers 的功能

tiny-classifiers 是一个用于训练小型、特定任务文本分类器的实用方案。它使用拥有 1,700 万参数的 Ettin-17M 编码器,对其全部权重进行微调,并将结果保存为标准的 Hugging Face 模型。

该项目面向多种分类任务,例如路由银行消息、对新闻分类、识别用户意图、检测情感,或将法律文档分配到预定义类别。如果没有足够的标注样本,可以让更大的语言模型充当教师,为训练集生成标签。

在仓库的 Banking77 实验中,Ettin-17M 达到了 91.5% 的准确率,而 Claude Opus 的准确率为 92%。在一块游戏 GPU 上,训练耗时 42 秒,推理速度约为每条消息 5 毫秒。在笔记本电脑 CPU 上训练约需 11 分钟,在手机 GPU 上约需 21 分钟。

Banking77 准确率与训练时间对比

Banking77 准确率与训练时间对比。

主要特性

  • 小型本地模型: Ettin-17M 拥有 1,700 万参数,并为每个类别输出一个分数。
  • 人工或教师标注: 使用经过验证的标签训练,或让 Kimi K3 为原本未标注的消息生成标签。
  • GPU 和 CPU 训练: 训练脚本同时支持这两种环境。
  • 标准模型输出: 训练好的分类器可以通过 Hugging Face 的 transformers pipeline 加载。
  • 可恢复的标注: 标注脚本支持重试、自适应并发、慢请求对冲和提供商预算控制。
  • 内置评估: 训练会报告测试准确率,教师标注还可以在带标签的测试集上测量教师的准确率。
  • 成本分析: 盈亏平衡脚本会估算标注和训练何时比通过 API 支付分类费用更便宜。
  • 可复用的数据准备: 项目可以使用统一结构准备十个公开分类数据集。

训练方案的工作原理

Ettin-17M 是由约翰斯·霍普金斯大学开发的开源编码器,与 BERT 风格模型有关。不同于逐个 token 生成文本的生成式模型,它会读取完整输入,并为每个可用类别分配一个分数。

该仓库为每个类别添加一个输出,并对模型的每个权重进行微调。默认方案使用 32 的批量大小、学习率为 1e-4 的 AdamW、权重衰减 0.01、5% 的预热阶段后接余弦衰减、1.0 的梯度裁剪,以及交叉熵损失。

对于约 9,500 条消息,训练会运行六轮。只有 2,000 个样本时,优化步数保持不变,相当于约 28 轮。README 强调,这些设置并未针对每项任务分别调优。

安装与设置

1. 安装 uv

这些脚本使用 uv 创建所需环境,并在首次运行时自动安装依赖。请按照操作系统对应的说明安装 uv,然后在仓库根目录中打开终端。

2. 准备公开数据集

运行准备脚本:

uv run recipe/prepare.py

该脚本会从 Hugging Face Hub 下载 Banking77、CLINC150、英文和法文版本的 MASSIVE、TREC、AG News、SST-5、Financial PhraseBank、LEDGAR,以及一个推文仇恨言论数据集。

对于每项任务,脚本都会在 data/tasks/ 下创建一个目录。它会构建任务定义、2,000 条训练消息、一个每个类别最多包含 150 个样本的更大训练分片,以及一个测试集。

3. 配置标注提供商

如果希望教师模型生成标签,请为一个或多个受支持的提供商设置 API 密钥:

export OPENROUTER_API_KEY=...

该方案还支持 Fireworks、Together、DeepInfra 和 Parasail 的提供商密钥。在发送数据或将生成的答案用于训练之前,请查看相关提供商当前的价格、使用政策和模型条款。

基础教程:训练 AG News 分类器

步骤 1:使用 Kimi K3 生成标签

准备好数据集后,为 2,000 条 AG News 训练消息生成标签:

uv run recipe/label.py data/tasks/agnews

在报告的运行中,Kimi K3 用约 20 秒为 2,000 个样本生成了标签,成本约为 1 美元。实际耗时和成本可能因提供商而异。该脚本支持断点续作,因此中断的标注工作无需从头开始。

步骤 2:使用教师标签微调 Ettin-17M

将生成的标签文件传递给训练脚本,并选择输出目录:

uv run recipe/train.py data/tasks/agnews --labels labels/agnews-train.jsonl --save models/agnews

该脚本会微调分类器,在测试集上进行评估,输出测试准确率,并将兼容 Hugging Face 的模型保存到 models/agnews。

步骤 3:训练人工标注基线

不提供教师标签参数,运行相同的训练脚本,使用数据集原有的人工标签进行训练:

uv run recipe/train.py data/tasks/agnews

这一对比有助于了解知识蒸馏过程中损失了多少性能。在仓库的教程运行中,人工标签得到 89.2% 的准确率,Kimi K3 标签得到 85.1%,Qwen3.8-27B 标签得到 81.8%。

第 4 步:对新文本进行分类

使用 Hugging Face pipeline 加载已保存的模型:

from transformers import pipeline

classify = pipeline(
    "text-classification",
    model="models/agnews",
    device="cpu"
)

result = classify(
    "NASA's new telescope finds water vapour on a distant planet"
)
print(result)

结果是一个包含预测标签及其得分的列表。在本例中,预期类别是 Sci/Tech。报告中的 AG News 模型在 CPU 上处理一条消息约需 6 毫秒。

使用自己的数据训练 Tiny Classifiers

1. 创建任务目录

按照 data/tasks/agnews/ 的相同布局创建文件夹。每个自定义任务都需要 task.json、train.jsonl 和 test.jsonl 文件。

2. 定义类别

task.json 文件必须包含名称、一条指令语句以及完整的标签列表:

{"name":"support-routing","instruction":"Assign each support message to the correct team.","labels":["billing","technical","account"]}

使用彼此 distinct 且有意义的标签名称。指令应清楚描述模型或教师需要做出的分类判断。

3. 添加训练和测试记录

每行存储一个 JSON 对象。带标签的记录结构如下:

{"id":"msg-001","text":"I was charged twice for my subscription.","label":"billing"}

如果由教师模型为训练数据添加标签,train.jsonl 中的记录可以省略 label 字段:

{"id":"msg-002","text":"The application closes whenever I upload a file."}

测试记录应包含经过核验的标签,以便同时衡量教师和学生模型的准确率。项目建议在生产环境信任模型之前,人工检查几百条测试消息。

4. 添加标签、训练并评估

在标准命令中替换为你的目录:

uv run recipe/label.py data/tasks/support-routing
uv run recipe/train.py data/tasks/support-routing \
  --labels labels/support-routing-train.jsonl \
  --save models/support-routing

省略 --labels 后,也可以直接使用人工标签进行训练。若要使用其他编码器替代 Ettin-17M,请通过训练脚本的 --model 选项传入模型。

衡量微调何时值得

准备好任务后,运行盈亏平衡分析:

uv run recipe/breakeven.py

该脚本会综合考虑资金和时间,估算在收回标签和训练的前期成本之前必须分类多少条消息。与 Jev 零样本分类 API 相比,该仓库发现盈亏平衡点约为 50,000 至 500,000 条消息,具体取决于任务。

如果你的使用量较小或尚不确定,API 可能是更简单的选择。当任务稳定、已有评估数据且分类量较高时,微调更具吸引力。

高级技巧

优先保证标签质量

实验发现,标签的重要性高于模型规模。随着添加更多带标签的示例,学习曲线仍在持续提升。由教师训练的学生模型通常会比教师低几个准确率百分点,而人工标签可以突破这一上限。

在更改架构或调节大量超参数之前,先检查含义模糊的类别,修正系统性的标注错误,并添加具有代表性的示例。

单独评估教师模型

如果教师模型在任务上的表现不佳,学生模型无法可靠地弥补这一问题。十项任务的结果显示,在教师本身较弱的领域,使用教师标签训练的模型表现会落后。保留一份经过人工核验的测试集,并在付费标注更大规模的数据集之前测量教师准确率。

考虑实验差异

README 报告称,随机种子会带来约 ±0.5 个百分点的差异,测试集大小会带来 ±1.5 至 2 个百分点的差异。发布的表格使用三次运行的平均值。当细微的准确率差异会影响部署决策时,应使用重复运行和足够大的测试集。

遵守许可证和供应商条款

只有在教师模型的许可证和供应商条款允许的情况下,才能仅使用生成的答案进行训练。该仓库使用了 Kimi K3,但部分模型和 API 禁止使用其输出训练其他模型。公共数据集也有各自的许可证;该仓库会下载这些数据集,而不是重新分发它们。

探索替代硬件

主要训练脚本支持 CPU 和 GPU 执行。该仓库还包含一个独立的手机实现,可通过 Chrome 使用 WebGPU 和 jax-js 进行训练。请将手机工作流视为专用实现,并遵循项目 phone/ 目录中的说明。

解决文档所述的 NixOS 问题

如果在 NixOS 上训练时因找不到 /sbin/ldconfig 而失败,请在运行训练前设置 CUDA 库路径:

export TRITON_LIBCUDA_PATH=/run/opengl-driver/lib

结论

tiny-classifiers 提供了一套紧凑的工作流,可将带标签的文本转换为快速的本地分类器:准备任务,获取人工或教师标签,微调 Ettin-17M,使用经过核验的示例进行评估,并估算本地推理在经济上是否优于 API。

最重要的经验是投入精力确保标签和评估数据可靠。一旦这些条件具备,一个拥有 17 百万个参数的编码器就能提供出色的分类准确率、毫秒级推理速度和可预测的本地运营成本,而无需为每条消息调用大型模型。