![image](https://habrastorage.org/getpro/habr/post_images/119/29f/c52/11929fc524a8961f865bc0b9ef10ab5a.gif)
Сразу стоит отметить, что эта статья — лишь субъективные размышления от том, как может выглядеть и быть реализовано поведение элементов интерфейса, которые знают что делает пользователь в конкретный момент. Размышления, впрочем, подкрепленные небольшим исследованием и реализацией. Поехали.
На заре интернета сайты не искали индивидуальность в стилизации базовых элементов интерфейса. Вариативность была небольшой, поэтому страницы были довольно однородны по своим составляющим.
![image](https://habrastorage.org/getpro/habr/post_images/ef4/e5f/623/ef4e5f623e5542eef0ae83969c631e2e.png)
Каждая ссылка выглядела как ссылка, кнопка как кнопка, а чекбокс как чекбокс. Пользователь знал к чему приведет его действие, потому что имел ясное представление о принципе работы каждого элемента.
Ссылка должна отправить на другую страницу, не важно откуда эта ссылка, из меню навигации или из текста в описании. Кнопка изменит содержимое текущей страницы, возможно, при этом, отправив запрос на сервер. Состояние чекбокса, скорее всего, никак не отразится на содержимом, пока мы не нажмем кнопку какого-нибудь действия, использующего это состояние. Таким образом, пользователю было достаточно посмотреть на элемент интерфейса, чтобы с большой долей вероятности понять как с ним взаимодействовать и к чему это приведет.
![image](https://habrastorage.org/getpro/habr/post_images/867/c01/3a2/867c013a2dc0ef560b7800f2b5d19497.png)
Современные сайты предоставляют пользователю гораздо большее количество загадок. Все ссылки выглядят абсолютно по-разному, кнопки не похожи на кнопки и так далее. Чтобы понять, является ли строчка ссылкой, пользователь должен навести на нее курсор, чтобы увидеть изменение цвета на более контрастный. Чтобы понять является ли элемент кнопкой — также наводим мышь, чтобы увидеть изменение в тоне заливки. С элементами различных меню тоже все сложно, какие-то из них вероятно развернут дополнительное подменю, а какие-то нет, хотя внешне они идентичны.
Однако, мы быстро привыкаем к интерфейсам, которыми пользуемся регулярно, и уже не путаемся в функционале элементов. Большую роль играет и общая преемственность интерфейсов. Взглянув на страницу выше, мы, скорее всего, сразу поймем, что желтая стрелочка с надписью «Найти» — это не просто декоративный элемент, а кнопка, хотя она совсем не похожа на стандартную HTML-ную кнопку. Так что, в плане предсказуемости и индивидуальности большинство ресурсов пришли к стабильному консенсусу, принятому пользователями.
С другой стороны было бы интересно получить интерфейс, заранее рассказывающий пользователю о специфике того или иного элемента либо выполняющий за него часть рутинной работы. Курсор движется в направлении к пункту меню — можно заранее развернуть подменю, тем самым ускорив взаимодействие с интерфейсом, пользователь направляет курсор к кнопке — можно подгрузить дополнительный контент, потребующийся лишь после нажатия. В шапке статьи приведено сравнение стандартного интерфейса (слева) и предиктивного.
Простой визуальный тест показывает, что анализируя скорость курсора и ее производные можно за определенное количество шагов предсказать направление движения и координаты остановки. Учитывая, что события о движении вызываются с частотой постоянной относительно величины ускорения, скорость при приближении к цели уменьшается. Тем самым можно узнать запланированное пользователем действие заранее, что ведет к уже озвученным преимуществам.
![image](https://habrastorage.org/getpro/habr/post_images/2b1/d91/a0e/2b1d91a0e63c8ed700f5b2d33e734681.gif)
Таким образом, проблема включает в себя две задачи: определение будущих координат курсора и определение намерений пользователя (наведение, клик, выделение и так далее). Все эти данные должны быть получены лишь на основе анализа предшествующих значений координат курсора.
![image](https://habrastorage.org/getpro/habr/post_images/c83/a52/26f/c83a5226f6beecbc081608e2564d9db0.png)
Первичной задачей является оценка направления движения курсора, нежели предсказание момента остановки, что является более сложной проблемой. Как оценка параметров зашумленной величины, задача вычисления направления движения может быть решена массой известных способов.
Первый приходящий в голову вариант — фильтр на основе скользящего среднего. Усредняя значения скорости в предыдущие моменты можно получить ее значение в последующие. Предыдущие значения могут быть взвешены по определенному закону (линейному, степенному, экспоненциальному), чтобы усилить влияние ближайших состояний, уменьшая вклад более далеких значений.
Другой вариант — использовать рекурсивный алгоритм, например фильтр частиц. Для оценки скорости курсора фильтр создает множество гипотез о текущем значении скорости, также называемых частицами. В начальный момент эти гипотезы абсолютно случайны, но далее по ходу движения, фильтр убирает недостоверные гипотезы и периодически на этапе перераспределения генерирует новые на основе достоверных. Таким образом из множества гипотез в итоге остаются лишь наиболее близкие к истинному значению скорости.
На примере ниже при движении курсора каждой из частиц для визуализации задается значение радиуса прямо пропорциональное ее весу. Таким образом область с наибольшей концентрацией тяжелых частиц характеризует наиболее вероятное направление движения курсора.
Однако, полученного направления движения недостаточно для определения намерений пользователя. При большой плотности элементов интерфейса путь курсора может пролегать поверх множества из них, что приведет к массе ложных срабатываний алгоритма предсказания. Здесь на помощь приходят методы машинного обучения, а именно рекуррентные нейронные сети.
Координаты движения курсора являются последовательностью сильно коррелирующих значений. При замедлении движения разница между координатами соседних по временной шкале положений уменьшаться от события к событию. В начале движения заметна обратная тенденция —координатные интервалы увеличиваются. Вероятно, с приемлемой точностью, данную задачу можно решить и аналитически, исследовав значения производных на разных участках пути и закодировав порог срабатывания, основываясь на поведении этих значений. Но по своей природе координатная последовательность положений курсора выглядит как набор данных, хорошо вписывающийся в принципы работы сетей долгой краткосрочной памяти.
LSTM сети представляют собой специфичную разновидность архитектуры рекуррентных нейронных сетей, приспособленную к обучению долговременным зависимостям. Этому способствует возможность запоминания информации модулями сети на протяжении целого ряда состояний. Таким образом, сетью может быть выявлены признаки основанные, например на том, как давно началось замедление курсора, что этому предшествовало, как изменялась скорость курсора в начале замедления и так далее. Эти признаки характеризуют конкретные паттерны поведения пользователя при определенных действиях, например клике на кнопку.
![image](https://habrastorage.org/getpro/habr/post_images/c1d/292/68a/c1d29268a2f6fcc49aca687c674f3c06.png)
Таким образом, непрерывно анализируя данные, полученные на выходе фильтра частиц и нейронной сети получаем момент, когда можно, например, показать выпадающее меню, так как пользователь ведет к нему курсор, чтобы открыть его в ближайшую секунду. Выполняя данный анализ по каждому событию от мыши, подходящий момент пропустить сложно.
![image](https://habrastorage.org/getpro/habr/post_images/4dc/a9a/7d8/4dca9a7d8c67435651caf2a9ced2f9b8.png)
Обучение LSTM сети можно провести на наборе данных, полученном в процессе анализа поведения пользователя, выполняющего ряд заданий, призванных выявить его особенности при взаимодействии с интерфейсом: нажать на кнопку, навести курсор на ссылку, открыть меню и так далее. Далее приведен пример срабатывания матрицы предиктивных элементов только на основе фильтра частиц, без нейросетевого анализа.
![image](https://habrastorage.org/getpro/habr/post_images/5af/4e9/a75/5af4e9a754029b708564c49d863c31fd.gif)
Анимация ниже демонстрируют вклад нейронной сети в процесс предсказания поведения пользователя. Ложных срабатываний становится значительно меньше.
![image](https://habrastorage.org/getpro/habr/post_images/040/f0b/461/040f0b46101752fe8c4af497ccce4f06.gif)
В целом, задача сводится к балансирования между двумя величинами — периодом времени между действием и его предсказанием и количеством ошибок (ложных срабатываний и пропусков). Два крайних случая — выбрать все элементы на странице (максимальный период предсказания, огромное число ошибок), либо заставить алгоритм срабатывать уже непосредственно при действии пользователя (нулевой период предсказания и отсутствующие ошибки).
![image](https://habrastorage.org/getpro/habr/post_images/2ce/b2f/358/2ceb2f358f68aa92e55a2c72f38a9cd4.png)
На диаграммах приведены нормированные на максимальные значения результаты, так как скорость пользователя сугубо индивидуальна, а количество ошибок зависит от рассматриваемого интерфейса. Алгоритмы на основе скользящего среднего и фильтра частиц показывают примерно схожие результаты. Второй немного точнее, особенно в случае с использованием тачпада. В конечном счете все эти параметры могут сильно зависеть от конкретных пользователя и устройства.
![image](https://habrastorage.org/getpro/habr/post_images/783/cc9/b94/783cc9b942794228a38f1b7de7523d3f.png)
В завершение небольшой демонстрационный пример предиктивного поведения HTML элементов, далеко не идеальный, но немного раскрывающий суть.
Конечно, в такого рода задачах критически важно соблюсти баланс между функциональностью и предсказуемостью. Если полученное поведение будет непонятно пользователю, вызванное раздражение сводит на нет все усилия. Сложно говорить о том, возможно ли сделать процесс обучения алгоритма незаметным для пользователя, например, в первые сеансы его общения с интерфейсом страницы, чтобы затем уже, используя обученные алгоритмы, заставить элементы интерфейса вести себя предиктивно. В любом случае дополнительное дообучение будет необходимо из-за индивидуальных особенностей каждого человека и это предмет дополнительных исследований.