Как работает weak supervision для synthetic данных (создание правил разметки)?

Краткий тезис

Weak supervision (слабая разметка) — это подход, при котором вместо ручной разметки тысяч примеров инженер пишет набор эвристических правил — labeling functions (LFs). Инструменты вроде Snorkel автоматически комбинируют эти правила, оценивают их точность и корреляции, и выдают label|вероятностные метки для каждого примера. Для синтетических данных (например, сгенерированных LLM) weak supervision позволяет быстро создавать большие размеченные датасеты, проверяя корректность ответов через LFs, без привлечения человека.


1. Термин: Weak Supervision (слабая разметка)

Weak supervision — это парадигма data-centric AI, где обучающая разметка создаётся не вручную, а с помощью программных правил, внешних моделей или эвристик. В отличие от strong supervision (сильной разметки, где каждый пример размечен экспертом), weak supervision даёт шумные, но дешёвые метки.

Основная идея: пусть каждая отдельная эвристика (labeling function) может быть неточной, но если их много и они независимы, то комбинация даёт достаточно качественные метки для обучения модели.

Термин «Labeling function» (LF) — функция, которая для каждого примера возвращает метку (например, 1, 0 или -1, если воздержалась).


2. Labeling Functions (LFs) — эвристики разметки

Labeling functions — это строительные блоки weak supervision. Они могут быть основаны на:

  • Регулярных выражениях (regex): например, если в тексте есть слово «отрицательный», то метка «negative».
  • Ключевых словах: проверка наличия/отсутствия определённых терминов.
  • Внешних моделях: использование предобученного классификатора или LLM как одной из LFs.
  • Эвристиках из предметной области: например, для синтетических данных — проверка, что сгенерированный ответ не длиннее исходного контекста.

Пример LFs на Python (с использованием библиотеки Snorkel):

import re
from snorkel.labeling import labeling_function

# LF на основе ключевых слов
@labeling_function()
def lf_contains_positive(x):
    return 1 if "хороший" in x.text.lower() else -1

# LF на основе regex
@labeling_function()
def lf_negative_pattern(x):
    return 0 if re.search(r"плох|ужасн", x.text) else -[[1. Как бы вы спроектировали RAG-систему для 10 000 документов с разной структурой|1]]

# LF с внешней моделью (например, предобученный sentiment)
@labeling_function(resources={"model": sentiment_model})
def lf_external_model(x, model):
    pred = model.predict(x.text)
    return pred if pred in (0, 1) else -1

Каждая LF возвращает метку (0, 1) или -1 (воздержалась). Воздержание важно — LF не обязана всегда давать ответ.


3. Проблема конфликтов и корреляции LFs

Если несколько LFs дают разные метки для одного примера, возникает конфликт. Если две LFs всегда голосуют одинаково, они коррелированы — их совместное использование не даёт новой информации.

Наивное голосование (majority vote) не учитывает:

  • Разную точность LFs (одна может быть точнее другой).
  • Корреляции между LFs (они могут ошибаться одинаково).

Поэтому нужна генеративная модель, которая учится на самих LFs, без доступа к истинным меткам.


4. Snorkel: генеративная модель для объединения LFs

Snorkel — самая известная библиотека для weak supervision. Её ключевой компонент — генеративная модель (обычно факторный граф), которая:

  1. Оценивает веса каждой LF (насколько она точна).
  2. Учитывает попарные корреляции между LFs.
  3. Для каждого примера вычисляет вероятностную метку (probabilistic label) — распределение по классам.

Процесс:

  • На вход подаются все LFs и неразмеченные данные.
  • Генеративная модель обучается максимизировать правдоподобие наблюдаемых голосов LFs.
  • На выходе — для каждого примера вектор вероятностей (например, [0.8, 0.2] для двух классов).

Формально: пусть есть n LFs, каждая даёт метку λᵢ ∈ {0, 1, -1}. Генеративная модель P(λ | Y) параметризуется весами wᵢ (точность) и параметрами корреляции. Обучение без учителя — через EM или градиентный спуск.

from snorkel.labeling import PandasLFApplier
from snorkel.labeling.model import LabelModel

# Применяем LFs к датасету
applier = PandasLFApplier(lfs)
L_train = applier.apply(df_train)

# Обучаем генеративную модель
label_model = LabelModel(cardinality=2, verbose=True)
label_model.fit(L_train, n_epochs=500, log_freq=100)

# Получаем вероятностные метки
probs = label_model.predict_proba(L_train)

5. Выход: вероятностные метки (probabilistic labels)

Вероятностные метки — это не жёсткие классы, а распределение. Например, для бинарной классификации: [0.9, 0.1] означает, что модель с 90% уверена в классе 0.

Эти метки можно использовать:

  • Для обучения downstream модели (например, нейросети) с шумной разметкой — часто используют взвешенную функцию потерь.
  • Для фильтрации: оставить только примеры с высокой уверенностью (например, >0.8).
  • Для оценки качества LFs: если метки слишком неопределённые (0.5/0.5), значит LFs плохо согласованы.

6. Применение для синтетических данных

Синтетические данные (например, сгенерированные LLM) часто не имеют «золотых» меток. Weak supervision позволяет разметить их автоматически.

Пример: мы сгенерировали 100 000 QA-пар для RAG (вопрос-ответ на основе документов). Нужно оценить, корректный ли ответ дала LLM. Можно написать LFs:

  • LF_factual_consistency: проверяет, что все факты в ответе присутствуют в исходном документе (через NER и overlap).
  • LF_length: ответ не должен быть короче 5 слов и длиннее 500.
  • LF_keywords: ответ должен содержать ключевые слова из вопроса.
  • LF_llm_judge: использовать другую LLM (например, GPT-4) для оценки корректности (одна LF).

Snorkel объединит эти LFs и выдаст вероятностную метку «корректный/некорректный» для каждой QA-пары.


7. Пример: разметка синтетических QA-пар для RAG

Допустим, у нас есть датасет синтетических вопросов и ответов, сгенерированных LLM на основе корпуса документов. Мы хотим отфильтровать только качественные пары для дообучения реранкера.

Шаги:

  1. Определяем 5–10 LFs:

    • lf_answer_in_context: ответ полностью содержится в контексте (проверка substring).
    • lf_no_hallucination: в ответе нет имен, не упомянутых в контексте.
    • lf_question_type: если вопрос «да/нет», ответ должен быть коротким.
    • lf_sentiment_match: тональность ответа не противоречит контексту.
    • lf_llm_judge: вызов LLM с промптом «Оцени корректность ответа по шкале 0-1».
  2. Применяем LFs к датасету через Snorkel.

  3. Обучаем LabelModel, получаем вероятностные метки.

  4. Отбираем примеры с вероятностью >0.9 для обучения реранкера.

Результат: вместо ручной разметки 1000 примеров мы получаем 30 000 размеченных с приемлемым качеством.


8. Инструменты для weak supervision

ИнструментОписание
SnorkelФлагманская библиотека от Stanford. Поддерживает LFs, генеративные модели, обучение downstream моделей.
WRENCHБенчмарк и набор инструментов для weak supervision. Включает несколько методов объединения LFs.
FlyingsquidБыстрая реализация генеративных моделей на основе матричных операций.
SkweakСпециализируется на NLP-задачах (NER, классификация текста).
LLM-as-LFИспользование LLM как одной из LFs через промптинг.

9. Преимущества weak supervision для синтетических данных

  • Масштабируемость: можно разметить миллионы примеров за часы.
  • Скорость итераций: изменили LFs — переразметили датасет за минуты.
  • Снижение затрат: не нужно нанимать аннотаторов.
  • Контролируемый шум: можно оценить качество меток через вероятности.
  • Гибкость: LFs легко адаптировать под новые типы синтетических данных.

10. Ограничения и риски

  • Шум в метках: если все LFs плохие, итоговые метки будут бесполезны.
  • Необходимость качественных LFs: написание хороших LFs требует экспертизы в предметной области.
  • Смещение (bias): LFs могут систематически ошибаться на определённых подгруппах данных.
  • Корреляции: если LFs сильно скоррелированы, генеративная модель может переоценить их точность.
  • Применимость: weak supervision лучше всего работает для задач, где можно легко сформулировать эвристики (классификация, NER). Для сложных генеративных задач (например, оценка креативности) LFs могут быть слабыми.

11. Связь с Agentic RAG

В контексте Agentic RAG weak supervision может использоваться для:

  • Разметки траекторий действий агента (какие инструменты вызывать, в каком порядке).
  • Оценки качества сгенерированных ответов в процессе саморефлексии агента.
  • Создания синтетических датасетов для обучения компонентов RAG (реранкеры, классификаторы запросов, детекторы галлюцинаций).

Например, агент генерирует несколько шагов: поиск → чтение → ответ. Можно написать LFs, которые проверяют, что каждый шаг корректен (например, что поисковый запрос релевантен исходному вопросу). Snorkel объединит эти LFs и даст метку «успешная траектория» или «нет».


Пет-проект для закрепления

Задача: Разметить синтетический датасет вопросов и ответов (сгенерированных LLM) на корректность с помощью weak supervision.

Инструменты: Python, Snorkel, Hugging Face Datasets (для загрузки/генерации данных), предобученная LLM (например, через API).

Шаги:

  1. Сгенерировать 10 000 QA-пар на основе случайных статей из Wikipedia (можно использовать datasets.load_dataset("wikipedia") и LLM для генерации).
  2. Написать 5–7 labeling functions:
    • lf_answer_in_context: проверка, что ответ — подстрока контекста.
    • lf_keyword_overlap: доля ключевых слов из вопроса в ответе.
    • lf_length_ratio: отношение длины ответа к длине контекста (не должно быть слишком большим).
    • lf_llm_judge: вызов LLM с промптом «Is the answer correct? 0 or 1».
    • lf_no_new_entities: в ответе не должно быть имен, отсутствующих в контексте (через NER).
  3. Применить LFs к датасету через PandasLFApplier.
  4. Обучить LabelModel и получить вероятностные метки.
  5. Отобрать 2000 примеров с наивысшей вероятностью (например, >0.95) и 2000 с низкой (<0.3). Вручную проверить 100 из каждой группы — оценить качество weak supervision.
  6. Обучить простой классификатор (например, DistilBERT) на вероятностных метках и сравнить с моделью, обученной на 500 вручную размеченных примерах.

Ожидаемый результат: Вы увидите, что weak supervision позволяет достичь сопоставимого качества при значительно меньших затратах на ручную разметку. Вы также поймёте, как качество LFs влияет на итоговые метки.


Связь с другими вопросами

ВопросТема
693Как генерировать синтетические данные для RAG?
695Как оценивать качество синтетических данных?
680Что такое data-centric AI и как его применять в NLP?
710Как использовать Snorkel для разметки датасетов?
645Какие методы борьбы с шумом в разметке существуют?
720Как обучать модели с шумными метками?

Навигация