码力全开 / 使用BERT实现中文层次化分类

Created Sat, 18 Apr 2026 14:28:45 +0800 Modified Sat, 18 Apr 2026 14:58:06 +0800
933 Words 1 min

最近项目中需要实现类似如下的一个工单需求:

怎么电梯又坏了,这个月都坏了多少次了? -> 一级应急安全 / 电梯维修

即根据一段文本将其划分了多级的分类,而这些分类具有层次化。结果发现这是NLP中一个难点与热点问题,即Hierachical (multi-label) text classification(HMC),层次多标签分类任务。

对于这个问题,可以使用NeuralNLP-NeuralClassifier中的方案解决。

下面我们通过StructBERT及二郎神大模型来实现类似的效果。

from transformers import pipeline
from transformers import AutoModelForSequenceClassification, AutoTokenizer

model_checkpoint = "StructBERT"
classifier = pipeline("zero-shot-classification",model_checkpoint)

text = "昨天下的单今天就发货了,速度超快!但收到后发现耳机左耳没声音,联系客服说要寄回检测,流程太麻烦。"
candidate_labels = [
    ["[情感]正面","[情感]负面","[情感]中性"],
    ["[主题]物流","[主题]新闻","[主题]质量","[主题]售后","[主题]科技","[主题]娱乐","[主题]饮食"]
]
result = classifier(
    text, 
    candidate_labels=candidate_labels,
    hypothesis_template="这段文本属于{}类别。",
)
scores_dict = dict(zip(result['labels'], result['scores']))
max_labels = {}
for k,v in scores_dict.items():
    start = k.find("[")
    end = k.find("]")
    t = k[start:end+1]
    if t in max_labels:
        score = max_labels[t][1]
        if v > score:
             max_labels[t] = (k[end+1:], v)
    else:
        max_labels[t] = (k[end+1:],v)
print("文本: {}\n".format(text))
for k,v in max_labels.items():
    print(k,v[0])

其结果类似如下:

文本: 昨天下的单今天就发货了,速度超快!但收到后发现耳机左耳没声音,联系客服说要寄回检测,流程太麻烦。

[主题] 质量
[情感] 负面

但是发现实际效果不怎么问题且存在划分错误的情况。而实际更应该生成所有完整路径标签:

科技 > 人工智能 > 自然语言处理
科技 > 人工智能 > 计算机视觉
科技 > 硬件
体育 > 足球
体育 > 篮球

然后通过一次性分类。

# 假设层级结构
paths = [
    "科技 > 人工智能 > 自然语言处理",
    "科技 > 人工智能 > 计算机视觉",
    "科技 > 硬件",
    "体育 > 足球",
    "体育 > 篮球"
]

text = "这篇关于Transformer模型的文章很有趣"

# 直接将完整路径作为候选标签
result = classifier(text, paths, multi_label=False)

需要对上述文本进行微调才能得到较好的效果。

参考文章:

https://gitee.com/hf-models/bart-large-mnli https://fengshenbang-doc.readthedocs.io/zh/latest/docs/%E5%9C%BA%E6%99%AF%E5%BA%94%E7%94%A8/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E6%8E%A8%E7%90%86.html

如果喜欢这篇文章或对您有帮助,可以:[☕] 请我喝杯咖啡 | [💓] 小额赞助