---
title: product-title-classifier-chinese-macbert-base
canonical_url: "https://www.modelscope.cn/models/bangbangkido/product-title-classifier-chinese-macbert-base"
md_url: "https://www.modelscope.cn/models/bangbangkido/product-title-classifier-chinese-macbert-base.md"
repository: bangbangkido/product-title-classifier-chinese-macbert-base
chinese_name: "商品标题分类器 chinese-macbert-base 27类"
last_updated: 2026-11-07
license: apache-2.0
pipeline_tag: text-classification
tasks:
  - text-classification
base_model:
  - hfl/chinese-macbert-base
base_model_relation: finetune
library_name:
  - pytorch
  - transformer
  - onnx
frameworks:
  - PyTorch
language:
  - zh
downloads: 0
stars: 0
---

# product-title-classifier-chinese-macbert-base

> product-title-classifier-chinese-macbert-base - bangbangkido 在 ModelScope 开源的模型。中文商品标题分类（27 类），BERT-base-chinese 微调，提供 PyTorch 与 FP32/INT8 ONNX。

bangbangkido/product-title-classifier-chinese-macbert-base 是 ModelScope 魔搭社区上的text-classification模型，采用 apache-2.0 许可，基于 hfl/chinese-macbert-base 构建。

- **Repository**: bangbangkido/product-title-classifier-chinese-macbert-base
- **License**: apache-2.0
- **Tasks**: text-classification
- **Base model**: hfl/chinese-macbert-base
- **Downloads**: 0
- **Stars**: 0
- **Last updated**: 2026-11-07

Source: https://www.modelscope.cn/models/bangbangkido/product-title-classifier-chinese-macbert-base

---

# 商品标题分类器（MacBERT-base，27 类）

中文电商商品标题的细粒度分类模型，基于 `hfl/chinese-macbert-base` 全参数微调。
输入一条商品标题，输出 27 个品类中每一类的概率，并给出 Top-3 候选。
提供 PyTorch 权重，以及 FP32、动态 INT8、INT4 weight-only 三套 ONNX。

## 平台入口

| 平台 | 仓库 | 说明 |
| --- | --- | --- |
| ModelScope | 当前仓库 | 主入口，PyTorch + FP32 / INT8 / INT4 |
| Hugging Face | [Product-Classifier-MacBERT](https://huggingface.co/bangbangkido/Product-Classifier-MacBERT) | 27 类 PyTorch |
| Hugging Face | [Product-Classifier-MacBERT-ONNX-INT8](https://huggingface.co/bangbangkido/Product-Classifier-MacBERT-ONNX-INT8) | 27 类 INT8 ONNX |

## 版本

- 版本：`20261028-170527-431825_seq32_bs512_lr2e-05_ep60_seed42_samplesall`
- 训练时间：2026-10-28T17:05:27+08:00
- 基座模型：`hfl/chinese-macbert-base`
- 输入长度：32 token
- 训练数据：88,448 条训练 / 11,059 条验证，27 类
- 最佳轮次：第 30 轮（计划 60 轮，early stopping patience=8）
- 正则：label smoothing 0.05、token 噪声 0.05、BERT dropout 0.2、分类头 dropout 0.2、R-Drop 0.5、梯度裁剪 1.0

## 验证集指标

| 指标 | 数值 |
| --- | --- |
| Accuracy | 0.9537 |
| Macro-F1 | 0.9237 |
| Weighted-F1 | 0.9536 |
| Macro-Precision | 0.9351 |
| Macro-Recall | 0.9162 |
| Loss | 0.2129 |
| ECE（10 bins） | 0.0079 |

ONNX FP32 校验（128 条验证样本）：accuracy 0.9766，PyTorch/ONNX 最大绝对误差 4.53e-6。
该 128 条子集精度不等于完整验证集精度，仅用于数值一致性检查。

ONNX 量化校验（完整验证集 11,059 条，macBERT 分词器）：

| 变体 | Accuracy | Macro-F1 | 相对 FP32 |
| --- | --- | --- | --- |
| FP32 ONNX | 0.9537 | 0.9237 | — |
| INT8 ONNX（动态 U8S8） | 0.9516 | 0.9172 | −0.21 / −0.65 个百分点 |
| INT4 ONNX（weight-only UInt4） | 0.9533 | 0.9190 | −0.05 / −0.46 个百分点 |

两种量化均通过 2 个百分点的门槛。INT4 仅量化权重、激活保持 FP32，MatMul 使用 GPTQ + UInt4
非对称（block_size 16），词嵌入使用 UInt4 非对称（block_size 128），ONNX opset 21，需要
onnxruntime 1.31 及以上。

> 验证集同时用于早停和模型选择，以上不是独立测试集成绩。

## 标签（id 顺序）

| id | 标签 | id | 标签 | id | 标签 |
| --- | --- | --- | --- | --- | --- |
| 0 | 3C数码 | 9 | 家电 | 18 | 粮油速食 |
| 1 | 个护 | 10 | 服饰内衣 | 19 | 美妆 |
| 2 | 乳品 | 11 | 母婴 | 20 | 肉禽蛋 |
| 3 | 休闲食品 | 12 | 水产 | 21 | 蔬菜 |
| 4 | 健康 | 13 | 水果 | 22 | 运动 |
| 5 | 健康食品 | 14 | 汽车用品 | 23 | 酒饮冲调 |
| 6 | 办公 | 15 | 清洁 | 24 | 鞋靴箱包 |
| 7 | 宠物 | 16 | 玩具 | 25 | 餐饮 |
| 8 | 家居 | 17 | 礼品 | 26 | 香烟 |

## 文件说明

```text
onnx/
  model.fp32.onnx          # FP32 ONNX
  model.int8.onnx          # 动态 INT8 ONNX（CPU 部署，约为 FP32 的 37.5%）
  config.json              # BERT 结构配置
  labels.json              # id2label / label2id
  inference_config.json    # max_length=32、版本、训练时间
  tokenizer.json           # 可直接给 tokenizers.Tokenizer.from_file 使用
  tokenizer_config.json
  vocab.txt
  quantization_report.json # FP32 / INT8 校验报告
onnx-int4/
  model.int4.onnx          # INT4 weight-only ONNX（MatMulNBits + GatherBlockQuantized）
  quantization_report.int4.json
  config.json
  labels.json
  inference_config.json
  tokenizer.json
  tokenizer_config.json
  vocab.txt
trained/
  model.pt                 # PyTorch state_dict（需配合 modeling.py）
  config.json
  labels.json
  inference_config.json
  tokenizer.json
  tokenizer_config.json
  vocab.txt
  special_tokens_map.json
  added_tokens.json
metadata.json              # 训练参数、数据指纹、标签、设备
best_validation.json       # 最佳轮次的整体指标与 per-class 指标
modeling.py                # PyTorch 模型结构（MacBERT/BERT 编码器 + 线性分类头）
```

**关于 INT8**：`model.int8.onnx` 由同目录的 `model.fp32.onnx` 动态量化得到（U8S8，分类头保持
FP32），无需校准样本。完整验证集上 Accuracy 0.9516、Macro-F1 0.9172，相对 FP32 为 −0.21 /
−0.65 个百分点。文件大小 152,770,306 字节，约为 FP32 的 37.5%。

**关于 INT4**：`onnx-int4/model.int4.onnx` 为 weight-only 量化（激活保持 FP32），完整验证集上
Accuracy 0.9533、Macro-F1 0.9190，相对 FP32 为 −0.05 / −0.46 个百分点；文件大小 77,385,139
字节，约为 FP32 的 19%。三种 ONNX 共用同一套 tokenizer、labels 和 max_length=32，使用时只需
替换模型文件名；INT4 需要 onnxruntime 1.31 及以上。

## ONNX 推理示例

```python
import json
import numpy as np
import onnxruntime as ort
from tokenizers import Tokenizer

model_dir = "onnx"
max_length = 32
tokenizer = Tokenizer.from_file(f"{model_dir}/tokenizer.json")
tokenizer.enable_truncation(max_length=max_length)
tokenizer.enable_padding(length=max_length)

encoded = tokenizer.encode("蓝牙耳机 主动降噪 入耳式")
inputs = {
    "input_ids": np.array([encoded.ids], dtype=np.int64),
    "attention_mask": np.array([encoded.attention_mask], dtype=np.int64),
}

# 使用 INT8 时换成 model.int8.onnx；使用 INT4 时改为 ../onnx-int4/model.int4.onnx
session = ort.InferenceSession(
    f"{model_dir}/model.fp32.onnx", providers=["CPUExecutionProvider"]
)
logits = session.run(["logits"], inputs)[0][0]
probs = np.exp(logits - logits.max())
probs = probs / probs.sum()
id2label = json.load(open(f"{model_dir}/labels.json", encoding="utf-8"))["id2label"]

for i in probs.argsort()[::-1][:3]:
    print(id2label[str(i)], float(probs[i]))
```

## PyTorch 推理示例

```python
import json
import torch
from transformers import AutoConfig, AutoTokenizer
from modeling import BertTitleClassifier

trained_dir = "trained"
max_length = 32
labels = json.load(open(f"{trained_dir}/labels.json", encoding="utf-8"))["id2label"]

config = AutoConfig.from_pretrained(trained_dir)
model = BertTitleClassifier(config, num_classes=len(labels))
model.load_state_dict(
    torch.load(f"{trained_dir}/model.pt", map_location="cpu", weights_only=True)
)
model.eval()

tokenizer = AutoTokenizer.from_pretrained(trained_dir)
batch = tokenizer(
    ["蓝牙耳机 主动降噪 入耳式"],
    padding="max_length", truncation=True, max_length=max_length,
    return_tensors="pt",
)
with torch.no_grad():
    logits = model(batch["input_ids"], batch["attention_mask"])
print(logits.softmax(dim=-1))
```

## 训练配置

```text
SEQ_LEN=32, BATCH_SIZE=512, EPOCHS=60, LEARNING_RATE=2e-5,
EARLY_STOPPING_PATIENCE=8, SEED=42
LABEL_SMOOTHING=0.05, TOKEN_NOISE_PROB=0.05,
BERT_DROPOUT=0.2, CLASSIFIER_DROPOUT=0.2, R_DROP_ALPHA=0.5, MAX_GRAD_NORM=1.0
AdamW（bias/LayerNorm 不做 weight decay）, AMP fp16, warmup 10% + 线性衰减
全参数微调（freeze_bert=False），按验证集 Macro-F1 选最佳模型
硬件：RTX 4090 24GB，torch 2.13.0+cu130
```

## 数据与限制

- 原始 30 类中，`书籍`(24)、`鲜花绿植`(87)、`钟表配饰`(99) 因训练样本少于 100 被剔除，
  当前版本只有 27 类，不能预测这 3 类。
- 类别严重不均衡：最小 `汽车用品` 127 条，最大 `家居` 14,217 条。尾部类指标明显偏低，
  例如 `汽车用品` F1 0.710、`运动` F1 0.812、`礼品` F1 0.819、`餐饮` F1 0.829；
  头部类通常在 0.95 以上。
- 训练语料是中文商品标题，不适合非商品文本、其他语言或完全空白的输入。
- 本版本没有 `其他/无法分类` 类别；分布外输入仍会被强行分到 27 类之一。
  上线时建议加置信度阈值（例如 max prob < 0.5 时转人工）并对尾部类单独监控。
- 验证集参与早停与模型选择，指标偏乐观；正式上线前建议用独立测试集复测。

## 许可

基座模型 `hfl/chinese-macbert-base` 的许可见其模型页。本仓库的微调权重和训练数据以 Apache-2.0 发布。

## 相关版本

- BERT-base-chinese 基线：[product-title-classifier-bert-base-chinese-v2](https://www.modelscope.cn/models/bangbangkido/product-title-classifier-bert-base-chinese-v2)
- 轻量 CPU 版本：[product-title-classifier-minirbt-h288](https://www.modelscope.cn/models/bangbangkido/product-title-classifier-minirbt-h288)
