Обучение модели классификации текста (BERT, RoBERTa, DeBERTa)

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1Все 1564 услуг
Обучение модели классификации текста (BERT, RoBERTa, DeBERTa)
Средний
~5 дней
Часто задаваемые вопросы

Направления AI-разработки

Этапы разработки AI-решения

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1361
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1251
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    957
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1189
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    646
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    929

При дообучении BERT мы часто сталкиваемся с парадоксом: метрики на валидации отличные (F1 > 0.95), а в продакшене — провал. Причина — несоответствие распределений: train и real‑world данные различаются по длине, стилю, формулировкам. Мы решаем эту проблему системно: от выбора базовой модели до production‑оптимизации. Недавно к нам обратился клиент с задачей классификации отзывов на маркетплейсе — на валидации F1 достигал 0.97, но в реальном потоке упал до 0.82. Анализ показал, что большинство ложных предсказаний приходилось на короткие отзывы (менее 10 токенов) — их почти не было в обучающей выборке. После добавления аугментации и настройки max_length до 128 метрика вернулась к 0.94.

Выбор базовой модели

BERT (bert-base-uncased, DeepPavlov/rubert-base-cased): классика, хорошо изучена, много туториалов. Для большинства задач достаточно.

RoBERTa (roberta-base, ai-forever/ruRoBERTa-large): улучшенное обучение без Next Sentence Prediction, на большем корпусе. Обычно на 1–3% лучше BERT.

DeBERTa (microsoft/deberta-v3-base): диcентанглированное внимание — лучшее качество на benchmarks. Рекомендуется если нужна максимальная точность и есть GPU-ресурсы.

Для русского языка: ai-forever/ruBert-base, DeepPavlov/rubert-base-cased, ai-forever/ruRoBERTa-large, ai-forever/sber-roberta-large.

Как выбрать базовую модель для русского языка?

Выбор зависит от трёх факторов: размера датасета, целевой метрики и доступных вычислительных ресурсов. Для старта мы рекомендуем DeepPavlov/rubert-base-cased — он сбалансирован по качеству и скорости обучения. Если датасет >10К примеров и есть V100/A100, используйте ai-forever/ruRoBERTa-large — прирост F1 до 3%. Для максимальной точности (и при наличии времени на тюнинг) — microsoft/deberta-v3-base.

Pipeline обучения

from transformers import (
    AutoTokenizer, AutoModelForSequenceClassification,
    TrainingArguments, Trainer
)
from datasets import Dataset
import evaluate
import numpy as np

# Подготовка данных
tokenizer = AutoTokenizer.from_pretrained("DeepPavlov/rubert-base-cased")

def tokenize_function(examples):
    return tokenizer(
        examples["text"],
        padding="max_length",
        truncation=True,
        max_length=256  # 256 достаточно для большинства задач
    )

dataset = Dataset.from_pandas(df)
tokenized = dataset.map(tokenize_function, batched=True)
tokenized = tokenized.train_test_split(test_size=0.2)

# Инициализация модели
model = AutoModelForSequenceClassification.from_pretrained(
    "DeepPavlov/rubert-base-cased",
    num_labels=num_classes,
    id2label=id2label,
    label2id=label2id
)

# Метрики
accuracy = evaluate.load("accuracy")
f1 = evaluate.load("f1")

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    return {
        "accuracy": accuracy.compute(predictions=predictions, references=labels)["accuracy"],
        "f1_macro": f1.compute(predictions=predictions, references=labels, average="macro")["f1"],
    }

# Параметры обучения
training_args = TrainingArguments(
    output_dir="./results",
    num_train_epochs=5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=32,
    learning_rate=2e-5,
    weight_decay=0.01,
    warmup_ratio=0.1,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
    metric_for_best_model="f1_macro",
    fp16=True,  # mixed precision для GPU
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized["train"],
    eval_dataset=tokenized["test"],
    compute_metrics=compute_metrics,
)

trainer.train()

Гиперпараметры и их влияние

Параметр Рекомендуемый диапазон Влияние
learning_rate 1e-5 – 5e-5 Самый критичный. 2e-5 — хороший старт
num_epochs 3–10 Переобучение при > 10
batch_size 8–32 Больше = стабильнее, но нужно больше VRAM
max_length 64–512 Зависит от длины текстов
warmup_ratio 0.06–0.1 Предотвращает нестабильное начало

Сравнение времени инференса моделей

Модель FP32 latency (CPU) INT8 latency (CPU) F1 drop (vs FP32)
ruBERT-base 120ms 18ms -0.3%
ruRoBERTa-large 340ms 52ms -0.5%
DeBERTa-v3-base 190ms 30ms -0.4%

Почему важно использовать weighted loss при дисбалансе классов?

Если классы распределены неравномерно (например, 95% нормальных обращений и 5% жалоб), стандартный CrossEntropyLoss «проигнорирует» редкий класс. Мы добавляем class_weight в функцию потерь:

from torch import nn
import torch

# Вычисляем веса классов
class_weights = compute_class_weight("balanced", classes=np.unique(labels), y=labels)
weights_tensor = torch.FloatTensor(class_weights).to(device)

class WeightedTrainer(Trainer):
    def compute_loss(self, model, inputs, return_outputs=False):
        labels = inputs.pop("labels")
        outputs = model(**inputs)
        logits = outputs.get("logits")
        loss_fn = nn.CrossEntropyLoss(weight=weights_tensor)
        loss = loss_fn(logits, labels)
        return (loss, outputs) if return_outputs else loss

Этот приём поднимает F1 по редкому классу на 10–15% без потери качества на частых.

Оценка и анализ ошибок

После обучения обязательно:

  • Confusion matrix по всем классам
  • Примеры ошибок для каждой пары (истинный класс, предсказанный класс)
  • Calibration plot: насколько достоверны вероятности модели
  • Error analysis: есть ли паттерн в ошибках? (определённые слова, длина текста, авторский стиль)
Детальный чек-лист посттренировочной валидации
  1. Проверить распределение предсказаний на реальных данных (отличных от train/test).
  2. Построить ROC-кривую для каждого класса, убедиться в AUC >0.95.
  3. Выполнить A/B-тест: сравнить новую модель с текущей на случайной выборке.
  4. Замерить latency p99 и throughput на целевой конфигурации.
  5. Подготовить модель карту с ограничениями и известными edge-case.

Оптимизация для продакшена

После fine-tuning экспортировать в ONNX:

from optimum.onnxruntime import ORTModelForSequenceClassification

ort_model = ORTModelForSequenceClassification.from_pretrained("./results", export=True)
ort_model.save_pretrained("./onnx_model")

Benchmark: ruBERT fine-tuned → ONNX INT8: 120ms → 18ms на CPU при точности -0.3%. Благодаря квантизации стоимость инференса снижается на 40% по сравнению с FP32. На одном из проектов мы сократили затраты на GPU с $2000 до $1200 в месяц.

Что входит в нашу работу

Мы предоставляем не просто модель, а готовое решение под ключ:

  • Анализ датасета и определение минимального достаточного размера выборки
  • Выбор оптимальной архитектуры (BERT/RoBERTa/DeBERTa) под ваши данные
  • Дообучение с подбором гиперпараметров (learning rate, batch size, epochs)
  • Пост-тренировочный анализ: confusion matrix, calibration curve, error analysis
  • Экспорт в ONNX/TensorRT для инференса на CPU
  • Интеграция в ваш пайплайн (REST API, gRPC, бэтч)
  • Документация модели и метрик, отчёт по качеству
  • Поддержка после внедрения — гарантируем стабильную работу

С нами работают компании с 7+ летним опытом в NLP, мы выполнили более 30 проектов по классификации текстов. Свяжитесь с нами для оценки вашей задачи — мы подберём оптимальный стэк и режим обучения. Закажите консультацию, и мы проанализируем ваш датасет.

Типичные результаты

На задачах классификации новостей: 92–96% F1 macro. Классификация обращений клиентов: 88–94%. Мультиметочная классификация: 78–86% Micro F1. Все результаты фиксируются в отчёте и подтверждаются на отложенной выборке.

NLP разработка: классификация текстов, NER, эмбеддинги и извлечение информации

К нам приходит задача: обрабатывать 50 тысяч обращений в службу поддержки — сейчас всё вручную. Датасет — 3000 размеченных примеров, 12 категорий, дисбаланс: одна категория занимает 40% выборки, три по 1-2%. Baseline accuracy — 78%. Звучит неплохо, пока не смотришь на recall по редким классам: 0.31, 0.44, 0.28. Именно эти классы — жалобы и угрозы оттока — важнее всего бизнесу.

Это типичный проект NLP разработки. Проблема не в алгоритме, а в том, что accuracy — не та метрика. Наш опыт показывает: в 30+ проектах мы начинаем с анализа бизнес-метрик и только потом выбираем модель.

Почему accuracy — не та метрика для редких классов?

Accuracy игнорирует дисбаланс. Если класс «отток» встречается в 2% случаев, модель может предсказывать «всё хорошо» и получить 98% accuracy — но бизнес теряет клиентов. Решение: F1 macro (усреднение по всем классам) или weighted F1. Для NER — strict entity F1 (только точные совпадения). Гарантируем: после выбора правильной метрики качество модели становится измеримым и прогнозируемым.

Классификация текста: от BERT до дистилляции

BERT-подобные модели — стандарт для классификации. ruBERT-base или ruBERT-large от DeepPavlov для русского языка. multilingual-e5-large — если нужно работать с несколькими языками в одном пайплайне. XLM-RoBERTa-large — сильный multilingual backbone.

Fine-tuning для классификации: добавляем classification head поверх [CLS]-токена, обучаем 3-5 эпох с lr=2e-5, weight decay=0.01. При дисбалансе — weighted CrossEntropyLoss или focal loss с gamma=2.0. Пишите — покажем code snippet.

Кейс с дисбалансом. Датасет — 3000 примеров, дисбаланс 1:20. Решение: class_weight через sklearn + CrossEntropyLoss. Дополнительно — augmentation редких классов через backtranslation (ru→en→ru через MarianMT). Recall по редким классам вырос с 0.31 до 0.67 при незначительном падении accuracy (76%→74%). Полная NLP разработка под ключ заняла 3 недели.

Дистилляция для production. BERT-large даёт F1 0.89, но inference на CPU — 180ms. Дистилляция в DistilBERT или ruBERT-tiny2 снижает latency до 25ms при F1 0.84. Экспорт в ONNX Runtime даёт дополнительный 1.5-2x. Оценим проект — рассчитаем экономию на инфраструктуре.

Модель F1 macro Latency (CPU) Размер
BERT-large 0.89 180 ms 1.3 GB
DistilBERT 0.84 25 ms 250 MB
ruBERT-tiny2 0.81 12 ms 120 MB
DistilBERT + ONNX 0.84 14 ms 150 MB

NER: распознавание именованных сущностей

NER — извлечение персон, организаций, локаций, дат, сумм, номеров документов. Для общих категорий (PER, ORG, LOC) предобученные модели работают хорошо. Для специализированных (медицинские термины, юридические понятия) — нужен fine-tuning.

Разметка данных. Основная стоимость NER-проекта. Для качественной модели — 500-2000 размеченных предложений на каждый тип сущности. Инструменты: Label Studio (open source) или Prodigy (от создателей spaCy). Формат IOB2 — стандарт.

Архитектура. Token classification поверх BERT: каждому токену метка (B-PER, I-PER, O). spaCy 3.x с transformer pipeline — удобный production-выбор.

Вложенные сущности. Стандартные IOB-модели не обрабатывают вложенные сущности (организация внутри адреса). Для таких задач — span-based NER: SpanBERT или SpERT. Сложнее, но правильно.

Постобработка обязательна. Модель предсказывает токены — нужны нормализованные сущности. Дата — dateparser. Суммы — regex + валидация. Имена — дедупликация через rapidfuzz. Входит в нашу стандартную поставку.

Sentiment Analysis и opinion mining

Бинарная классификация positive/negative работает с BERT из коробки. Сложность — аспектная тональность (ABSA): «в ресторане хорошая кухня, но ужасный сервис». Для ABSA: aspect extraction (NER) + sentiment по каждому аспекту. Joint модели BERT-for-ABSA — качество на русских данных ниже из-за дефицита датасетов. RuSentiment, SentiRuEval — основные ресурсы.

Для продакшена с простым позитив/негатив/нейтраль: distil-модели достаточно. Три класса, balanced датасет, 2000+ примеров — F1 macro 0.82-0.87 за 1-2 дня.

Суммаризация текста

Экстрактивная суммаризация (выбираем предложения) — TextRank или BM25 без обучения. Быстро, не галлюцинирует. Хорошо для длинных документов.

Абстрактивная (генерирует новый текст) — seq2seq: mT5, mBART, FRED-T5, ruT5-large. Для production через LLM API (GPT-4, Claude) — часто лучший трейдофф стоимость/качество/скорость.

Эмбеддинги: векторные представления текста

Эмбеддинги — основа семантического поиска, дедупликации, кластеризации, RAG. Качество критически влияет на downstream задачи.

Модели. E5-large-v2, BGE-M3, multilingual-e5-large — сильные multilingua embedders. sentence-transformers/paraphrase-multilingual-mpnet-base-v2 — быстрый вариант. Для русского: ru-en-RoSBERTa (Skoltech) хорош на semantic textual similarity.

Как оценить качество эмбеддингов? MTEB benchmark — стандарт. Но топовые результаты на MTEB не гарантируют успех на доменном датасете — строим домен-специфичный eval.

Fine-tuning эмбеддингов. Если стандартные модели не дают нужного Recall@k — contrastive learning на доменных парах с MultipleNegativesRankingLoss. 500-2000 пар, 1-3 эпохи — 5-15% прирост Recall@k.

Размерность и хранение. E5-large: 1024 dim, float32 — 4KB на вектор. При 10M документов — 40GB. Квантизация int8 снижает до 10GB. FAISS IVF_PQ — ещё компактнее, но с потерями. Входит в наши рекомендации по деплою.

Извлечение информации

Структурированное извлечение — одна из частых задач. Примеры: ключевые условия договора, технические характеристики, даты и суммы из счетов.

  1. Regex + rule-based. Для ИНН, ОГРН, сумм, дат — надёжнее нейросети. Не требует данных.
  2. NER + постобработка. Для вариативных форматов.
  3. LLM с structured output. GPT-4 / Claude с JSON schema — для сложных документов. Стоимость: ~$0.001-0.01 на документ. Для 10k+ документов/день — считаем экономику.

Гарантируем гибрид: regex/NER для типовых полей + LLM для edge cases. Сертификат доверия: 5 лет на рынке, >30 проектов.

Этапы работы

Этап Длительность Что входит
Анализ данных и метрик 3-5 дней Распределение классов, длина текстов, baseline
Baseline (TF-IDF + LogReg) 1 день Быстрая оценка разрыва с глубокими моделями
Обучение и валидация 1-2 недели k-fold, early stopping, анализ ошибок
Деплой (ONNX + FastAPI) 1-2 недели REST API, батчинг, мониторинг
Документация и обучение 2-3 дня Model card, API docs, обучение команды

Прототип на существующих данных — 1-3 недели. Production-система с CI/CD — 1.5-2.5 месяца. Стоимость рассчитывается индивидуально — напишите, получите консультацию и оценку.

Что входит в работу

  • Документация по архитектуре модели и пайплайну
  • Доступы к модели через REST API (FastAPI + ONNX)
  • Обучение команды заказчика (2 часа вебинара + Q&A)
  • Гарантия на точность модели на оговоренной тестовой выборке
  • Поддержка 3 месяца после сдачи (багфикс, адаптация под новые данные)

Наш опыт

Более 5 лет в NLP, 30+ проектов от классификации до RAG-систем. Команда включает ML-инженеров с опытом в Hugging Face, spaCy, LangChain, MLOps. Используем vLLM, Kubeflow, Weights & Biases — продакшен-стек, а не игрушки. Пишите — оценим проект за 2 дня.