Обучение с подкреплением основано на том, как люди/животные учатся методом проб и ошибок.

Представьте, что вы учите собаку сидеть, когда вы говорите «Сидеть», и вставать, когда вы говорите «Встать».

· Сначала собака не знает, что делать. Итак, вы начинаете с того, что пробуете разные вещи.

· Вы говорите «Сидеть» и осторожно переводите собаку в сидячее положение.

· Если собака садится, вы даете ей лакомство в качестве поощрения.

· Если собака стоит, вы не даете угощение.

· Собака начинает усваивать, что сидение, когда вы говорите «Сидеть», приводит к вознаграждению.

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

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

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

Теперь вам дано ограниченное количество изменений, и вы хотите максимизировать свой выигрыш.

Если кто-то скажет вам, какая машина даст вам максимальную награду, вы просто потянете печень этой машины и получите максимальную награду.

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

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

Что может быть интуитивным подходом?

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

Здесь есть 2 стратегии:

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

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

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

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

Как оценить свои действия?

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

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

Где K — номер игрового автомата, действие, выбранное на временном шаге «t», — «At», соответствующее вознаграждение — «Rt». P – вероятность вознаграждения при выполнении действия "a".

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

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

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

Это известно как метод выборочного среднего.

Затем вы можете обновить ожидаемые вознаграждения, используя приведенную ниже формулу приращения.

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

Существует задача найти правильный баланс между изучением новых вариантов и использованием наилучшего из известных на данный момент вариантов в процессах принятия решений. Это называется дилеммой Исследуй — Используй.

Как получить лучшее из обоих миров?

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

· На каждом этапе агент выбирает между разведкой и эксплуатацией.

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

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

Гиперпараметр ε!

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

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

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

import numpy as np

class Bandit:
    def __init__(self, num_arms):
        self.num_arms = num_arms
        self.true_rewards = np.random.normal(0, 1, self.num_arms)
        
    def get_reward(self, action):
        true_reward = self.true_rewards[action]
        reward = np.random.normal(true_reward, 1)
        return reward

class EpsilonGreedyAgent:
    def __init__(self, num_arms, epsilon):
        self.num_arms = num_arms
        self.epsilon = epsilon
        self.Q = np.zeros(self.num_arms)
        self.action_counts = np.zeros(self.num_arms)
        
    def choose_action(self):
        if np.random.random() < self.epsilon:
            # Explore: Choose a random action
            action = np.random.randint(self.num_arms)
        else:
            # Exploit: Choose action with maximum estimated value
            action = np.argmax(self.Q)
        return action
    
    def update_estimates(self, action, reward):
        self.action_counts[action] += 1
        self.Q[action] += (reward - self.Q[action]) / self.action_counts[action]

# Initialize bandit environment and agent
num_arms = 5
epsilon = 0.1
bandit = Bandit(num_arms)
agent = EpsilonGreedyAgent(num_arms, epsilon)

num_steps = 1000

# Run the epsilon-greedy agent
for step in range(num_steps):
    action = agent.choose_action()
    reward = bandit.get_reward(action)
    agent.update_estimates(action, reward)

# Print the estimated values for each action
print("Estimated Action Values:")
for i in range(num_arms):
    print(f"Action {i+1}: {agent.Q[i]}")

На данный момент мы узнали о проблемах с MAB (многорукий бандит). Они также известны как проблемы обучения с подкреплением без сохранения состояния, когда мы выполняем только одно действие (вытаскиваем бандита) и получаем вознаграждение.

Что делать, если действие отличается в разных ситуациях (состояние)?

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

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

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

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

import numpy as np

class ContextualBandit:
    def __init__(self, num_actions, num_features):
        self.num_actions = num_actions
        self.num_features = num_features
        self.theta = np.random.normal(0, 1, size=(num_actions, num_features))
        
    def get_reward(self, action, context):
        theta_a = self.theta[action]
        context = np.array(context)
        prob = np.exp(np.dot(theta_a, context))
        prob /= np.sum(np.exp(np.dot(self.theta, context)))
        reward = np.random.binomial(1, prob)
        return reward

class ContextualBanditAgent:
    def __init__(self, num_actions, num_features):
        self.num_actions = num_actions
        self.num_features = num_features
        self.theta_hat = np.zeros((num_actions, num_features))
        self.action_counts = np.zeros(num_actions)
        
    def choose_action(self, context):
        context = np.array(context)
        action_probs = np.exp(np.dot(self.theta_hat, context))
        action_probs /= np.sum(action_probs)
        action = np.random.choice(self.num_actions, p=action_probs)
        return action
    
    def update_estimates(self, action, context, reward):
        context = np.array(context)
        self.action_counts[action] += 1
        step_size = 1 / self.action_counts[action]
        self.theta_hat[action] += step_size * (reward - np.dot(self.theta_hat[action], context)) * context

# Initialize contextual bandit environment and agent
num_actions = 3
num_features = 5
bandit = ContextualBandit(num_actions, num_features)
agent = ContextualBanditAgent(num_actions, num_features)

num_steps = 1000

# Run the contextual bandit agent
for step in range(num_steps):
    context = np.random.normal(0, 1, num_features)  # Random context for each step
    action = agent.choose_action(context)
    reward = bandit.get_reward(action, context)
    agent.update_estimates(action, context, reward)

# Print the estimated theta values for each action
print("Estimated Theta Values:")
for i in range(num_actions):
    print(f"Action {i+1}: {agent.theta_hat[i]}")

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

Ссылка:

Обучение с подкреплением: введение - Ричард С. Саттон и Эндрю Дж. Барто