Что такое weak supervision для разметки данных для fine-tuning и как его применить?

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

Weak supervision (слабое обучение) — это подход к автоматической разметке данных с помощью набора эвристик, правил и внешних моделей, называемых labeling functions (LFs). Вместо ручной разметки тысяч примеров вы пишете 5–20 LFs, которые могут конфликтовать и быть неточными. Фреймворк Snorkel обучает генеративную модель, которая взвешивает LFs по их точности и выдаёт label|вероятностные метки для каждого примера. Это экономит до 90% времени на разметку и позволяет быстро создавать датасеты для fine-tuning, требуя лишь ~100 ручных меток для валидации.


1. Проблема ручной разметки данных

Fine-tuning (дообучение) больших языковых моделей (LLM) или других ML-моделей требует размеченных данных высокого качества. evaluation|Ручная разметка — узкое место:

  • Высокая стоимость: час работы эксперта может стоить $50–100.
  • Медлительность: разметка 10 000 примеров может занять недели.
  • Субъективность: разные аннотаторы могут давать разные метки.
  • Масштабируемость: при изменении задачи или домена разметку нужно делать заново.

Weak supervision решает эти проблемы, заменяя ручную разметку на программируемые эвристики.


2. Основная идея weak supervision

Weak supervision (слабое обучение) — это парадигма, в которой вы определяете набор labeling functions (LFs) — функций, которые автоматически присваивают метку примеру на основе правил, регулярных выражений, ключевых слов, результатов других моделей или даже краудсорсинга. Каждая LF может быть неточной и покрывать только часть данных, но их комбинация через вероятностную модель даёт надёжные метки.

Ключевые компоненты:

  • Labeling functions (LFs) — эвристические «аннотаторы».
  • Generative model (model|генеративная модель) — учится взвешивать LFs по их точности и корреляции.
  • Probabilistic labels (label|вероятностные метки) — для каждого примера получаем распределение вероятностей по классам.

3. Labeling functions (LFs)

Labeling function — это функция, которая принимает на вход неразмеченный пример (например, текст) и возвращает метку или ABSTAIN (воздержание). Примеры LFs:

import re

def lf_keyword_positive(text):
    if re.search(r'\b(отлично|превосходно|замечательно)\b', text, re.IGNORECASE):
        return 1  # positive
    return -1  # abstain

def lf_keyword_negative(text):
    if re.search(r'\b(ужасно|плохо|отвратительно)\b', text, re.IGNORECASE):
        return 0  # negative
    return -1

def lf_emoji_positive(text):
    if '😊' in text or '👍' in text:
        return 1
    return -1

LFs могут:

  • Использовать regex и ключевые слова.
  • Опираться на внешние модели (например, предобученный классификатор тональности).
  • Учитывать длину текста, наличие ссылок и т.д.
  • Быть результатом краудсорсинга (метки от нескольких людей).

Каждая LF может быть неточной, но в совокупности они дают сигнал.


4. Проблема конфликтов и шума

Разные LFs могут давать противоречивые метки на одном примере. Например:

  • LF_keyword_positive говорит «positive» (есть слово «отлично»).
  • LF_emoji_negative говорит «negative» (есть грустный смайлик).

Как определить истинную метку? Простое голосование неэффективно, потому что LFs имеют разную точность и могут быть коррелированы.


5. Snorkel: генеративная модель для взвешивания LFs

Snorkel — это фреймворк для weak supervision, разработанный в Stanford. Он решает проблему конфликтов с помощью генеративной модели (generative model), которая обучается на выходе LFs без доступа к истинным меткам.

Как работает генеративная модель:

  1. Для каждого примера собираются метки от всех LFs (вектор λ).
  2. Модель оценивает параметры точности каждой LF и корреляции между ними.
  3. Используя эти параметры, модель вычисляет апостериорное распределение истинной метки для каждого примера.

Математически это факторный граф (factor graph), где узлы — истинные метки и метки LFs, а факторы — точность и корреляция. Обучение происходит через стохастический градиентный подъём (SGD) для максимизации правдоподобия наблюдаемых меток LFs.

Результат: для каждого примера получаем probabilistic label — вектор вероятностей (например, [0.8, 0.2] для двух классов). Эти вероятности можно использовать как мягкие метки при fine-tuning (например, через cross-entropy loss с весами).


6. Процесс применения weak supervision для fine-tuning

Шаги:

  1. Определить задачу и собрать неразмеченные данные (например, 50 000 отзывов).
  2. Разработать 5–20 labeling functions на основе эвристик, правил, внешних моделей.
  3. Запустить LFs на всех неразмеченных данных — получить матрицу меток (примеры × LFs).
  4. Обучить генеративную модель в Snorkel (или аналогичном фреймворке) — получить вероятностные метки.
  5. Проверить качество на небольшом валидационном наборе (~100 ручных меток). Если метрики низкие — добавить/уточнить LFs.
  6. Использовать вероятностные метки для fine-tuning модели (например, LLM или классификатора).
  7. Оценить модель на тестовом наборе с ручными метками.

7. Преимущества и ограничения

ПреимуществаОграничения
Экономия времени: до 90% меньше ручной разметкиТребует разработки LFs — нужна экспертиза в домене
Быстрая итерация: можно менять LFs и перезапускатьLFs могут быть смещены (bias) — нужна валидация
Масштабируемость: легко применить к миллионам примеровГенеративная модель может быть сложной в настройке
Объединение разных источников сигналаНе подходит для задач, где эвристики невозможны
Интерпретируемость: можно анализировать вклад каждой LFТребуется хотя бы небольшой валидационный набор

8. Пример кода на Python с Snorkel

import snorkel
from snorkel.labeling import labeling_function, PandasLFApplier, LFAnalysis
from snorkel.labeling.model import LabelModel

# Определяем LFs
@labeling_function()
def lf_positive_keywords(x):
    return 1 if any(word in x.text for word in ['отлично', 'супер']) else -1

@labeling_function()
def lf_negative_keywords(x):
    return 0 if any(word in x.text for word in ['ужасно', 'плохо']) else -1

@labeling_function()
def lf_contains_exclamation(x):
    return 1 if '!' in x.text else -1

# Применяем LFs к датасету
applier = PandasLFApplier(lfs=[lf_positive_keywords, lf_negative_keywords, lf_contains_exclamation])
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)
df_train['weak_label'] = probs[:, 1]  # вероятность положительного класса

9. Связь с fine-tuning

Fine-tuning (дообучение) — это процесс обновления весов предобученной модели на размеченных данных. Weak supervision предоставляет эти данные автоматически. При fine-tuning можно использовать:

  • Мягкие метки (soft labels) — вероятности из генеративной модели. Функция потерь — cross-entropy с весами.
  • Жёсткие метки (hard labels) — argmax от вероятностей, если модель уверена.

Weak supervision особенно полезна для fine-tuning LLM под специфические домены (медицина, юриспруденция), где ручная разметка дорога.


10. Альтернативы и расширения

  • Data programming — общий термин для подхода, популяризированный Snorkel.
  • Active learning — итеративный выбор примеров для ручной разметки, может комбинироваться с weak supervision.
  • Self-training — модель размечает сама себя, но требует начальных меток.
  • Programmatic labeling — использование SQL-запросов, правил из бизнес-логики.

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

Задача Разметить датасет отзывов на фильмы (IMDB) для fine-tuning классификатора тональности (positive/negative) с помощью weak supervision.

Инструменты Python, Snorkel, pandas, transformers (для fine-tuning BERT).

Шаги:

  1. Загрузить неразмеченные отзывы (например, 20 000 текстов).
  2. Написать 5–10 LFs: по ключевым словам, длине, наличию восклицательных знаков, оценке из метаданных (если есть), результату предобученного sentiment-анализатора.
  3. Обучить LabelModel в Snorkel, получить вероятностные метки.
  4. Валидировать на 100 вручную размеченных отзывах (посчитать accuracy, precision, recall).
  5. Взять предобученный BERT (например, bert-base-uncased) и дообучить его на полученных вероятностных метках (использовать Trainer с кастомной loss-функцией для soft labels).
  6. Оценить модель на тестовом наборе (ручные метки). Сравнить с моделью, обученной на 1000 ручных метках.

Ожидаемый результат Модель, дообученная с weak supervision, покажет качество, близкое к модели на полностью ручной разметке, но с затратами времени на разметку в 10 раз меньше.


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

ВопросТема
512Fine-tuning LLM: методы и best practices
514Data augmentation для текстов
515Active learning: стратегии отбора примеров
516Programmatic labeling: автоматическая разметка
517Snorkel: фреймворк для weak supervision
518Labeling functions: проектирование и отладка

Навигация