
Когда нужно классифицировать текст, дефолтный ход в 2026 — взять предобученный трансформер и дообучить. TF‑IDF воспринимается как музейный экспонат: работал в эпоху до BERT, сейчас не всерьез. Обычно этот выбор никто не проверяет на своих данных, потому что и так понятно, кто победит.
Мы решили проверить. Взяли одну задачу, один корпус, одну метрику и прогнали три подхода подряд: счетный бейзлайн на TF‑IDF, сверточную сеть TextCNN и дообученный русский энкодер. Считали не только качество, но и стоимость — время обучения и скорость предсказания на обычном процессоре.
Короткий вывод: на этой задаче счетный бейзлайн обучается за три секунды и по честной метрике держится вровень с трансформером, который дообучался восемь минут. А трансформер, взятый по стандартному рецепту, сначала вообще проиграл — и проиграл поучительно.
Дальше — как так вышло и что из этого забрать себе.
Данные и методика
Корпус — отзывы об организациях с Яндекс Карт (d0rj/geo-reviews-dataset-2023, лицензия MIT, 500 тысяч записей). Из него собран воспроизводимый учебный срез: чистка по длине текста и валидности рейтинга, дедупликация по нормализованному тексту до разбиения (иначе один отзыв утечет и в train, и в test), стратифицированный сплит с фиксированным seed.
Задача — тональность в три класса. Метка берется из рейтинга: 1–2 негатив, 3 нейтрально, 4–5 позитив. Это дешевая разметка из готового поля, и у нее есть цена, к которой мы еще вернемся.
Вот важное свойство данных, которое определит весь результат: классы сильно несбалансированы.
Выборка | Всего | Позитив | Негатив | Нейтрально |
|---|---|---|---|---|
train | 41 998 | 36 199 (86%) | 3 963 (9%) | 1 836 (4%) |
test | 9 002 | 7 758 | 850 | 394 |
Позитива — 86 процентов. Нейтральных отзывов — четыре. Это типичная картина для отзывов: люди чаще пишут, когда все хорошо, а тройка встречается редко и звучит невнятно.
Из‑за перекоса метрику надо выбирать аккуратно. Accuracy тут почти бесполезна: модель, которая всегда отвечает «позитив», получит 86 процентов и ничему не научится. Поэтому основная метрика — macro‑F1: она усредняет F1 по трем классам с равным весом, и провал на редком классе сразу виден. Она же меняться не должна между моделями, иначе сравнение нечестное.
Чтобы бой был честным, всем моделям, где это возможно, включили балансировку классов: линейной модели через class_weight, сверточной и трансформеру — через веса в функции потерь. Разбиение, seed и тестовая выборка у всех одни и те же.
Все прогоны — на процессоре (12 ядер, без GPU). Это осознанно: если задача решается на CPU, стоимость решения становится частью ответа.
Бейзлайн: TF‑IDF и линейная модель
Начинаем с нижней границы. TF‑IDF превращает текст в разреженный вектор частот слов, поверх — логистическая регрессия с балансировкой классов. Векторизатор обучается только на train, иначе тестовые тексты влияли бы на признаки — тихая утечка.
Две конфигурации: только униграммы и униграммы вместе с биграммами.
TF‑IDF на униграммах: macro‑F1 0.664, обучение 1.5 секунды.
TF‑IDF с биграммами: macro‑F1 0.671, обучение 2.8 секунды, 107 тысяч признаков.
Биграммы добавляют совсем немного и стоят почти столько же. Инференс — сотые доли секунды на тысячу текстов. Линейная модель еще и объяснима: можно посмотреть слова с наибольшим весом по каждому классу и поймать, что модель выучила названия конкретных сетей вместо тональности.
TextCNN: обучаемые векторы
Следующий шаг сложности — своя нейросеть. TextCNN учит эмбеддинги слов с нуля и собирает из них признаки сверткой по n‑граммам. Модель на 3.8 миллиона параметров, три эпохи, тоже с балансировкой классов.
Результат неожиданный: macro‑F1 0.624 — ниже обоих вариантов TF‑IDF. При этом обучение заняло 166 секунд, в шестьдесят раз дольше бейзлайна.
Причина простая. Обучаемым эмбеддингам нужно много данных, чтобы обогнать честный счет частот. Сорок тысяч отзывов — мало: словарь получается разреженным, и на редких классах свертка выучивает меньше, чем линейная модель на явных признаках. Сложнее не значит лучше.
Дообученный трансформер: сначала ловушка
Теперь тяжелая артиллерия. Берем cointegrated/rubert-tiny2 — компактный русский энкодер на 29 миллионов параметров, который дообучается на процессоре за разумное время. Стандартный рецепт: две эпохи, обычная кросс‑энтропия, без ручной балансировки.
И вот тут первый сюрприз:
accuracy 0.923 — выше всех в статье;
macro‑F1 0.574 — ниже всех, кроме константы.
Как одна модель может быть одновременно лучшей и худшей? Смотрим на F1 по классам и все становится ясно: по классу «нейтрально» F1 равен нулю. Трансформер ни разу не предсказал нейтральную тональность. Он выучил негатив и позитив, а редкий класс просто выбросил — и почти ничего не потерял в accuracy, потому что нейтральных всего четыре процента.

Это и есть ловушка. Если смотреть только на accuracy, дообученный трансформер — чемпион. Стоит посмотреть на честную метрику, и оказывается, что он собрал высокий процент, сдав самый трудный класс.
Возникает справедливый вопрос: но бейзлайнам‑то мы дали балансировку, а трансформеру нет. Нечестно. Согласны — поэтому дали.
Дообученный трансформер: честный бой
Тот же rubert‑tiny2, но теперь с весами классов в функции потерь и с третьей эпохой — ровно те же условия, что у бейзлайна, плюс запас времени.
macro‑F1 0.675;
класс «нейтрально» ожил: F1 поднялся с нуля до 0.30.
Балансировка вернула редкий класс, и модель наконец обошла TF‑IDF. На 0.004. То есть в пределах шума.

Вот теперь можно свести все в одну таблицу.
Сводная таблица
Модель | macro‑F1 | accuracy | F1 “нейтр.” | Обучение | Инференс, с/1000 | Параметры |
|---|---|---|---|---|---|---|
Константа (частый класс) | 0.309 | 0.862 | 0.00 | – | – | 0 |
TF‑IDF 1-gram + logreg | 0.664 | 0.879 | 0.32 | 1.5 с | 0.01 | ~0.1M |
TF‑IDF 1–2-gram + logreg | 0.671 | 0.891 | 0.32 | 2.8 с | 0.03 | ~0.3M |
TextCNN | 0.624 | 0.848 | 0.28 | 166 с | 0.82 | 3.8M |
rubert‑tiny2 (без весов, 2 эп.) | 0.574 | 0.923 | 0.00 | 293 с | 0.92 | 29M |
rubert‑tiny2 (с весами, 3 эп.) | 0.675 | 0.912 | 0.30 | 478 с | 1.18 | 29M |
Два лучших результата почти совпали: 0.671 у бейзлайна и 0.675 у трансформера. Разница между ними — цена.
Качество против стоимости
Это главный график для нас. По горизонтали — время обучения на процессоре в логарифмическом масштабе, по вертикали — качество.

Левый верхний угол — мечта: дешево и хорошо. Там сидит TF‑IDF. Трансформер того же качества стоит правее на два порядка.
Цифры ребром:
обучение: 2.8 секунды против 478, разница примерно в 170 раз;
предсказание: 0.03 против 1.18 секунды на тысячу текстов, около 40 раз;
размер: 0.3 против 29 миллионов параметров.
За все это — плюс 0.004 macro‑F1. На потоке в миллион текстов в сутки разница в инференсе превращается в реальные деньги на железо, а прирост качества по‑прежнему теряется в шуме.
Как это читать на своей задаче
Вывод не в том, что трансформеры не нужны. Вывод в том, что порядок действий обратный привычному.
Начинать с бейзлайна. TF‑IDF с логистической регрессией собирается за минуты и сразу дает честную планку. Без нее непонятно, улучшает ли тяжелая модель хоть что‑то или просто дороже.
Смотреть на правильную метрику. На несбалансированных данных accuracy убаюкивает. macro‑F1, F1 по редкому классу и матрица ошибок показывают, что происходит на самом деле.
Считать стоимость как часть результата. Строка сравнения без времени обучения и инференса не дает принять решение о внедрении.
Тянуться за трансформером, когда бейзлайн уперся. Если планка взята и ее не хватает — тогда есть смысл в дообучении, длинном контексте, переносе знаний из претрейна. Но это осознанный следующий шаг, а не первый рефлекторный.
Что осталось за кадром
Честно опишу границы этого сравнения
Модель маленькая. rubert‑tiny2 — компактный энкодер под CPU. Модель побольше (rubert‑base, многоязычные e5) скорее всего оторвется от бейзлайна заметнее. Но и стоимость вырастет еще, а тезис про «сначала померь цену» станет только крепче.
Задача простая. Тональность отзывов — короткие тексты и явные сигналы, где счетные признаки сильны. На NER, разрешении кореференции или семантическом поиске расклад другой, и там трансформер отрывается по‑настоящему.
Разметка дешевая. Тональность из рейтинга — это прокси. Человек с рейтингом 3 мог написать вполне позитивный отзыв. Часть путаницы на классе «нейтрально» — не вина моделей, а свойство меток.
Мы не выжимали максимум. Ни у одной модели не крутили гиперпараметры до предела. Цель была не рекорд, а честное сравнение при равных условиях.
Если вы гоняете классификацию текста в проде — соберите свой бейзлайн и свой график «качество против стоимости». Вполне возможно, что скучная линейная модель уже дает вам девяносто процентов результата за один процент цены.
Весь пайплайн из этой статьи — от сборки среза до дообученного энкодера и сводной таблицы — собирается руками с нуля в нашем курсе «NLP на практике: от токенов до трансформеров и эмбеддингов». Разборы того, где инженерные решения ломаются и что реально работает в проде, выходят в канале @torch_lab.

