Автор статьи: Рустем Гулиев

IBM Senior DevOps Engineer & Integration Architect. Официальный DevOps ментор и коуч в IBM

Всем привет. Сегодня поговорим про RL в ML с использованием Google RecSim.

Reinforcement Learning (RL) - это подход в машинном обучении, который для того, чтобы максимизировать некоторую целевую функцию, в обучении агентов (испытуемых систем) принимать решение в окружении, использует методы обучения с подкреплением. Основной идеей RL является то, что агент взаимодействует с окружением, выполняя действия и получает обратную связь в виде награды или штрафа за свои действия. Агент стремится научиться выбирать такие действия, которые максимизируют накопленную награду на протяжении времени. RL может использоваться для решения разнообразных задач, таких как управление роботами, игры, автономная навигация и многое другое.

Google RecSim - это библиотека для разработки и экспериментов с рекомендательными системами с использованием обучения с подкреплением. Она предназначена для исследования и разработки рекомендательных систем, которые могут предоставлять рекомендации пользователям, учитывая их предпочтения и интересы, и максимизировать какие-либо ключевые метрики эффективности, такие как клики, конверсии или удовлетворенность пользователями.

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

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

Начнем с азов

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

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

Вместо того, чтобы создавать такую среду с нуля, мы будем использовать пакет Python RecSim от Google.

RecSim позволяет легко определять различные строительные блоки рекомендательной системы и поставляется с предварительно созданными средами.

Установим RecSim с помощью следующей команды pip:

pip install recsim

Мы очищаем вывод терминала, запускаем Python и загружаем библиотеку RecSim со следующим кодом:

clear
python
import recsim
from recsim import environments
from pprint import pprint # for better print formatting

Что такое RecSim?

В документации RecSim на GitHub представлен рисунок, показывающий различные классы, необходимые для создания среды в RecSim. Синие классы относятся к документам, зеленые — к пользователю, а красные — к агенту. Различные прямоугольники представляют условные распределения вероятностей. Таким образом, среду RecSim можно рассматривать как динамическую байесовскую сеть (DBN).

Мы не будем подробно описывать их все. Вместо этого будем полагаться на готовые среды с некоторыми настройками.

Одна из настроек заключается в определении того, сколько документов-кандидатов должен наблюдать агент (NUM_CANDIDATES) и сколько из них следует рекомендовать (SLATE_SIZE).

Запустим следующий код, чтобы определить, что наш агент получит 10 документов-кандидатов, из которых он должен рекомендовать 3:

NUM_CANDIDATES = 10
SLATE_SIZE = 3


RecSim поставляется с тремя готовыми средами:

  • Долгосрочное удовлетворение (которое мы будем использовать в текущей работе) - Long term satisfaction.

  • Эволюция интереса - Interest evolution.

  • Исследование интересов - Interest exploration.

Каждая из этих сред делает разные предположения о поведении пользователя.

Продолжим использовать среду долгосрочного удовлетворения (LTS). Если вас интересуют другие, ознакомьтесь со ссылками на ресурсы в конце этой статьи.

Среда LTS моделирует ситуацию, когда пользователь онлайн-сервиса взаимодействует с элементами контента, которые характеризуются уровнем кликбейтности (по шкале от 0 до 1).

Кликбейтные элементы (еще называют choc) вызывают вовлечение, но приводят к снижению долгосрочного удовлетворения.

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

Задача состоит в том, чтобы сбалансировать эти два фактора и достичь некоторого долгосрочного оптимального компромисса, что является очень распространенным сценарием для систем рекомендаций по контенту.

Давайте инициализируем среду, используя следующий код, и подключим наши ранее определенные NUM_CANDIDATES и SLATE_SIZE:

lts_env = recsim.environments.long_term_satisfaction.create_environment({
    "num_candidates": NUM_CANDIDATES,
    "slate_size": SLATE_SIZE,
    "resample_documents": False
})

Давайте узнаем, как выглядит наша свежая среда.

Запустим следующий код, чтобы вернуть среду в исходное состояние и распечатать начальное наблюдение:

observation_space = lts_env.reset()
pprint(observation_space)

Посмотрите на результат. Это то, что увидит агент в нашей среде.

Вы можете увидеть, что агенту на выбор доступно десять документов. У каждого документа есть одна особенность — кликбейтность (по шкале от 0 до 1).

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

Давайте перезагрузим среду, снова запустив код. Попробуем запустить следующий код несколько раз:

observation_space = lts_env_resample.reset()
pprint(observation_space)

Вы увидите, что документы не меняются; это всегда будет один и тот же список из десяти документов. Это потому, что мы установили для resample_documents значение False при настройке среды. Это означает, что агент всегда будет видеть одни и те же документы для этой среды.

Давайте изменим параметр и разрешим нашей среде выполнять повторную выборку документов, выполнив следующий код:

lts_env_resample = recsim.environments.long_term_satisfaction.create_environment({
    "num_candidates": NUM_CANDIDATES,
    "slate_size": SLATE_SIZE,
    "resample_documents": True
})

Запустим код несколько раз:

observation_space = lts_env_resample.reset()
pprint(observation_space)

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

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

На данный момент мы пару раз перезагружали среду, но фактически не предпринимали в ней никаких действий. Давайте сделаем это сейчас!

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

Какие действия можно предпринять? Давайте выясним это, исследуя пространство действий.

Запустим следующий код:

print(lts_env.action_space)

Как видно из вывода, наш агент сталкивается с пространством действий MultiDiscrete.

Если вы помните, среду мы определили таким образом, что агент может выбирать из 10 документов для 3 разных слотов (шиферов).

И это именно то, что мы здесь наблюдаем — 10 возможных действий для каждого из 3-х слотов.

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

Допустим, мы всегда будем рекомендовать первые три пункта из документов-кандидатов.

RECOMMENDATIONS = [0, 1, 2]

Давайте подключим это к нашей среде и посмотрим, что произойдет.

Можно применить действие, используя метод шага.

observation_0 = lts_env.reset()
observation_1, reward, done, _ = lts_env.step(RECOMMENDATIONS)
pprint(observation_1)

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

Метод шага, который мы только что вызвали в среде, вернул кортеж из четырех элементов (observation, reward, done, info), где:

  • observation— наблюдение агента, включающее в себя особенности состояния пользователя, документы, ответы пользователя.

  • reward— это сумма вознаграждения, возвращенная после предыдущего действия.

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

  • info — словарь, содержащий информацию для отладки/обучения.

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

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

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

done = False
total_reward = 0
step_count = 0
lts_env.reset()
while not done:
  observation, reward, done, _ = lts_env.step(RECOMMENDATIONS)
  total_reward += reward
  step_count += 1

print("Episode has ended after %(a)s steps with an accumulated reward of %(r)d. The latest observation was:" % {'a': step_count, 'r': total_reward})

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

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

Дополнительные источники:

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