BERT 中文新闻分类实战:THUCNews 十分类的几个关键点
背景
中文文本分类是最基础也最实用的 NLP 任务之一:新闻归类、工单路由、评论审核,本质都是把一段文本映射到一个类别。
传统做法是 TF-IDF 加线性模型,速度快、可解释性好,但在语义相近的类别上容易混淆。现在更常见的做法是用预训练语言模型微调。本文记录一次用 BERT 在 THUCNews 上做 10 分类的实践,重点不在跑通流程,而在几个容易被忽略的细节。
数据
THUCNews 是中文新闻语料,常见做法是取其中 10 个类别(体育、财经、房产、家居、教育、科技、时尚、时政、游戏、娱乐)作为分类任务。
这份数据的几个特点,直接决定了后面要处理的问题:
- 各类别样本量不均衡,长尾类别容易被大类压住
- 正文长度跨度大,短的几十字,长的上千字
- 标题往往比正文更能代表类别
模型与训练
基础模型用 bert-base-chinese,后面接一个分类头做微调。核心逻辑很短:
outputs = model(input_ids=input_ids, attention_mask=attention_mask)
logits = outputs.logits
loss = criterion(logits, labels)
但真正决定效果的并不是这几行,而是下面三件事。
三个关键点
一、截断策略比想象中重要
BERT 的最大长度是 512,中文新闻经常超长。如果直接用 truncation 从头截断,结尾的结论性内容会被丢掉。
一种更稳的做法是把标题拼在正文前面再截断——标题通常浓缩了主题,把它保留下来,判别信号会更强。
二、学习率要小
微调不是从头训练。学习率常用 2e-5 到 5e-5 这个量级,如果用 1e-3,很容易把预训练权重冲掉,表现是 loss 先降后炸。
配合 warmup 会更稳定一些。
三、评估指标别被不均衡数据骗了
10 个类别样本量差得多,直接训练时模型会偏向大类。这种分布下,accuracy 会虚高——全部猜成最大的那个类,也能拿到一个看起来不错的数字。
更合适的指标是 macro-F1,它对每个类别一视同仁。用它做早停和模型选择,比看 accuracy 可靠。
如果想让模型本身更均衡,也可以在损失函数里按类别频率反比加 weight。
结果
最终在测试集上准确率 88.43%。
这个数字属于正常区间。THUCNews 10 分类上,BERT 类模型普遍落在 88% 到 93% 之间,差距主要来自数据清洗和截断策略,而不是模型结构本身。
换句话说,把时间花在数据上,比换更大的模型更划算。
部署
训练完成后用 Flask 包了一层,一个输入框加一个接口,方便演示和联调:
@app.route("/predict", methods=["POST"])
def predict():
text = request.json["text"]
inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=256)
with torch.no_grad():
logits = model(**inputs).logits
label = id2label[logits.argmax(-1).item()]
return {"label": label}
注意推理时的 max_length 可以不等于训练时的长度,短一些能明显降低延迟。
小结
做中文分类,模型选型往往不是瓶颈。真正拉开差距的是三件事:
- 截断时保留了多少有判别力的信息
- 学习率是否匹配微调场景
- 评估指标是否被不均衡数据误导
这三点在任何中文分类任务上都能复用。
- 点赞
- 收藏
- 关注作者
评论(0)