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

Казалось бы, что между ними нет ничего общего, но это не так. Абсолютно все эти компоненты объединяет одно — языковая модель. Чем выше её качество, тем меньше ошибок будет допущено при вводе текста, а значит, пользователь будет чуточку счастливее.

В этом посте я расскажу, как мы создавали нейроязыковую модель для Яндекс Клавиатуры, ушли от облачных подсказок и научили клавиатуру адаптироваться к приложениям. 

Немного истории

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

Но эту технологию нельзя было применить напрямую в Клавиатуре из-за ограничений, связанных с её спецификой:

  • Размер моделей: модель должна занимать несколько десятков мегабайт, потому что ресурсы мобильного устройства ограничены.

  • Задержка: мы должны успевать обрабатывать запросы в строго отведённое время. Подсказки должны появляться за 200 мс, а реакция на нажатие клавиши должна быть меньше 10 мс.

  • Энергопотребление: нам нельзя сильно нагружать ЦПУ, часто обращаться к сети или тратить много времени на отрисовку.

  • Универсальность: все предыдущие условия должны выполняться на любых смартфонах под всевозможными архитектурами.

Для Спеллера, который работает на наших серверах, ограничения куда более щадящие. В его случае модель в несколько десятков, а то и сотни гигабайт, выглядит совершенно уместно. Поэтому нам пришлось проделать большую работу по сжатию и ускорению моделей, при этом сохранив качество.

Со временем стало понятно, что мы начали потихоньку упираться в предел технологий, некогда породивших Клавиатуру. Спеллер основан на классическом подходе в машинном обучении, который включает в себя n-граммные языковые модели. N-граммные языковые модели строятся на основе статистик, собранных на больших корпусах текстов. Для этого все тексты нарезаются на n-граммы длиной от 1 до n, где n — максимальная длина сниппета или порядок модели. Дальше все одинаковые n-граммы объединяются и им выставляется общее количество. На основе такой большой таблички (n-грамма и её количество), можно аппроксимировать вероятность слова в данном контексте. Например, для триграммной модели вероятность слова в контексте приближается вот такой формулой:

P(w_i|w_{i-2},w_{i-1})=C(w_{i-2},w_{i-1},w_i)/C(w_{i-2},w_{i-1})

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

Но на этом проблемы не исчерпываются, и появляется всё больше вопросов:

  • Как передать дополнительную информацию, например, названия приложений: следует ли дополнительно хранить множество маленьких n-граммных моделей и смешивать их с основной?

  • Как сделать персонализацию: следует ли держать дополнительную персональную n-граммную модель и так же подмешивать её к основной?

  • Что делать с незнакомыми словами в контексте?

  • Как обрабатывать более длинные контексты?

Ответ на большинство этих вопросов уже известен: необходимо использовать более выразительную языковую модель, а именно — нейронную.

Нейроязыковая модель 

Изучаем подходы

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

Для языковой модели Samsung используют обычную LSTM, а для эмбеддингов и финального слоя с softmax — полносвязанные матрицы. Чтобы уменьшить размер полученных моделей, они делают SVD-разложение, используют общие веса для эмбеддингов и для слоя softmax, а затем полученную модель дополнительно квантизуют. В результате размер модели уменьшается почти в 8 раз — до 7,4 Мб. Качество после таких сжатий незначительно проседает, но всё равно остаётся значительно выше предыдущей n-граммной модели. А генерация подсказок укладывается в 10 мс, что очень хорошо.

Статья Samsung ценна ещё тем, что она обозначает основные проблемные места в таких моделях: большой размер эмбеддингов и слоя softmax. Это наблюдение пригодится нам в дальнейшем.

В статье Google про Federated Learning есть очень краткое описание архитектуры: вместо обычной LSTM они используют CIFG, что позволяет сократить количество параметров на 25% и упростить обучение на устройствах. Так же, как и в Samsung, они шарят веса эмбеддингов и слоя softmax. В результате получается очень компактная модель размером всего 1,4 Мб. Но даже при таком маленьком размере, они с большим запасом выигрывают у n-граммной модели. 

Из этих статей становится ясно две вещи:

  • В клавиатуре стоит использовать нейроязыковые модели: они значительно лучше по качеству n-граммных моделей и достаточно быстрые даже для мобильных устройств.

  • Все основные оптимизации связаны с размером эмбеддингов и слоя softmax. Поэтому на них бы и обратим всё своё внимание.

Архитектура

Итоговая архитектура языковой модели в клавиатуре выглядит так:

Архитектура нашей Клавиатуры
Архитектура нашей Клавиатуры

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

Encoder

Здесь мы не стали выдумывать ничего хитрого и взяли стандартную LSTM, которая показала себя с лучшей стороны на фоне других вариантов RNN. Хотя её использование может показаться несколько устаревшим в 2023 году, но в данном случае это полностью оправдано. Пользователи вводят текст последовательно, и LSTM, в силу своей авторегрессионности, нам отлично подходит. 

Для каждого нового токена достаточно пересчитать только одно состояние LSTM. Это то же самое, что выполнить одну достаточно тяжёлую итерацию энкодера. Учитывая ограниченные вычислительные ресурсы мобильных устройств, это достаточно эффективный подход.                 

Embedding

Здесь мы рассмотрели несколько вариантов. 

Стандартный Word Embedding, где каждому слову из закрытого словаря ставится в соответствие свой вектор. Главный недостаток этого подхода — большой размер: размер эмбеддинга × количество слов. Кроме того, такой подход не умеет эффективно обрабатывать незнакомые слова, но его основное преимущество заключается в скорости работы. Именно такой эмбеддинг (с некоторыми оптимизациями) и используют Samsung и Google.

BPE (Byte Pair Encoding). Решает все проблемы стандартного подхода: большой размер и незнакомые слова. Такой подход позволяет эффективно обрабатывать незнакомые слова, так как любое слово может быть разбито на BPE-токены, и так как количество токенов значительно меньше количества слов, то и размер модели получается меньше. 

Однако у BPE есть свой недостаток — недетерминированность. Количество BPE-токенов может отличаться для разных слов, что приводит к разному количеству итераций для энкодера. Это сильно усложняет работу с кэшами и делает время работы крайне непредсказуемым.

CHAR-CNN (свёрточные эмбеддинги). Основная идея была взята из статьи Character-Aware Neural Language Models и звучит примерно так: «Давайте строить эмбеддинги на побуквенных свёртках». Этот подход позволяет модели учитывать информацию о структуре слова на уровне символов. 

Каждое слово разбивается на буквы, затем для каждой буквы считаются их эмбеддинги, после чего мы прогоняем эти побуквенные эмбеддинги через ряд свёрток с различными размерами фильтров. В такой постановке, фильтр размера 1 для свёрток представляет собой рассмотрение только побуквенных униграмм, а фильтр размера 2 — побуквенных биграмм. Полученные выходы объединяются для формирования финального эмбеддинга слова.

Такой подход позволяет учесть информацию о внутренней структуре слова и захватить контекстуальные зависимости на уровне символов. Это особенно полезно при работе с незнакомыми словами и с языками с богатой морфологией, таким как русский. 

 

Схема свёрточных эбмеддингов из статьи Character-Aware Neural Language Models
Схема свёрточных эбмеддингов из статьи Character-Aware Neural Language Models

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

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

Сводная таблица эмбеддингов
Сводная таблица эмбеддингов

Softmax-слой

Помимо того, что Softmax-слой много весит, он и работает дольше всех компонент из-за большого размера словаря. Можно попробовать использовать BPE, но так же, как и в эмбеддингах, это портит свойство детерминированности: мы можем сгенерировать как один токен, так и пять. 

Оказывается, что у этой проблемы есть очень элегантное решение — Differentiated Softmax. Идея очень простая: самым частотным словам выделять проекции побольше, а менее частотным — поменьше. Это убивает сразу двух зайцев: размер и количество вычислений становятся заметно меньше. 

Влияние на другие компоненты клавиатуры

Так как мы решили заменить такую важную составляющую клавиатуры как языковую модель, то это должно повлиять и на остальные компоненты. Однако на деле это затронуло только динамическую сетку. Для автокорректа и классического свайпа всё осталось, как прежде, потому что здесь мы используем Сatboost-классификатор. Языковая модель здесь выступает только в роли фичи.

А с динамической сеткой дела обстоят уже поинтереснее. Раз уж мы отказались от n-граммной модели, которая хранится в побуквенном префиксном дереве в пользу пословной нейромодели, то теперь предсказывать следующую букву становится невозможным. Чтобы исправить эту ситуацию, мы обучили ещё один небольшой декодер для побуквенного предсказания слов, используя те же эмбеддинги и энкодер, что и в пословной модели. 

Пословные и побуквенные модели
Пословные и побуквенные модели

Производительность и качество

Таким образом, на двух простых и красивых идеях (использовать побуквенные свёртки для эмбеддингов и выдавать более частотным словам большие проекции в Softmax-слое) мы решили все наши проблемы. 

Итоговые размеры и скорости у нас получились примерно следующими:

  • Embedding: 1 МБ — 2 мс;

  • Encoder: 5 МБ — 5 мс;

  • Softmax: 12 МБ — 20 мс. 

По итоговым замерам скорость работы новой языковой модели оказалась хоть и медленнее классической n-граммной на 30%, но она укладывалась в наш порог в 200 мс с большим запасом.

В клавиатурах есть две основные оффлайн-метрики:

  • Saved keys — процент сэкономленных нажатий клавиш пользователем с учётом подсказок.

  • Predicted words — процент верно угаданных слов по пустому префиксу вводимого слова. 

С использованием нейроязыковой модели показатель saved keys вырос с 43,1% до 47,5% (+4.3 п.п), а predicted words — с 16,2% до 19,0% (+2,8 п.п).

Это много или мало? Ответить на этот вопрос можно так: наша большая облачная модель, которая превосходит по размеру нейромодель более чем в 200 раз, выдаёт качество хуже. Однозначно это хорошо, только не для облачной модели: от неё нам пришлось отказаться. Возможно, когда-нибудь мы снова вернёмся к ней.  

По онлайн-метрикам тоже всё хорошо:

  • Доля символов из саджеста выросла на 7% (основная метрика подсказок).

  • Количество отмен автокорректа упало на 2% (основная метрика автокорректа).

  • Количество полезных символов на нажатие увеличилось на 1% (интегральная метрика хорошести ввода).

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

App-Specific подсказки

Как было сказано в самом начале, проблем у классической языковой модели было много:

  • Незнакомые слова в контексте: например, опечатки при вводе предыдущих слов. Для обычной n-граммной модели опечатка в контексте это почти тоже самое, что и разрыв контекста.

  • Длинные контексты: n-граммные модели ограничены порядком и им сложно держать в памяти начало длинной фразы.

  • Сложность использования дополнительной информации, которая отличается от текстовой. Например, идентификатор приложения, где вводится текст, может очень сильно влиять на предсказания.

И если мы, внедрив новую нейромодель, решили первые две проблемы за счёт CNN-эмбеддингов и энкодера, то почему бы сразу не решить и третью проблему?

Начнём с того, что люди пишут совершенно разные тексты в разных приложениях. И исходя из этого хочется уметь показывать разные подсказки. Например, подсказка «привет» совершенно уместна по префиксу «п» в мессенджерах, но в приложениях, связанных с картами или контактами, мы хотим увидеть «проспект» или «Паша». 

Оказывается, что с новой моделью это сделать очень просто: достаточно подмешивать дополнительный эмбеддинг для приложений. Вот и всё! 

В итоге мы получили приличный прирост по метрике saved keys в разных группах приложениях:

  • food: 37% → 52% (+15 п.п),

  • contacts: 22% → 28% (+6 п.п),

  • geo: 38% → 45% (+7 п.п),

  • market: 40% → 48% (+8 п.п).

 А по онлайн-замерам мы получаем дополнительные 2% символов из саджеста. 

Примеры по префиксу «п». Думаю, ни для кого не составит сложности определить, в каких приложениях это было написано
Примеры по префиксу «п». Думаю, ни для кого не составит сложности определить, в каких приложениях это было написано

Подведём итог

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

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

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


  1. berng
    02.08.2023 09:48
    +2

    А где CIFG брали, сами писали? На чем сеть реализовывали?


    1. LB_K Автор
      02.08.2023 09:48
      +4

      На стадии экспериментов что-то более сложное, чем LSTM, GRU, писали сами.

      Т.е. CIFG писали сами, но в CIFG особого смысла не оказалось: обычный LSTM из коробки проще и такого же качества.

      Обучение у нас написано на keras + tensorflow, инференс - на tflite.


  1. it-navy
    02.08.2023 09:48
    +4

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


    1. LB_K Автор
      02.08.2023 09:48
      +4

      Спасибо! Возможно, когда-нибудь напишем более подробно про наш нейросвайп.


  1. iAMDiver
    02.08.2023 09:48

    Ваша клавиатура просто замчательна, но вот с чем я столкунлся (извините, что не по теме NN). На S23 Ultra я весьма часто пользую DeX-mode (это когда я подключаю телефон через док станцию к монитору и работаю в режиме ПК). И если у меня по умолчанию в обычном режиме выбрана ваша клавиатура, то при переходе в режим ПК и подключении физической клавиатуры - она у меня не работает. Из-за этого приходится по умолчанию использовать Samsung Keyboard, которой в части кирилических текстов до вашей весьма далеко.


    1. LB_K Автор
      02.08.2023 09:48

      Спасибо! Обязательно попробуем разобраться с этой проблемой.


      1. wilerat
        02.08.2023 09:48

        Попробовал вашу клавиатуру. Замечательные подсказки.

        Однако при использовании dex mode (Samsung S10) к сожалению нажатие cmd+space не меняет язык.

        Приходится перевыбирать клавиатуру от Samsung и обратно.


  1. timaaos
    02.08.2023 09:48

    Никогда не юзал свайп в клавиатурах, но свайп в Яндекс.Клавиатуре очень удобный.


    1. LB_K Автор
      02.08.2023 09:48

      Спасибо!


    1. IvanPetrof
      02.08.2023 09:48
      +1

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

      P.s. Всякими автонаборами тоже не пользуюсь.как-то не срослось...


      1. LB_K Автор
        02.08.2023 09:48

        По нашим замерам, скорость ввода свайпом в 2-3 раза быстрее обычного побуквенного ввода.

        К сожалению, чтобы научиться писать свайпом нужно затратить некоторое время, но это время очень быстро окупается.


        1. IvanPetrof
          02.08.2023 09:48
          +3

          в 2-3 раза быстрее

          Я так быстро думать не умею)). скорость набора, в моём случае, не является бутылочным горлышком.


    1. ganzmavag
      02.08.2023 09:48

      Всегда его юзал, после ухода собственно Swype, которым и пользовался, долго искал замену и реально у Яндекса сейчас, по моим ощущениям, лучший вариант (по крайней мере для русского языка). Причем так было не всегда, поначалу работал плохо, я даже им сюда возмущенные комменты писал, типа Яндекс столько лет с русским языком работает, у вас просто обязан быть хороший свайп. С какой-то версии сильно шагнули вперед (причем еще до нейросвайпа, с ним я кстати принципиальной разницы не заметил).


      1. LB_K Автор
        02.08.2023 09:48

        Спасибо за отзыв!


  1. destroyer
    02.08.2023 09:48
    +7

    Ваша клавиатура часто за меня выполняет задания в dualingo. Слово за словом подсказывает всё предложение. Что конечно круто для неё. Но получается что клавиатура учится, а я не учусь.


    1. LB_K Автор
      02.08.2023 09:48

      В настройках можно отключить подсказки, а потом вернуть обратно. Но это, конечно, не очень удобно.


    1. Hait
      02.08.2023 09:48

      Skyeng на Гугл клавиатуре как-то отключает подсказки и свайпы


  1. DoMoVoY
    02.08.2023 09:48
    +7

    Можно ли настроить вашу клавиатуру, чтобы она ну совсем не ходила в сеть? даже за gif и в яндекс на сервера.


    1. LB_K Автор
      02.08.2023 09:48

      Такой настройки на данный момент нет.

      Походы в сеть нужны, как минимум, для загрузки и обновлений словарей.


    1. Dare95
      02.08.2023 09:48
      +1

      В настройках отключить подключение к мобильной и вай фай сетям.


  1. ganzmavag
    02.08.2023 09:48

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

    Сейчас неприятный баг наблюдаю, такое ощущение что с новой моделью появился. Клавиатура иногда слова с ошибками стала предлагать в подсказках. Раньше никогда такого не было.


    1. LB_K Автор
      02.08.2023 09:48

      Можете написать в форму обратной связи клавиатуры?

      Мы обязательно рассмотрим и постараемся разобраться.

      Спасибо.


      1. ganzmavag
        02.08.2023 09:48

        Да, если ещё раз попадётся, постараюсь заскринить.


  1. NooneAtAll3
    02.08.2023 09:48

    Вот бы ещё эта сетка сразу при установке клавы появлялась...


    При полной блокаде от интернета сразу после установки, приложение подсказок совсем не выдаёт. Даже на английском


    1. LB_K Автор
      02.08.2023 09:48

      При полной блокаде от интернета сразу после установки, приложение подсказок совсем не выдаёт. Даже на английском

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

      Спасибо!


      1. Akr0n
        02.08.2023 09:48

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


        1. LB_K Автор
          02.08.2023 09:48

          Да, словари не встроены в клавиатуру.

          Можно зайти в "настройки -> языки" и посмотреть, какие словари уже скачаны.

          Но без интернета уже скачанные словари не будут обновляться.


          1. Akr0n
            02.08.2023 09:48

            Как я понял из статьи, тут уже обученная языковая модель, а зачем ещё что-то обновлять?


            1. LB_K Автор
              02.08.2023 09:48

              Мы постоянно переобучаем и улучшаем языковую модель.


  1. ivodopyanov
    02.08.2023 09:48

    Зачем использовать LSTM или GRU, когда уже давно есть SRU и SRU++?


    1. LB_K Автор
      02.08.2023 09:48

      Мы брали те архитектуры, которые использовались в статьях от гугла и самсунга.

      В планах есть попробовать и другие архитектуры, такие как: QRNN, RWKV, RetNet.

      Добавлю SRU в этот список. Спасибо.

      Если честно, то веры в другие архитектуры особой нет: трансформер выдает примерно такое же качество, как и LSTM. А лучше трансформера что-то придумать сложно.