AI Annotation Workflow Expert
Эксперт по проектированию и управлению процессами разметки данных для машинного обучения.
Основные принципы
Цикл разметки данных
-
Планирование: Определение задачи, создание guidelines
-
Пилот: Тестирование с малой выборкой
-
Масштабирование: Расширение на полный датасет
-
Контроль качества: Постоянный мониторинг
-
Итерация: Улучшение на основе обратной связи
Типы задач разметки
-
Классификация: Категоризация данных
-
Детекция объектов: Bounding boxes
-
Сегментация: Пиксельная разметка
-
NER: Named Entity Recognition
-
Sentiment: Анализ тональности
-
Транскрипция: Аудио в текст
Создание Guidelines
Структура документа
Annotation Guidelines v1.0
Задача
Разметка изображений товаров для e-commerce
Категории
-
Одежда
- Верхняя одежда
- Нижняя одежда
- Аксессуары
-
Электроника
- Смартфоны
- Ноутбуки
- Аксессуары
Правила разметки
- Выбирайте наиболее специфичную категорию
- При неопределённости используйте "Другое"
- Один объект = одна категория
Примеры
[Примеры с изображениями и правильной разметкой]
Edge Cases
- Товар частично виден: размечайте если >50% видно
- Несколько товаров: размечайте каждый отдельно
Метрики качества
Inter-Annotator Agreement (IAA)
from sklearn.metrics import cohen_kappa_score, fleiss_kappa
def calculate_agreement(annotations_a, annotations_b): """Расчёт согласованности между аннотаторами"""
# Cohen's Kappa для двух аннотаторов
kappa = cohen_kappa_score(annotations_a, annotations_b)
# Интерпретация
if kappa < 0.20:
interpretation = "Poor"
elif kappa < 0.40:
interpretation = "Fair"
elif kappa < 0.60:
interpretation = "Moderate"
elif kappa < 0.80:
interpretation = "Good"
else:
interpretation = "Excellent"
return {
'kappa': kappa,
'interpretation': interpretation
}
Quality Metrics
class AnnotationQualityMonitor: def init(self): self.metrics = []
def calculate_metrics(self, annotations, gold_standard):
"""Расчёт метрик качества относительно эталона"""
from sklearn.metrics import precision_score, recall_score, f1_score
precision = precision_score(gold_standard, annotations, average='weighted')
recall = recall_score(gold_standard, annotations, average='weighted')
f1 = f1_score(gold_standard, annotations, average='weighted')
return {
'precision': precision,
'recall': recall,
'f1': f1,
'accuracy': sum(a == g for a, g in zip(annotations, gold_standard)) / len(annotations)
}
def detect_drift(self, window_size=100):
"""Обнаружение дрифта качества"""
if len(self.metrics) < window_size * 2:
return False
recent = self.metrics[-window_size:]
previous = self.metrics[-window_size*2:-window_size]
recent_avg = sum(m['f1'] for m in recent) / len(recent)
previous_avg = sum(m['f1'] for m in previous) / len(previous)
# Дрифт если падение > 5%
return (previous_avg - recent_avg) / previous_avg > 0.05
Workflow автоматизации
Label Studio интеграция
from label_studio_sdk import Client
class AnnotationPipeline: def init(self, api_key, url): self.client = Client(url=url, api_key=api_key)
def create_project(self, name, label_config):
"""Создание проекта разметки"""
project = self.client.create_project(
title=name,
label_config=label_config
)
return project
def import_tasks(self, project_id, data):
"""Импорт задач для разметки"""
project = self.client.get_project(project_id)
project.import_tasks(data)
def export_annotations(self, project_id, format='JSON'):
"""Экспорт готовых аннотаций"""
project = self.client.get_project(project_id)
return project.export_tasks(format=format)
Active Learning Pipeline
class ActiveLearningAnnotation: def init(self, model, unlabeled_pool): self.model = model self.unlabeled_pool = unlabeled_pool self.labeled_data = []
def select_samples_for_annotation(self, n_samples=100, strategy='uncertainty'):
"""Выбор образцов для разметки"""
if strategy == 'uncertainty':
# Выбор образцов с наибольшей неопределённостью
predictions = self.model.predict_proba(self.unlabeled_pool)
uncertainties = -np.sum(predictions * np.log(predictions + 1e-10), axis=1)
indices = np.argsort(uncertainties)[-n_samples:]
elif strategy == 'diversity':
# Выбор разнообразных образцов
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=n_samples)
kmeans.fit(self.unlabeled_pool)
indices = [
np.argmin(np.linalg.norm(self.unlabeled_pool - center, axis=1))
for center in kmeans.cluster_centers_
]
return self.unlabeled_pool[indices]
def update_model(self, new_annotations):
"""Обновление модели после получения аннотаций"""
self.labeled_data.extend(new_annotations)
X = [item['features'] for item in self.labeled_data]
y = [item['label'] for item in self.labeled_data]
self.model.fit(X, y)
Управление аннотаторами
Онбординг
class AnnotatorOnboarding: def init(self, gold_standard_samples): self.gold_standard = gold_standard_samples self.passing_threshold = 0.85
def run_qualification_test(self, annotator_id, annotations):
"""Квалификационный тест для новых аннотаторов"""
correct = sum(
a == g for a, g in zip(annotations, self.gold_standard)
)
accuracy = correct / len(self.gold_standard)
return {
'annotator_id': annotator_id,
'accuracy': accuracy,
'passed': accuracy >= self.passing_threshold,
'errors': [
{'index': i, 'expected': g, 'actual': a}
for i, (a, g) in enumerate(zip(annotations, self.gold_standard))
if a != g
]
}
Мониторинг производительности
class AnnotatorPerformanceTracker: def init(self): self.annotator_stats = {}
def log_annotation(self, annotator_id, task_id, time_spent, quality_score):
if annotator_id not in self.annotator_stats:
self.annotator_stats[annotator_id] = []
self.annotator_stats[annotator_id].append({
'task_id': task_id,
'time_spent': time_spent,
'quality_score': quality_score,
'timestamp': datetime.now()
})
def get_annotator_report(self, annotator_id):
stats = self.annotator_stats.get(annotator_id, [])
if not stats:
return None
return {
'total_tasks': len(stats),
'avg_time': sum(s['time_spent'] for s in stats) / len(stats),
'avg_quality': sum(s['quality_score'] for s in stats) / len(stats),
'tasks_per_hour': len(stats) / (
(stats[-1]['timestamp'] - stats[0]['timestamp']).total_seconds() / 3600
) if len(stats) > 1 else 0
}
Инструменты разметки
Популярные платформы
-
Label Studio: Open-source, гибкая конфигурация
-
Labelbox: Enterprise, ML-assisted labeling
-
Scale AI: Managed workforce
-
Amazon SageMaker Ground Truth: AWS интеграция
-
Prodigy: NLP-focused, active learning
Выбор инструмента
Критерий Label Studio Labelbox Scale AI
Стоимость Free/Open $$ $$$
Workforce Self-managed Optional Included
ML Assist Basic Advanced Advanced
Customization High Medium Low
Лучшие практики
-
Начинайте с пилота — 100-200 образцов для калибровки
-
Итерируйте guidelines — обновляйте по мере обнаружения edge cases
-
Используйте gold standard — 5-10% данных для контроля качества
-
Балансируйте скорость и качество — не давите на аннотаторов
-
Документируйте решения — записывайте все разъяснения
-
Автоматизируйте что можно — pre-labeling, validation rules