Мы часто рассказываем о технологиях и библиотеках, которые зародились и сформировались в Яндексе. На самом деле мы ничуть не реже применяем и развиваем сторонние решения.

Сегодня я расскажу сообществу Хабра об одном из таких примеров. Вы узнаете, зачем мы научили нейросеть BERT находить опечатки в заголовках новостей, а не воспользовались готовой моделью, почему нельзя взять и запустить BERT на нескольких видеокартах и как мы использовали ключевую особенность этой технологии — механизм attention.



Задача


Яндекс.Новости — это сервис, собирающий новости подключённых к нам изданий. Это не только наиболее читаемые и цитируемые новости СМИ на главной, но и тематические разделы или даже персональные подборки со всех изданий. В любом случае это тысячи сайтов и миллионы заголовков, из которых машина каждые несколько минут должна сформировать подборку.

Именно машина, потому что мы никогда не вмешиваемся в картину дня: не добавляем туда новости вручную, не удаляем их оттуда (как бы сильно этого ни хотелось), не правим заголовки. Вокруг этого уже было сломано множество копий. У полностью алгоритмического подхода есть и плюсы, и минусы. Что-то мы можем улучшить с помощью технологий, что-то нет. Даже если в заголовках есть орфографические ошибки и опечатки — мы не исправляем их. Мы добавили фавиконки изданий к заголовкам, чтобы было понятно, откуда взяты новости. Отчасти это помогло, но мы не смирились с ошибками и стали искать способ избавиться от них, не внося правки в текст.

Если нельзя исправить ошибку, то можно натренировать машину находить заголовки, которые из-за ошибок не годятся для топа. Тем более что Яндекс специализируется на русской морфологии с тех времён, когда и название-то ему ещё не придумали. Казалось бы, берём нейросеть — и дело в шляпе.

Инструменты


У Яндекса есть технология Спеллер для поиска и исправления ошибок. Благодаря библиотеке машинного обучения CatBoost Спеллер может расшифровывать искажённые до неузнаваемости слова («адникасниеи» > «одноклассники») и учитывать контекст при поиске опечаток («скучать музыку» > «скачать музыку»). Может показаться, что Спеллер идеален для нашей задачи, но нет.

Спеллер (который внутри известен как поисковый опечаточник) уже на уровне архитектуры заточен для решения совершенно другой задачи: помогать пользователям восстановить корректную форму запроса. В Поиске не так важно, верно ли подобран падеж, проставлена заглавная буква или запятая. Там важнее по поисковому запросу «Хамингуэль» догадаться, что человек имел в виду Хемингуэя.

Ошибки в заголовках делают относительно грамотные люди, которые вряд ли напишут «Хамингуэль». А вот неверное согласование («рейс задержалась»), пропущенные слова («молодой человек пытался автомобиль») и лишние заглавные буквы («Президент Банка») — обычное дело. Наконец, бывает формально верное предложение «В Пскове отремонтирую улицу Горького», к которому нормальный опечаточник не придерётся (ну а вдруг это обещание автора?), — но это очевидно испорченный новостной заголовок. Кроме того, в Новостях задача ставилась не такая, как в Поиске: не исправить опечатки и ошибки, а обнаружить их.

У нас были и другие варианты, например модели, основанные на DSSM (если интересно, то об этом подходе мы коротко рассказывали в посте про алгоритм Палех), но и они имели ограничения. Например, не идеально учитывали порядок слов.

В общем, готовые инструменты или не подходили для нашей задачи, или были ограниченными. А значит, надо создавать свой собственный — тренировать свою модель. И это был хороший повод поработать с технологией BERT, которая стала доступна разработчикам в 2018 году и демонстрировала впечатляющие результаты.

Знакомство с BERT


Основная проблема современных задач обработки естественного языка (NLP) — найти достаточно размеченных людьми примеров, чтобы обучить нейросеть. Если вам нужен рост качества, то обучающая выборка должна быть очень большой — миллионы и миллиарды примеров. При этом задач в NLP много и все они разные. Собрать данные в подобных объёмах под каждую задачу долго, дорого, а зачастую невозможно. Даже для крупнейших компаний в мире.

Но есть вариант обойти эту проблему — с помощью обучения в два этапа. Сначала долго и дорого на огромном корпусе в миллиарды слов нейросеть учат структуре языка (это pre-training). Потом сеть быстро и дёшево подкручивают под конкретную задачу — например, для разделения отзывов на плохие и хорошие (это fine-tuning). Хватит каких-нибудь 10 тысяч примеров, размеченных в Толоке.

На этой идее и основана технология BERT (Bidirectional Encoder Representations from Transformers). Сама идея не нова и применялась раньше, но есть существенное отличие. Transformer — это такая архитектура нейросетки, которая позволяет учитывать весь контекст сразу, включая другой конец предложения и причастный оборот где-нибудь в середине. И в этом её отличие от предыдущих модных архитектур, которые учитывали контекст. Например, у нейросети LSTM длина контекста — в лучшем случае десятки слов, а тут все 200.

На GitHub доступен исходный код на TensorFlow и даже предобученная универсальная модель на 102 языка, от русского до волапюка. Бери, казалось бы, решение из коробки — и получай результат немедленно. Но нет.

Оказалось, что универсальная модель на русских текстах показывала существенно меньшее качество, чем английская модель, бьющая рекорды на английских текстах (что, согласитесь, логично). На русских текстах она проигрывала нашим внутренним моделям на DSSM.

Окей, предобучиться можно и самим — к счастью, русских текстов и опыта в машинном обучении у Яндекса хватает. Но есть нюанс. Обучаться надо год!

Дело в том, что BERT заточена под тензорные процессоры Google (TPU), поэтому из коробки умеет работать только с одной видеокарточкой (GPU). И распараллелить в лоб с помощью какого-нибудь horovod нельзя: перебрасывать с карты на карту 400 мегабайт данных на каждом шаге очень дорого, распараллеливание станет бессмысленным. Что делать?

Оптимизация


Начали искать любые идеи и решения, способные значительно ускорить дело. В первую очередь обратили внимание на то, что каждое число в нашей модели занимало 32 бита памяти (стандартный float для чисел в компьютере). Вроде бы мало, но когда у вас 100 миллионов весов, то это критично. Такая точность нам не везде была нужна, поэтому мы решили частично перевести числа в 16-битный формат (это то, что называется mixed precision training).

Попутно с помощью множества напильников и костылей прикрутили XLA-компиляцию, опираясь на тогда ещё сырой коммит NVIDIA. Благодаря этому наши карточки NVIDIA Tesla V100 (небольшой сервер из них стоит как квартира в недорогом районе Москвы) смогли в полной мере раскрыть свой потенциал за счёт 16-битной арифметики на Tensor Cores.

Нас интересовали только русскоязычные заголовки, но мультиязыковая модель, которую мы взяли за основу, обучена на сотне языков, включая даже искусственный волапюк. Слова всех языков, переведённые в векторное пространство, хранились в модели. Причём взять и просто так удалить их оттуда нельзя — пришлось попотеть, чтобы сократить размер словаря.

И ещё кое-что. Если ты учёный и твой компьютер стоит под столом, то ты можешь всё там перенастроить под каждую конкретную задачу. А в реальном вычислительном облаке, где тысячи машин сконфигурированы одинаково, достаточно проблематично, например, пересобирать ядро под каждую новую фичу TensorFlow. Поэтому мы потратили немало усилий на то, чтобы собрать такие версии пакетов, которые и умеют все новомодные фишки, и не требуют радикального обновления и перенастройки видеокарт в облаке.

В общем, выжимали все соки везде, где могли. И у нас получилось. Год превратился в неделю.

Обучение


Собрать правильный датасет — обычно самая трудная часть работы. Сначала мы учили классификатор на трёх миллионах заголовков, размеченных толокерами. Вроде бы много, но только 30 тысяч из них — с опечатками. Где взять ещё примеров?

Мы решили поглядеть, какие заголовки исправляют сами СМИ. Таких за всю историю Яндекс.Новостей набралось больше 2 миллионов. Бинго! Хотя радоваться было рано.

Оказалось, что очень часто СМИ переделывают заголовки не из-за ошибок. Выяснились новые детали — и редактор заменил одну правильную формулировку другой. Поэтому мы ограничились только исправлениями с разницей между версиями до трёх букв (хотя и здесь некоторый шум остался: было «нашли двоих» — стало «нашли троих»). Так мы набрали миллион опечаток. Обучились сначала на этой большой подборке с шумом, а затем на небольшой толокерской разметке без шума.

Качество


В подобных задачах принято измерять точность и полноту. В нашем случае точность — это доля правильных вердиктов среди всех вердиктов об ошибке в заголовке. Полнота — доля заголовков с ошибками, которые мы поймали, среди всех заголовков с ошибками. И то и другое в идеальном мире должно стремиться к 100%. Но в задачах машинного обучения эти показатели, как правило, конфликтуют. То есть чем сильнее выкручиваем точность, тем больше падает полнота. И наоборот.

В нашем предыдущем подходе на базе DSSM мы уже добились точности 95% (то есть 5% ложноположительных вердиктов). Это уже достаточно высокий показатель. Поэтому мы решили сохранить такой же уровень точности и посмотреть, как с помощью новой модели изменится полнота. И она подскочила с 21 до 78%. И это определённо успех.

Здесь можно было бы поставить точку, но я помню про обещание рассказать об attention.

Нейросеть с фломастером


Принято считать, что нейросеть — это такой чёрный ящик. Мы подаём что-то на вход и получаем что-то на выходе. А почему и как — загадка.

Это ограничение призваны обойти интерпретируемые нейронные сети. BERT — одна из них. Её интерпретируемость заключается в механизме attention. Грубо говоря, в каждом слое нейросетки мы повторяем один и тот же приём: смотрим на соседние слова с разным «вниманием» и учитываем взаимодействие с ними. Например, когда нейросеть обрабатывает местоимение «он», то «внимательно смотрит» на существительное, к которому «он» относится.

Картинка ниже показывает разными оттенками красного, на какие слова «смотрит» токен, который накапливает информацию обо всём заголовке для финального слоя-классификатора. Если опечатка в слове — attention подсвечивает его, если слова рассогласованы — то оба (и, возможно, зависимые от них).



В этом месте, кстати, можно разглядеть возможности нейросетей в полный рост. Ни на одном этапе обучения наша модель не знает, где именно находится опечатка в примере: она знает только, что весь заголовок неправильный. И всё равно она выучивает, что «школа на 1224 мест» писать неправильно из-за несогласованного числительного, — и подсвечивает конкретно цифру 4.

На опечатках мы не остановились и начали применять новый подход не только для поиска ошибок, но и для определения устаревших заголовков. Но это уже совсем другая история, с которой мы надеемся вернуться на Хабр в ближайшем будущем.

Полезные ссылки для тех, кто хочет углубиться в тему


Комментарии (10)


  1. YMA
    12.12.2019 12:42
    +1

    «пятизвездночный» — пропущено специально для привлечения внимания к статье? :)


    1. BarakAdama Автор
      12.12.2019 13:05

      100% полноты достичь невозможно, НО конкретно в этом случае причина в другом. Механизм attention подсвечивает те ошибки, которые стали решающими. Грамматическая рассогласованность нескольких слов — более сильный сигнал, чем ошибка в одном слове.


  1. CrazyElf
    12.12.2019 16:07

    Интересно ещё, почему «ресторан для птиц» не вызвал интереса. Либо такие примеры были в обучении, либо нейросеть действительно ловит только рассогласования, а смысл ей по барабану? Что вообще странно — бывают же и грамматически корректные фразы без всякого смысла.


    1. BarakAdama Автор
      12.12.2019 20:27

      СМИ часто используют необычные комбинации слов для привлечения внимания читателей, поэтому обученная на них нейросеть не удивляется таким вещам.

      Что касается смысла, то сетка понимает, что грамматически верная фраза «В Пскове отремонтирую улицу Горького» — это некорректный по смыслу новостной заголовок.


  1. algotrader2013
    12.12.2019 20:39

    Как оцениваете влияние BERT на SEO?
    Ведь, с одной стороны, уверен, можно горы автогенеренного говна найти по частоте и распределениям срабатывания аттеншена.
    А, с другой, черти сейчас тоже перевооружатся, и начнут сами в автогенераторы мусорного контента добавлять контроль качества перед отгрузкой на сайт


    1. ideological
      14.12.2019 12:33

      В SEO-компаниях сейчас очень низкие зарплаты. Набирают не творческих людей, а шаблонных исполнителей, им не до машинного обучения.


      А частные кудесники такого уровня (которые умеют в нейросети с пользой) — спам обычно не фигачат, любят эстетику.


      1. algotrader2013
        14.12.2019 18:57

        А как же сетки сайтов? Я не из этой отрасли, но бахвальство некоторых товарищей в интервью на ютубе, которые утверждают, что у них компании на пару десятков человек со своим движком — сайтогенератором, мимикрирующим под вордпресс, и тысячами говносайтов, не выглядит абсолютно беспочвенным.


  1. rinnaatt
    13.12.2019 13:22

    Интересно, существует ли такая сеть или алгоритм, в который достаточно "загрузить" набор правил нужного языка и он будет работать?


    1. algotrader2013
      13.12.2019 14:48

      Так уже ж ушли от этого лет 30 назад. Изначально так и хотели все порешать. Чтобы комп сам по чётко заданной структуре правил все вывел. Сильный ии где-то там.


    1. BarakAdama Автор
      13.12.2019 15:04

      Если смотреть на это со стороны машинного перевода, то от такого подхода как раз и ушли:

      В основе таких систем лежали словари и правила, которые и определяли качество перевода. Профессиональные лингвисты годами работали над тем, чтобы вывести всё более подробные и всеохватывающие ручные правила (по сути, регулярные выражения). Работа эта была столь трудоемкой, что серьезное внимание уделялось лишь наиболее популярным парам языков, но даже в рамках них машины справлялись плохо. Живой язык – очень сложная система, которая плохо подчиняется правилам, постоянно развивается и практически каждый день обогащается новыми словами или конструкциями. Ещё сложнее описать правилами соответствия двух языков. Одни и те же слова могут иметь совершенно разные переводы в зависимости от контекста… Единственный способ машине постоянно адаптироваться к изменяющимся условиям и учитывать контекст – это учиться на большом количестве актуальных текстов и самостоятельно выявлять закономерности и правила.


      (с) habr.com/ru/company/yandex/blog/317910