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

Первоначально опубликовано в Taboola Engineering Blog 4 сентября 2019 г.

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

Функции истории пользователей сильно различаются у разных пользователей; например, одна популярная функция - это категории пользователей - темы, которые пользователь ранее читал. Пример такого списка может выглядеть так - {«спорт», «бизнес», «новости»}. Каждое значение в этих списках является категориальным, и в них есть несколько записей, поэтому мы называем их мульти-категориальными функциями. Многозначные списки могут иметь любое количество значений для каждого пользователя - это означает, что наша модель должна обрабатывать как очень длинные списки, так и полностью пустые списки (для новых пользователей).

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

Быть средним

Продолжим с категориями пользователей. Как мы можем превратить список неизвестной длины в функцию фиксированной длины, которую мы можем использовать? Самый наивный, но очень популярный подход - это просто усреднение. Предположим, у нас есть отдельное вложение длины d для каждой категории, так что каждое значение списка сопоставляется с вектором. Мы можем использовать средний пул - усреднять все категории пользователя и каждый раз получать вектор длины d. Более формально, если это вложение j -го слова из всего N слов, тогда средний пул пользователя может быть записан как:

Но это далеко не идеально. Усреднение может работать хорошо, но когда список очень длинный, коэффициент 1 / N дает небольшой конечный результат; суммирование разных указывающих векторов может привести к тому, что они уравняют друг друга, а деление на N значительно ухудшает ситуацию (если вы пришли из опыта физики / EE, это должно вызвать тревогу, так как это очень похоже на то, что происходит при некогерентной интеграции). Это плохо, поскольку вредит пользователям с более длинными векторами истории, о которых у нас больше всего информации и которые могут дать более точные прогнозы. Из-за этого мы (и люди из Alibaba research) удаляем фактор 1 / N и используем объединение сумм в пользовательских историях, чтобы гарантировать, что предсказуемые клиенты не окажут незначительного влияния. в сети.

Тяжелая атлетика, наивно

При усреднении всем элементам автоматически присваивается одинаковый вес. Мы этого хотим? Рассмотрим пользователя со следующим списком: {"футбол", "теннис", "баскетбол", "мода"}. Наивное их усреднение сделает упор на спортивные категории и пренебрегает «модой». Для некоторых это было бы правильно - людей, которые больше интересуются спортом, чем модой; для других - нет. Что мы могли бы сделать, чтобы дать разным категориям разные веса, чтобы лучше отображать пользователей?

Лучшим решением будет использование некоторой другой информации, например: количества прошлых просмотров (показов), которые пользователь имел для каждой категории. Поскольку количество раз, когда пользователь прочитал статью, коррелирует с его личным вкусом, мы можем использовать эти подсчеты как веса и делать средневзвешенное объединение. Это поможет нам различать, например, следующих двух очень разных пользователей:

Пользователь 1 = {«футбол»: 2, «теннис»: 2, «баскетбол»: 2, «мода»: 200}

Пользователь 2 = {"футбол": 2, "теннис": 2, "баскетбол": 2, "мода": 2}

Вы обращаете внимание?

Можем ли мы сложить еще больше информации? Скажем, у нас есть не только количество просмотров каждого пользователя в каждой категории, но и такие вещи, как последний раз, когда пользователь читал статью этой категории, или CTR (рейтинг кликов) этой категории на пользователя (то есть, во сколько раз больше пользователь прочитал статью из этой категории из всех случаев, когда эта категория была представлена). Как лучше всего объединить эти функции без бесконечного A / B-тестирования алгоритмов? Ответ, конечно же, заключается в том, чтобы использовать возможности машинного обучения и применить дополнительный уровень, задача которого - выводить вес для каждого значения. Иногда это называют «слоем внимания». Этот слой имеет все необходимые данные, доступные в качестве входных данных, и изучает идеальные веса для усреднения значений. Давайте посмотрим на пример подсети внимания для единственного значения категории - «теннис». Предполагая, что встраивание для «тенниса» равно {5,0.3,5,1,4.2}, и пользователю рекомендовали 10 статей о теннисе, но щелкнули только один раз, последовательность действий можно проиллюстрировать следующим образом:

Слой внимания вычисляет вес для встраивания каждой категории. В приведенном выше примере расчетный вес равен 0,2. Предположим, этого пользователя также интересовала «мода», и уровень внимания выводит 0,5 для этой категории, окончательный расчет для встраивания истории этого пользователя будет 0,2 * emb (теннис) + 0,5 * emb (мода). Эти уровни внимания узнают, как использовать всю имеющуюся у нас информацию об истории этого пользователя для расчета весов для каждой категории.

Большой! Но можем ли мы сделать это еще лучше?

Представляем: архитектура Deep Interest

Помните, мы пытаемся предсказать, сможет ли определенный пользователь нажать на определенное объявление, так почему бы не добавить в плагин некоторую информацию о текущем предложенном объявлении? Допустим, у нас есть пользователь, история которого - {«теннисное снаряжение», «детская одежда»}, а наша текущая реклама - теннисная ракетка. Конечно, мы хотели бы иметь больший вес на теннисном оборудовании и пренебречь детской частью в этом конкретном случае. Наш предыдущий уровень внимания предназначен только для моделирования интересов пользователя и не учитывает взаимодействия между личными предпочтениями пользователя и рекламой, предложенной ему на этапе объединения. Мы хотели бы связать это взаимодействие пользователя с рекламой до того, как произойдет объединение, чтобы вычислить вес, который более специфичен для текущей рекламы, представленной пользователю.

Для этого мы можем использовать архитектуру Deep Interest, работу, которая была представлена ​​на конференции KDD2018 группой исследователей Alibaba. Если мы вернемся к нашей предыдущей иллюстрации, теперь мы можем добавить встраивание для конкретной рекламы, предложенной пользователю:

В Deep Interest рекламные функции используются в качестве входных данных для нейронной сети дважды: один раз в качестве входных данных для самой модели (предоставляя информацию о том, приведет ли показ этой рекламы пользователю к клику), и второй раз в качестве входных данных. вход для слоя встраивания истории пользователя (настройка внимания истории пользователя к частям, относящимся к данному конкретному объявлению).

У нас также могут быть разные способы создания вложений для рекламных функций: один - использовать один и тот же вектор встраивания для обоих случаев, упомянутых выше, а другой вариант - создать два разных вложения для двух случаев. Первый вариант дает вложениям вдвое больше градиентов во время обучения и может лучше сходиться. В последнем случае у нас может быть два разных внедрения (скажем, вложение размера 12 для всей сети и вложение размера 3 для слоя веса истории пользователя). Более короткое встраивание может сэкономить время выполнения, но добавляет больше параметров в процесс обучения и может увеличить время обучения. Выбор между двумя вариантами, конечно, зависит от конкретного варианта использования.

Резюме

Многокатегориальные функции имеют решающее значение для прогнозирования различных общих проблем, особенно при попытке предсказать будущее поведение пользователя (например, клики, конверсии) на основе прошлых взаимодействий. Есть простые способы сделать это, но для лучшего прогнозирования мы рекомендуем архитектуру Deep Interest, поскольку она позволяет динамически взвешивать вектор признаков в соответствии с соответствующим контекстом. Эта архитектура довольно проста в реализации и дает отличные результаты для многих рекомендательных систем. Давай, попробуй!