🏷️ 数据标注 · 核心基础

分类标注 · 最简单也最常用

为每条样本打一个或多个类别标签,是几乎所有监督学习项目的必经之路。看似简单,做好却需要规范、工具和质量控制。

什么是分类标注?

📝

定义

给每条数据分配预定义类别中的一个或多个标签

🎯

应用场景

情感分析、垃圾邮件过滤、图文分类、意图识别等

难度

★☆☆☆☆ 入门级,标注效率高,适合众包

三种标注类型

1

单分类(Single Label)

每条样本只能属于一个类别,互斥关系。

示例:情感分析
😀
正面
"产品真的很棒"
😐
中性
"一般般吧"
😠
负面
"太差了,退款"
2

多分类(Multi Label)

每条样本可以同时属于多个类别,独立勾选。

示例:新闻主题标注
"AI大模型再次突破:GPT-5发布引爆科技圈,股价创新高"
✔ 科技 ✔ 财经 ✔ AI ○ 体育 ○ 娱乐
3

层级分类(Hierarchical)

类别之间有父子关系,先选大类再选小类。

示例:电商商品分类
📱 数码产品 📱 手机 📱 iPhone 系列
👕 服饰 👕 男装 👕 T恤

标注工作全流程

1

定义标签体系

明确有哪些类别、互斥还是多选、以及遇到模棱两可的样本怎么判(如"一般吧不算好也不算差"算正面还是负面?)。产出 label_guide.md

# 情感分类标签定义
positive: 明确正面评价,含推荐/表扬 → 关键词:好、棒、满意、推荐
neutral: 无明显情感倾向 → 关键词:一般、还可以、普通
negative: 明确负面评价 → 关键词:差、糟、失望、退款
ambiguous: 无法判断或混合情感 → 选这个
2

准备数据 & 标注工具

按格式准备数据,选标注工具(开源/商业/自研)

📤 数据格式
JSONL / CSV / COCO
🛠️ 开源工具
Label Studio · Doccano
🏢 商业平台
Labelbox · 阿里云 · 百度众测
3

批量标注(人 + AI)

人工逐条打标,可用 LLM 做弱监督预标注提速

纯人工:准确率高,成本高 LLM 预标 + 人工复核:性价比最优 主动学习:模型挑最有价值的给人标
4

质量控制(QC)

1 多人交叉标注 2 计算一致性系数 3 仲裁分歧
Kappa 系数解读(3人交叉标注):
≥ 0.8 几乎一致 → 高质量
0.6~0.8 基本一致 → 可接受
< 0.6 分歧较大 → 需重新审标签定义
5

导出 & 验证

导出标注结果,做数据分布检查

🔍 分布检查
各类别样本是否均衡?长尾类要不要过采样?
💾 格式转换
CSV/JSONDataFrame训练格式

常用标注工具对比

工具 类型 费用 分类标注 亮点
Label Studio 开源自部署 免费 ✅ 强 支持 text/image/audio,插件丰富
Doccano 开源自部署 免费 ✅ 强 专为 NLP 设计,界面极简
Labelbox SaaS 平台 付费 ✅ 强 UI 精致,团队协作好
Prodigy Python 库 付费 ✅ 强 主动学习 + spaCy 生态

实战:Label Studio 接入 + Python 导出

# 1. 启动 Label Studio(Docker 一键起)
docker run -p 8080:8080 -v $(pwd)/mydata:/label-studio/data \
  heartexlabs/label-studio:latest

# 2. 准备待标注数据 (JSONL)
import json

with open('reviews.jsonl', 'r') as f:
    for line in f:
        item = json.loads(line)
        print('{"text": "%s"}' % item['review'])

# 3. Label Studio 里配置标签 → 批量导入 → 开始标注

# 4. 导出结果后用 Python 解析
import pandas as pd
import json

with open('annotations.json') as f:
    data = json.load(f)

rows = []
for item in data:
    text = item['data']['text']
    # 提取第一个标注结果
    labels = item['annotations'][0]['result']
    tag = labels[0]['value']['choices']
    rows.append({'text': text, 'label': tag[0]})

df = pd.DataFrame(rows)
print(df.head())

接下来:看看另外两种标注类型