Actor-Critic算法

Actor-Critic算法

1.Actor网络

Actor网络是基于策略的策略梯度(policy-gradient)算法,基于概率选择行为。

Actor直接按照当前策略和环境交互,然后将交互后的到的奖励直接优化当前策略。

2.Critic网络

Critic网络是基于值(value)函数的Q-Learning算法,用来评判Actor网络的行为得分,Critic网络的更新采用梯度下降的方法。

Critic直接通过当前的值函数获得策略与环境交互,交互得到的奖励用来优化当前值函数,进而帮助Actor进行策略更新。

3.Actor-Critic算法

Actor用于选择动作,Critic评论选择该动作的好坏。Actor选择动作的方法是依据存储的策略。Critic的评论是根据TD error获得的,TD error是根据当前的值函数计算获得的。

对于状态值函数的 T D e r r o r = V s t , 预测 − V s t , 真实 TD\quad error=V_{s_{t},预测}-V_{s_{t},真实} TDerror=Vst,预测Vst,真实

= r t + 1 + V s t + 1 , 真实 − V s t , 真实 =r_{t+1}+V_{s_{t+1},真实}-V_{s_{t},真实} =rt+1+Vst+1,真实Vst,真实

对于动作值函数的 T D e r r o r = Q s t , a t , 预测 − Q s t , a t , 真实 TD\quad error=Q_{s_t,a_t,预测}-Q_{s_t,a_t,真实} TDerror=Qst,at,预测Qst,at,真实

= r t + 1 + Q s t + 1 , a t + 1 , 真实 − V s t , a t , 真实 =r_{t+1}+Q_{s_{t+1},a_{t+1},真实}-V_{s_t,a_t,真实} =rt+1+Qst+1,at+1,真实Vst,at,真实

4.算法流程

在第t步根据 π ( a ∣ s t , θ t ) \pi(a|s_t,\theta_t) π(ast,θt)产生 a t a_t at,得到 r t + 1 , s t + 1 r_{t+1},s_{t+1} rt+1,st+1,然后根据 π ( a ∣ s t + 1 , θ t ) \pi(a|s_{t+1},\theta_t) π(ast+1,θt)产生 θ t + 1 \theta_{t+1} θt+1,得到一组数据:

( s t , a t , r t + 1 , s t + 1 , a t + 1 ) (s_t,a_t,r_{t+1},s_{t+1},a_{t+1}) (st,at,rt+1,st+1,at+1),可以发现,这组数据就是SARSA里面用到的数据。

1.Critic(value update)

ω t + 1 = ω t + α ω × [ Q s t , a t , ω t , 预测 − Q s t , a t , ω t , 真实 ] × ∂ ω Q s t , a t , ω t \omega_{t+1}=\omega_t+\alpha_{\omega}\times[Q_{s_t,a_t,\omega_t,预测}-Q_{s_t,a_t,\omega_t,真实}]\times\partial_\omega{Q_{s_t,a_t,\omega_t}} ωt+1=ωt+αω×[Qst,at,ωt,预测Qst,at,ωt,真实]×ωQst,at,ωt

= ω t + α ω × [ r t + 1 + Q s t + 1 , a t + 1 , ω t , 真实 − Q s t , a t , ω t , 真实 ] × ∂ ω Q s t , a t , ω t =\omega_t+\alpha_{\omega}\times[r_{t+1}+Q_{s_{t+1},a_{t+1},\omega_t,真实}-Q_{s_t,a_t,\omega_t,真实}]\times\partial_\omega{Q_{s_t,a_t,\omega_t}} =ωt+αω×[rt+1+Qst+1,at+1,ωt,真实Qst,at,ωt,真实]×ωQst,at,ωt

​ 在这里, ω \omega ω更新后会得到一个新的 Q Q Q

2.Actor(policy update)

θ t + 1 = θ t + α θ × ∂ θ ln ⁡ π ( a t ∣ s t , θ t ) × Q ( s t , a t , ω t + 1 ) \theta_{t+1}=\theta_t+\alpha_{\theta}\times\partial_{\theta}\ln\pi(a_t|s_t,\theta_t)\times Q(s_t,a_t,\omega_{t+1}) θt+1=θt+αθ×θlnπ(atst,θt)×Q(st,at,ωt+1)

5.Actor-Critic算法可选形式

在这里插入图片描述

6.总结

​ Critic:SARSA+value function approximation

​ Actor:policy update

7.代码

RL_brain.py

import torch
from torch import nn
from torch.nn import functional as F
import numpy as np

# ------------------------------------ #
# 策略梯度Actor,动作选择
# ------------------------------------ #

class PolicyNet(nn.Module):
    def __init__(self, n_states, n_hiddens, n_actions):
        super(PolicyNet, self).__init__()
        self.fc1 = nn.Linear(n_states, n_hiddens)
        self.fc2 = nn.Linear(n_hiddens, n_actions)
    # 前向传播
    def forward(self, x):
        x = self.fc1(x)  # [b,n_states]-->[b,n_hiddens]
        x = F.relu(x)  
        x = self.fc2(x)  # [b,n_hiddens]-->[b,n_actions]
        # 每个状态对应的动作的概率
        x = F.softmax(x, dim=1)  # [b,n_actions]-->[b,n_actions]
        return x

# ------------------------------------ #
# 值函数Critic,动作评估输出 shape=[b,1]
# ------------------------------------ #

class ValueNet(nn.Module):
    def __init__(self, n_states, n_hiddens):
        super(ValueNet, self).__init__()
        self.fc1 = nn.Linear(n_states, n_hiddens)
        self.fc2 = nn.Linear(n_hiddens, 1)
    # 前向传播
    def forward(self, x):
        x = self.fc1(x)  # [b,n_states]-->[b,n_hiddens]
        x = F.relu(x)
        x = self.fc2(x)  # [b,n_hiddens]-->[b,1]
        return x

# ------------------------------------ #
# Actor-Critic
# ------------------------------------ #

class ActorCritic:
    def __init__(self, n_states, n_hiddens, n_actions,
                 actor_lr, critic_lr, gamma):
        # 属性分配
        self.gamma = gamma

        # 实例化策略网络
        self.actor = PolicyNet(n_states, n_hiddens, n_actions)
        # 实例化价值网络
        self.critic = ValueNet(n_states, n_hiddens)
        # 策略网络的优化器
        self.actor_optimizer = torch.optim.Adam(self.actor.parameters(), lr=actor_lr)
        # 价值网络的优化器
        self.critic_optimizer = torch.optim.Adam(self.critic.parameters(), lr=critic_lr)
    
    # 动作选择
    def take_action(self, state):
        # 维度变换numpy[n_states]-->[1,n_sates]-->tensor
        state = torch.tensor(state[np.newaxis, :])
        # 动作价值函数,当前状态下各个动作的概率
        probs = self.actor(state)
        # 创建以probs为标准类型的数据分布
        action_dist = torch.distributions.Categorical(probs)
        # 随机选择一个动作 tensor-->int
        action = action_dist.sample().item()
        # 返回动作
        return action

    # 模型更新
    def update(self, transition_dict):
        # 训练集
        states = torch.tensor(transition_dict['states'], dtype=torch.float)
        actions = torch.tensor(transition_dict['actions']).view(-1,1)
        rewards = torch.tensor(transition_dict['rewards'], dtype=torch.float).view(-1,1)
        next_states = torch.tensor(transition_dict['next_states'], dtype=torch.float)
        dones = torch.tensor(transition_dict['dones'], dtype=torch.float).view(-1,1)

        # 预测的当前时刻的state_value
        td_value = self.critic(states)
        # 目标的当前时刻的state_value
        td_target = rewards + self.gamma * self.critic(next_states) * (1-dones)
        # 时序差分的误差计算,目标的state_value与预测的state_value之差
        td_delta = td_target - td_value
        
        # 对每个状态对应的动作价值用log函数
        log_probs = torch.log(self.actor(states).gather(1, actions))
        # 策略梯度损失
        actor_loss = torch.mean(-log_probs * td_delta.detach())
        # 值函数损失,预测值和目标值之间
        critic_loss = torch.mean(F.mse_loss(self.critic(states), td_target.detach()))

        # 优化器梯度清0
        self.actor_optimizer.zero_grad()  # 策略梯度网络的优化器
        self.critic_optimizer.zero_grad()  # 价值网络的优化器
        # 反向传播
        actor_loss.backward()
        critic_loss.backward()
        # 参数更新
        self.actor_optimizer.step()
        self.critic_optimizer.step()

run.py

import numpy as np
import matplotlib.pyplot as plt
import gym
import torch
from RL_brain import ActorCritic

import wandb
import os
import random


# 使用自己在wandb网站上面申请的密钥
os.environ["WANDB_API_KEY"] = '***********************************************'


def seed_torch(seed):
    # 设置随机种子,确保每次运行结果都相同
    torch.manual_seed(seed)
    if torch.backends.cudnn.enabled:
        torch.backends.cudnn.benchmark = False
        torch.backends.cudnn.deterministic = True


# ----------------------------------------- #
# 参数设置
# ----------------------------------------- #

num_episodes = 3000  # 总迭代次数
gamma = 0.98  # 折扣因子
actor_lr = 1e-3  # 策略网络的学习率
critic_lr = 1e-2  # 价值网络的学习率
n_hiddens = 128  # 隐含层神经元个数
env_name = 'CartPole-v1'
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# return_list = []  # 保存每个回合的return


if torch.cuda.is_available():
    # 如果GPU可用,则将模型放到GPU运行
    device = torch.device("cuda")

seed = 42

# ----------------------------------------- #
# 环境加载
# ----------------------------------------- #

env = gym.make(env_name, render_mode="human")
n_states = env.observation_space.shape[0]  # 状态数 4
n_actions = env.action_space.n  # 动作数 2


np.random.seed(seed)
random.seed(seed)
seed_torch(seed)
env.reset(seed=seed)



wandb.init(
    project="Actor-Critic",
    name="Actor-Critic",
    config={
        "env_name": env_name,
        "num_episodes": num_episodes,
        "gamma": gamma,
        "actor_lr": actor_lr,
        "critic_lr": critic_lr,
        "n_hiddens": n_hiddens,
        "n_states": n_states,
        "n_actions": n_actions,
        "device": device
    }
)


# ----------------------------------------- #
# 模型构建
# ----------------------------------------- #

agent = ActorCritic(n_states=n_states,  # 状态数
                    n_hiddens=n_hiddens,  # 隐含层数
                    n_actions=n_actions,  # 动作数
                    actor_lr=actor_lr,  # 策略网络学习率
                    critic_lr=critic_lr,  # 价值网络学习率
                    gamma=gamma)  # 折扣因子

# ----------------------------------------- #
# 训练--回合更新
# ----------------------------------------- #

for i in range(num_episodes):
    state = env.reset()[0]  # 环境重置

    done = False  # 任务完成的标记
    episode_return = 0  # 累计每回合的reward
    # env.render()

    # 构造数据集,保存每个回合的状态数据
    transition_dict = {
        'states': [],
        'actions': [],
        'next_states': [],
        'rewards': [],
        'dones': [],
    }

    while not done:
        action = agent.take_action(state)  # 动作选择
        next_state, reward, done, _, _= env.step(action)  # 环境更新
        # 保存每个时刻的状态\动作\...
        transition_dict['states'].append(state)
        transition_dict['actions'].append(action)
        transition_dict['next_states'].append(next_state)
        transition_dict['rewards'].append(reward)
        transition_dict['dones'].append(done)
        # 更新状态
        state = next_state
        # 累计回合奖励
        episode_return += reward

        # 当累积奖励大于3000时,强制退出
        if episode_return>=3000:
            break
    
    # 保存每个回合的return
    # return_list.append(episode_return)
    # 模型训练
    agent.update(transition_dict)

    # 打印回合信息
    print(f'iter:{i}, return:{episode_return}')
    wandb.log(
            {"episode_return": episode_return},
        )

# -------------------------------------- #
# 绘图
# -------------------------------------- #
wandb.finish()
env.close()
···
### 回答1: 我很抱歉,我不懂actor-critic算法的matlab代码。很抱歉,我不能用中文提供回答,但我会尽力为您提供英文回答: Here is a basic implementation of the actor-critic algorithm in MATLAB: ``` % Initialize parameters alpha_c = 0.1; % Critic learning rate alpha_a = 0.01; % Actor learning rate gamma = 0.9; % Discount factor n_episodes = 100; % Number of episodes n_steps = 1000; % Maximum number of steps per episode % Initialize value function weights w = rand(4,1); % Initialize policy parameters theta = rand(4,1); for i = 1:n_episodes % Initialize the environment state = [0; 0; 0; 0]; done = false; t = 0; % Initialize eligibility traces e_w = zeros(4,1); e_theta = zeros(4,1); while ~done && t < n_steps % Choose action based on current policy action = (theta'*state > 0); % Take action and observe next state and reward [next_state, reward, done] = take_action(state, action); % Update value function weights using TD error td_error = reward + gamma*w'*next_state - w'*state; e_w = gamma*lambda*e_w + state; w = w + alpha_c*td_error*e_w; % Update policy parameters using policy gradient d_ln_pi = state - theta*(state'*theta); e_theta = gamma*lambda*e_theta + d_ln_pi; theta = theta + alpha_a*td_error*e_theta; % Update state and time state = next_state; t = t + 1; end end ``` Note that this is just a basic implementation and there are many ways to customize and improve it for specific applications. ### 回答2: Actor-critic算法是一种强化学习算法,它结合了actorcritic两个方面的优点,可以有效地解决连续动作状态下的强化学习问题。这篇文章将介绍如何使用Matlab实现Actor-critic算法。 首先,让我们来介绍Actor-critic算法的一些基本概念。Actor是agent的决策系统,它负责根据当前状态选择合适的动作;Critic则是价值评估系统,它对agent在当前状态下采取某种行动的后果进行评估。Actor-critic算法中,ActorCritic是相互独立的,但在训练过程中它们相互作用,互相影响。 Actor-critic算法的核心是策略评估和策略提升。策略评估是指评估当前策略的性能,即评估Actor在当前状态下选择某个动作的后果,用来产生Critic的反馈。策略提升是指利用策略评估的结果来改进Actor的决策过程,即根据Critic的反馈对Actor的参数进行更新。 下面是Actor-critic算法的Matlab代码: ``` %初始化 critic_weights=zeros(1,num_features); %初始化Critic的权重 actor_weights=rand(1,num_features); %初始化Actor的权重 gamma=0.99; %折扣因子 alpha_theta=0.01; %Actor的学习率 alpha_w=0.1; %Critic的学习率 %Simulate the game once state=initialize_game(); %初始化游戏状态 action=select_random_action(); %随机选择一个动作 next_state,reward=execute(action); %执行动作并获得奖励 critic_error=reward-gamma*q(next_state)*critic_weights'; %计算Critic的误差 grad=log(action_prob(state,action))-mean_actions(state); %计算Actor的梯度 %主循环 while condition state=next_state; %更新状态 %actor step actor_weights=actor_weights+alpha_theta*critic_error*grad; %更新Actor的参数 %critic step delta=reward-gamma*q(next_state)*critic_weights'; %计算Critic误差的更新值 critic_weights=critic_weights+alpha_w*delta*phi(state); %更新Critic的参数 %Simulate the game once action=select_action(state); next_state,reward=execute(action); critic_error=reward-gamma*q(next_state)*critic_weights'; grad=log(action_prob(state,action))-mean_actions(state); end ``` 上述代码中,首先定义了ActorCritic的权重weights,同时定义了折扣因子gamma,Actor的学习率alpha_theta和Critic的学习率alpha_w。接着,里面的while循环中执行了主要的Actor-critic算法操作。其中actor step用来更新Actor的权重,critic step则是用来更新Critic的权重。同时,为了模拟游戏的状态和动作,代码还使用了其他几个函数(不在此列表中)。 综上所述,上述代码实现了基本的Actor-critic算法,并利用Matlab来执行操作。同时,由于Actor-critic算法是一种基于模型的强化学习方法,因此可以应用于各种问题,例如机器人控制,自然语言处理等等。 ### 回答3: Acter-critic算法是一种重要的强化学习算法,在解决复杂的控制问题时表现出了良好的效果。Matlab是一种常用的科学计算软件,也常被用于实现强化学习算法。下面,我将介绍如何用Matlab实现Actor-critic算法。 首先,我们需要定义ActorCritic的网络结构。Actor的任务是生成动作,Critic的任务是评估状态的价值。这里我们使用神经网络来实现。实现代码如下: ```MATLAB %% Define neural networks for actor and critic state_dim = ... % number of state variables action_dim = ... % number of action variables actor_net = network(state_dim, ... % input layer [50, 50], ... % hidden layers action_dim, ... % output layer 'regression'); % set up the network as a regression problem critic_net = network(state_dim, ... % input layer [50, 50], ... % hidden layers 1, ... % output layer 'regression'); % set up the network as a regression problem % initialize the networks actor_net = init(actor_net); critic_net = init(critic_net); ``` 接下来,我们需要定义ActorCritic的损失函数。Actor的损失函数是最大化状态-动作值函数的预测值,也就是使得选择的动作能够最大化状态-动作值函数。Critic的损失函数是最小化目标状态值与当前状态值的差距,也就是使得当前状态的价值与目标状态价值的差距最小。实现代码如下: ```MATLAB %% Define loss functions for actor and critic actor_loss = @(a, s, td) -mean(td.*a(s')); critic_loss = @(t, s, v) mean((t-v(s)').^2); ``` 其中,a(s')表示在状态s'下,Actor生成的动作,td表示当前状态下的价值与目标状态下的价值的差距,v(s')表示在状态s'下Critic的预测价值。 接下来,我们需要定义ActorCritic的更新策略。Actor的更新策略是根据损失函数的梯度来更新参数。Critic的更新策略是根据损失函数的梯度来更新参数,同时也要更新目标状态的价值。实现代码如下: ```MATLAB %% Define updates for actor and critic actor_update = @(a, s, td, lr) update(actor_net, s, lr*actor_loss(a, s, td), []); % update only the actor network critic_update = @(t, s, lr, gamma) update(critic_net, s, lr*critic_loss(t, s, @(s_) gamma*v(s_)), []); % update the critic and target networks ``` 其中,lr为学习率,gamma为折扣因子,v(s_)表示在状态s'下目标价值的预测值。 最后,我们需要训练Actor-critic模型。训练过程由以下步骤组成: 1. 利用Actor生成一个动作,并根据该动作得到一个新状态; 2. 利用Critic预测目标状态值和当前状态值,计算出td; 3. 利用td来更新Actor的参数; 4. 利用td来更新Critic的参数,并更新目标状态的价值; 5. 如果达到了最大步数或者目标任务已经完成,则停止训练。 实现代码如下: ```MATLAB %% Train the actor-critic model max_steps = ... % maximum number of steps gamma = ... % discount factor lr_actor = ... % actor learning rate lr_critic = ... % critic learning rate % initialize the first state s = ... % loop over the maximum number of steps for i = 1:max_steps % generate an action from the actor network a = sim(actor_net, s); % take the action to get a new state [s_, r, done] = env.step(a); % calculate td using the critic network t = r + gamma*v(s_); td = t - v(s); % update the actor network actor_update(a, s, td, lr_actor); % update the critic network critic_update(t, s, lr_critic, gamma); % update the target network update(critic_target, [], [], critic_net); % save the current state for future reference s = s_; % check if the task is done if done break; end end ``` 其中,env表示环境,包含初始状态、状态转移函数和终止条件。在训练过程中,每一步都会执行以上5个步骤,直到达到最大步数或目标任务完成为止。 以上就是通过Matlab实现Actor-critic算法的全部步骤。实际使用中,可能还需要对其进行一些调参和优化。在实现中需要格外注意,ActorCritic需要分别定义网络结构、损失函数和更新策略,而训练过程中需要迭代地用Actor生成动作、更新CriticActor的参数。掌握这些关键要素,就可以用Matlab实现Actor-critic算法了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值