跳转至

Label Studio 完全指南

为什么要学 Label Studio

  1. 最灵活的开源标注工具:Label Studio 支持文本、图像、音频、视频、HTML、时间序列等几乎所有数据类型的标注。文本分类、NER、图像目标检测、语义分割、音频转写、视频标注——一个工具全搞定。

  2. 模板化配置,高度可定制:通过 XML 模板定义标注界面。预置 50+ 模板涵盖常见场景,也可以完全自定义界面布局、标签体系、快捷键。不需要写前端代码就能创建专业的标注界面。

  3. ML Backend 主动学习:可以连接 ML 模型作为预标注引擎(ML Backend)。模型先给出预测,标注者只需确认或修正,效率提升 3-10 倍。支持主动学习循环——模型不确定的样本优先标注。

  4. 团队协作与质量管理:支持多人协作标注、标注者间一致性检查(Inter-Annotator Agreement)、评审流程、角色权限。企业版还有详细的标注质量仪表板。

  5. 丰富的导出格式:标注结果可导出为 JSON、CSV、COCO、VOC、YOLO、CoNLL 等格式,直接对接下游训练框架。


核心概念详解

Label Studio 是什么(白话解释)

机器学习模型需要大量标注好的数据来训练。Label Studio 就是一个"数据标注工作台"——你把原始数据(图片、文本、音频等)导入,定义标注规则(比如"标出图片中的猫和狗"),然后标注者在网页上进行标注,最后导出标注结果用于模型训练。

核心概念

概念说明
Project标注项目,包含数据、配置和标注结果
Task一条待标注的数据记录
Annotation一条标注结果
Label ConfigXML 格式的标注界面配置
ML Backend连接的 ML 模型,提供预标注
PredictionML 模型给出的预标注结果
Review标注质量审核流程

支持的标注类型

类型标注任务模板
文本分类、NER、情感分析、关系抽取Text Classification, NER
图像目标检测、分割、关键点、OCRObject Detection, Semantic Segmentation
音频转写、分类、说话人识别Audio Classification, Transcription
视频目标跟踪、动作标注Video Timeline Labeling
HTML网页元素标注HTML Labeling
时间序列异常检测、事件标注Time Series Labeling
多模态图文匹配、VQAPairwise Comparison

Label Studio vs Prodigy vs CVAT vs Labelbox 对比

特性Label StudioProdigyCVATLabelbox
开源完全开源闭源(买断)开源SaaS
价格免费 + 企业版一次性购买$490免费付费
数据类型全类型文本/图像为主图像/视频全类型
界面Web UI命令行+WebWeb UIWeb UI
主动学习ML Backend核心特性有限支持
团队协作企业版不支持支持支持
自定义XML 模板(高)Python recipe(高)预设模式编辑器
部署自托管/Cloud本地自托管Cloud
适合场景通用NLP/小团队CV专项企业级

安装与配置

安装

# pip 安装(推荐)
pip install label-studio

# Docker 安装
docker run -it -p 8080:8080 \
  -v $(pwd)/mydata:/label-studio/data \
  heartexlabs/label-studio:latest

# Docker Compose

docker-compose.yml:

version: '3.8'
services:
  label-studio:
    image: heartexlabs/label-studio:latest
    ports:
      - "8080:8080"
    volumes:
      - ./data:/label-studio/data
    environment:
      - LABEL_STUDIO_LOCAL_FILES_SERVING_ENABLED=true
      - LABEL_STUDIO_LOCAL_FILES_DOCUMENT_ROOT=/label-studio/files

启动

# 直接启动
label-studio start

# 指定端口和数据目录
label-studio start --port 8080 --data-dir ./ls-data

# 打开 http://localhost:8080
# 首次使用需要注册管理员账号

命令行工具

# 创建用户
label-studio user create --username admin --password admin123

# 重置密码
label-studio user reset_password --username admin --password newpass

# 导出数据
label-studio export --project-id 1 --format JSON --output annotations.json

快速上手:5 分钟最小示例

示例一:文本分类

  1. 创建项目 → 选择"Text Classification"模板
  2. 标注配置自动生成:
<View>
  <Header value="请选择文本的情感倾向"/>
  <Text name="text" value="$text"/>
  <Choices name="sentiment" toName="text" choice="single">
    <Choice value="正面"/>
    <Choice value="负面"/>
    <Choice value="中性"/>
  </Choices>
</View>
  1. 导入数据(JSON 格式):
[
  {"text": "这个产品非常好用,推荐购买!"},
  {"text": "质量太差了,退货了"},
  {"text": "一般般吧,没什么特别的"},
  {"text": "超出预期的好!会回购"},
  {"text": "发货速度很慢,不满意"}
]
  1. 开始标注 → 点击对应标签
  2. 导出为 JSON/CSV

示例二:NER 命名实体识别

<View>
  <Labels name="label" toName="text">
    <Label value="人名" background="red"/>
    <Label value="地点" background="blue"/>
    <Label value="组织" background="green"/>
    <Label value="时间" background="orange"/>
  </Labels>
  <Text name="text" value="$text"/>
</View>

数据:

[
  {"text": "2024年12月,张三在北京大学发表了重要演讲。"},
  {"text": "李四上周去了上海,参加了阿里巴巴的技术大会。"}
]

示例三:图像目标检测

<View>
  <Image name="image" value="$image"/>
  <RectangleLabels name="label" toName="image">
    <Label value="猫" background="red"/>
    <Label value="狗" background="blue"/>
    <Label value="人" background="green"/>
  </RectangleLabels>
</View>

数据:

[
  {"image": "https://example.com/image1.jpg"},
  {"image": "/data/local-files/?d=images/photo1.jpg"}
]


进阶用法

场景一:复杂标注模板

<!-- NER + 关系抽取 + 分类 多任务标注 -->
<View>
  <Header value="1. 实体标注"/>
  <Labels name="entities" toName="text">
    <Label value="药物" background="#ff6666"/>
    <Label value="疾病" background="#66ff66"/>
    <Label value="症状" background="#6666ff"/>
  </Labels>

  <Header value="2. 关系标注"/>
  <Relations>
    <Relation value="治疗"/>
    <Relation value="引起"/>
    <Relation value="缓解"/>
  </Relations>

  <Text name="text" value="$text"/>

  <Header value="3. 文档分类"/>
  <Choices name="doc_type" toName="text" choice="single">
    <Choice value="病例报告"/>
    <Choice value="药物说明"/>
    <Choice value="研究论文"/>
  </Choices>

  <Header value="4. 标注质量自评"/>
  <Rating name="confidence" toName="text" maxRating="5"/>
  <TextArea name="notes" toName="text" placeholder="备注..." rows="2"/>
</View>

场景二:图像语义分割

<View>
  <Header value="请标注图片中的区域"/>
  <Image name="image" value="$image" zoom="true" negativeZoom="true"
         crosshair="true" rotateControl="true"/>

  <PolygonLabels name="label" toName="image" strokeWidth="3"
                 pointSize="small" opacity="0.6">
    <Label value="建筑" background="red"/>
    <Label value="道路" background="blue"/>
    <Label value="植被" background="green"/>
    <Label value="水体" background="cyan"/>
    <Label value="天空" background="lightblue"/>
  </PolygonLabels>

  <BrushLabels name="brush" toName="image">
    <Label value="裂缝" background="yellow"/>
    <Label value="锈蚀" background="orange"/>
  </BrushLabels>
</View>

场景三:ML Backend 预标注

# ml_backend.py
from label_studio_ml import LabelStudioMLBase
from label_studio_ml.utils import get_single_tag_keys
import spacy

class SpacyNERBackend(LabelStudioMLBase):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.nlp = spacy.load("zh_core_web_sm")
        self.from_name, self.to_name, self.value, self.labels = get_single_tag_keys(
            self.parsed_label_config, "Labels", "Text"
        )

    def predict(self, tasks, **kwargs):
        results = []
        for task in tasks:
            text = task["data"][self.value]
            doc = self.nlp(text)
            predictions = []
            for ent in doc.ents:
                if ent.label_ in self.labels:
                    predictions.append({
                        "from_name": self.from_name,
                        "to_name": self.to_name,
                        "type": "labels",
                        "value": {
                            "start": ent.start_char,
                            "end": ent.end_char,
                            "text": ent.text,
                            "labels": [ent.label_],
                        },
                        "score": 0.8,
                    })
            results.append({
                "result": predictions,
                "score": sum(p.get("score", 0) for p in predictions) / max(len(predictions), 1),
            })
        return results

    def fit(self, event, data, **kwargs):
        # 可选:用新标注数据重新训练模型
        pass

启动 ML Backend:

pip install label-studio-ml

# 启动
label-studio-ml start ./ml_backend \
    --with SpacyNERBackend \
    --port 9090

在 Label Studio 中添加 ML Backend: Settings → Machine Learning → Add Model → URL: http://localhost:9090

场景四:通过 API 批量导入数据

import requests
import json

LS_URL = "http://localhost:8080"
API_KEY = "your-api-key"  # 在 Account Settings 中获取
PROJECT_ID = 1

headers = {
    "Authorization": f"Token {API_KEY}",
    "Content-Type": "application/json",
}

# 批量导入
tasks = [
    {"data": {"text": f"这是第 {i} 条文本"}}
    for i in range(1000)
]

response = requests.post(
    f"{LS_URL}/api/projects/{PROJECT_ID}/import",
    headers=headers,
    json=tasks,
)
print(f"导入了 {response.json()['task_count']} 条任务")

场景五:导出和格式转换

import requests

headers = {"Authorization": f"Token {API_KEY}"}

# 导出为不同格式
# JSON
response = requests.get(
    f"{LS_URL}/api/projects/{PROJECT_ID}/export?exportType=JSON",
    headers=headers,
)
annotations = response.json()

# COCO 格式(图像检测)
response = requests.get(
    f"{LS_URL}/api/projects/{PROJECT_ID}/export?exportType=COCO",
    headers=headers,
)

# YOLO 格式
response = requests.get(
    f"{LS_URL}/api/projects/{PROJECT_ID}/export?exportType=YOLO",
    headers=headers,
)

# CoNLL 格式(NER)
response = requests.get(
    f"{LS_URL}/api/projects/{PROJECT_ID}/export?exportType=CONLL2003",
    headers=headers,
)

场景六:Python SDK

from label_studio_sdk import Client

ls = Client(url="http://localhost:8080", api_key="your-api-key")

# 创建项目
project = ls.start_project(
    title="情感分类",
    label_config="""
    <View>
      <Text name="text" value="$text"/>
      <Choices name="sentiment" toName="text">
        <Choice value="正面"/>
        <Choice value="负面"/>
      </Choices>
    </View>
    """,
)

# 导入数据
project.import_tasks([
    {"data": {"text": "很好的产品"}},
    {"data": {"text": "太差了"}},
])

# 获取标注结果
annotations = project.get_labeled_tasks()
for task in annotations:
    for ann in task["annotations"]:
        print(ann["result"])

常见问题与排错

问题一:图片无法显示

原因:本地图片需要配置文件服务。

# 启动时启用本地文件服务
export LABEL_STUDIO_LOCAL_FILES_SERVING_ENABLED=true
export LABEL_STUDIO_LOCAL_FILES_DOCUMENT_ROOT=/path/to/images

label-studio start

问题二:中文显示问题

确保数据文件使用 UTF-8 编码。Label Studio 本身支持中文。

问题三:大量数据导入慢

# 分批导入
batch_size = 500
for i in range(0, len(tasks), batch_size):
    batch = tasks[i:i+batch_size]
    requests.post(f"{LS_URL}/api/projects/{PID}/import", headers=headers, json=batch)

问题四:如何备份数据

# 数据存储在 SQLite 或 PostgreSQL 中
# 默认位置:~/.local/share/label-studio/

# 导出所有标注
label-studio export --project-id 1 --format JSON --output backup.json

问题五:如何设置快捷键

<!-- 在 Label Config 中设置 hotkey -->
<Choices name="label" toName="text" choice="single">
  <Choice value="正面" hotkey="1"/>
  <Choice value="负面" hotkey="2"/>
  <Choice value="中性" hotkey="3"/>
</Choices>

参考资源

  • 官方文档:https://labelstud.io/guide/
  • GitHub:https://github.com/HumanSignal/label-studio
  • 模板库:https://labelstud.io/templates/
  • Label Studio SDK:https://github.com/HumanSignal/label-studio-sdk
  • ML Backend SDK:https://github.com/HumanSignal/label-studio-ml-backend
  • Slack 社区:https://label-studio.slack.com/
  • 教程视频:https://www.youtube.com/@LabelStudio