强化学习之DQN

一.算法详解

DQN是Q-learning的改进,两者都是基于值迭代的算法。但是在Q-learning中,当状态和动作空间是离散且维数是不变时,可使用Q-table储存每个状态动作对应的Q值,而当状态和动作空间是高维连续的,需要使用Q-learning和神经网络相结合,这就成 了DQN。
其实就是Q-learning的框架中加了三样东西
1.experience replay经验池
2.神经网络计算Q值
3.暂时冻结Q-target(固定Q值)

1.1.经验回放(经验池)

使用神经网络的话,其样本数据是独立的,没有关联的,但是强化学习样本数据之间是有关系的,利用off-policy的特点,打乱数据之间的关联才能更好地利用神经网络,然后存储一个batch的数据,所以在这里设置经验池(固定队列的长度),打乱样本之间的相关性,提高样本利用率(将之前的经验重复利用),不会像之前那样用完之后就扔了

1.2.神经网络计算Q值

在这里插入图片描述

我们使用表格来存储每一个状态 state, 和在这个 state 每个行为 action 所拥有的 Q 值. 如果全用表格来存储它们, 恐怕我们的计算机有再大的内存都不够, 而且每次在这么大的表格中搜索对应的状态也是一件很耗时的事. 不过, 在机器学习中, 有一种方法对这种事情很在行, 那就是神经网络. 我们可以将状态和动作当成神经网络的输入, 然后经过神经网络分析后得到动作的 Q 值, 这样我们就没必要在表格中记录 Q 值, 而是直接使用神经网络生成 Q 值. 还有一种形式的是这样, 我们也能只输入状态值, 输出所有的动作值, 然后按照 Q learning 的原则, 直接选择拥有最大值的动作当做下一步要做的动作. 我们可以想象, 神经网络接受外部的信息, 相当于眼睛鼻子耳朵收集信息, 然后通过大脑加工输出每种动作的值, 最后通过强化学习的方式选择动作.

1.3.固定Q值

  1. 由于使用神经网络产生Q值时,Q值具有一定的随机性和不稳定性,在目标值MaxQ那部分是随机的,这个给二者的比较带来了不便,同时也不便于收敛,所以固定Q值,一时间进行更新,这样便于比较。
  2. 使用Q-target会让神经网络中出现两个结构完全相同但是参数却不同的网络,预测Q现实的神经网络TargetNet参数使用的是很久之前的, 预测Q估计的网络MainNet使用的是最新的参数,引入Targ etNet后,每经过一定次数的迭代,将MainNet的参数复制给TargetNet
    在这里插入图片描述

二.马尔科夫决策

2.1要求

1.能够检测出理想的状态
2.可以多次尝试
3.系统的下个状态只与当前状态有关,而与更早之前的状态无关,在决策过程中还和当前采取的动作有关

2.2 由5个元素构成

S: state
A: actions
P:状态转移概率
R: reward function
Y: 折扣系数,表示当下的reward比未来反馈的reward更重要

2.3过程

1.智能体初始为s0
2.选择一个动作a0
3.转移到下一个状态
在这里插入图片描述

三.DQN流程

完整的DQN流程

在这里插入图片描述

DQN代码整体结构

在这里插入图片描述

四.算法流程

公式

Q现实表示当前的Q值
Q估计实现神经网络的更新
在这里插入图片描述

Q(s2,a1),Q(s2,a2)表示Q(s2)估计,然后选取Q估计中最大值的动作来换取环境中的奖励reward,而在Q现实中也包含神经网络中分析出来的Q估计值,这个Q估计是针对在下一个状态s‘的Q估计,最后再通过算法更新来提升神经网络中的参数

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

五.代码详解

import gym
import tensorflow as tf
import numpy as np
import random
from collections import deque

# Hyper Parameters
GAMMA = 0.95 # discount factor
LEARNING_RATE=0.01

class Policy_Gradient():
    def __init__(self, env):
        # init some parameters
        self.time_step = 0
        self.state_dim = env.observation_space.shape[0]
        self.action_dim = env.action_space.n
        self.ep_obs, self.ep_as, self.ep_rs = [], [], []
        self.create_softmax_network()

        # Init session
        self.session = tf.InteractiveSession()
        self.session.run(tf.global_variables_initializer())

    def create_softmax_network(self):
        # network weights
        W1 = self.weight_variable([self.state_dim, 20])
        b1 = self.bias_variable([20])
        W2 = self.weight_variable([20, self.action_dim])
        b2 = self.bias_variable([self.action_dim])
        # input layer
        self.state_input = tf.placeholder("float", [None, self.state_dim])
        self.tf_acts = tf.placeholder(tf.int32, [None, ], name="actions_num")
        self.tf_vt = tf.placeholder(tf.float32, [None, ], name="actions_value")
        # hidden layers
        h_layer = tf.nn.relu(tf.matmul(self.state_input, W1) + b1)
        # softmax layer
        self.softmax_input = tf.matmul(h_layer, W2) + b2
        #softmax output
        self.all_act_prob = tf.nn.softmax(self.softmax_input, name='act_prob')
        self.neg_log_prob = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=self.softmax_input,
                                                                      labels=self.tf_acts)
        self.loss = tf.reduce_mean(self.neg_log_prob * self.tf_vt)  # reward guided loss

        self.train_op = tf.train.AdamOptimizer(LEARNING_RATE).minimize(self.loss)

    def weight_variable(self, shape):
        initial = tf.truncated_normal(shape)
        return tf.Variable(initial)

    def bias_variable(self, shape):
        initial = tf.constant(0.01, shape=shape)
        return tf.Variable(initial)

    def choose_action(self, observation):
        prob_weights = self.session.run(self.all_act_prob, feed_dict={self.state_input: observation[np.newaxis, :]})
        action = np.random.choice(range(prob_weights.shape[1]), p=prob_weights.ravel())  # select action w.r.t the actions prob
        return action

    def store_transition(self, s, a, r):
        self.ep_obs.append(s)
        self.ep_as.append(a)
        self.ep_rs.append(r)

    def learn(self):

        discounted_ep_rs = np.zeros_like(self.ep_rs)
        running_add = 0
        for t in reversed(range(0, len(self.ep_rs))):
            running_add = running_add * GAMMA + self.ep_rs[t]
            discounted_ep_rs[t] = running_add

        discounted_ep_rs -= np.mean(discounted_ep_rs)
        discounted_ep_rs /= np.std(discounted_ep_rs)

        # train on episode
        self.session.run(self.train_op, feed_dict={
             self.state_input: np.vstack(self.ep_obs),
             self.tf_acts: np.array(self.ep_as),
             self.tf_vt: discounted_ep_rs,
        })

        self.ep_obs, self.ep_as, self.ep_rs = [], [], []    # empty episode data
# Hyper Parameters
ENV_NAME = 'CartPole-v0'
EPISODE = 3000 # Episode limitation
STEP = 3000 # Step limitation in an episode
TEST = 10 # The number of experiment test every 100 episode

def main():
  # initialize OpenAI Gym env and dqn agent
  env = gym.make(ENV_NAME)
  agent = Policy_Gradient(env)

  for episode in range(EPISODE):
    # initialize task
    state = env.reset()
    # Train
    for step in range(STEP):
      action = agent.choose_action(state) # e-greedy action for train
      next_state,reward,done,_ = env.step(action)
      agent.store_transition(state, action, reward)
      state = next_state
      if done:
        #print("stick for ",step, " steps")
        agent.learn()
        break

    # Test every 100 episodes
    if episode % 100 == 0:
      total_reward = 0
      for i in range(TEST):
        state = env.reset()
        for j in range(STEP):
          env.render()
          action = agent.choose_action(state) # direct action for test
          state,reward,done,_ = env.step(action)
          total_reward += reward
          if done:
            break
      ave_reward = total_reward/TEST
      print ('episode: ',episode,'Evaluation Average Reward:',ave_reward)

if __name__ == '__main__':
  main()
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值