DocAI извлёк сумму и дату: как считать точность полей без самообмана

Система извлекла из счёта дату «2026-10-26» и сумму «1250.00». В эталоне записано «26.10.2026» и «1 250,00». Проверка сырых строк объявляет оба поля ошибочными, хотя значения совпадают. Если команда начнёт улучшать OCR по такой оценке, она будет исправлять формат представления вместо настоящих пропусков и неверных реквизитов.

Определите значение поля до сравнения

Для даты полезен тип календарной даты, для суммы — точное десятичное число с валютой и правилами округления. Для номера документа наоборот важна исходная строка: ведущие нули, буквы и знак «№» могут быть частью идентификатора. Единая операция «удалить все пробелы и знаки» для всех полей способна скрыть реальные ошибки. Запишите допустимую нормализацию отдельно для каждого поля до оценки модели.

Код ниже сравнивает две пары сначала как строки, потом после явного разбора даты и суммы. Для денежного значения используется Decimal, чтобы десятичная сумма не зависела от двоичного представления float. В примере не выбирается валюта: в рабочей схеме она должна быть отдельным проверяемым полем.

from datetime import datetime
from decimal import Decimal

reference = {"date": "26.10.2026", "amount": "1 250,00"}
extracted = {"date": "2026-10-26", "amount": "1250.00"}

def normalize_date(value):
    for fmt in ("%d.%m.%Y", "%Y-%m-%d"):
        try:
            return datetime.strptime(value, fmt).date().isoformat()
        except ValueError:
            pass
    raise ValueError(f"неизвестный формат даты: {value}")

def normalize_amount(value):
    return Decimal(value.replace(" ", "").replace(",", "."))

raw = sum(reference[k] == extracted[k] for k in reference)
normalized = (normalize_date(reference["date"]) == normalize_date(extracted["date"])) + (
    normalize_amount(reference["amount"]) == normalize_amount(extracted["amount"]))
print("сырые совпадения:", raw, "из", len(reference))
print("после нормализации:", normalized, "из", len(reference))
assert raw == 0 and normalized == 2

Сырые строки дают 0 совпадений из 2, нормализованные значения — 2 из 2. Это не означает, что извлечение всегда идеально: мы показали один случай форматного расхождения. Добавьте в проверочный набор и настоящие ошибки: «1250» вместо «12500», неправильный месяц, пустое поле, неверную валюту. Нормализатор не должен превращать их в совпадения.

Агрегируйте по действиям, которые выполняет сервис

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

Нормализацию применяйте одинаково к эталону и ответу. Сохраняйте оба исходных значения рядом с нормализованными, чтобы можно было разобрать спорный случай. Если OCR перепутал «О» и «0» в номере, глобальная замена символов может сделать результат похожим на эталон, но отправить неверный номер во внешнюю систему. CER/WER для OCR полезны для качества текста, однако точность структурированных полей отвечает на следующий практический вопрос.

В курсе «Computer Vision Engineer: от детекции и Doc-AI до продакшна» вы проходите распознавание документов, извлечение полей в JSON и сборку сервиса с отчётом метрик. Проверка полей позволяет оценить путь от скана до записи, которую действительно можно использовать. Откройте программу курса.

Продолжить на практике

  • Computer Vision Engineer: от детекции и Doc-AI до продакшна ↗

    Практический курс по Computer Vision. Соберёте продакшн-сервис: датасет → обучение (YOLO/RT-DETR, SAM), трекинг, OCR/Doc-AI, веб-приложение (UI+API) и мониторинг. Экспорт в ONNX/TensorRT/OpenVINO, батчинг/квантование под CPU/GPU. Плюс профессиональные блоки: mAP/IoU/Dice и калибровка доверия, QA разметки и аугментации, p95/стоимость, дрейф данных и алерты, guardrails (NMS/правила), A/B-тесты, Triton/gRPC/FastAPI.