# Классификатор типов документов — задача 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. ```powershell 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: ```powershell 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-сборка уже установлена, исправьте текущее активное окружение: ```powershell python -m pip uninstall -y torch torchvision python -m pip install --no-cache-dir -r requirements.txt ``` Проверьте, что PyTorch видит видеокарту: ```powershell 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, а не русским заголовком: ```text 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. Обучение ```powershell 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. Честная проверка ```powershell 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% точности среди принятых ответов; остальные файлы должны оставаться на ручном выборе типа. Порог можно сделать строже: ```powershell python document_type_classifier.py evaluate ` --model .\models\request_document_types.pt ` --data .\test_dataset ` --threshold 0.85 ``` ## 5. Распознавание Один документ: ```powershell python document_type_classifier.py predict ` --model .\models\request_document_types.pt ` --file .\document.pdf ``` Каталог документов: ```powershell python document_type_classifier.py predict ` --model .\models\request_document_types.pt ` --file .\incoming ``` На каждый файл выводится одна JSON-строка: ```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. Возможная интеграция после завершения тестового пилота 1. Загрузить модель один раз при старте отдельного worker/API-сервиса, а не заново для каждого HTTP-запроса. 2. После получения временного файла вызвать классификацию до `document.upload_file(...)`. 3. Проверить, что предсказанная строка входит в `RequestFileType`. 4. При `accepted=true` передать её как `filetype`; при `false` сохранить текущий ручной выбор. 5. Логировать ожидаемый/исправленный пользователем тип и confidence. Эти исправления формируют следующую версию датасета. 6. Версионировать файл модели и иметь возможность мгновенно выключить автоклассификацию конфигурационным флагом. Не рекомендуется запускать тяжёлый инференс синхронно внутри нескольких web-процессов без замера времени и памяти. Для промышленной интеграции лучше обернуть классификатор внутренним API или фоновой задачей и ограничить размер и число страниц входного файла. ## 7. Скачивание документов через авторизованный браузер Создайте, например, `links.txt`, указав одну HTTP/HTTPS-ссылку на строку: ```text https://example.org/document-1.pdf https://example.org/document-2.jpg ``` Скрипт не скачивает файлы HTTP-клиентом Python. Он последовательно передаёт ссылки системному браузеру, поэтому используется уже существующая браузерная авторизация, а имя и расширение файла определяет сам сервер. Перед запуском откройте настройки загрузок Chrome/Edge: 1. Установите каталог загрузки: `.\downloads`. 2. Отключите запрос места сохранения для каждого файла. 3. Разрешите сайту автоматическое скачивание нескольких файлов, если браузер покажет соответствующий запрос. Затем запустите: ```powershell python download_files.py links.txt ``` Пустые строки и строки, начинающиеся с `#`, игнорируются. Между ссылками по умолчанию выдерживается пауза 1.5 секунды. Для пробного запуска первых десяти: ```powershell python download_files.py links.txt --limit 10 ``` Если выполнение было прервано после 350-й ссылки: ```powershell python download_files.py links.txt --start 351 ``` Пауза настраивается параметром `--delay`, например `--delay 3`. Скрипт не переименовывает файлы: браузер сохраняет оригинальное имя из ответа сервера.