name: data-labeling description: 使用人工标注工具、半自动化流水线、主动学习和编程式弱监督,建立并管理数据标注工作流。 license: MIT metadata: author: AI Agent Skills version: 1.0.0
本技能让 AI Agent 为机器学习项目设计并执行数据标注工作流。涵盖使用 Label Studio 等工具的人工标注、使用模型辅助预标注的半自动标注、优先标注信息量最大样本的主动学习循环,以及使用标注函数的编程式弱监督。Agent 处理标签 schema 设计、标注员指南、通过标注者间一致性进行质量控制,以及导出为 ML 可用格式。
定义标注 schema 与指南: 设计标签分类体系——分类的类别、NER 的实体类型、目标检测的边界框类别,或语义分割的分割标签。为每个标签编写清晰的标注员指南,包含正例与反例,覆盖边界情况与歧义场景。
搭建标注环境: 配置标注工具(Label Studio、Labelbox 或 Prodigy),载入 schema,导入原始数据,并设置具有适当权限的用户账户。定义与任务类型匹配的标注界面模板——文本分类、跨度标注、图像边界框,或多轮对话标注。
用模型预测预标注: 使用现有模型或启发式规则为数据集生成初步标签。标注员随后审查并修正这些预测,而非从零开始标注,这可将标注时间减少 40–60%。当已存在不错的基线模型时,此方式尤其有价值。
带质量控制地执行标注: 将标注任务分配给标注员时内置冗余——让 2–3 名标注员标注相同条目,以衡量标注者间一致性(Cohen's kappa 或 Fleiss' kappa)。将一致性低的条目标记出来,交由资深标注员审查。对照嵌入任务队列中的黄金标准集跟踪标注员准确率。
运行主动学习迭代: 在创建初始标注集后,训练一个模型,并使用不确定性采样或委员会查询(query-by-committee)选择信息量最大的未标注样本,进入下一轮标注。这能最大化每个标注样本带来的模型提升,在标注预算有限时尤为关键。
导出与验证: 以训练流水线所需的格式(JSONL、COCO、CoNLL、CSV)导出标注数据。运行校验检查以确保标签一致性、检查缺失标注,并验证类别分布满足要求。记录标注过程与数据集统计以便复现。
为 Agent 提供原始数据集、任务类型(分类、NER、目标检测等)和标签类别。可选择指定标注工具偏好和质量要求(最小标注者间一致性)。Agent 将配置标注环境、建立质量控制并管理标注工作流。
Label Studio 标注界面配置(config.xml):
<View> <Header value="Classify the customer review sentiment:" /> <Text name="text" value="$text" /> <Choices name="sentiment" toName="text" choice="single-column" showInline="true"> <Choice value="positive" /> <Choice value="negative" /> <Choice value="neutral" /> </Choices> <Textarea name="notes" toName="text" placeholder="Optional: explain ambiguous cases" maxSubmissions="1" editable="true" /> </View>小葱技能站7w4.net,专业的AI技能分享平台。
用于建立项目并导入数据的 Python 脚本:
from label_studio_sdk import Client
ls = Client(url="http://localhost:8080", api_key="your-api-key")
project = ls.start_project(
title="Customer Review Sentiment",
label_config=open("config.xml").read(),
description="Label customer reviews as positive, negative, or neutral.",
)
# Import tasks from a CSV file
import csv
tasks = []
with open("reviews.csv") as f:
for row in csv.DictReader(f):
tasks.append({"data": {"text": row["review_text"]}, "meta": {"source_id": row["id"]}})
project.import_tasks(tasks)
# Configure inter-annotator overlap: each task gets 2 annotators
project.set_params(maximum_annotations=2, overlap_cohort_percentage=100)
print(f"Created project with {len(tasks)} tasks, 2 annotators per task")
# After annotation, export results
annotations = project.export_tasks(export_type="JSON")
# Compute agreement
from sklearn.metrics import cohen_kappa_score
labels_a1 = [a["annotations"][0]["result"][0]["value"]["choices"][0] for a in annotations if len(a["annotations"]) >= 2]
labels_a2 = [a["annotations"][1]["result"][0]["value"]["choices"][0] for a in annotations if len(a["annotations"]) >= 2]
print(f"Cohen's kappa: {cohen_kappa_score(labels_a1, labels_a2):.3f}")
import pandas as pd
import numpy as np
from snorkel.labeling import labeling_function, PandasLFApplier, LFAnalysis
from snorkel.labeling.model import LabelModel
SPAM = 1
HAM = 0
ABSTAIN = -1
df = pd.DataFrame({
"text": [
"Congratulations! You've won a free iPhone!", "Meeting at 3pm tomorrow",
"URGENT: claim your prize now!!!", "Can you review the Q3 report?",
"Buy cheap meds online fast", "Lunch plans for Thursday?",
"Click here for a free vacation", "Project deadline is next Friday",
]
})
@labeling_function()
def lf_contains_free(x):
return SPAM if "free" in x.text.lower() else ABSTAIN
@labeling_function()
def lf_contains_urgent(x):
return SPAM if "urgent" in x.text.lower() else ABSTAIN
@labeling_function()
def lf_contains_click(x):
return SPAM if "click" in x.text.lower() else ABSTAIN
@labeling_function()
def lf_excessive_punctuation(x):
return SPAM if x.text.count("!") >= 3 else ABSTAIN
@labeling_function()
def lf_contains_meeting(x):
return HAM if any(w in x.text.lower() for w in ["meeting", "project", "report", "deadline"]) else ABSTAIN
@labeling_function()
def lf_short_and_casual(x):
return HAM if len(x.text.split()) < 8 and "?" in x.text else ABSTAIN
lfs = [lf_contains_free, lf_contains_urgent, lf_contains_click,
lf_excessive_punctuation, lf_contains_meeting, lf_short_and_casual]
applier = PandasLFApplier(lfs=lfs)
L_train = applier.apply(df=df)
print(LFAnalysis(L=L_train, lfs=lfs).lf_summary())
# Train the label model to combine noisy labeling functions
label_model = LabelModel(cardinality=2, verbose=True)
label_model.fit(L_train=L_train, n_epochs=500, log_freq=100, seed=42)
# Get probabilistic labels
probs = label_model.predict_proba(L=L_train)
df["label"] = label_model.predict(L=L_train)
df["confidence"] = np.max(probs, axis=1)
# Filter out low-confidence samples for manual review
confident = df[df["confidence"] > 0.8]
needs_review = df[df["confidence"] <= 0.8]
print(f"Confidently labeled: {len(confident)}, needs manual review: {len(needs_review)}")
这个技能质量不错,内容专业且实用。它完整覆盖了数据标注的各种场景和方法,从基础的人工标注到进阶的主动学习和弱监督都有涉及。代码示例丰富,最佳实践建议很有参考价值。美中不足的是README过于简略,缺少直观的使用引导,且没有配套的示例数据文件供用户快速上手体验。