Классификатор типов документов — задача 62625
Этот репозиторий — автономный тестовый прототип. Он не импортирует код Vetro и не меняет текущий механизм загрузки. Сначала модель необходимо обучить и измерить качество на документах, которых она не видела.
Текущее состояние модели
Текущая тестовая модель request_document_types.pt обучена распознавать только
четыре типа документов:
Значение RequestFileType |
Тип документа |
|---|---|
referral_for_repairs |
Направление на ремонт |
inspection_act |
Акт осмотра |
cc_approval |
Согласование страхового случая |
inspection_photo |
Фото осмотра |
Документ другого типа модель пока не сможет корректно определить: она выберет
наиболее похожий из этих четырёх классов либо вернёт unknown, если
уверенность ниже установленного порога.
Полученные результаты распознавания
Порог принятия результата — 0.70. Все четыре проверенных документа были приняты моделью:
| Файл | Распознанный тип | Уверенность | Следующие варианты |
|---|---|---|---|
1.pdf |
referral_for_repairs |
99.6794% | cc_approval — 0.2871%, inspection_act — 0.0221% |
2.pdf |
inspection_act |
97.1619% | referral_for_repairs — 2.2419%, cc_approval — 0.3883% |
3.png |
cc_approval |
92.1763% | referral_for_repairs — 7.6405%, inspection_act — 0.1245% |
4.jpg |
inspection_photo |
99.7211% | inspection_act — 0.2390%, referral_for_repairs — 0.0324% |
Каждый файл содержал одну страницу. Эти результаты подтверждают, что запуск
инференса работает и модель уверенно классифицировала четыре конкретных
примера. Они не являются оценкой общей точности модели: для такой оценки
нужно выполнить команду evaluate на независимом test_dataset, который не
использовался при обучении.
1. Подготовка окружения
Для Windows рекомендуется Python 3.12 (64-bit) и отдельное виртуальное окружение. PyTorch для Windows официально поддерживает Python до версии 3.12. Если Python ещё не установлен, используйте Python 3.12.10 — это последняя версия ветки 3.12 с готовым Windows installer.
python -m venv .venv-document-classifier
.\.venv-document-classifier\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
Если существующее окружение перестало запускаться
Файл .venv-document-classifier\pyvenv.cfg содержит путь к Python, на основе
которого создавалось окружение. Если этот Python был удалён или перемещён,
появляется ошибка Unable to create process. Такое окружение нужно создать
заново после установки Python 3.12:
deactivate
Rename-Item .venv-document-classifier .venv-document-classifier-old
py -3.12 -m venv .venv-document-classifier
.\.venv-document-classifier\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
Старый каталог оставлен как резервная копия. После успешной проверки новой среды его можно удалить вручную.
В requirements.txt зафиксированы совместимые версии PyTorch и torchvision
с CUDA 12.8 и официальный индекс cu128. Поэтому все зависимости устанавливаются
одной командой. Обычный pip install torch torchvision без CUDA-индекса может
установить CPU-сборку, которая не умеет работать с RTX 3060 Ti.
Если CPU-сборка уже установлена, исправьте текущее активное окружение:
python -m pip uninstall -y torch torchvision
python -m pip install --no-cache-dir -r requirements.txt
Проверьте, что PyTorch видит видеокарту:
python -c "import torch; ok=torch.cuda.is_available(); print('torch:',torch.__version__,'cuda build:',torch.version.cuda,'available:',ok,'GPU:',torch.cuda.get_device_name(0) if ok else 'нет')"
Ожидаемый результат на текущем ПК: True и NVIDIA GeForce RTX 3060 Ti.
Если выводится False, установлена CPU-сборка PyTorch — до обучения нужно
поставить CUDA-сборку командой выше.
Для первого запуска обучения нужен интернет: torchvision скачает
предобученные ImageNet-веса MobileNetV3. Если интернета нет, можно добавить
--no-pretrained, но качество обычно будет ниже.
2. Подготовка датасета
Создайте один каталог на каждый тип. Имя каталога должно быть точным
строковым значением RequestFileType из Vetro, а не русским заголовком:
dataset/
├── referral_for_repairs/
│ ├── direction_0001.pdf
│ └── direction_0002.jpg
├── inspection_act/
│ ├── act_0001.pdf
│ └── act_0002.png
└── check/
├── invoice_0001.pdf
└── invoice_0002.pdf
Поддерживаются PDF, PNG, JPG/JPEG, BMP, TIFF и WEBP. DOC/DOCX/XLS следует заранее преобразовать в PDF. Один многостраничный PDF считается одним документом: все его страницы попадут только в train или только в validation.
Практические требования к данным:
- минимум — 2 документа на тип, разумный старт — 50–100;
- лучше 200+ документов на каждый часто встречающийся тип;
- не складывайте копии одного документа под разными именами;
- включите сканы и фото разного качества, документы разных страховых компаний;
- номера дел, ФИО и прочие персональные данные должны храниться только в защищённой инфраструктуре; этот скрипт никуда их не отправляет;
- число документов по типам желательно выровнять. В коде есть компенсация дисбаланса классов, но она не заменяет реальные примеры.
Отложите отдельный каталог test_dataset (обычно 10–20% исходных документов)
до обучения. Он должен иметь ту же структуру и не должен пересекаться с
dataset. Встроенный validation нужен для выбора эпохи, а test_dataset —
для честной финальной оценки.
3. Обучение
python document_type_classifier.py train `
--data .\dataset `
--model .\models\request_document_types.pt `
--device cuda `
--epochs 25 `
--batch-size 64 `
--workers 0 `
--log-every 10
Эти значения подобраны для текущего компьютера:
- AMD Ryzen 5 7500F: 6 ядер / 12 потоков;
- 32 ГБ оперативной памяти;
- NVIDIA GeForce RTX 3060 Ti, 8 ГБ видеопамяти.
По умолчанию уже используются batch-size=64, workers=0, размер изображения
224×224 и mixed precision. В памяти хранится только индекс путей и страниц;
каждое изображение декодируется непосредственно перед своим batch. Это не
позволяет фотографиям высокого разрешения занять всю оперативную память перед
первой эпохой. Явные параметры в примере оставлены для воспроизводимости. Если
появляется CUDA out of memory, сначала установите
--batch-size 32, затем 16. Если CUDA работает нестабильно, добавьте
--no-amp; для принудительного CPU используйте --device cpu --batch-size 16 --workers 0.
Во время запуска логируются сканирование и состав датасета, чтение каждых 25
документов, загрузка модели, каждый 10-й batch, validation, время эпохи и
примерное оставшееся время. Частоту можно изменить параметрами
--dataset-log-every и --log-every.
Скрипт печатает val_accuracy после каждой эпохи, сохраняет только лучшую
модель и останавливается после пяти эпох без улучшения.
Реальные JPEG из Vetro могут содержать неполный последний блок или
нестандартную структуру, хотя нормально открываются браузером. Для таких
файлов включён tolerant-режим Pillow: доступная часть изображения участвует в
обучении. Сообщение Пропуск поврежденного файла теперь остаётся только для
файлов, которые действительно невозможно декодировать.
4. Честная проверка
python document_type_classifier.py evaluate `
--model .\models\request_document_types.pt `
--data .\test_dataset
В отчёте:
accuracy_with_unknown_as_error— доля всех верных ответов;accepted_share— доля документов, для которых уверенность не ниже порога;by_expected_type— ошибки по каждому реальному типу.
Для автозагрузки недостаточно одной общей accuracy. Проверьте каждый тип и особенно пары, которые модель путает. Рекомендуемый критерий пилота: не менее 95% точности среди принятых ответов; остальные файлы должны оставаться на ручном выборе типа.
Порог можно сделать строже:
python document_type_classifier.py evaluate `
--model .\models\request_document_types.pt `
--data .\test_dataset `
--threshold 0.85
5. Распознавание
Один документ:
python document_type_classifier.py predict `
--model .\models\request_document_types.pt `
--file .\document.pdf
Каталог документов:
python document_type_classifier.py predict `
--model .\models\request_document_types.pt `
--file .\incoming
На каждый файл выводится одна JSON-строка:
{"file":"document.pdf","document_type":"inspection_act","confidence":0.9631,"accepted":true,"pages":2,"alternatives":[...]}
Если уверенность ниже 0.70, document_type будет unknown и
accepted=false. При интеграции такой документ нужно показывать пользователю
для ручного выбора. alternatives полезны для интерфейса и анализа ошибок.
Все команды следует выполнять из корня репозитория.
6. Возможная интеграция после завершения тестового пилота
- Загрузить модель один раз при старте отдельного worker/API-сервиса, а не заново для каждого HTTP-запроса.
- После получения временного файла вызвать классификацию до
document.upload_file(...). - Проверить, что предсказанная строка входит в
RequestFileType. - При
accepted=trueпередать её какfiletype; приfalseсохранить текущий ручной выбор. - Логировать ожидаемый/исправленный пользователем тип и confidence. Эти исправления формируют следующую версию датасета.
- Версионировать файл модели и иметь возможность мгновенно выключить автоклассификацию конфигурационным флагом.
Не рекомендуется запускать тяжёлый инференс синхронно внутри нескольких web-процессов без замера времени и памяти. Для промышленной интеграции лучше обернуть классификатор внутренним API или фоновой задачей и ограничить размер и число страниц входного файла.
7. Скачивание документов через авторизованный браузер
Создайте, например, links.txt, указав одну HTTP/HTTPS-ссылку на строку:
https://example.org/document-1.pdf
https://example.org/document-2.jpg
Скрипт не скачивает файлы HTTP-клиентом Python. Он последовательно передаёт ссылки системному браузеру, поэтому используется уже существующая браузерная авторизация, а имя и расширение файла определяет сам сервер.
Перед запуском откройте настройки загрузок Chrome/Edge:
- Установите каталог загрузки:
.\downloads. - Отключите запрос места сохранения для каждого файла.
- Разрешите сайту автоматическое скачивание нескольких файлов, если браузер покажет соответствующий запрос.
Затем запустите:
python download_files.py links.txt
Пустые строки и строки, начинающиеся с #, игнорируются. Между ссылками по
умолчанию выдерживается пауза 1.5 секунды. Для пробного запуска первых десяти:
python download_files.py links.txt --limit 10
Если выполнение было прервано после 350-й ссылки:
python download_files.py links.txt --start 351
Пауза настраивается параметром --delay, например --delay 3. Скрипт не
переименовывает файлы: браузер сохраняет оригинальное имя из ответа сервера.