Классификация обращений: как разобрать путаницу между отделами
Классификатор отправляет обращения в три отдела. Общая accuracy скрывает, какие именно маршруты ломаются. Построим матрицу ошибок и превратим её в план доработки данных.
У ошибки есть отправитель и получатель
В поддержке работают отделы оплаты, доставки и возвратов. Модель назначает обращению один из трёх классов. Если ошибиться, клиенту приходится ждать повторного перенаправления. Общая доля правильных ответов полезна для сводки, но для исправления маршрутизации нужно знать, какой класс с каким перепутан.
Матрица ошибок хранит число случаев для каждой пары «правильный отдел — предсказанный отдел». По строке видно, куда уходит поток определённой темы. По столбцу — какими чужими обращениями загружен отдел. Диагональ соответствует правильным решениям. Явно задайте порядок классов; при сравнении отчётов переставленные строки легко принять за изменение качества.
Полнота отдела отвечает на вопрос, какую долю предназначенных ему обращений он получает. Точность — какая доля направленных ему обращений действительно относится к нему. Для руководителя отдела это разные операционные проблемы: пропуск своих клиентов и лишняя нагрузка. Численность нужно показывать рядом с долей.
Считаем пары и полноту каждого отдела
В примере три обращения о доставке, два об оплате и одно о возврате. Намеренно оставим два маршрута доставки ошибочными. Код строит целочисленную матрицу и вычисляет полноту из её строк; он не требует установленного ML-фреймворка. В библиотечном отчёте то же направление осей использует confusion_matrix.
У входной таблицы уже есть проверенные метки. Если метка взята из первого назначения оператора, вы можете обучать модель воспроизводить старые ошибки. Для выборочной проверки полезен конечный отдел, решивший вопрос, и отдельный разбор случаев, где несколько тем присутствуют одновременно.
classes = ["payment", "delivery", "return"]
true = ["payment", "payment", "delivery", "delivery", "delivery", "return"]
pred = ["payment", "delivery", "payment", "delivery", "return", "return"]
index = {name: i for i, name in enumerate(classes)}
matrix = [[0] * len(classes) for _ in classes]
for y, p in zip(true, pred):
matrix[index[y]][index[p]] += 1
for name, row in zip(classes, matrix):
i = index[name]
recall = row[i] / sum(row)
print(name, row, "recall=", round(recall, 3))
assert matrix == [[1, 1, 0], [1, 1, 1], [0, 0, 1]]
Полнота доставки равна 1/3. Она теряет два из трёх своих обращений: одно уходит в оплату, одно — в возвраты. У возвратов полнота единица, но это всего один проверочный пример. Кроме того, туда попало чужое обращение доставки. Высокая полнота сама по себе не означает чистый входящий поток.
Дальше соберите тексты для двух проблемных пар. Фраза «не пришли деньги за недоставленный товар» действительно относится сразу к нескольким процессам. Возможно, класс нужно определять по следующему необходимому действию, а инструкция разметки этого не объясняет. Обновление инструкции и повторная разметка небольшого спорного набора иногда полезнее замены архитектуры.
Для распространённых пар ошибок можно добавить признаки, если они доступны заранее: статус заказа, наличие запроса на возврат, этап оплаты. Проверьте, что эти сведения не появляются только после решения оператора. Иначе модель получит готовую подсказку в обучении и потеряет её при реальном распределении новых обращений.
Когда продукт допускает ручной разбор, отдельно проверьте маршрут неопределённых случаев. Выберите правило на валидации и измерьте, сколько обращений попадёт людям, какая полнота сохранится в автоматической части и хватит ли мощности. Сохраняйте общую accuracy, но решение о запуске принимайте по понятным ограничениям на потоки отделов и стоимости перенаправления.
Для следующего шага пригодится выбор вероятности нужного класса.
В платном курсе «ML Engineer / Data Scientist: табличные модели в продакшн» вы сравните модели классификации и разберёте причины ошибок с помощью метрик и интерпретации. Это помогает перейти от общей доли правильных ответов к конкретным исправлениям данных и признаков. Откройте программу курса.
Продолжить на практике
- ML Engineer / Data Scientist: табличные модели в продакшн ↗
Практический курс для тех, кто хочет получить навыки ML Engineer / Data Scientist на реальных табличных задачах. В курсе Вы не просто обучите CatBoost/LightGBM, а соберёте полноценный production-style пайплайн: подготовка данных, feature engineering (генерация признаков), корректная валидация, защита от leakage (утечек), тюнинг через Optuna, интерпретация через SHAP, batch-инференс и REST API для предсказаний.
