• 2021-08-09 11:04:00

A3C

核心思想：Global NetWork和每个Worker网络结构是一样的。拿每个Worker网络去训练，训练完之后，拿自己的梯度去更新Global NetWork梯度。Global NetWork再将自己的梯度去更新每个Worker的梯度

代码实现
参考一个博主的github

a3c_main.py

import gym
import numpy as np
import matplotlib.pyplot as plt
from Actor_Critic.A3C.agent_a3c import A3C

def get_env_prop(env_name, continuous):
env = gym.make(env_name)
state_dim = env.observation_space.shape[0]
if continuous:
action_dim = env.action_space.shape[0]
else:
action_dim = env.action_space.n

return env,state_dim, action_dim

def train_a3c(env_name,continuous):
env,state_size,action_size = get_env_prop(env_name,continuous)
agent = A3C(env,continuous,state_size,action_size)
scores = agent.train_worker()
return scores

def train_agent_for_env(env_name,continuous):
env = gym.make(env_name)

state_dim = env.observation_space.shape[0]
if continuous:
action_dim = env.action_space.shape[0]
else:
action_dim = env.action_space.n

agent = A3C(env, continuous,state_dim,action_dim)
scores = agent.train_worker()

return agent,scores

def plot_scores(scores,filename):
fig = plt.figure()
plt.plot(np.arange(1, len(scores) + 1), scores)
plt.ylabel('Score')
plt.xlabel('Episode #')
plt.savefig(filename)
plt.show()

if __name__ == "__main__":
# env = gym.make("Pendulum-v0")
# train_scores = train_a3c(env,True)

# train A3C on discrete env : CartPole
scores_cartPole = train_agent_for_env("CartPole-v0",False)
plot_scores(scores_cartPole,"cartPole_trainPlot.png")

# train A3C on continuous env : continuous
# a3c_mCar = train_agent_for_env("MountainCarContinuous-v0", True)


agent_a3c.py

import random
import torch
import torch.optim as optim
import multiprocessing as mp
from multiprocessing import Process
from Actor_Critic.A3C.untils import ValueNetwork,ActorDiscrete,ActorContinous
from Actor_Critic.A3C.worker import Worker

GAMMA = 0.9
LR = 1e-4
GLOBAL_MAX_EPISODE = 5000

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

class A3C():
def __init__(self,env,continuous,state_size,action_size):
self.max_episode=GLOBAL_MAX_EPISODE
#pytorch的多进程可以参考https://zhuanlan.zhihu.com/p/328271397
self.global_episode = mp.Value('i', 0)  # 进程之间共享的变量
#用法例子如下
#self.global_episode .value += 1

self.global_epi_rew = mp.Value('d',0)
self.rew_queue = mp.Queue()  #self.rew_queue是一个队列  可以往里面存储值和取出值 和普通队列的作用一样。但队列不能修改变量的值，只能存储值。而共享变量可以修改变量的值
self.worker_num = mp.cpu_count()

# define the global networks
self.global_valueNet= ValueNetwork(state_size,1).to(device)
# global 的网络参数放入 shared memory，以便复制给各个进程中的 worker网络
self.global_valueNet.share_memory()

if continuous:
self.global_policyNet = ActorContinous(state_size, action_size).to(device)
else:
self.global_policyNet = ActorDiscrete(state_size, action_size).to(device)
self.global_policyNet.share_memory()

# global optimizer

# define the workers
self.workers=[Worker(env,continuous,state_size,action_size,i,
self.global_valueNet,self.global_optimizer_value,
self.global_policyNet,self.global_optimizer_policy,
self.global_episode,self.global_epi_rew,self.rew_queue,
self.max_episode,GAMMA)
for i in range(self.worker_num)]

def train_worker(self):
scores=[]
[w.start() for w in self.workers]
while True:
r = self.rew_queue.get()
if r is not None:
scores.append(r)
else:
break
[w.join() for w in self.workers]

return scores

def save_model(self):
torch.save(self.global_valueNet.state_dict(), "a3c_value_model.pth")
torch.save(self.global_policyNet.state_dict(), "a3c_policy_model.pth")


untils.py

import torch
from collections import namedtuple
import torch.nn as nn
import torch.nn.functional as F
from torch.distributions import Categorical
from torch.distributions import Normal

class ValueNetwork(nn.Module):

def __init__(self, input_dim, output_dim):
super(ValueNetwork, self).__init__()
self.fc1 = nn.Linear(input_dim, 256)
self.fc2 = nn.Linear(256, output_dim)

def forward(self, state):
value = F.relu(self.fc1(state))
value = self.fc2(value)

return value

class ActorDiscrete(nn.Module):
"""
用于离散动作空间的策略网络
"""
def __init__(self,state_size,action_size):
super(ActorDiscrete, self).__init__()
self.seed = torch.manual_seed(0)
self.fc1 = nn.Linear(state_size, 128)
# self.fc2 = nn.Linear(64,128)
self.fc2= nn.Linear(128, action_size)

def forward(self, x):
"""
Build a network that maps state -> action probs.
"""

x=F.relu(self.fc1(x))
out = F.softmax(self.fc2(x),dim=1)
return out

def act(self,state):
"""
返回 action 和 action的概率
"""
# probs for each action (2d tensor)
probs = self.forward(state)
m = Categorical(probs)
action = m.sample()

# return action for current state, and the corresponding probability
return action.item(),probs[:,action.item()].item()

class ActorContinous(nn.Module):
"""
用于连续动作空间的策略网络
"""
def __init__(self,state_size,action_size):
super(ActorContinous, self).__init__()
self.fc1 = nn.Linear(state_size, 128)
self.fc2 = nn.Linear(128,128)

def forward(self, x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
return (mu, sigma)

def act(self,state):
"""
返回 action 和 action 的 log prob
"""
(mu, sigma) = self.policy(state)  # 2d tensors
dist = Normal(mu, sigma)
action = dist.sample()
action_log_prob = dist.log_prob(action)

return action.numpy()[0], action_log_prob.numpy()[0]


worker.py

import math
import torch.multiprocessing as mp
import torch
import torch.nn.functional as F
from torch.distributions import Normal
from Actor_Critic.A3C.untils import ValueNetwork,ActorDiscrete,ActorContinous

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

class Worker(mp.Process):
def __init__(self,env,continuous,state_size,action_size,id, global_valueNet,global_value_optimizer,
global_policyNet,global_policy_optimizer,
global_epi,global_epi_rew,rew_queue,
max_epi,gamma):
super(Worker, self).__init__()
# define env for individual worker
self.env = env
self.continuous = continuous
self.name = str(id)
self.env.seed(id)
self.state_size = state_size
self.action_size = action_size
self.memory=[]

# passing global settings to worker
self.global_valueNet,self.global_value_optimizer = global_valueNet,global_value_optimizer
self.global_policyNet,self.global_policy_optimizer = global_policyNet,global_policy_optimizer
self.global_epi,self.global_epi_rew = global_epi,global_epi_rew
self.rew_queue = rew_queue
self.max_epi = max_epi
# self.batch_size = batch_size
self.gamma = gamma

# define local net for individual worker
self.local_policyNet = ActorDiscrete(self.state_size,self.action_size).to(device)
if self.continuous:
self.local_policyNet = ActorContinous(self.state_size,self.action_size).to(device)
self.local_valueNet = ValueNetwork(self.state_size,1).to(device)

def sync_global(self):

def calculate_loss(self):
# get experiences from current trajectory
states = torch.tensor([t[0] for t in self.memory], dtype=torch.float)

#好像这里有点问题 因为self.memory.append([state,action,reward,next_state,done])
#所以t[1]是action?
#105行和107行代码
log_probs = torch.tensor([t[1] for t in self.memory], dtype=torch.float)

# -- calculate discount future rewards for every time step
rewards = [t[2] for t in self.memory]
fur_Rewards = []
for i in range(len(rewards)):
discount = [self.gamma ** i for i in range(len(rewards) - i)]
f_rewards = rewards[i:]
fur_Rewards.append(sum(d * f for d, f in zip(discount, f_rewards)))
fur_Rewards = torch.tensor(fur_Rewards, dtype=torch.float).view(-1, 1)

# calculate loss for critic
V = self.local_valueNet(states)
value_loss = F.mse_loss(fur_Rewards, V)

# compute entropy for policy loss
(mu, sigma) = self.local_policyNet(states)
dist = Normal(mu, sigma)
entropy = 0.5 + 0.5 * math.log(2 * math.pi) + torch.log(dist.scale)  # exploration

# calculate loss for actor
policy_loss = (policy_loss - 0.005 * entropy).mean()

return value_loss,policy_loss

def update_global(self):
value_loss, policy_loss = self.calculate_loss()

value_loss.backward()
# propagate local gradients to global parameters
for local_params, global_params in zip(self.local_valueNet.parameters(), self.global_valueNet.parameters()):
self.global_value_optimizer.step()

#求梯度
policy_loss.backward()
# propagate local gradients to global parameters
for local_params, global_params in zip(self.local_policyNet.parameters(), self.global_policyNet.parameters()):
#复制梯度
#更新参数w和b
self.global_policy_optimizer.step()

self.memory=[]  # clear trajectory

def run(self):
while self.global_epi.value < self.max_epi:
state = self.env.reset()
total_reward=0
while True:
state = torch.from_numpy(state).float().unsqueeze(0).to(device)
action, prob = self.local_policyNet.act(state)  # 离散空间取直接prob，连续空间取log prob
next_state, reward, done, _ = self.env.step(action)
self.memory.append([state,action,reward,next_state,done])
total_reward += reward
state = next_state

if done:
# recoding global episode and episode reward
with self.global_epi.get_lock():
self.global_epi.value += 1
with self.global_epi_rew.get_lock():
if self.global_epi_rew.value == 0.:
self.global_epi_rew.value = total_reward
else:
# Moving average reward
self.global_epi_rew.value = self.global_epi_rew.value * 0.99 + total_reward * 0.01
self.rew_queue.put(self.global_epi_rew.value)

print("w{} | episode: {}\t , episode reward:{:.4} \t  "
.format(self.name,self.global_epi.value,self.global_epi_rew.value))
break

# update and sync with the global net when finishing an episode
self.update_global()
self.sync_global()

self.rew_queue.put(None)


更多相关内容
• 强化学习算法-基于python的强化学习a3c算法实现
• 基于强化学习A3C与DQN的月球着陆游戏训练设计与实现
• 浅谈利用A3C玩转超级玛丽奥前言github什么是Actor-Critic？A3C算法loss值计算 前言 很早以前看过超级玛丽奥利用人工智能玩，以前感觉很高档。就写一篇吧。 github 什么是Actor-Critic？ Actor-Critic，其实是用了两...

# 前言

很早以前看过超级玛丽奥利用人工智能玩，以前感觉很高档。就写一篇吧。

# github

https://github.com/yanjingke/Super-mario

# 什么是Actor-Critic？

Actor-Critic，其实是用了两个网络：两个网络有一个共同点，输入状态S: 一个输出策略，负责选择动作，我们把这个网络成为Actor； 一个负责计算每个动作的分数，我们把这个网络成为Critic。
大家可以形象地想象为，Actor是舞台上的舞者，Critic是台下的评委。Actor在台上跳舞，一开始舞姿并不好看，Critic根据Actor的舞姿打分。Actor通过Critic给出的分数，去学习：如果Critic给的分数高，那么Actor会调整这个动作的输出概率；相反，如果Critic给的分数低，那么就减少这个动作输出的概率。
在AC中中的Critic，估算的是V值也就是一个评分，因为在强化学习中，往往没有足够的时间让我们去和环境互动。在Critic中如果预测动作评价，假设我们用Critic网络，预估到S状态下三个动作A1，A2，A3的Q值分别为1,2,10。但在开始的时候，我们采用平均策略，于是随机到A1。于是我们用策略梯度的带权重方法更新策略，这里的权重就是Q值。于是策略会更倾向于选择A1，意味着更大概率选择A1。结果A1的概率就持续升高…
这就掉进了正数陷阱。我们明明希望A3能够获得更多的机会，最后却是A1获得最多的机会。这是为什么呢？
这是因为Q值用于是一个正数，如果权重是一个正数，那么我们相当于提高对应动作的选择的概率。权重越大，我们调整的幅度将会越大。其实当我们有足够的迭代次数，这个是不用担心这个问题的。因为总会有机会抽中到权重更大的动作，因为权重比较大，抽中一次就能提高很高的概率。

但在强化学习中，往往没有足够的时间让我们去和环境互动。这就会出现由于运气不好，使得一个很好的动作没有被采样到的情况发生。要解决这个问题，我们可以通过减去一个baseline，令到权重有正有负。而通常这个baseline，我们选取的是权重的平均值。减去平均值之后，值就变成有正有负了。

所以我们可以得到更新的权重：Q(s,a)-V(s)。然而在每次的奖励中会进行得分的衰减gamma。
总结

1、为了避免正数陷阱，我们希望Actor的更新权重有正有负。因此，我们把Q值减去他们的均值V。有：Q(s,a)-V(s)

2、为了避免需要预估V值和Q值，我们希望把Q和V统一；由于Q(s,a) = gamma * V(s’) + r - V(s)。所以我们得到TD-error公式： TD-error = gamma * V(s’) + r - V(s)

# A3C算法

在A3C中有一个公共的神经网络模型，这个神经网络包括Actor网络和Critic网络两部分的功能这样加快了速度。下面有n个worker线程，每个线程里有和公共的神经网络一样的网络结构，每个线程会独立的和环境进行交互得到经验数据，这些线程之间互不干扰，独立运行。

它是怎么实现公共网络的啦？
在A3C中需要解决的问题：

由于智能体在与环境交互过程中有大量的随机性，所以算的是期望，为了计算A，现在出现了Q和V，那我得训练俩网络了
来个近似让问题简单些吧：

是不是不用训练两个网络啦？

它俩好像都是根据状态来预测结果：


class ActorCritic(nn.Module):
def __init__(self, num_inputs, num_actions):
super(ActorCritic, self).__init__()
self.conv1 = nn.Conv2d(num_inputs, 32, 3, stride=2, padding=1)
self.conv2 = nn.Conv2d(32, 32, 3, stride=2, padding=1)
self.conv3 = nn.Conv2d(32, 32, 3, stride=2, padding=1)
self.conv4 = nn.Conv2d(32, 32, 3, stride=2, padding=1)
self.lstm = nn.LSTMCell(32 * 6 * 6, 512)
self.critic_linear = nn.Linear(512, 1)
self.actor_linear = nn.Linear(512, num_actions)
self._initialize_weights()

def _initialize_weights(self):
for module in self.modules():
if isinstance(module, nn.Conv2d) or isinstance(module, nn.Linear):
nn.init.xavier_uniform_(module.weight)
# nn.init.kaiming_uniform_(module.weight)
nn.init.constant_(module.bias, 0)
elif isinstance(module, nn.LSTMCell):
nn.init.constant_(module.bias_ih, 0)
nn.init.constant_(module.bias_hh, 0)

def forward(self, x, hx, cx):
x = F.relu(self.conv1(x))
x = F.relu(self.conv2(x))
x = F.relu(self.conv3(x))
x = F.relu(self.conv4(x))
# print( (hx, cx))
hx, cx = self.lstm(x.view(x.size(0), -1), (hx, cx))
return self.actor_linear(hx), self.critic_linear(hx), hx, cx#隐层和记忆单元



AC整体流程：
1.获取数据： （不断与环境交互，通过策略 ）
2.前向传播计算：

3.计算梯度：

4.更新参数：

def local_train(index, opt, global_model, optimizer, save=False):
torch.manual_seed(123 + index)
if save:
start_time = timeit.default_timer()
writer = SummaryWriter(opt.log_path)
env, num_states, num_actions = create_train_env(opt.world, opt.stage, opt.action_type)#单独玩
local_model = ActorCritic(num_states, num_actions)
if opt.use_gpu:
local_model.cuda()
local_model.train()
state = torch.from_numpy(env.reset())
if opt.use_gpu:
state = state.cuda()
done = True
curr_step = 0
curr_episode = 0
while True:
if save:
if curr_episode % opt.save_interval == 0 and curr_episode > 0:
torch.save(global_model.state_dict(),
"{}/a3c_super_mario_bros_{}_{}".format(opt.saved_path, opt.world, opt.stage))
print("Process {}. Episode {}".format(index, curr_episode))
curr_episode += 1
if done:
h_0 = torch.zeros((1, 512), dtype=torch.float)
c_0 = torch.zeros((1, 512), dtype=torch.float)
else:
h_0 = h_0.detach()
c_0 = c_0.detach()
if opt.use_gpu:
h_0 = h_0.cuda()
c_0 = c_0.cuda()

log_policies = []
values = []
rewards = []
entropies = []

for _ in range(opt.num_local_steps):
curr_step += 1
logits, value, h_0, c_0 = local_model(state, h_0, c_0)#return self.actor_linear(hx), self.critic_linear(hx), hx, cx#隐层和记忆单元
policy = F.softmax(logits, dim=1)
log_policy = F.log_softmax(logits, dim=1)
entropy = -(policy * log_policy).sum(1, keepdim=True)#计算当前熵值

#进行分布采样
m = Categorical(policy)#采样
action = m.sample().item()

state, reward, done, _ = env.step(action)
# env.render()
state = torch.from_numpy(state)
if opt.use_gpu:
state = state.cuda()
if curr_step > opt.num_global_steps:
done = True

if done:
curr_step = 0
state = torch.from_numpy(env.reset())
if opt.use_gpu:
state = state.cuda()

values.append(value)
log_policies.append(log_policy[0, action])
rewards.append(reward)
entropies.append(entropy)

if done:
break

R = torch.zeros((1, 1), dtype=torch.float)
if opt.use_gpu:
R = R.cuda()
if not done:
_, R, _, _ = local_model(state, h_0, c_0)#这个R相当于最后一次的V值，第二个返回值是critic网络的

gae = torch.zeros((1, 1), dtype=torch.float)#额外的处理，为了减小variance
if opt.use_gpu:
gae = gae.cuda()
actor_loss = 0
critic_loss = 0
entropy_loss = 0
next_value = R

for value, log_policy, reward, entropy in list(zip(values, log_policies, rewards, entropies))[::-1]:
gae = gae * opt.gamma * opt.tau
gae = gae + reward + opt.gamma * next_value.detach() - value.detach()#Generalized Advantage Estimator 带权重的折扣项
next_value = value
actor_loss = actor_loss + log_policy * gae
R = R * opt.gamma + reward
critic_loss = critic_loss + (R - value) ** 2 / 2
entropy_loss = entropy_loss + entropy

total_loss = -actor_loss + critic_loss - opt.beta * entropy_loss
total_loss.backward()

for local_param, global_param in zip(local_model.parameters(), global_model.parameters()):
break

optimizer.step()

if curr_episode == int(opt.num_global_steps / opt.num_local_steps):
print("Training process {} terminated".format(index))
if save:
end_time = timeit.default_timer()
print('The code runs for %.2f s ' % (end_time - start_time))
return


# loss值计算

策略损失（Policy）:
（起决策的网络）
Value网络损失：
（预期与实际的差异）
熵：（熵越大表示各种行为可能性都能有一些，别太绝对）
整体损失函数：

  for value, log_policy, reward, entropy in list(zip(values, log_policies, rewards, entropies))[::-1]:
gae = gae * opt.gamma * opt.tau
gae = gae + reward + opt.gamma * next_value.detach() - value.detach()#Generalized Advantage Estimator 带权重的折扣项
next_value = value
actor_loss = actor_loss + log_policy * gae
R = R * opt.gamma + reward
critic_loss = critic_loss + (R - value) ** 2 / 2
entropy_loss = entropy_loss + entropy

total_loss = -actor_loss + critic_loss - opt.beta * entropy_loss
total_loss.backward()


展开全文
• 从结果上看，改进的A3C算法计算效率更高，寻优效果更好，目前深度强化学习非常火热，很容易出成果，非常适合在本代码的基础上稍微加点东西，即可形成自己的成果，非常适合深度强化学习方向的人学习！ ID:69150641

主题：基于改进A3C算法的微网优化调度与需求响应管理

内容简介：

代码主要做的是基于深度强化学习的微网/虚拟电厂优化调度策略研究，微网的聚合单元包括风电机组，储能单元，温控负荷（空调、热水器）以及需求响应负荷，并且考虑并网，可与上级电网进行能量交互，采用A3C算法以及改进的A3C算法进行求解，从结果上看，改进的A3C算法计算效率更高，寻优效果更好，目前深度强化学习非常火热，很容易出成果，非常适合在本代码的基础上稍微加点东西，即可形成自己的成果，非常适合深度强化学习方向的人学习！

ID:69150641830359180

小代码狂人

技术交流 资源共享 莫如博客陪您进步！

本文转载自：莫如博客

展开全文
• 基于强化学习算法A3C，DDPG，DDPO的机器人手臂游戏训练设计与实现
• 二、核心算法(A3C) Asynchronous Advantage Actor-critic 前言 强化学习（Reinforcement Learning, RL），又称再励学习、评价学习或增强学习，是机器学习的范式和方法论之一，用于描述和解决智能体（agent）在与...

# 系列文章目录

强化学习

提示：写完文章后，目录可以自动生成，如何生成可参考右边的帮助文档

# 前言

强化学习（Reinforcement Learning, RL），又称再励学习、评价学习或增强学习，是机器学习的范式和方法论之一，用于描述和解决智能体（agent）在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题 。

# 一、强化学习是什么？

强化学习是智能体（Agent）以“试错”的方式进行学习，通过与环境进行交互获得的奖赏指导行为，目标是使智能体获得最大的奖赏，强化学习不同于连接主义学习中的监督学习，主要表现在强化信号上，强化学习中由环境提供的强化信号是对产生动作的好坏作一种评价(通常为标量信号)，而不是告诉强化学习系统RLS(reinforcement learning system)如何去产生正确的动作。由于外部环境提供的信息很少，RLS必须靠自身的经历进行学习。通过这种方式，RLS在行动-评价的环境中获得知识，改进行动方案以适应环境。
理解：强化学习其实就是和人一样，一开始是什么都不懂的，所谓吃一堑长一智，他像一个新生的孩子，它在不断的试错过程中慢慢知道了做什么有奖励，做什么对得到奖励会有一定的价值，做什么会被打。在这个过程中不会像监督学习一样有个师傅带你，完全需要自己去摸索，就像修仙宗门一样，有背景的宗门弟子是继承掌门之位（监督），创立宗门的人是开山立派（强化），必须一步一个脚印去不断成长。

其实强化学习吸引我的就是因为它主要使用在游戏上，例如：
在 Flappy bird 这个游戏中，我们需要简单的点击操作来控制小鸟，躲过各种水管，飞的越远越好，因为飞的越远就能获得更高的积分奖励。

机器有一个玩家小鸟——Agent
需要控制小鸟飞的更远——目标
整个游戏过程中需要躲避各种水管——环境
躲避水管的方法是让小鸟用力飞一下——行动
飞的越远，就会获得越多的积分——奖励

if __name__ == "__main__":
# 创建会话
SESS = tf.Session()
# 用cpu跑
with tf.device("/cpu:0"):
# 训练Actor与Critic，分开学习会更好
OPT_A = tf.train.RMSPropOptimizer(LR_A, name='RMSPropA')
OPT_C = tf.train.RMSPropOptimizer(LR_C, name='RMSPropC')
# 全局神经网络
GLOBAL_AC = ACNet(GLOBAL_NET_SCOPE)  # we only need its params
workers = []
# Create worker，根据cpu内核数量分配
for i in range(N_WORKERS):
i_name = 'W_%i' % i  # worker name
workers.append(Worker(i_name, GLOBAL_AC))

# 创建一个多线程管理
COORD = tf.train.Coordinator()
SESS.run(tf.global_variables_initializer())
# tensorboard可视化
if OUTPUT_GRAPH:
if os.path.exists(LOG_DIR):
shutil.rmtree(LOG_DIR)
tf.summary.FileWriter(LOG_DIR, SESS.graph)

# 开启多个线程，线程情况上面已经添加好了
for worker in workers:
job = lambda: worker.work()
# 开启多线程神经网络的训练
t.start()
#     将线程放到管理者中

plt.plot(np.arange(len(GLOBAL_RUNNING_R)), GLOBAL_RUNNING_R)
plt.xlabel('step')
plt.ylabel('Total moving reward')
plt.show()



网络因为环境问题，命令行被配置到Tensorboard 2.8.0去了，所以无法显示网络的可视化

class ACNet(object):
def __init__(self, scope, globalAC=None):

if scope == GLOBAL_NET_SCOPE:  # get global network
with tf.variable_scope(scope):
self.s = tf.placeholder(tf.float32, [None, N_S], 'S')
self.a_params, self.c_params = self._build_net(scope)[-2:]
else:  # local net, calculate losses
with tf.variable_scope(scope):
self.s = tf.placeholder(tf.float32, [None, N_S], 'S')
self.a_his = tf.placeholder(tf.float32, [None, N_A], 'A')
self.v_target = tf.placeholder(tf.float32, [None, 1], 'Vtarget')

mu, sigma, self.v, self.a_params, self.c_params = self._build_net(scope)

td = tf.subtract(self.v_target, self.v, name='TD_error')
with tf.name_scope('c_loss'):
self.c_loss = tf.reduce_mean(tf.square(td))

with tf.name_scope('wrap_a_out'):
mu, sigma = mu * A_BOUND[1], sigma + 1e-4

normal_dist = tf.distributions.Normal(mu, sigma)

with tf.name_scope('a_loss'):
log_prob = normal_dist.log_prob(self.a_his)
entropy = normal_dist.entropy()  # encourage exploration
self.exp_v = ENTROPY_BETA * entropy + exp_v
self.a_loss = tf.reduce_mean(-self.exp_v)

with tf.name_scope('choose_a'):  # use local params to choose action
self.A = tf.clip_by_value(tf.squeeze(normal_dist.sample(1), axis=[0, 1]), A_BOUND[0], A_BOUND[1])

with tf.name_scope('sync'):
with tf.name_scope('pull'):
self.pull_a_params_op = [l_p.assign(g_p) for l_p, g_p in zip(self.a_params, globalAC.a_params)]
self.pull_c_params_op = [l_p.assign(g_p) for l_p, g_p in zip(self.c_params, globalAC.c_params)]
with tf.name_scope('push'):

def _build_net(self, scope):
w_init = tf.random_normal_initializer(0., .1)
with tf.variable_scope('actor'):
l_a = tf.layers.dense(self.s, 200, tf.nn.relu6, kernel_initializer=w_init, name='la')
mu = tf.layers.dense(l_a, N_A, tf.nn.tanh, kernel_initializer=w_init, name='mu')
sigma = tf.layers.dense(l_a, N_A, tf.nn.softplus, kernel_initializer=w_init, name='sigma')
with tf.variable_scope('critic'):
l_c = tf.layers.dense(self.s, 100, tf.nn.relu6, kernel_initializer=w_init, name='lc')
v = tf.layers.dense(l_c, 1, kernel_initializer=w_init, name='v')  # state value
a_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope=scope + '/actor')
c_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope=scope + '/critic')
return mu, sigma, v, a_params, c_params

def update_global(self, feed_dict):  # run by a local
SESS.run([self.update_a_op, self.update_c_op], feed_dict)  # local grads applies to global net

def pull_global(self):  # run by a local
SESS.run([self.pull_a_params_op, self.pull_c_params_op])

def choose_action(self, s):  # run by a local
s = s[np.newaxis, :]
return SESS.run(self.A, {self.s: s})



因为开启的是线程，所以将核心操作代码都放在了Worker类中

class Worker(object):
def __init__(self, name, globalAC):
# 创建游戏环境
self.env = gym.make(GAME).unwrapped
# 线程名
self.name = name
# 线程名传入神经网络
self.AC = ACNet(name, globalAC)

def work(self):
# 回合制循环
global GLOBAL_RUNNING_R, GLOBAL_EP
total_step = 1
buffer_s, buffer_a, buffer_r = [], [], []
while not COORD.should_stop() and GLOBAL_EP < MAX_GLOBAL_EP:
s = self.env.reset() #重置环境
ep_r = 0 #总价值
for ep_t in range(MAX_EP_STEP):
# 最大步数的循环
# if self.name == 'W_0':
#     self.env.render()
# 通过网络选择动作
a = self.AC.choose_action(s)
# 环境检测当前状态的观测值，价值，是否结束，，，
s_, r, done, info = self.env.step(a)
# 如果没结束，但是走到最大步数时也结束
done = True if ep_t == MAX_EP_STEP - 1 else False
# 累计总价值
ep_r += r
# 记忆库存储，让价值符合正态分布
buffer_s.append(s)
buffer_a.append(a)
buffer_r.append((r + 8) / 8)  # normalize

if total_step % UPDATE_GLOBAL_ITER == 0 or done:  # update global and assign to local net
if done:
v_s_ = 0  # terminal
else:
v_s_ = SESS.run(self.AC.v, {self.AC.s: s_[np.newaxis, :]})[0, 0]
#
buffer_v_target = []
for r in buffer_r[::-1]:  # reverse buffer r
v_s_ = r + GAMMA * v_s_
buffer_v_target.append(v_s_)
#     将结果反向传递到ACNet神经网络中
buffer_v_target.reverse()
# 没有创建记忆库，还是使用最初的QLearning 调用np.hstack栈存储
buffer_s, buffer_a, buffer_v_target = np.vstack(buffer_s), np.vstack(buffer_a), np.vstack(
buffer_v_target)
# 将占位符的值传递到ACNet神经网络中
feed_dict = {
self.AC.s: buffer_s,
self.AC.a_his: buffer_a,
self.AC.v_target: buffer_v_target,
}
# 更新网络权重参数
self.AC.update_global(feed_dict)
# 清空记忆库
buffer_s, buffer_a, buffer_r = [], [], []
self.AC.pull_global()
# 赋值为下一个观测值
s = s_
# 下一步
total_step += 1
if done:
if len(GLOBAL_RUNNING_R) == 0:  # record running episode reward
GLOBAL_RUNNING_R.append(ep_r)
else:
# 价值等于0.95历史价值，和当前价值的0.05
GLOBAL_RUNNING_R.append(0.9 * GLOBAL_RUNNING_R[-1] + 0.1 * ep_r)
print(
self.name,
"Ep:", GLOBAL_EP,
"| Ep_r: %i" % GLOBAL_RUNNING_R[-1],
)
GLOBAL_EP += 1
break


展开全文
• 这样一来一回, 形成了一种有效率的强化学习方式. 我们知道目前的计算机多半是有双核, 4核, 甚至 6核, 8核. 一般的学习方法, 我们只能让机器人在一个核上面玩耍. 但是如果使用 A3C 的方法, 我们可以给他们安排去不同...
• ## 深度强化学习——A3C

万次阅读 多人点赞 2017-06-13 20:32:33
异步的优势行动者评论家算法（Asynchronous Advantage Actor-Critic，A3C）是Mnih等人根据异步强化学习（Asynchronous Reinforcement Learning， ARL） 的思想，提出的一 种轻量级的 DRL 框架，该框架可以使用异步的...
• 简单介绍A3C （第五部分） 从本系列课程开始，我们研究了两种不同的强化学习方法： 基于数值的方法（Q-learning，Deep Q-learning）：该方法是学习一个值函数，该值函数将每组状态、动作映射到一个数值。多亏了这个...
• for p in threads: p.join() global_model.save_weights('./A3C_LunarLander_2e3_epochs.h5') plt.plot(rewards_plt) plt.show() plt.plot(losses_plt) plt.show() 训练2000轮的奖励变化 训练2000轮的loss变化
• 本项目利用深度强化学习中的A3C算法提取某支股票的历史数据特征，然后预测未来15天的收盘价格走势。 注： 1）本项目使用tensorflow1.14版本。 2）投资有风险，理财需谨慎。 3）本人选择某股训练结果如下，通过实践...
• 包括DP, MC, TD, TD-lambda, DQN, PG, AC, A3C, DDPG, Dyna_Q, Bandit, AlphaGoBangZero以及部分仿真游戏源码
• ## 强化学习(十五) A3C

千次阅读 2019-08-01 10:50:35
• 本课程是一次理论+实战的结合，首先介绍强化学习的模型原理，详解A3C模型的原理，其次通过实践落实强化学习在游戏中的应用。
• 为此，DeeoMind团队提出了一种新的算法，称为异步优势行为者评论家(A3C)算法，该算法要优于其他深度强化学习算法，因为其需要较少的计算能力和训练时间。A3C的主要思想是通过多个智能体并行学习并整合其所有经验。 ...
• ## 学习笔记：强化学习之A3C代码详解

千次阅读 多人点赞 2018-11-18 15:34:21
• 论文共实现了四种异步训练的强化学习算法，分别是one-step Q-learning, one-step Sarsa, n-step Q-learning, and advantage actor-critic（A3C）。 不同线程的agent，其探索策略不同以保证多样性，不需要经验...
• 基于python的强化学习算法A3C设计与实现
• 与其他强化学习库（例如著名的 ， 和。 Machin尝试仅提供RL算法的简单明了的实现。 Machin中的所有算法均以最小的抽象设计，并具有非常详细的文档以及各种有用的教程。 2.可重复使用 Machin采用与pytorch类似的方法...
• 基于策略搜索的强化学习方法 1.policy gridient 1.1 基础推导 1.2 Tip Tip1： add a baseline（增加基线） 因为原来的梯度，一直都会取正数，不是特别合适，但是这样其实无可厚非，因为可以用过大小进行区分，但...
• 随机选择action 特别感谢这位博主的分享，代码亲测注释详细、效果超群 ... QLearning选择action 同样非常感谢这位博主的分享，代码亲测...A3C训练小车爬山 感谢这位博主的分享，这是一份言简意赅的代码，训练过程中小车..
• # A3C做出的改进： # 解决AC难以收敛的问题 # 不一样的地方： # import threading # import tensorflow as tf import tensorflow.compat.v1 as tf tf.compat.v1.disable_eager_execution() import numpy as np ...

...