中文翻译暂不可用,显示俄语原文。
Как вы детектируете и удаляете низкокачественные примеры из синтетического датасета?
Краткий тезис
Детекция низкокачественных примеров в синтетическом датасете — это многоэтапный процесс, сочетающий эвристические правила, анализ эмбеддингов (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).
Шаги:
- Получить эмбеддинги для каждого примера (например, объединить вопрос и ответ в одну строку).
- Применить кластеризацию (KMeans, DBSCAN, HDBSCAN).
- Для каждого примера вычислить расстояние до центроида своего кластера (или до k ближайших соседей).
- Отбросить примеры, расстояние которых превышает порог (например, 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 API | LLM-оценка |
| 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. Метрики оценки эффективности фильтрации
Чтобы понять, насколько хорошо работает фильтрация, нужен валидационный датасет с размеченными метками качества (хороший/плохой). Метрики:
| Метрика | Формула | Интерпретация |
|---|---|---|
| Precision | TP / (TP + FP) | Доля действительно плохих среди отброшенных |
| Recall | TP / (TP + FN) | Доля плохих примеров, которые мы отбросили |
| F1-score | 2 * 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.
Шаги:
- Сгенерировать 500 синтетических QA-пар с помощью GPT-4 (например, на тему «История Рима»).
- Применить эвристики: удалить пары с длиной вопроса < 10 символов или ответа > 300 токенов.
- Вычислить эмбеддинги (all-MiniLM-L6-v2) и выполнить outlier detection (Isolation Forest, contamination=0.05).
- Для оставшихся примеров запросить LLM-оценку (GPT-4 mini) и отбросить с оценкой < 7.
- Оценить качество оставшегося датасета: визуализировать распределение эмбеддингов (t-SNE), посчитать долю отброшенных.
- Сравнить метрики RAG (faithfulness, answer relevance) на исходном и отфильтрованном датасете.
Ожидаемый результат Чистый датасет (примерно 70-80% от исходного) с улучшенными метриками RAG. Код пайплайна с настраиваемыми порогами и логами.
11. Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 680 | Генерация синтетических данных для RAG |
| 681 | Оценка качества RAG-системы |
| 683 | Активное обучение для разметки |
| 684 | Человеческая разметка vs синтетика |
| 686 | Балансировка датасета |
| 688 | Data augmentation для RAG |
12. Навигация
- Предыдущий: 684
- Следующий: 686
- Индекс: 00. Индекс разборов
Навигация
- Предыдущий: 684
- Следующий: 686
- Индекс: 00. Индекс разборов