强化学习--Deep Deterministic Policy Gradient

系列文章目录

强化学习


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


前言

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


一、强化学习是什么?

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

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

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

二、核心算法(深度强化学习)Deep Deterministic Policy Gradient

什么是Actor-Critic ?
Actor-Critic算法分为两部分,我们分开来看actor的前身是policy gradient他可以轻松地在连续动作空间内选择合适的动作,value-based的Qlearning做这件事就会因为空间过大而爆炸,但是又因为Actor是基于回合更新的所以学习效率比较慢,这时候我们发现可以使用一个value-based的算法作为Critic就可以实现单步更新。这样两种算法相互补充就形成了Actor-Critic。
这跟深度学习中的对抗神经网络思想类似,一个生成器一个判别器对应的就是Actor与Critic。
优势:可以进行单步更新, 相较于传统的PG回合更新要快.
劣势:Actor的行为取决于 Critic 的Value,但是因为 Critic本身就很难收敛和actor一起更新的话就更难收敛了。
为了解决收敛问题, Deepmind 提出了 Actor Critic 升级版 Deep Deterministic Policy Gradient,所以DDPG可以看成Actor Critic+DQN的版本。

Actor Critic分别是两个神经网络,Actor主要是为了动作的选择存储,而Critic主要是对当前状态价值的评估,也就是Q现实-Q预测之间的误差,转递给Actor。就好像中国好声音,台上的Actor演唱完后,导师Critic告诉你某个地方唱得好,那个地方不满意。
对于网络的可视化可以看出,Critic的输入是在当前环境所处的状态,最后返回一个TD误差,Actor输入的是当前状态,选择动作,TD误差。在这里插入图片描述在这里插入图片描述

import numpy as np
import tensorflow as tf
import gym

np.random.seed(2)
tf.set_random_seed(2)  # reproducible

# Tensorboard可视化
OUTPUT_GRAPH = True
MAX_EPISODE = 3000  #最大存储空间
DISPLAY_REWARD_THRESHOLD = 200  # renders environment if total episode reward is greater then this threshold
MAX_EP_STEPS = 1000   # 一轮最大的步数
RENDER = False  # 是否显示游戏界面
GAMMA = 0.9     # TD误差的衰减率
LR_A = 0.001    # Actor的学习率
LR_C = 0.01     # Critic的学习率

env = gym.make('CartPole-v1')
env.seed(1)  # reproducible
env = env.unwrapped

N_F = env.observation_space.shape[0] #获取初始环境
N_A = env.action_space.n #获取可操作的动作情况


class Actor(object):
    def __init__(self, sess, n_features, n_actions, lr=0.001):
        self.sess = sess

        self.s = tf.placeholder(tf.float32, [1, n_features], "state")
        self.a = tf.placeholder(tf.int32, None, "act")
        self.td_error = tf.placeholder(tf.float32, None, "td_error")  # TD_error

        with tf.variable_scope('Actor'):
            l1 = tf.layers.dense(
                inputs=self.s,
                units=20,    # number of hidden units
                activation=tf.nn.relu,
                kernel_initializer=tf.random_normal_initializer(0., .1),    # weights
                bias_initializer=tf.constant_initializer(0.1),  # biases
                name='l1'
            )

            self.acts_prob = tf.layers.dense(
                inputs=l1,
                units=n_actions,    # output units
                activation=tf.nn.softmax,   # get action probabilities
                kernel_initializer=tf.random_normal_initializer(0., .1),  # weights
                bias_initializer=tf.constant_initializer(0.1),  # biases
                name='acts_prob'
            )

        with tf.variable_scope('exp_v'):
            log_prob = tf.log(self.acts_prob[0, self.a])
            self.exp_v = tf.reduce_mean(log_prob * self.td_error)  # advantage (TD_error) guided loss

        with tf.variable_scope('train'):
            self.train_op = tf.train.AdamOptimizer(lr).minimize(-self.exp_v)  # minimize(-exp_v) = maximize(exp_v)

    def learn(self, s, a, td):
        s = s[np.newaxis, :]
        feed_dict = {self.s: s, self.a: a, self.td_error: td}
        _, exp_v = self.sess.run([self.train_op, self.exp_v], feed_dict)
        return exp_v

    def choose_action(self, s):
        s = s[np.newaxis, :]
        probs = self.sess.run(self.acts_prob, {self.s: s})   # get probabilities for all actions
        return np.random.choice(np.arange(probs.shape[1]), p=probs.ravel())   # return a int


class Critic(object):
    def __init__(self, sess, n_features, lr=0.01):
        self.sess = sess

        self.s = tf.placeholder(tf.float32, [1, n_features], "state")
        self.v_ = tf.placeholder(tf.float32, [1, 1], "v_next")
        self.r = tf.placeholder(tf.float32, None, 'r')

        with tf.variable_scope('Critic'):
            l1 = tf.layers.dense(
                inputs=self.s,
                units=20,  # number of hidden units
                activation=tf.nn.relu,  # None
                # have to be linear to make sure the convergence of actor.
                # But linear approximator seems hardly learns the correct Q.
                kernel_initializer=tf.random_normal_initializer(0., .1),  # weights
                bias_initializer=tf.constant_initializer(0.1),  # biases
                name='l1'
            )

            self.v = tf.layers.dense(
                inputs=l1,
                units=1,  # output units
                activation=None,
                kernel_initializer=tf.random_normal_initializer(0., .1),  # weights
                bias_initializer=tf.constant_initializer(0.1),  # biases
                name='V'
            )

        with tf.variable_scope('squared_TD_error'):
            self.td_error = self.r + GAMMA * self.v_ - self.v
            self.loss = tf.square(self.td_error)    # TD_error = (r+gamma*V_next) - V_eval
        with tf.variable_scope('train'):
            self.train_op = tf.train.AdamOptimizer(lr).minimize(self.loss)

    def learn(self, s, r, s_):
        s, s_ = s[np.newaxis, :], s_[np.newaxis, :]

        v_ = self.sess.run(self.v, {self.s: s_})
        td_error, _ = self.sess.run([self.td_error, self.train_op],
                                          {self.s: s, self.v_: v_, self.r: r})
        return td_error


sess = tf.Session()

actor = Actor(sess, n_features=N_F, n_actions=N_A, lr=LR_A)
critic = Critic(sess, n_features=N_F, lr=LR_C)     # we need a good teacher, so the teacher should learn faster than the actor

sess.run(tf.global_variables_initializer())

# 是否Tensorboard可视化
if OUTPUT_GRAPH:
    tf.summary.FileWriter("logs/", sess.graph)
# 类似Policy Gradient的学习情况(回合制)
for i_episode in range(MAX_EPISODE):
    s = env.reset()#初始化环境
    t = 0 
    track_r = []
    while True:
        # 是否显示游戏界面
        if RENDER: env.render()
        # 选择动作
        a = actor.choose_action(s)
        #当前动作后的状态,返回预测下一个观测值,价值,是否结束,info信息
        s_, r, done, info = env.step(a)
        # 如果结束了价值为-20
        if done: r = -20
        # 存储当前价值
        track_r.append(r)
        # 得到当前状态和预测下一个状态之间的价值 TD误差
        td_error = critic.learn(s, r, s_)  # gradient = grad[r + gamma * V(s_) - V(s)]
        # actor神经网络根据得到的误差对当前状态进行训练选择更有价值的动作
        actor.learn(s, a, td_error)     # true_gradient = grad[logPi(s,a) * td_error]
        
        # 赋值为下一个观测值
        s = s_
        # 下一步
        t += 1
        # 如果当前结束或者轮次到达最大步数
        if done or t >= MAX_EP_STEPS:
            # 将存储价值的数组统计当前步数的总价值
            ep_rs_sum = sum(track_r)
            # 如果未定义running_reward,将总价值赋值
            if 'running_reward' not in globals():
                running_reward = ep_rs_sum
            else:
                # 否则获得前一轮总价值和当前轮总价值的概率发生变化
                running_reward = running_reward * 0.95 + ep_rs_sum * 0.05
            #     如果价值大于200,就显示游戏界面
            if running_reward > DISPLAY_REWARD_THRESHOLD: RENDER = True  # rendering
            # 输出轮次和当前轮次下步数的总价值,最后结束死循环
            print("episode:", i_episode, "  reward:", int(running_reward))
            break

DDPG基于Actor_Critic中改善了啥呢?

Deep指的是和DQN一样使用一个记忆库存储当前状态,动作,价值, Policy Gradient是回合制,对一回合内连续的结果做价值评估,Deterministic改变了输出动作的随机过程,让回合制只输出一个动作值,,DDPG的神经网络也是使用的Actor和Critic的神经网络。

在这里插入图片描述
在这里插入图片描述

import tensorflow as tf
import numpy as np
import gym
import time


#####################  hyper parameters  ####################

MAX_EPISODES = 200   #规定轮次
MAX_EP_STEPS = 200 #每轮次最大步数
LR_A = 0.001    # learning rate for actor
LR_C = 0.002    # learning rate for critic
GAMMA = 0.9     # reward discount
TAU = 0.01      # soft replacement
MEMORY_CAPACITY = 10000#记忆库最大存储空间
BATCH_SIZE = 32 #每批次进入的神经元数量(存储记忆库中的批次)

RENDER = False  #游戏界面可视化
ENV_NAME = 'Pendulum-v1' #旋转让指针立起来的游戏,这是个连续性的游戏


###############################  DDPG  ####################################

# 建立DDPG神经网络
class DDPG(object):
    def __init__(self, a_dim, s_dim, a_bound,):
        # 记忆库初始化,可以试着用sumTree的方式改进
        self.memory = np.zeros((MEMORY_CAPACITY, s_dim * 2 + a_dim + 1), dtype=np.float32)
        self.pointer = 0 #记忆库存储内容条目计数
        self.sess = tf.Session() #创建神经网络会话
        # 存储该游戏的动作,初始环境状态,动作的最高值
        self.a_dim, self.s_dim, self.a_bound = a_dim, s_dim, a_bound,
        # 建立观测值情况占位符
        self.S = tf.placeholder(tf.float32, [None, s_dim], 's')
        # 建立预测观测值情况占位符
        self.S_ = tf.placeholder(tf.float32, [None, s_dim], 's_')
        # 建立价值占位符
        self.R = tf.placeholder(tf.float32, [None, 1], 'r')
        # 调用建立Actor网络的值,获得Deterministic选的动作
        self.a = self._build_a(self.S,)
        # 根据观测值和选择的动作获得 TD误差
        q = self._build_c(self.S, self.a, )
        # 将两个神经网络的变量收集起来
        a_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='Actor')
        c_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='Critic')
        # 调节指数加权平均衰减值
        ema = tf.train.ExponentialMovingAverage(decay=1 - TAU)          # soft replacement

        def ema_getter(getter, name, *args, **kwargs):
            return ema.average(getter(name, *args, **kwargs))
        # 调整指数加权平均更新参数和保留历史参数
        target_update = [ema.apply(a_params), ema.apply(c_params)]      # soft update operation
        a_ = self._build_a(self.S_, reuse=True, custom_getter=ema_getter)   # replaced target parameters
        q_ = self._build_c(self.S_, a_, reuse=True, custom_getter=ema_getter)

        a_loss = - tf.reduce_mean(q)  # maximize the q
        # 添加损失和优化器
        self.atrain = tf.train.AdamOptimizer(LR_A).minimize(a_loss, var_list=a_params)

        with tf.control_dependencies(target_update):    # soft replacement happened at here
            # 获取q现实
            q_target = self.R + GAMMA * q_
            # 获取q现实和q预测之间的价值误差
            td_error = tf.losses.mean_squared_error(labels=q_target, predictions=q)
            self.ctrain = tf.train.AdamOptimizer(LR_C).minimize(td_error, var_list=c_params)

        self.sess.run(tf.global_variables_initializer())

    # 动作选取,deterministic 直接选择
    def choose_action(self, s):
        return self.sess.run(self.a, {self.S: s[np.newaxis, :]})[0]

    # 学习并随机抽取记忆库参数学习
    def learn(self):
        indices = np.random.choice(MEMORY_CAPACITY, size=BATCH_SIZE)
        bt = self.memory[indices, :]
        bs = bt[:, :self.s_dim]
        ba = bt[:, self.s_dim: self.s_dim + self.a_dim]
        br = bt[:, -self.s_dim - 1: -self.s_dim]
        bs_ = bt[:, -self.s_dim:]

        self.sess.run(self.atrain, {self.S: bs})
        self.sess.run(self.ctrain, {self.S: bs, self.a: ba, self.R: br, self.S_: bs_})
    # 记忆库存储内容
    def store_transition(self, s, a, r, s_):
        transition = np.hstack((s, a, [r], s_))
        index = self.pointer % MEMORY_CAPACITY  # replace the old memory with new memory
        self.memory[index, :] = transition
        self.pointer += 1
    # actor神经网络
    def _build_a(self, s, reuse=None, custom_getter=None):
        trainable = True if reuse is None else False
        with tf.variable_scope('Actor', reuse=reuse, custom_getter=custom_getter):
            net = tf.layers.dense(s, 30, activation=tf.nn.relu, name='l1', trainable=trainable)
            a = tf.layers.dense(net, self.a_dim, activation=tf.nn.tanh, name='a', trainable=trainable)
            return tf.multiply(a, self.a_bound, name='scaled_a')
    # critic神经网络
    def _build_c(self, s, a, reuse=None, custom_getter=None):
        trainable = True if reuse is None else False
        with tf.variable_scope('Critic', reuse=reuse, custom_getter=custom_getter):
            n_l1 = 30
            w1_s = tf.get_variable('w1_s', [self.s_dim, n_l1], trainable=trainable)
            w1_a = tf.get_variable('w1_a', [self.a_dim, n_l1], trainable=trainable)
            b1 = tf.get_variable('b1', [1, n_l1], trainable=trainable)
            net = tf.nn.relu(tf.matmul(s, w1_s) + tf.matmul(a, w1_a) + b1)
            return tf.layers.dense(net, 1, trainable=trainable)  # Q(s,a)


###############################  training  ####################################

env = gym.make(ENV_NAME) #创建指针游戏
env = env.unwrapped  #解压
env.seed(1) #为此环境的随机数生成器设置种子

s_dim = env.observation_space.shape[0] #得到当前初始化环境状态值
a_dim = env.action_space.shape[0]#获取动作可选值
a_bound = env.action_space.high #获得动作的最高值

ddpg = DDPG(a_dim, s_dim, a_bound)#调用DDPG

var = 3  # control exploration
t1 = time.time()
# policy gradient 回合制框架
for i in range(MAX_EPISODES):
    s = env.reset() #初始化环境
    ep_reward = 0 #该回合价值
    for j in range(MAX_EP_STEPS):
        # 游戏界面可视化
        if RENDER:
            env.render()

        # Add exploration noise
        # 神经网络选择动作
        a = ddpg.choose_action(s)
        # 为探索的动作选择添加随机性
        a = np.clip(np.random.normal(a, var), -2, 2)
        # 获得该动作的下一步状态,价值,是否结束,无用信息
        s_, r, done, info = env.step(a)
        # 开始存储记忆库
        ddpg.store_transition(s, a, r / 10, s_)
        #当前记忆库的存储下标限制
        if ddpg.pointer > MEMORY_CAPACITY:
            var *= .9995    # decay the action randomness
            # 存得差不多就开始学习了
            ddpg.learn()
        # 下一步观测值赋值
        s = s_
        # 累计这一回合的价值
        ep_reward += r
        # 如果到了最后一步就结束当前回合
        if j == MAX_EP_STEPS-1:
            print('Episode:', i, ' Reward: %i' % int(ep_reward), 'Explore: %.2f' % var, )
            # if ep_reward > -300:RENDER = True
            break
# 记录运行时间
print('Running time: ', time.time() - t1)
### 回答1: Deep Deterministic Policy Gradient(DDPG)是一种基于深度神经网络的强化学习算法。它是用来解决连续控制问题的,即输出动作的取值是连续的。DDPG是在DPG(Deterministic Policy Gradient)的基础上进行改进得到的,DPG是一种在连续动作空间中的直接求导策略梯度的方法。DDPG和DPG都属于策略梯度算法的一种,与其他策略梯度算法(如REINFORCE)的不同之处在于,DPG和DDPG都是基于偏微分方程的直接求导,而不是蒙特卡罗方法进行计算。DDPG使用一个确定性策略来生成动作,但同时使用一个噪声过程来扰动输出的动作,以产生更多的状态动作样本。这样一来,DDPG就具有了良好的探索能力,使得它在解决复杂的连续动作问题时能取得较好的效果。 ### 回答2: 深度确定性策略梯度(Deep Deterministic Policy Gradient,DDPG)是一种用于解决深度强化学习问题的方法。 DDPG是基于确定性策略梯度(Deterministic Policy Gradient,DPG)的算法,可以在连续动作空间下进行强化学习。与传统的策略梯度方法不同,DDPG直接学习确定性策略,在给定状态下选择最优的动作。 DDPG主要由两个网络组成:一个是Actor网络,用于学习确定性策略;另一个是Critic网络,用于估计状态-动作对的Q值。Actor网络根据当前状态选择动作,Critic网络根据当前状态和动作的组合估计其对应的Q值。通过不断地交互环境、收集数据和更新网络参数,DDPG算法逐渐优化确定性策略和Q值估计,以使得智能体在环境中获得更高的累积奖励。 DDPG算法的核心思想是通过使用Experience Replay和目标网络来提高学习的稳定性和收敛性。Experience Replay将智能体与环境的交互经验存储在一个经验回放缓冲区中,然后从中随机采样进行训练;目标网络通过延迟更新目标网络的方式,减小训练中的目标值变动,从而提高算法的稳定性。 DDPG算法在解决连续控制任务中表现出良好的性能和收敛性,可以应用于机器人控制、无人驾驶、金融交易等复杂任务中。然而,DDPG算法也存在一些挑战和问题,如对超参数的敏感性、样本效率较低等,这些问题是DDPG算法持续改进的方向之一。 ### 回答3: Deep Deterministic Policy Gradient(DDPG)是一种用于连续动作空间的深度强化学习算法。它结合了深度神经网络和确定性策略梯度的优势,可以应用于诸如机器人控制和金融投资等领域。 DDPG算法的核心思想是通过在连续动作空间中学习一个行动者-评论家系统。行动者使用确定性策略,即给定状态输出一个具体的动作,而评论家则评估行动者的动作质量。这两个网络都是用深度神经网络来表示,并通过梯度下降来进行优化。 在训练过程中,DDPG使用了经验回放缓冲区来存储之前的转换并随机采样进行训练。这样做可以解决样本相关性和非稳定性问题。同时,为了保持算法的探索性,DDPG采用了一个目标网络,用于与主网络进行定期的软更新。 DDPG的优点在于能够处理连续动作空间,通过近似价值函数和策略函数,对高维、非线性状态空间进行建模。此外,DDPG还有很好的收敛性和稳定性,可以在复杂任务中取得较好性能。 然而,DDPG也存在一些挑战。由于使用了神经网络近似值函数,对网络结构的选择和超参数的调整都非常重要。此外,训练过程中可能会出现训练不稳定的问题,需要进行合适的技巧和调整。 总结来说,DDPG是一种深度强化学习算法,适用于连续动作空间的问题。通过结合确定性策略梯度和深度神经网络的优势,DDPG能够解决高维、非线性状态空间的问题,并在复杂任务中取得好的性能。然而,对网络结构和超参数的选择需要仔细调整,且训练过程中可能存在稳定性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值