Классификатор может отказаться: как оценить автоматизацию и ручную очередь
Классификатор документов определяет, что пришло в бухгалтерию: счёт, акт или накладная. Ошибка отправляет документ в неверный процесс. Команда решает автоматически обрабатывать только уверенные ответы, а остальные показывать сотруднику. После этого одной accuracy недостаточно: модель может получить прекрасную точность, передав человеку почти всю работу.
Сначала опишем действие при отказе
Отказ — отдельный результат сервиса. Он должен сохранять документ в ручную очередь, а не тихо возвращать наиболее вероятный класс. В ответе полезно различать proposed_class, который предложила модель, и решение об автоматической обработке. Тогда интерфейс сотрудника может показывать подсказку, а система маршрутизации соблюдает установленное правило.
Пусть решение принимается по максимальному score среди трёх классов: если он не ниже порога, документ идёт автоматически. Score здесь используется для ранжирования уверенности. Значение 0,9 само по себе ещё не доказывает 90% правильных ответов. Качество выбранного подмножества нужно измерить по реальным меткам, а порог подбирать на отдельной валидационной выборке.
Для каждого порога считаем покрытие: долю документов, получивших автоматическое решение. Внутри этой доли измеряем accuracy. Отдельно сохраняем число ошибочно обработанных документов и размер ручной очереди. Процент ошибок внутри автоматизации помогает оценить риск, а количество ошибок и отказов позволяет посчитать работу отдела.
У двух хороших процентов разная цена
В примере восемь размеченных документов. Числа score и предлагаемые классы уже получены классификатором; код оценивает политику после его вызова. Нулевое покрытие получает значение None для accuracy: среди пустого множества решений нельзя объявлять стопроцентную точность.
rows = [
("d1", "invoice", "invoice", 0.98),
("d2", "act", "act", 0.95),
("d3", "waybill", "invoice", 0.92),
("d4", "invoice", "invoice", 0.85),
("d5", "act", "act", 0.80),
("d6", "waybill", "act", 0.70),
("d7", "invoice", "act", 0.60),
("d8", "act", "act", 0.55),
]
for threshold in (0.0, 0.8, 0.94, 1.0):
auto = [r for r in rows if r[3] >= threshold]
manual = [r[0] for r in rows if r[3] < threshold]
errors = sum(r[1] != r[2] for r in auto)
accuracy = (len(auto) - errors) / len(auto) if auto else None
print(threshold, "coverage", len(auto) / len(rows),
"accuracy", accuracy, "errors", errors, "manual", manual)
assert len(auto) + len(manual) == len(rows)
Без отказов accuracy равна 0,625: пять правильных решений из восьми. При пороге 0,8 автоматически проходят пять документов, четыре из них правильно. Получаем покрытие 0,625 и accuracy 0,8. Порог 0,94 оставляет два правильных решения: accuracy становится 1,0, но покрытие падает до 0,25. Шесть документов из восьми теперь должен обработать человек.
Высокоуверенная ошибка d3 особенно полезна для разбора. Простое повышение порога может убрать её вместе с множеством полезных решений. Откройте исходный документ: возможно, счёт и накладная похожи по шапке, а различие находится в таблице. Тогда нужны изменения признаков или состава обучающей выборки. Работа с этим случаем может дать больше, чем дальнейшее сокращение автоматизации.
Переведём порог в операционное решение
Начните обсуждение с пропускной способности отдела. Если за день приходит тысяча документов, а команда может проверить двести, покрытие должно быть не ниже 80% при сопоставимом потоке. После этого проверьте допустимую частоту и стоимость неверных автоматических решений. Если ни один порог не выполняет оба требования, система пока не готова к заданному масштабу автоматизации.
Сделайте такой же отчёт по каждому истинному классу. При общем хорошем покрытии накладные могут почти целиком попадать человеку, а счета проходить автоматически. У сотрудника останется более сложная очередь, поэтому среднее историческое время ручной обработки после запуска тоже может измениться. Для планирования полезно отдельно замерить обработку отказов на пилоте.
Проверьте ещё сбои чтения и пустые документы. Их нельзя исключать из знаменателя, если они приходят в обычный сервис: для пользователя это тоже ручная работа. При этом технические ошибки загрузки стоит считать отдельной причиной отказа. Такая детализация позволяет решить, что улучшать: распознавание текста, классификацию или приём файлов.
Заморозьте выбранный порог и оцените его на отложенном наборе. В дальнейшем следите за покрытием, причинами отказа и качеством автоматики после получения меток. Резкое улучшение accuracy вместе с падением покрытия может означать, что автоматизация стала выполнять меньше работы. Обе величины должны лежать рядом на одном отчёте.
При построении очереди сохраняйте причину каждого отказа. Низкий максимальный score и маленькая разница между двумя ведущими классами описывают разные ситуации. В первом случае модель может вообще не узнавать документ, во втором — уверенно относить его к двум близким типам. Для сотрудника полезны разные подсказки: выбрать тип с нуля или сравнить два предложенных варианта. Любое новое правило отказа затем оценивайте тем же расчётом покрытия.
Не удаляйте из истории документы после ручного исправления. Для проверки автоматики нужны первоначальное предложение модели, решение политики и окончательная метка сотрудника. Если перезаписать предложенный класс правильным, отчёт задним числом покажет идеальный результат. Сохранённые версии также позволяют оценить другой порог на прошлых данных, не запуская классификатор повторно и не смешивая результаты разных моделей.
В платном курсе «Data Scientist: от данных до деплоя моделей» вы связываете постановку задачи, оценку качества, анализ ошибок и API предсказаний. Это следующий шаг к сервису, у которого отказ становится проверяемым рабочим сценарием, а метрики доходят до мониторинга. Откройте программу курса.
Продолжить на практике
- Data Scientist: от данных до деплоя моделей ↗
Практический курс по Data Science: от постановки ML-задачи и работы с данными до inference API, CI/CD и мониторинга моделей в продакшне. Вы пройдёте EDA, feature engineering, обучение и оценку моделей, experiment tracking, error analysis и deployment — чтобы собирать полноценный рабочий контур вокруг ML-решения.
