Реалізація автоматичної класифікації документів за типом

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Реалізація автоматичної класифікації документів за типом
Середній
~3-5 днів
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

Реализация автоматической классификации документов по типу

Классификация документов — первый этап в Document Processing Pipeline: прежде чем извлекать данные, система должна понять, что за документ перед ней. Счёт-фактура, накладная, паспорт, водительские права, акт выполненных работ — для каждого типа свой экстрактор. Точность классификации напрямую влияет на качество всего pipeline.

Мультимодальная классификация

Лучший подход — одновременно использовать визуальные признаки (как выглядит документ) и текстовые (что написано):

from transformers import LayoutLMv3ForSequenceClassification, LayoutLMv3Processor
import torch
import torch.nn as nn

class DocumentClassifier:
    def __init__(self, model_path: str, doc_types: list[str]):
        self.processor = LayoutLMv3Processor.from_pretrained(model_path)
        self.model = LayoutLMv3ForSequenceClassification.from_pretrained(
            model_path,
            num_labels=len(doc_types)
        )
        self.doc_types = doc_types
        self.model.eval()

    @torch.no_grad()
    def classify(self, image_path: str) -> dict:
        from PIL import Image
        image = Image.open(image_path).convert('RGB')

        encoding = self.processor(
            image, return_tensors='pt',
            truncation=True, max_length=512
        )

        outputs = self.model(**encoding)
        probs = torch.softmax(outputs.logits, dim=-1).squeeze()

        top_idx = probs.argmax().item()
        return {
            'document_type': self.doc_types[top_idx],
            'confidence': float(probs[top_idx]),
            'all_scores': {
                self.doc_types[i]: float(probs[i])
                for i in range(len(self.doc_types))
            }
        }

Навчання без LayoutLM: EfficientNet + BERT

Для быстрого прототипа без доступа к большим моделям:

import timm
from transformers import AutoTokenizer, AutoModel

class LightweightDocClassifier(nn.Module):
    def __init__(self, num_classes: int):
        super().__init__()
        # Visual encoder
        self.visual = timm.create_model('efficientnet_b2',
                                         pretrained=True, num_classes=0)
        # Text encoder
        self.text_encoder = AutoModel.from_pretrained('DeepPavlov/rubert-base-cased')
        self.tokenizer = AutoTokenizer.from_pretrained('DeepPavlov/rubert-base-cased')

        # Fusion
        vis_dim = self.visual.num_features  # 1408
        text_dim = 768
        self.fusion = nn.Sequential(
            nn.Linear(vis_dim + text_dim, 512),
            nn.GELU(),
            nn.Dropout(0.3),
            nn.Linear(512, num_classes)
        )

    def forward(self, image_tensor, input_ids, attention_mask):
        vis_features = self.visual(image_tensor)
        text_out = self.text_encoder(input_ids, attention_mask)
        text_features = text_out.pooler_output  # [CLS] token

        combined = torch.cat([vis_features, text_features], dim=-1)
        return self.fusion(combined)

Типовые классы документов

Домен Классы документов
Бухгалтерия Счёт, накладная, акт, счёт-фактура, договор, доверенность
KYC/AML Паспорт, СНИЛС, ИНН, права, загранпаспорт
Медицина Направление, рецепт, выписка, результат анализа
Юриспруденция Исковое заявление, решение суда, договор, доверенность
Логистика Накладная, CMR, таможенная декларация, коносамент

Коллекция признаков для классификации

Для повышения точности — дополнительные признаки помимо визуальных и текстовых:

def extract_document_features(image_path: str, ocr_text: str) -> dict:
    return {
        # Структурные признаки
        'has_table': detect_tables(image_path),
        'has_signature': detect_signature_zone(image_path),
        'has_stamp': detect_stamp(image_path),
        'has_photo': detect_person_photo(image_path),

        # Текстовые паттерны (регулярные выражения)
        'has_inn': bool(re.search(r'\bИНН\b', ocr_text)),
        'has_kpp': bool(re.search(r'\bКПП\b', ocr_text)),
        'has_passport_series': bool(re.search(r'\d{4}\s\d{6}', ocr_text)),
        'has_invoice_number': bool(re.search(r'№\s*\d+', ocr_text)),

        # Метаданные
        'aspect_ratio': get_aspect_ratio(image_path),
        'orientation': detect_orientation(image_path),
    }

Метрики на российских документах

Типичная точность на корпусе российских документов (25 классов):

Метрика Значение
Top-1 Accuracy 94–97%
Macro F1 92–96%
Recall на редких классах 85–91%

Сложные случаи: документы одного типа в разных форматах (разные банки, разные поставщики), плохое качество сканов, ламинированные документы.

Задача Срок
5–10 классов, достаточно данных 2–3 недели
20–50 классов, разные форматы 4–7 недель
Continuous learning (добавление новых классов) 6–10 недель