PyTorch中的强化学习算法与实践

算法之美 2019-05-05 ⋅ 16 阅读

强化学习是一种通过智能体与环境的交互来学习如何做出决策的机器学习方法。它在许多领域,如游戏、机器人控制和交通管制等方面具有广泛的应用。在本文中,我们将介绍PyTorch中的强化学习算法及其实践方法。

简介

强化学习基于马尔可夫决策过程(Markov Decision Process, MDP)模型。MDP是一个四元组$(S, A, P, R)$,其中$S$是状态空间,$A$是动作空间,$P$是状态转移概率矩阵,$R$是奖励函数。强化学习的目标是找到一个策略$\pi(a|s)$,使得智能体能够最大化累积奖励。

PyTorch是一个基于Python的开源机器学习库,它提供了丰富的工具和函数来构建和训练深度神经网络模型。在PyTorch中,我们可以使用多种强化学习算法来训练智能体,如深度Q网络(Deep Q-Network, DQN)和确定性策略梯度(Deterministic Policy Gradient, DPG)等。

DQN算法实践

DQN是一种经典的强化学习算法,它使用深度神经网络来近似值函数。DQN的目标是学习一个Q值函数$Q(s, a)$,用于评估状态动作对的价值。

首先,我们需要定义一个深度神经网络模型来近似Q值函数。使用PyTorch,我们可以定义一个继承自nn.Module的类来构建模型。然后,我们可以使用nn.Sequential来组织网络层。

import torch
import torch.nn as nn

class QNetwork(nn.Module):
    def __init__(self, state_size, action_size):
        super(QNetwork, self).__init__()
        self.fc1 = nn.Linear(state_size, 64)
        self.fc2 = nn.Linear(64, 64)
        self.fc3 = nn.Linear(64, action_size)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x

然后,我们可以定义一个经验回放缓冲区,用于存储智能体的经验样本。在每个时间步,智能体会将当前的状态、动作、奖励、下一个状态和终止标志存储到经验回放缓冲区中。

import random
from collections import namedtuple

Experience = namedtuple('Experience', ('state', 'action', 'reward', 'next_state', 'done'))

class ReplayBuffer:
    def __init__(self, buffer_size):
        self.buffer = []
        self.buffer_size = buffer_size

    def push(self, state, action, reward, next_state, done):
        experience = Experience(state, action, reward, next_state, done)
        self.buffer.append(experience)
        if len(self.buffer) > self.buffer_size:
            self.buffer.pop(0)

    def sample(self, batch_size):
        return random.sample(self.buffer, batch_size)

接下来,我们可以定义DQN算法的训练过程。在每个时间步,智能体会根据当前状态选择一个动作,并观察环境返回的奖励和下一个状态。然后,智能体会将这些信息存储到经验回放缓冲区中,并从中随机抽取一批样本用于训练。

import torch.optim as optim
import torch.nn.functional as F

def train_dqn(env, q_network, target_network, replay_buffer, num_episodes, batch_size, gamma, epsilon):
    optimizer = optim.Adam(q_network.parameters())
    loss_fn = F.mse_loss

    for episode in range(num_episodes):
        state = env.reset()
        episode_reward = 0

        while True:
            action = select_action(q_network, state, epsilon)
            next_state, reward, done, _ = env.step(action)
            episode_reward += reward

            replay_buffer.push(state, action, reward, next_state, done)

            if len(replay_buffer) >= batch_size:
                experiences = replay_buffer.sample(batch_size)
                loss = compute_loss(q_network, target_network, experiences, gamma, loss_fn)
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

            if done:
                break

            state = next_state

        # update target network every episode
        target_network.load_state_dict(q_network.state_dict())

        print(f'Episode {episode+1}/{num_episodes}, Reward: {episode_reward}')

def select_action(q_network, state, epsilon):
    if random.random() < epsilon:
        return random.randint(0, q_network.fc3.out_features-1)
    else:
        with torch.no_grad():
            return q_network(state).argmax().item()

def compute_loss(q_network, target_network, experiences, gamma, loss_fn):
    states = torch.cat([experience.state for experience in experiences])
    actions = torch.tensor([experience.action for experience in experiences])
    rewards = torch.tensor([experience.reward for experience in experiences])
    next_states = torch.cat([experience.next_state for experience in experiences])
    dones = torch.tensor([experience.done for experience in experiences])

    q_values = q_network(states)[range(len(experiences)), actions]
    with torch.no_grad():
        next_q_values = target_network(next_states).max(dim=1)[0]
        target_q_values = rewards + gamma * next_q_values * (1 - dones)

    return loss_fn(q_values, target_q_values)

在训练过程中,我们使用了一个目标网络来稳定训练。目标网络是一个与Q网络结构相同的模型,但参数不会被更新,而是定期从Q网络中复制来保持一致。

DPG算法实践

DPG是一种基于确定性策略梯度的强化学习算法,它通过直接优化策略函数来学习一个确定性的动作策略。DPG的核心思想是通过策略梯度方法来更新策略函数,同时使用一个值函数来评估策略。

首先,我们需要定义一个策略函数和一个值函数。策略函数接受状态作为输入,并输出一个确定性的动作。值函数接受状态和动作作为输入,并输出一个状态动作对的价值。

class PolicyNetwork(nn.Module):
    def __init__(self, state_size, action_size):
        super(PolicyNetwork, self).__init__()
        self.fc1 = nn.Linear(state_size, 64)
        self.fc2 = nn.Linear(64, 64)
        self.fc3 = nn.Linear(64, action_size)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = torch.tanh(self.fc3(x))
        return x

class ValueNetwork(nn.Module):
    def __init__(self, state_size):
        super(ValueNetwork, self).__init__()
        self.fc1 = nn.Linear(state_size, 64)
        self.fc2 = nn.Linear(64, 64)
        self.fc3 = nn.Linear(64, 1)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x

然后,我们可以定义DPG算法的训练过程。在每个时间步,智能体会根据当前状态选择一个动作,并观察环境返回的奖励和下一个状态。然后,智能体会计算策略梯度和值函数的损失,并更新网络参数。

def train_dpg(env, policy_network, value_network, num_episodes, gamma, lr):
    policy_optimizer = optim.Adam(policy_network.parameters(), lr=lr)
    value_optimizer = optim.Adam(value_network.parameters(), lr=lr)
    value_loss_fn = F.mse_loss

    for episode in range(num_episodes):
        state = env.reset()
        episode_reward = 0

        while True:
            action = select_action(policy_network, state)
            next_state, reward, done, _ = env.step(action)
            episode_reward += reward

            state_tensor = torch.tensor(state, dtype=torch.float32).unsqueeze(0)
            action_tensor = torch.tensor(action, dtype=torch.float32).unsqueeze(0)
            next_state_tensor = torch.tensor(next_state, dtype=torch.float32).unsqueeze(0)
            reward_tensor = torch.tensor(reward, dtype=torch.float32).unsqueeze(0)
            done_tensor = torch.tensor(done, dtype=torch.float32).unsqueeze(0)

            value = value_network(state_tensor)
            next_value = value_network(next_state_tensor)
            target_value = reward_tensor + gamma * (1 - done_tensor) * next_value

            value_loss = value_loss_fn(value, target_value.detach())

            policy_optimizer.zero_grad()
            policy_loss = -value.detach() * policy_network(state_tensor)
            policy_loss.backward()
            policy_optimizer.step()

            value_optimizer.zero_grad()
            value_loss.backward()
            value_optimizer.step()

            if done:
                break

            state = next_state

        print(f'Episode {episode+1}/{num_episodes}, Reward: {episode_reward}')

def select_action(policy_network, state):
    with torch.no_grad():
        return policy_network(torch.tensor(state, dtype=torch.float32)).detach().numpy()

在训练过程中,我们使用了一个值网络来评估策略。值网络的参数会在每个时间步更新,以提供更新的价值估计。

总结

本文介绍了PyTorch中的强化学习算法及其实践方法。我们以DQN和DPG为例,展示了如何使用PyTorch构建和训练强化学习模型。希望这些内容能帮助读者更好地理解强化学习算法并进行实践。


全部评论: 0

    我有话说: