Гайд · TNWS AI

Как построить матрицу ошибок AI-классификатора без библиотеки ML

6 мин—

Считаем TP/FP/FN/TN на размеченных синтетических обращениях через Counter и разбираем каждую ошибку по ID.

Практическая задача

Понять, какие заявки AI ошибочно пометил срочными, а какие срочные пропустил, вместо одного непрозрачного процента. Для двоичной метки urgent положительный класс — urgent. TP означает совпавший срочный случай, FP — ложную тревогу, FN — пропущенный срочный, TN — корректный обычный. В примере четыре искусственные записи с явным expected/actual. Это не измерение работающей модели и не готовое основание для бизнес-решения. Перед подсчётом проверьте, что каждая пара относится к одному и тому же ID и что один ID не встречается дважды. Если модель вернула неизвестную метку, не записывайте её автоматически в TN или FN: сначала разрешите ошибку схемы. Для независимого аудита сохраните таблицу из ID, expected, actual и вычисленной корзины. Саму матрицу показывайте вместе с исходными количествами классов, потому что четыре агрегата без контекста состава корпуса легко вводят в заблуждение. Этот сценарий применим, когда у команды есть контроль над корпусом AI-приложения и требуется конкретный сигнал о нарушении правила, а не общее впечатление от нескольких ответов. Все входы ниже вымышлены; числовые результаты относятся только к этим примерам.

Документация методов Python и синтаксиса workflow сверена 19.09.2026. Если вы используете другое окружение, проверьте совместимость до копирования команд. Статья не утверждает, что показанный код измеряет качество конкретной модели или заменяет предметную разметку людьми.

Подготовка и проверяемый контракт

Перед запуском запишите, какие данные считаются входом, что является ожидаемым результатом, что именно означает отказ и кому предстоит разбирать расхождение. Для AI-оценки важно отдельно хранить вход, ожидаемую метку и фактический результат: если они смешаны, тест может подтверждать сам себя. Используйте стабильные синтетические ID, чтобы видеть ошибку в журнале, не раскрывая содержимое клиентских обращений.

Сначала прогоните тест на маленьком входе, где правильное поведение известно вручную. Затем внесите одну контролируемую ошибку и убедитесь, что код её замечает. После этого верните корректный набор и только тогда расширяйте проверку до реальных данных. Не переносите демонстрационные численные значения или пороги в производство без отдельного обоснования: они выбраны для наглядности, а не рассчитаны по вашей аудитории.

Вход и ожидаемый результат

U1 urgent/urgent, U2 urgent/normal, N1 normal/urgent, N2 normal/normal. Ожидается по одному примеру каждого из четырёх исходов. Для синтетических U1,U2,N1,N2 получаются TP=1, FN=1, FP=1, TN=1. Это арифметика четырёх сконструированных записей, не опубликованная метрика AI-сервиса. Перед тем как применять правило к закрытому корпусу, обсудите пограничные случаи, которые могут поменять интерпретацию входа. Запись в документации о границах теста не менее важна, чем зелёный check.

Пошаговые действия

  1. Создайте scripts/check.py в корне репозитория и вставьте код из блока ниже. Он использует названия функций стандартной библиотеки, указанные в официальных ссылках в конце статьи.
  2. Выполните python scripts/check.py локально. Не продолжайте, если уже демонстрационная фикстура даёт иной результат: сначала проверьте копирование кода и кодировку файла.
  3. Скопируйте скрипт и проследите каждый ID, прежде чем смотреть на итоговые числа. Затем подключите загрузку результатов вашего корпуса и сделайте логику проверки разрешённых меток строгой. Для ревью сохраняйте список ID по четырём корзинам, а не только агрегат. Особое внимание уделите FN, если пропущенная срочная заявка опаснее лишнего уведомления; приоритет ошибок зависит от вашего процесса, его нельзя выводить из демонстрационных данных.
  4. Создайте .github/workflows/ai-corpus-check.yml из YAML-шаблона. Событие pull_request полезно для проверки корпуса до слияния; чтение репозитория ограничено permissions: contents: read. Скрипт не должен получать ключ внешней модели или реальные секреты.
  5. В разделе Actions откройте job check, сопоставьте его код завершения с локальным прогоном и зафиксируйте ссылку на проверенный коммит в PR. Не принимайте зелёный результат на старой ревизии за проверку последнего изменения.
# scripts/check.py
from collections import Counter

rows = [("U1","urgent","urgent"), ("U2","urgent","normal"),
        ("N1","normal","urgent"), ("N2","normal","normal")]
counts = Counter()
for case_id, expected, actual in rows:
    if expected not in {"urgent","normal"} or actual not in {"urgent","normal"}:
        raise SystemExit("Unknown label in " + case_id)
    name = ("TP" if expected == actual == "urgent" else
            "TN" if expected == actual == "normal" else
            "FN" if expected == "urgent" else "FP")
    counts[name] += 1
    print(case_id, name)
assert all(counts[key] == 1 for key in ("TP","TN","FP","FN"))
print("Demo confusion counts:", dict(counts))
name: AI corpus checks
on:
  pull_request:
permissions:
  contents: read
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-python@v7
        with:
          python-version: '3.13'
      - run: python scripts/check.py

Ошибки интерпретации и границы

Матрица ошибок требует достоверных expected, проверенных людьми. На неразмеченном потоке она невозможна. Если категорий больше двух, такой двоичный код недостаточен: определите матрицу по каждой паре классов. Если вы увеличиваете корпус, добавляйте не только новые примеры, но и отрицательные случаи, на которых тест обязан упасть. Проверяйте, что изменение expected прошло ревью отдельно от изменения кода: иначе можно незаметно изменить правило под текущий ответ системы. Избегайте вывода полного корпуса в CI и не сохраняйте в артефактах ответ закрытой модели без решения о доступе и хранении.

Ошибка выполнения самого Python, нераспознанный формат входа и обнаруженный бизнес-дефект — разные ситуации. В сообщении теста указывайте тип проблемы и безопасный ID. Если тест требует внешний сервис, вынесите его из PR с недоверенным кодом и явно ограничьте доступ к токенам; этот пример намеренно работает локально. Перед публикацией каких-либо результатов опишите методику, размер и происхождение набора, иначе читатель воспримет демонстрационную арифметику как характеристику продукта.

Чек-лист финальной проверки

  • Синтетический вход и ожидаемый исход согласованы предметным владельцем.
  • Команда python scripts/check.py работает локально и в CI на одной версии файлов.
  • Негативный случай обнаруживается, а не только успешный случай проходит.
  • Имена ID и меток уникальны там, где этого требует контракт.
  • В репозитории, логах и артефактах нет реальных секретов и приватных текстов.
  • Понятно, какой дефект тест находит и каких выводов о качестве AI он не даёт.
  • Ссылки на применённые функции и синтаксис workflow перепроверены при переносе.

FAQ

Чем FP отличается от FN?

FP — обычный кейс помечен срочным; FN — срочный ошибочно назван обычным.

Почему показывать ID?

Они позволяют воспроизвести конкретную ошибку и проверить разметку.

Можно ли считать accuracy по четырём кейсам?

Математически да, но представлять число как качество сервиса нельзя: набор синтетический.

Что делать с неизвестной меткой?

Не помещать её в normal по умолчанию; остановить оценку и исправить входной контракт.

Что делать после обнаружения сбоя

Сохраните конкретный ID, воспроизведите его на текущей ревизии и отделите ошибку входного корпуса от ошибки функции. Если неверна разметка, исправьте её после предметного ревью; если неверен код, сначала оставьте проваливающийся тест, затем вносите исправление. После зелёного запуска просмотрите соседние случаи с похожими признаками, чтобы локальная правка не изменила другое согласованное поведение. Сохраните версии кода, набора и параметров запуска рядом с выводом: без них сравнивать результаты в будущем нельзя. Не приводите цифру из синтетического примера как измеренный показатель продукта.

Официальные первоисточники

Проверено 19.09.2026: 1, 2, 3, 4. Описание переписано своими словами; изменяемые версии и поля нужно повторно сверять перед дальнейшим использованием.

Читайте также

Комментарии

Пока тихо. Скажите первое слово