
- Рейтинг Литрес:4.8
Полная версия:
Кевин Корт Нейросети Основы
- + Увеличить шрифт
- - Уменьшить шрифт
Пример реализации Q-обучения на Python с использованием библиотеки `numpy` для обучения агента в простой среде, такой как "Cliff Walking" из OpenAI Gym.
Задача в приведенном коде заключается в обучении агента, который должен найти оптимальный путь по "обрыву" (Cliff Walking) в окружении OpenAI Gym. В этой задаче агент должен научиться перемещаться по сетке от начальной позиции до цели, избегая падения с обрыва.
Описание задачи Cliff Walking
В задаче "Cliff Walking" агент перемещается по сетке размером 4x12. Начальная позиция агента находится в левом нижнем углу, а цель – в правом нижнем углу. Ячейки между начальной позицией и целью представляют собой обрыв. Если агент попадает в обрыв, он получает большое отрицательное вознаграждение и возвращается в начальную позицию.
Цель агента – найти оптимальный путь от начальной позиции до цели, минимизируя общие штрафы (отрицательные вознаграждения) и избегая обрыва.
Основные компоненты задачи
1. Окружение:
– `CliffWalking-v0` представляет собой сетку размером 4x12.
– Агент начинает в ячейке (3, 0) и должен достичь ячейки (3, 11).
2. Действия:
– Агент может двигаться в четырех направлениях: влево, вправо, вверх и вниз.
3. Награды:
– Каждое движение агента дает штраф -1.
– Падение с обрыва приводит к большому штрафу (например, -100) и возвращает агента в начальную позицию.
4. Конечное состояние:
– Когда агент достигает цели в ячейке (3, 11), эпизод заканчивается.
Примерный процесс выполнения задачи
1. Инициализация:
– Создаем окружение и инициализируем параметры Q-обучения.
– Инициализируем Q-таблицу нулями.
2. Цикл обучения:
– В каждом эпизоде агент начинает в начальной позиции и выполняет действия, выбираемые согласно ε-жадной стратегии.
– Обновляем Q-таблицу на основе полученного опыта (текущее состояние, действие, вознаграждение и следующее состояние).
– Эпизод продолжается, пока агент не достигнет цели или не упадет в обрыв.
3. Тестирование:
– После завершения обучения тестируем агента, чтобы увидеть, как он выполняет задачу, используя обученную политику (выбор действий с максимальными Q-значениями).
Этот код демонстрирует, как агент учится принимать решения на основе опыта взаимодействия со средой, чтобы достичь цели с минимальными потерями.
Для начала нужно установить OpenAI Gym, если он еще не установлен:
```bash
pip install gym
```
Пример кода
```python
import numpy as np
import gym
# Создаем окружение "CliffWalking-v0"
env = gym.make('CliffWalking-v0')
# Параметры Q-обучения
alpha = 0.1 # Скорость обучения
gamma = 0.99 # Коэффициент дисконтирования
epsilon = 0.1 # Вероятность выбора случайного действия
# Инициализация Q-таблицы
q_table = np.zeros((env.observation_space.n, env.action_space.n))
def choose_action(state):
if np.random.uniform(0, 1) < epsilon:
return env.action_space.sample() # Случайное действие
else:
return np.argmax(q_table[state]) # Действие с максимальным Q-значением
def update_q_table(state, action, reward, next_state):
best_next_action = np.argmax(q_table[next_state])
td_target = reward + gamma q_table[next_state][best_next_action]
td_error = td_target – q_table[state][action]
q_table[state][action] += alpha td_error
# Основной цикл обучения
num_episodes = 500
for episode in range(num_episodes):
state = env.reset()
done = False
while not done:
action = choose_action(state)
next_state, reward, done, _ = env.step(action)
update_q_table(state, action, reward, next_state)
state = next_state
# Тестирование агента после обучения
state = env.reset()
done = False
total_reward = 0
while not done:
action = np.argmax(q_table[state])
state, reward, done, _ = env.step(action)
total_reward += reward
env.render()
print(f"Total reward after training: {total_reward}")
env.close()
```
Объяснение кода
1. Инициализация окружения и параметров:
– Создаем окружение `CliffWalking-v0` из OpenAI Gym.
– Устанавливаем параметры Q-обучения: `alpha` (скорость обучения), `gamma` (коэффициент дисконтирования) и `epsilon` (вероятность выбора случайного действия).
2. Инициализация Q-таблицы:
– Q-таблица инициализируется нулями. Она будет хранить Q-значения для всех пар «состояние-действие».
3. Выбор действия:
– Используем ε-жадную стратегию для выбора действия. С вероятностью `epsilon` выбирается случайное действие, иначе выбирается действие с максимальным Q-значением для текущего состояния.
4. Обновление Q-таблицы:
– Вычисляем целевое значение (TD target), состоящее из текущего вознаграждения и максимального Q-значения для следующего состояния.
– Обновляем Q-значение для текущей пары «состояние-действие» с использованием разности TD (TD error).
5. Основной цикл обучения:
– В каждом эпизоде агент взаимодействует с окружением, выполняя действия и обновляя Q-таблицу на основе полученного опыта.
– Процесс повторяется до тех пор, пока агент не достигнет конечного состояния.
6. Тестирование агента:
– После завершения обучения агент тестируется в окружении, используя политику, основанную на максимальных Q-значениях.
– Выводится общее вознаграждение, полученное агентом.
Этот пример демонстрирует базовый алгоритм Q-обучения и его применение в простой среде. Q-обучение эффективно используется в задачах обучения с подкреплением, где агент должен принимать решения, основываясь на опыте взаимодействия со средой.
Случайные блуждания (Методы Монте-Карло)
Методы Монте-Карло (Monte Carlo methods) представляют собой класс алгоритмов, которые используют случайные блуждания для оценки стратегий на основе долгосрочных наград. В отличие от Q-обучения, методы Монте-Карло не требуют знания модели среды. Вместо этого, они основываются на многократных симуляциях взаимодействия агента со средой, в ходе которых вычисляются средние значения наград. Каждая симуляция представляет собой эпизод, включающий последовательность состояний, действий и полученных вознаграждений до достижения конечного состояния. После завершения эпизода метод Монте-Карло обновляет оценки значений состояний или действий, используя накопленные награды. Это позволяет агенту улучшать свою политику, опираясь на накопленный опыт.
Рассмотрим пример использования методов Монте-Карло для обучения агента в задаче "Blackjack" из OpenAI Gym. В этой задаче агент учится играть в блэкджек, используя эпизодическую оценку долгосрочных наград.
Описание задачи и игры "Blackjack"
"Blackjack" (или "21") – это популярная карточная игра, в которой игрок соревнуется против дилера. Цель игры – набрать количество очков, как можно ближе к 21, но не больше этого числа. В OpenAI Gym среда "Blackjack-v1" симулирует эту игру и предоставляет интерфейс для обучения агентов.
Правила игры
1. Карты и их значения:
– Номера карт от 2 до 10 имеют номинальную стоимость.
– Валет, Дама и Король (карты с картинками) имеют стоимость 10 очков.
– Туз может считаться как 1 очко или как 11 очков, в зависимости от того, что лучше для руки.
2. Начало игры:
– И игрок, и дилер получают по две карты.
– Одна из карт дилера открыта, а другая скрыта.
3. Действия игрока:
– Hit: Игрок берет еще одну карту.
– Stand: Игрок прекращает набор карт и передает ход дилеру.
4. Ход дилера:
– Дилер открывает свою скрытую карту.
– Дилер должен продолжать брать карты (hit), пока сумма его очков не станет 17 или больше.
5. Определение победителя:
– Если сумма очков игрока превышает 21, он проигрывает (bust).
– Если игрок и дилер остаются в игре (не превышают 21), выигрывает тот, у кого сумма очков ближе к 21.
– Если у дилера сумма очков превышает 21, дилер проигрывает (bust).
– Если сумма очков у игрока и дилера одинакова, игра заканчивается вничью (push).
Задача агента – научиться принимать оптимальные решения (hit или stand) в различных состояниях игры, чтобы максимизировать свое общее вознаграждение (выигрыши).
Установка необходимых библиотек
Для начала нужно установить OpenAI Gym, если он еще не установлен:
```bash
pip install gym
```
Пример кода
```python
import numpy as np
import gym
from collections import defaultdict
# Создаем окружение "Blackjack-v1"
env = gym.make('Blackjack-v1')
# Параметры Монте-Карло
num_episodes = 500000
gamma = 1.0 # Коэффициент дисконтирования
# Функция для выбора действия на основе ε-жадной стратегии
def epsilon_greedy_policy(state, Q, epsilon=0.1):
if np.random.rand() < epsilon:
return env.action_space.sample()
else:
return np.argmax(Q[state])
# Инициализация Q-таблицы и возвратов
Q = defaultdict(lambda: np.zeros(env.action_space.n))
returns_sum = defaultdict(float)
returns_count = defaultdict(float)
# Основной цикл обучения
for episode in range(num_episodes):
state = env.reset()
episode = []
done = False
while not done:
action = epsilon_greedy_policy(state, Q)
next_state, reward, done, _ = env.step(action)
episode.append((state, action, reward))
state = next_state
# Обновление Q-таблицы на основе эпизодических возвратов
G = 0
for state, action, reward in reversed(episode):
G = gamma G + reward
if not any((s == state and a == action) for s, a, _ in episode[:-1]):
returns_sum[(state, action)] += G
returns_count[(state, action)] += 1
Q[state][action] = returns_sum[(state, action)] / returns_count[(state, action)]
# Тестирование агента после обучения
def test_policy(Q, num_episodes=10000):
wins = 0
draws = 0
losses = 0
for _ in range(num_episodes):
state = env.reset()
done = False
while not done:
action = np.argmax(Q[state])
state, reward, done, _ = env.step(action)
if reward > 0:
wins += 1
elif reward == 0:
draws += 1
else:
losses += 1
print(f"Wins: {wins / num_episodes:.2f}, Draws: {draws / num_episodes:.2f}, Losses: {losses / num_episodes:.2f}")
test_policy(Q)
```
Объяснение кода
1. Инициализация окружения и параметров:
– Создаем окружение `Blackjack-v1` из OpenAI Gym.
– Устанавливаем количество эпизодов для обучения и коэффициент дисконтирования `gamma`.
2. Функция для выбора действия:
– Используем ε-жадную стратегию для выбора действия. С вероятностью `epsilon` выбирается случайное действие, иначе выбирается действие с максимальным Q-значением для текущего состояния.
3. Инициализация Q-таблицы и возвратов:
– Q-таблица инициализируется нулями с использованием `defaultdict`.
– `returns_sum` и `returns_count` используются для хранения сумм и счетчиков возвратов для каждой пары «состояние-действие».
4. Основной цикл обучения:
– В каждом эпизоде агент взаимодействует с окружением, выполняя действия и записывая последовательность состояний, действий и наград.
– После завершения эпизода вычисляется общий возврат `G` путем обратного прохода по эпизоду и обновляется Q-таблица для уникальных пар «состояние-действие».
5. Тестирование агента:
– После завершения обучения агент тестируется в окружении, используя политику, основанную на максимальных Q-значениях.
– Выводится статистика побед, ничьих и поражений.
Этот пример демонстрирует использование методов Монте-Карло для оценки стратегий на основе эпизодических возвратов в задаче блэкджека. Агент учится принимать оптимальные решения, основываясь на накопленном опыте из большого числа эпизодов.
Deep Q-Learning
Deep Q-Learning – это расширение Q-обучения, которое использует глубокие нейронные сети для представления и обновления Q-значений. Это позволяет агентам принимать более сложные и информированные решения в средах с высоким уровнем сложности и большим количеством состояний и действий. В традиционном Q-обучении Q-таблица используется для хранения значений всех возможных пар «состояние-действие», что становится неосуществимым в задачах с большой размерностью. Deep Q-Learning решает эту проблему, используя нейронные сети для аппроксимации функции Q. Агент обучается обновлять параметры нейронной сети, минимизируя разницу между предсказанными и реальными Q-значениями, что делает возможным обучение на больших наборах данных и в сложных средах. Один из ключевых компонентов Deep Q-Learning – это опытный буфер (experience replay), который позволяет агенту запоминать и повторно использовать предыдущие опыты для обучения, что повышает стабильность и эффективность процесса обучения.
Обучение с подкреплением применяется в робототехнике, играх, управлении ресурсами и других задачах, где требуется разработка стратегий и принятие решений в динамических и неопределённых средах.
Описание задачи
Рассмотрим задачу "CartPole" из OpenAI Gym. В этой задаче агент управляет тележкой, на которой закреплен вертикально стоящий столб. Цель агента – балансировать столб, не позволяя ему упасть, двигая тележку влево или вправо.
Описание среды "CartPole"
Состояния:
– Положение тележки (отрицательное значение – тележка слева от центра, положительное – справа).
– Скорость тележки.
– Угол отклонения столба от вертикального положения.
– Угловая скорость столба.
Действия:
– Двигать тележку влево.
– Двигать тележку вправо.
Награды:
– Агент получает награду +1 за каждый шаг, пока столб остается вертикально.
Конечное состояние:
– Эпизод заканчивается, если столб отклоняется слишком сильно от вертикального положения или тележка выходит за пределы поля.
Пример кода для Deep Q-Learning
Для реализации DQN мы будем использовать библиотеку PyTorch для создания и обучения нейронной сети.
Установка необходимых библиотек
Для начала нужно установить OpenAI Gym и PyTorch, если они еще не установлены:
```bash
pip install gym torch
```
Пример кода
```python
import gym
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
from collections import deque, namedtuple
import random
# Определение архитектуры нейронной сети
class DQN(nn.Module):
def __init__(self, state_size, action_size):
super(DQN, self).__init__()
self.fc1 = nn.Linear(state_size, 24)
self.fc2 = nn.Linear(24, 24)
self.fc3 = nn.Linear(24, action_size)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
return self.fc3(x)
# Параметры обучения
env = gym.make('CartPole-v1')
state_size = env.observation_space.shape[0]
action_size = env.action_space.n
batch_size = 64
gamma = 0.99 # Коэффициент дисконтирования
epsilon = 1.0 # Вероятность случайного действия
epsilon_min = 0.01
epsilon_decay = 0.995
learning_rate = 0.001
target_update = 10 # Как часто обновлять целевую сеть
memory_size = 10000
num_episodes = 1000
# Определение памяти для опыта
Transition = namedtuple('Transition', ('state', 'action', 'next_state', 'reward'))
memory = deque(maxlen=memory_size)
# Инициализация сети и оптимизатора
policy_net = DQN(state_size, action_size)
target_net = DQN(state_size, action_size)
target_net.load_state_dict(policy_net.state_dict())
target_net.eval()
optimizer = optim.Adam(policy_net.parameters(), lr=learning_rate)
# Функция для выбора действия
def select_action(state, epsilon):
if random.random() < epsilon:
return env.action_space.sample()
else:
with torch.no_grad():
return policy_net(torch.tensor(state, dtype=torch.float32)).argmax().item()
# Функция для обновления памяти
def store_transition(state, action, next_state, reward):
memory.append(Transition(state, action, next_state, reward))
# Функция для обучения сети
def optimize_model():
if len(memory) < batch_size:
return
transitions = random.sample(memory, batch_size)
batch = Transition(zip(transitions))
state_batch = torch.tensor(batch.state, dtype=torch.float32)
action_batch = torch.tensor(batch.action).unsqueeze(1)
reward_batch = torch.tensor(batch.reward, dtype=torch.float32)
non_final_mask = torch.tensor(tuple(map(lambda s: s is not None, batch.next_state)), dtype=torch.bool)
non_final_next_states = torch.tensor([s for s in batch.next_state if s is not None], dtype=torch.float32)
state_action_values = policy_net(state_batch).gather(1, action_batch)
next_state_values = torch.zeros(batch_size)
next_state_values[non_final_mask] = target_net(non_final_next_states).max(1)[0].detach()
expected_state_action_values = reward_batch + (gamma next_state_values)
loss = nn.functional.mse_loss(state_action_values.squeeze(), expected_state_action_values)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# Основной цикл обучения
for episode in range(num_episodes):
state = env.reset()
total_reward = 0
done = False
while not done:
action = select_action(state, epsilon)
next_state, reward, done, _ = env.step(action)
total_reward += reward
if done:
next_state = None
store_transition(state, action, next_state, reward)
state = next_state
optimize_model()
if epsilon > epsilon_min:
epsilon = epsilon_decay
if episode % target_update == 0:
target_net.load_state_dict(policy_net.state_dict())
print(f"Episode {episode}, Total Reward: {total_reward}")
# Тестирование агента после обучения
state = env.reset()
done = False
total_reward = 0
while not done:
action = select_action(state, epsilon=0.0) # Без ε-жадной стратегии
state, reward, done, _ = env.step(action)
total_reward += reward
env.render()
print(f"Total reward after training: {total_reward}")
env.close()
```
Объяснение кода
1. Определение архитектуры нейронной сети:
– Сеть состоит из трех полносвязных слоев. Входной слой принимает состояние среды, а выходной слой предсказывает Q-значения для каждого возможного действия.
2. Параметры обучения:
– Определены параметры обучения, такие как размер пакета, коэффициент дисконтирования, начальная вероятность случайного действия, скорость обучения и количество эпизодов.
3. Память для опыта:
– Используется `deque` для хранения недавних переходов, что позволяет повторно использовать их в процессе обучения.
4. Инициализация сети и оптимизатора:
– Инициализируются две сети: `policy_net` для предсказания Q-значений и `target_net` для стабильного обучения.
– `target_net` копирует веса из `policy_net` каждые несколько эпизодов.
5. Функция для выбора действия:
– Выбирается действие на основе ε-жадной стратегии.
6. Функция для обновления памяти:
– Сохраняются переходы (состояние, действие, следующее состояние, вознаграждение) в памяти.
7. Функция для обучения сети:
– Проводится выборка случайного мини-пакета переходов из памяти.
– Вычисляются текущие Q-значения и целевые Q-значения.
– Обновляются параметры сети путем минимизации ошибки MSE.
8. Основной цикл обучения:
– В каждом эпизоде агент взаимодействует со средой, выполняя действия и обновляя память.
– Периодически обновляются веса целевой сети.
– Постепенно уменьшается вероятность случайного действия.
9. Тестирование агента:
– После завершения обучения агент тестируется в среде, используя политику, основанную на максимальных Q-значениях.
– Выводится общее вознаграждение, полученное агентом.
Глава 4. Основные алгоритмы обучения
Обучение моделей машинного обучения часто сводится к оптимизации функции потерь, чтобы улучшить предсказательные способности модели. В этой главе мы рассмотрим три ключевых алгоритма, которые широко используются для этой цели: градиентный спуск, обратное распространение ошибки и стохастический градиентный спуск.
Градиентный спуск
Градиентный спуск – это метод оптимизации, который используется для минимизации функции потерь. Цель метода – найти значения параметров модели, которые минимизируют ошибку между предсказаниями модели и реальными значениями.
1. Инициализация параметров
Инициализация параметров является первым шагом в градиентном спуске. На этом этапе параметры модели (например, веса и смещения нейронной сети) устанавливаются в случайные значения. Инициализация случайными значениями помогает избежать симметричных решений и обеспечивает, что различные параметры начнут свое обновление с различных точек. Это важно для эффективного обучения, поскольку одинаковые начальные значения могут привести к тому, что параметры будут обновляться идентичным образом, что препятствует обучению модели. Часто используется инициализация из стандартного нормального распределения или других подходящих распределений.

