中文翻译暂不可用,显示俄语原文。
Как вы делаете synthetic data generation для редких классов в датасете?
Краткий тезис
Synthetic data generation (генерация синтетических данных) для редких классов — это процесс искусственного создания примеров, чтобы сбалансировать датасет и улучшить обобщающую способность модели. Основные подходы: использование LLM (Large Language Model) для генерации по шаблону, back-translation (обратный перевод) для создания вариаций, и маска+вставка (mask-and-fill) для аугментации существующих примеров. Ключевое правило — синтетика не должна превышать 30% датасета, а качество обязательно проверяется кросс-валидацией на реальных данных.
1. Проблема редких классов
Редкий класс (rare class) — категория в датасете, которая встречается значительно реже других. Например, в задаче классификации интентов чат-бота интент «отмена подписки» может составлять 1% от всех запросов, а «приветствие» — 40%. Дисбаланс классов ведёт к тому, что модель обучается игнорировать редкий класс, предсказывая только частые. Synthetic data generation решает эту проблему, искусственно увеличивая количество примеров редкого класса.
Почему нельзя просто скопировать существующие примеры?
Простое дублирование (oversampling) приводит к переобучению на шум и отсутствию разнообразия. Синтетические данные должны быть новыми, но правдоподобными.
2. Метод 1: LLM-генерация по промпту
Самый популярный подход — использовать LLM (например, GPT-4, Llama 3) для генерации примеров по заданной схеме.
Шаги:
- Определить схему (schema) — структуру примера. Для текстовой классификации это может быть: {"текст": "...", "интент": "редкий_класс"}.
- Написать промпт (prompt) с инструкцией, указанием класса, количеством примеров и требованиями к разнообразию.
- Запустить генерацию с разными temperature (0.7–1.2) для вариативности.
Пример промпта
Сгенерируй 10 примеров для класса "отмена подписки" в формате JSON:
{"текст": "запрос пользователя", "интент": "отмена подписки"}
Требования: разные формулировки (вежливые, грубые, короткие, развёрнутые),
упоминание разных сервисов (Netflix, Spotify, облачные хранилища).
Вариации промпта — ключевой приём. Меняйте:
- тон (официальный, разговорный);
- длину (1 слово, 5 предложений);
- контекст (техподдержка, чат-бот, email).
Плюсы простота, масштабируемость.
Минусы риск галлюцинаций (LLM может сгенерировать нереалистичные примеры), стоимость API.
3. Метод 2: Back-translation (обратный перевод)
Back-translation — техника аугментации текста: исходный пример переводится на промежуточный язык (например, французский), а затем обратно на исходный. Получается новая формулировка с тем же смыслом.
Процесс
Исходный текст (русский) → переводчик (русский→французский) → переводчик (французский→русский) → новый текст
Инструменты библиотека transformers (модели MarianMT, M2M100), Google Translate API, Yandex Translate.
Пример кода (Hugging Face):
from transformers import MarianMTModel, MarianTokenizer
model_name = 'Helsinki-NLP/opus-mt-ru-fr'
tokenizer = MarianTokenizer.from_pretrained(model_name)
model = MarianMTModel.from_pretrained(model_name)
text = "Хочу отменить подписку"
translated = model.generate(**tokenizer(text, return_tensors="pt"))
back_text = tokenizer.decode(translated[0], skip_special_tokens=True)
# back_text: "Je veux annuler l'abonnement" (фр.) — затем обратно на русский
Плюсы не требует размеченных данных, сохраняет семантику.
Минусы может потерять специфические термины (например, названия продуктов).
4. Метод 3: Маска + вставка (Mask-and-fill)
Основан на замене ключевых слов в реальном примере на другие, релевантные классу.
Шаги:
- Взять реальный пример редкого класса.
- Выделить слоты (slots) — слова, которые можно заменить (сущности, глаголы, объекты).
- Замаскировать их (например, с помощью
[Вики/attention masking|MASK). - Использовать LLM или rule-based генератор для заполнения масок новыми словами из словаря класса.
Пример:
- Исходный: «Отмените, пожалуйста, подписку на Netflix».
- Маска: «Отмените, пожалуйста, подписку на [Вики/Service|SERVICE».
- Заполнение: [Вики/Service|SERVICE → Spotify, Apple Music, Яндекс.Музыка.
- Новые примеры: «Отмените подписку на Spotify», «Пожалуйста, отмените Яндекс.Музыку».
Инструменты библиотека spaCy для NER (Named Entity Recognition), регулярные выражения, словари синонимов.
Плюсы контролируемое разнообразие, низкая вероятность галлюцинаций.
Минусы требует ручного выделения слотов, не подходит для сложных синтаксических вариаций.
5. Метод 4: Oversampling с шумом (Noise-based augmentation)
Добавление небольшого шума к существующим примерам: замена синонимов, вставка случайных слов, удаление слов, перестановка порядка. Используется, когда LLM недоступен.
Техники
- Synonym replacement (замена синонимами): «отменить» → «аннулировать», «отказаться».
- Random insertion (вставка случайного слова): «отменить подписку» → «отменить срочно подписку».
- Random swap (перестановка двух слов): «подписку отменить».
- Random deletion (удаление слова): «отменить подписку» → «отменить».
Плюсы дешево, быстро.
Минусы может исказить смысл, не подходит для строгих форматов (например, SQL-запросов).
6. Проверка качества синтетических данных
Синтетика может быть вредной, если она не похожа на реальные данные. Основные методы проверки:
6.1 Кросс-валидация на реальных данных
Обучите модель на смеси реальных + синтетических данных, затем оцените на отложенной реальной выборке (hold-out set). Если метрики (F1, precision, recall) на реальных данных падают по сравнению с моделью, обученной только на реальных (с oversampling), — синтетика низкого качества.
6.2 Human evaluation
Попросите аннотаторов оценить 100–200 синтетических примеров по шкале:
- 1 — нереалистично, не соответствует классу;
- 2 — сомнительно;
- 3 — полностью реалистично.
Отбрасывайте примеры с оценкой 1.
6.3 Consistency check (проверка согласованности)
Для LLM-генерации: прогнать синтетические примеры через ту же LLM с промптом «Определи класс» — если модель часто ошибается, примеры плохие.
Код для автоматической проверки
def check_quality(synthetic_texts, target_class, classifier):
correct = 0
for text in synthetic_texts:
pred = classifier.predict(text)
if pred == target_class:
correct += 1
return correct / len(synthetic_texts)
7. Баланс: сколько синтетики добавлять?
Эмпирическое правило: синтетические данные не должны превышать 30% от общего объёма датасета. Причины:
- Синтетика всегда проще реальных данных (меньше шума, более шаблонная).
- Перекос в сторону синтетики снижает обобщение на реальные примеры.
- Модель может выучить артефакты генерации (например, одинаковые обороты).
Рекомендация начинайте с 10–20% синтетики, постепенно увеличивайте, контролируя метрики на валидации.
8. Инструменты и библиотеки
| Инструмент | Назначение |
|---|---|
| LangChain | Упрощает LLM-генерацию с промптами и цепочками |
| OpenAI API / Anthropic API | Доступ к мощным LLM (GPT-4, Claude) |
| Hugging Face Datasets | Хранение и аугментация датасетов |
| nlpaug | Библиотека для текстовой аугментации (back-translation, synonym replacement) |
| TextAttack | Фреймворк для аугментации и adversarial attacks |
| spaCy / stanza | NER для выделения слотов |
Пример с LangChain
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
prompt = PromptTemplate(
input_variables=["class_name", "count"],
template="Сгенерируй {count} примеров для класса '{class_name}' в формате JSON."
)
llm = OpenAI(model="gpt-4", temperature=0.9)
chain = prompt | llm
result = chain.invoke({"class_name": "отмена подписки", "count": 10})
Пет-проект для закрепления
Задача У вас датасет запросов в техподдержку с 10 интентами. Интент «жалоба на качество» составляет 2% (50 примеров). Остальные классы — 2450 примеров. Нужно сбалансировать датасет до хотя бы 10% редкого класса.
Инструменты Python, OpenAI API, Hugging Face Datasets, scikit-learn.
Шаги:
- Выделите 50 реальных примеров редкого класса.
- Сгенерируйте 200 синтетических примеров через LLM (промпт с вариациями).
- Примените back-translation (русский → английский → русский) к 50 реальным примерам — получите ещё 50 вариаций.
- Используйте mask-and-fill: выделите слоты (названия продуктов, глаголы) и сгенерируйте 100 примеров.
- Объедините: 50 реальных + 200 LLM + 50 back-translation + 100 mask-and-fill = 400 примеров (редкий класс станет ~14%).
- Обучите классификатор (например, LogisticRegression на эмбеддингах) на смеси и на исходном датасете.
- Сравните F1-score на тестовой выборке (реальные данные).
Ожидаемый результат F1 редкого класса вырастет с 0.3 до 0.7–0.8, при этом F1 других классов не упадёт более чем на 2%.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 520 | Как бороться с дисбалансом классов в датасете? |
| 521 | Какие методы аугментации данных вы знаете? |
| 522 | Как вы оцениваете качество синтетических данных? |
| 524 | Как вы используете LLM для data augmentation? |
| 525 | Что такое few-shot learning и как он связан с синтетикой? |
| 530 | Как вы готовите данные для fine-tuning LLM? |
Навигация
- Предыдущий: 522
- Следующий: 524
- Индекс: 00. Индекс разборов