Automatic Document Classification by Type

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
Automatic Document Classification by Type
Medium
~3-5 business days
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823
  • image_logo-aider_0.jpg
    AIDER company logo development
    762
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    848

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

Классификация документов — первый этап в 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))
            }
        }

Training без 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),
    }

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

Типичная точность на корпусе российских документов (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 недель