Как вы дебажите, почему классификатор ошибся на конкретном примере (анализ эмбеддингов, ошибки токенизации)?
Краткий тезис
Диагностика ошибки классификатора на одном примере требует последовательного исключения возможных причин: от низкоуровневых проблем токенизации до качества эмбеддингов, важности признаков и ошибок разметки. В пайплайне дебага всегда начинают с проверки того, как текст превратился в числовой вход модели, затем анализируют положение эмбеддинга в пространстве, оценивают вклад признаков через SHAP/LIME и, наконец, сверяются с золотым стандартом. Каждый шаг даёт ответ либо «проблема на этом уровне», либо «ищем дальше».
2. Анализ эмбеддинга: ближайшие соседи
Если токенизация корректна, следующий шаг — понять, как модель «видит» этот пример в скрытом пространстве. Классификатор обычно принимает решение на основе эмбеддинга (чаще всего [CLS] или пулинг последнего слоя).
2.1. Извлечение эмбеддинга ошибочного примера
import torch
from transformers import AutoModel, AutoTokenizer
model = AutoModel.from_pretrained("bert-base-multilingual-cased")
tokenizer = AutoTokenizer.from_pretrained("bert-base-multilingual-cased")
text = "Ваш текст"
inputs = tokenizer(text, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)
embedding = outputs.last_hidden_state[:, 0, :].squeeze() # [CLS]
2.2. Поиск k ближайших соседей по косинусной близости
Возьмите эмбеддинги всех примеров из обучающей/валидационной выборки (или хотя бы 10 000 случайных) и найдите соседей для вашего спорного примера.
- Используйте FAISS или
sklearn.neighbors.NearestNeighbors. - Если соседи с другим классом очень близки — модель не видит разделяющей границы в этой области.
- Если соседи с верным классом далеко — возможно, эмбеддинг искажён шумом.
2.3. Визуализация
Понижайте размерность до 2D (PCA, t-SNE) и раскрасьте точки по предсказанным/истинным классам.
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
tsne = TSNE(n_components=2)
emb_2d = tsne.fit_transform(all_embeddings)
plt.scatter(emb_2d[:,0], emb_2d[:,1], c=labels)
plt.scatter(emb_2d[error_idx,0], emb_2d[error_idx,1], c='red', s=200)
Типовые выводы: эмбеддинг находится в «пограничной» зоне, либо в кластере неверного класса — тогда проблема в недостаточной разделимости.
3. SHAP/LIME для важности признаков
Даже если эмбеддинг аномален, нужно понять, какие именно токены заставили модель принять неверное решение. Для этого используют методы объяснения отдельных предсказаний.
3.1. SHAP (Shapley Additive Explanations)
- Требует специальных адаптеров для NLP (например,
shap.Explainerдля transformers). - Вычисляет вклад каждого токена в логарифм вероятности предсказанного класса.
import shap
from transformers import pipeline
classifier = pipeline("text-classification", model="bert-base-multilingual-cased")
explainer = shap.Explainer(classifier, tokenizer)
shap_values = explainer([text])
shap.plots.text(shap_values[0])
Красные токены — те, что «тянули» в сторону неверного класса. Если ключевые слова (например, «отлично» при негативной тональности) имеют высокое положительное влияние на негативный класс — модель выучила не то.
3.2. LIME (Local Interpretable Model-agnostic Explanations)
- Возмущает входной текст (удаляет/добавляет слова) и смотрит изменение предсказания.
- Более быстрый, но менее теоретически обоснованный.
import lime
from lime.lime_text import LimeTextExplainer
explainer = LimeTextExplainer(class_names=['neg','pos'])
exp = explainer.explain_instance(text, predictor_fn, num_features=10)
exp.show_in_notebook()
Ошибки на уровне токенов: модель может придавать избыточный вес редкому токену (например, название компании, которое в обучающем наборе было только с одним классом).
4. Ошибки разметки в датасете
Самая частая и «дешёвая» причина ошибки — неправильная метка у самого анализируемого примера. Прежде чем углубляться в модели, стоит проверить датасет.
4.1. Аудит аннотации
- Показать пример трём независимым экспертам/краудсорсерам.
- Посчитать каппу Коэна для размеченного датасета.
- Если согласие низкое — метка могла быть поставлена ошибочно.
4.2. Проверка аугментаций
- Если датасет аугментировали (back-translation, замена синонимов), мог появиться пример, который семантически далёк от исходного класса.
4.3. Оценка доли таких примеров
- Соберите все ошибки модели на валидации. Посчитайте, сколько из них можно отнести к «разметочным» (эксперт переразметил бы иначе). Если доля > 10% — проблема в качестве датасета, а не в модели.
Типовые признаки: модель ошибается на одном и том же лексическом паттерне, который в обучающем наборе размечен противоречиво, или метка противоречит здравому смыслу.
Пет-проект для закрепления
Задача: Реализовать инструмент дебага для классификатора русского языка (например, тональность), который на вход получает текст и выводит отчёт: список токенов, ближайшие соседи из обучающей выборки, SHAP-график и флаг «возможно, ошибка разметки».
Инструменты:
- Transformers (модель
DeepPavlov/rubert-base-cased). - FAISS или
sklearn.neighborsдля соседей. - SHAP для важности токенов.
- Flask / Streamlit для веб-интерфейса.
Шаги:
- Загрузить предобученный классификатор тональности.
- Реализовать функцию
debug_pipeline(text):- токенизация и проверка на non‑ASCII символы.
- извлечение эмбеддинга и поиск топ-5 соседей с их метками.
- расчёт SHAP-значений.
- сравнение предсказанной метки с меткой «золотого стандарта» из небольшого встроенного датасета.
- Отобразить результат: красные/зелёные токены, список соседей с расстоянием, подсказка «возможно, ошибка датасета» если соседи с другим классом показывают другую метку.
Ожидаемый результат: Приложение, которое для любого введённого текста детально объясняет, почему классификатор дал именно такой ответ, с указанием вероятных причин ошибки.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 943 | Как вы оцениваете сбалансированность классов и подбираете метрики? |
Навигация
- Предыдущий: 943
- Следующий: 945
- Индекс: 00. Индекс разборов