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

На связи Антон Дворкович. Вы можете помнить меня по постам о тонкостях чувашского языка и технологиях машинного перевода. Почему сегодня я рассказываю о Клавиатуре? Потому что в её основе — технологии и опыт Яндекс.Переводчика. Именно они помогают пользователям меньше ошибаться и печатать быстрее.

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

Чуть-чуть предыстории


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

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

Подсказки и автокорректор


Когда-то давно подсказки Клавиатуры для исправления набранных слов базировались на опенсорсном компоненте из проекта AOSP. Работало шустро, просто, но не особо точно для русского языка. Затем с этой задачей пришли к нам — команде машинного перевода. На тот момент мы уже собрали внушительный Опечаточник для своих задач (снаружи он отчасти известен под названием Яндекс.Спеллер). Эта штука умеет предлагать вероятное продолжение слова, используя технологии машинного обучения. Звучит как готовое решение, но нет.

Мобильная версия накладывает много ограничений, в том числе на объём памяти и вычислительные мощности. Для масштаба: исходный Опечаточник — сервис на сотнях серверов, с тяжёлыми моделями и огромными базами данных. Для нас же было важно уместить всё на смартфоне, выполнять операции локально, не отправляя введённые символы на сервер. Чтобы всё это заработало, мы ужали модели до единиц мегабайт и ускорили их применение.

Понятно, что никакая локальная логика пока что не сравнится в качестве с серверной, поэтому мы решили дать возможность включить в настройках и «облачные» подсказки. Причём так, чтобы они работали, только когда пользователь подключён к Wi-Fi (экономим трафик и батарейку). Пришлось повозиться с HTTP/2, чтобы тормоза сети не приводили к тормозам подсказок. Всё работает бесшовно: если «дозвониться» до сервера за отведённое время (150 мс) не удалось, включатся локальные подсказки.

Свайп


Считается, что свайп — это лучший способ набирать текст быстро. Отчасти это так: по нашим данным, опытные пользователи с помощью свайпа могут набирать сообщения до двух с половиной раз быстрее, чем с использованием точечного ввода. На самом деле можно вводить текст даже быстрее. А именно — так, как задумано человеческой природой: голосом. Для этого мы добавили в Клавиатуру распознавание речи с помощью SpeechKit, но, будем честны, свайп пока что популярнее, поэтому его мы тоже решили поддержать.

Но не всё так просто. Поддержка свайпа далась нам с трудом. Первый подход и вовсе оказался неуспешным: кривые, сопоставленные словам, распределены не нормально (по Гауссу), а в общем-то очень хаотично, поэтому нужно применять хитрые модели, чтобы понимать намерения пользователей. В итоге мы добавили свайп в Яндекс.Клавиатуру, но для этого потребовалось собрать дополнительно около двух миллионов примеров с помощью Толоки. Мы даже начали экспериментировать с нейросетями, хотя в итоге победил старый добрый noisy channel.

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

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

Динамическая сетка


Эта идея основана на двух тезисах.

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

Во-вторых, если человек набирает «ПРИВЕ», то вряд ли следующим касанием он попытается нажать Ь. Мы можем незаметно изменить размеры хитбоксов букв так, чтобы у буквы Т площадь оказалась больше, чем у мягкого знака.

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



Следите за мягким знаком: при наборе слова «привет» ему соответствует совсем маленький участок. В слове «приятель» — существенно больший.

То же самое, но в динамике:



Каждый введённый символ подаётся на вход двум моделям.

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

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

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

Языковой и геометрической моделью дело не ограничивается. Допустим, человек вводит «Пр». Что это может значить? Если он пишет кому-то сообщение, скорее всего, он собирается написать «Привет», а если хочет что-то найти на карте — «Проспект». Поэтому динамическая сетка подстраивается под специфику приложения, в котором она открыта. Для этого есть четыре режима: общий, карты, электронные магазины и мессенджеры.

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

Заключение


С помощью динамической сетки удаётся исправлять около 60% промахов гладко и незаметно для пользователей. Как следствие, пользователи начинают считать, что это именно они наловчились так метко попадать в клавиши, и подвох замечают только при отключении Клавиатуры. Иногда это даже обидно :)

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

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