中文翻译暂不可用,显示俄语原文。

Как вы детектируете и удаляете низкокачественные примеры из синтетического датасета?

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

Детекция низкокачественных примеров в синтетическом датасете — это многоэтапный процесс, сочетающий эвристические правила, анализ эмбеддингов (outlier detection), LLM-оценку и метрики неопределённости. Комбинируя эти методы, можно отсеять шумные, нерелевантные, повторяющиеся или галлюцинированные примеры, повышая качество датасета для fine-tuning или RAG. Ключевой принцип — не полагаться на один метод, а строить пайплайн фильтрации с настраиваемыми порогами.


1. Термин: Синтетический датасет и проблема низкого качества

Синтетический датасет — это набор данных, сгенерированный искусственно, обычно с помощью LLM (например, GPT-4, Llama). Такие датасеты широко используются для fine-tuning, RAG-систем и обучения reward-моделей, когда реальных данных недостаточно или их разметка слишком дорога.

Однако синтетические данные часто содержат низкокачественные примеры:

  • Галлюцинации — ответы, не соответствующие фактам или контексту.
  • Нерелевантность — вопрос и ответ не связаны по смыслу.
  • Повторения — дубликаты или near-duplicates (почти одинаковые пары).
  • Шум — грамматические ошибки, бессмысленные токены, слишком короткие или длинные ответы.
  • Несбалансированность — перекос в сторону определённых тем или форматов.

Без фильтрации такой датасет может ухудшить качество модели, внести bias или снизить обобщающую способность.


2. Эвристические правила: длина, дубликаты, near-duplicate detection

Первый уровень фильтрации — простые, быстрые правила, не требующие вызова LLM.

ПравилоОписаниеПример порога
Минимальная длинаОтбрасываем примеры, где вопрос или ответ короче N токенов/символов<5 слов или <10 токенов
Максимальная длинаСлишком длинные ответы часто содержат повторения или неструктурированный текст>200 токенов
Наличие обязательных полейПроверяем, что вопрос и ответ не пустые, нет NaN
Регулярные выраженияУдаляем примеры с HTML-тегами, спецсимволами, ссылкамиr'<.*?>'
Near-duplicate detectionНаходим почти одинаковые пары (например, с cosine similarity > 0.95)cos_sim > 0.95

Near-duplicate detection можно реализовать через MinHash + LSH (для больших датасетов) или через эмбеддинги и косинусную близость. Пример на Python:

from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

model = SentenceTransformer('all-MiniLM-L6-v2')
questions = [...]  # список вопросов
embeddings = model.encode(questions)
sim_matrix = cosine_similarity(embeddings)

# Удаляем пары с similarity > 0.95 (кроме диагонали)
duplicates = np.triu(sim_matrix > 0.95, k=1)

3. Outlier detection на основе эмбеддингов и кластеризации

После эвристик переходим к анализу распределения примеров в пространстве эмбеддингов. Идея: качественные примеры образуют плотные кластеры, а низкокачественные — выбросы (outliers).

Шаги:

  1. Получить эмбеддинги для каждого примера (например, объединить вопрос и ответ в одну строку).
  2. Применить кластеризацию (KMeans, DBSCAN, HDBSCAN).
  3. Для каждого примера вычислить расстояние до центроида своего кластера (или до k ближайших соседей).
  4. Отбросить примеры, расстояние которых превышает порог (например, 95-й перцентиль).

Пример кода

from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import numpy as np

embeddings = ...  # shape (N, dim)
scaler = StandardScaler()
emb_scaled = scaler.fit_transform(embeddings)

kmeans = KMeans(n_clusters=10, random_state=42)
labels = kmeans.fit_predict(emb_scaled)
distances = np.linalg.norm(emb_scaled - kmeans.cluster_centers_[labels], axis=1)

threshold = np.percentile(distances, 95)
outliers = distances > threshold

Альтернативы Isolation Forest, Local Outlier Factor (LOF). Эти методы не требуют предварительной кластеризации и хорошо работают с многомерными данными.


4. LLM-оценка качества примеров

Самый мощный, но дорогой метод — использовать LLM (например, GPT-4) для оценки каждого примера по шкале (1–10). Промпт должен быть чётким и включать критерии.

Пример промпта

Оцени качество следующей пары (вопрос, ответ) по шкале от 1 до 10, где 1 — полностью нерелевантно или содержит галлюцинации, 10 — идеально. Учитывай:
- Релевантность ответа вопросу
- Фактическую точность
- Полноту и ясность
- Отсутствие повторений

Вопрос: {question}
Ответ: {answer}

Оценка (только число):

Порог обычно отбрасывают примеры с оценкой < 7. Для снижения стоимости можно:

  • Использовать меньшую модель (GPT-3.5, Llama-3-8B) с калибровкой.
  • Оценивать только подозрительные примеры (после эвристик и outlier detection).
  • Применять batch scoring — один промпт для нескольких примеров.

Проблемы субъективность LLM, смещение в сторону определённых стилей, стоимость. Рекомендуется валидировать оценку на небольшой выборке, размеченной человеком.


5. Uncertainty и энтропия как индикатор шума

Если пример сгенерирован LLM, можно использовать uncertainty самой модели-генератора. Высокая неопределённость (энтропия) в ответе часто коррелирует с низким качеством.

Метрики:

  • Энтропия лог-вероятностей токенов — средняя энтропия по всем токенам ответа.
  • Variance при множественных выборках — сгенерировать несколько ответов на один вопрос (с temperature > 0) и измерить разброс (например, pairwise BLEU или cosine similarity).

Пример вычисления энтропии (при доступе к logits):

import torch
import torch.nn.functional as F

logits = model.generate(...)  # shape (seq_len, vocab_size)
probs = F.softmax(logits, dim=-1)
entropy = -torch.sum(probs * torch.log(probs + 1e-9), dim=-1).mean().item()

Порог отбрасывать примеры, где entropy > 0.8 * max_entropy (или выше 95-го перцентиля). Метод хорошо работает для детекции галлюцинаций, но требует доступа к logits (недоступно для API-моделей).


6. Комбинированный пайплайн фильтрации

На практике используют последовательность шагов, от самых дешёвых к дорогим:

1. Эвристические правила (длина, пустые поля)
2. Near-duplicate detection
3. Outlier detection (эмбеддинги)
4. LLM-оценка (только для оставшихся подозрительных)
5. Uncertainty (если доступны logits)

Пример реализации пайплайна

def filter_pipeline(df):
    # Шаг 1: эвристики
    df = df[(df['question'].str.len() >= 10) & (df['answer'].str.len() <= 500)]
    # Шаг 2: near-duplicates (опустим для краткости)
    # Шаг 3: outlier detection
    embeddings = get_embeddings(df['question'] + ' ' + df['answer'])
    outliers = detect_outliers(embeddings, threshold=0.95)
    df = df[~outliers]
    # Шаг 4: LLM оценка
    scores = llm_score(df[['question', 'answer']])
    df = df[scores >= 7]
    return df

Можно также взвешивать разные сигналы и отбрасывать примеры, набравшие суммарный «штраф» выше порога.


7. Инструменты и библиотеки для автоматизации

ИнструментНазначение
CleanlabОбнаружение ошибок в датасетах (включая синтетические) на основе confident learning
LangChainВстроенные фильтры (например, BaseDocumentTransformer) для RAG
Sentence-TransformersБыстрое получение эмбеддингов
scikit-learnКластеризация, Isolation Forest, LOF
OpenAI / Anthropic APILLM-оценка
Datasets (Hugging Face)Удобные структуры для фильтрации

Пример использования Cleanlab для синтетического датасета:

from cleanlab.classification import CleanLearning
from sklearn.linear_model import LogisticRegression

# Предполагаем, что у нас есть эмбеддинги и "шумные" метки (0 - плохой, 1 - хороший)
cl = CleanLearning(LogisticRegression())
cl.fit(embeddings, noisy_labels)
label_issues = cl.get_label_issues()
bad_indices = label_issues['is_label_issue']

8. Метрики оценки эффективности фильтрации

Чтобы понять, насколько хорошо работает фильтрация, нужен валидационный датасет с размеченными метками качества (хороший/плохой). Метрики:

МетрикаФормулаИнтерпретация
PrecisionTP / (TP + FP)Доля действительно плохих среди отброшенных
RecallTP / (TP + FN)Доля плохих примеров, которые мы отбросили
F1-score2 * P * R / (P + R)Гармоническое среднее
Impact on downstreamΔ accuracy / Δ lossНасколько улучшилась модель после фильтрации

Важно также оценить потерю хороших примеров (false positives). Если фильтрация слишком агрессивна, мы теряем полезные данные, что может ухудшить обобщение.


9. Trade-offs: precision vs recall при отбрасывании

При настройке порогов возникает дилемма:

  • Высокий порог (например, LLM score < 9) → высокая precision (мало ложных срабатываний), но низкий recall (много плохих примеров остаётся).
  • Низкий порог (score < 5) → высокий recall, но много хороших примеров отбрасывается.

Рекомендации

  • Начинать с консервативных порогов (отбрасывать только явный мусор).
  • Использовать кривую precision-recall для выбора оптимальной точки.
  • Проводить A/B тестирование на downstream задаче (fine-tuning + eval).
  • Для RAG-систем можно оценивать faithfulness и answer relevance до и после фильтрации.

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

Задача Разработать пайплайн фильтрации синтетического датасета вопрос-ответ (QA) для RAG-системы.

Инструменты Python, sentence-transformers, scikit-learn, OpenAI API (или локальная модель), Cleanlab.

Шаги:

  1. Сгенерировать 500 синтетических QA-пар с помощью GPT-4 (например, на тему «История Рима»).
  2. Применить эвристики: удалить пары с длиной вопроса < 10 символов или ответа > 300 токенов.
  3. Вычислить эмбеддинги (all-MiniLM-L6-v2) и выполнить outlier detection (Isolation Forest, contamination=0.05).
  4. Для оставшихся примеров запросить LLM-оценку (GPT-4 mini) и отбросить с оценкой < 7.
  5. Оценить качество оставшегося датасета: визуализировать распределение эмбеддингов (t-SNE), посчитать долю отброшенных.
  6. Сравнить метрики RAG (faithfulness, answer relevance) на исходном и отфильтрованном датасете.

Ожидаемый результат Чистый датасет (примерно 70-80% от исходного) с улучшенными метриками RAG. Код пайплайна с настраиваемыми порогами и логами.


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

ВопросТема
680Генерация синтетических данных для RAG
681Оценка качества RAG-системы
683Активное обучение для разметки
684Человеческая разметка vs синтетика
686Балансировка датасета
688Data augmentation для RAG

12. Навигация


Навигация