强化学习 -第三章 TD (Q_learning)

上一章与本章衔接的一个习题:无偏估计与有偏估计

方差越来越大: 

         它这里的第n步不是指更新了n次,而指的是,从现在这个(s,a)开始,往后取n个(r,s,a)数值对,用那n个的(r,s,a)数值对更新现在这个(s,a)的价值,n取得越大,越接近于monte carlo法。
         monte carlo法是一种无偏估计,也就是它是正儿八经去采样了,去执行了后面的状态和动作,用这些执行后的结果来更新,这些结果是真实数据,没有利用统计方法或其他方法进行数值平滑化,因此无偏估计的方差,相比起加入了数学方法的有偏估计的方差,会大一点。
因此一言以蔽之,n越大,越接近monte carlo法,越接近无偏估计,方差越大。

【因为方差描述的是预测值的变化范围、离散程度,而无偏估计更贴近直接采样,不确定性更大一些,因此离散程度会更高,距离根据无偏估计算出来的期望值的距离之和也会更大,因此方差更大】

 蒙特卡洛

      直接把N(St​)/1​ 变成 α (学习率)【超参数】,α 代表着更新的速率有多快,我们可以进行设置。

在每个回合中,如果在时间步 t 状态 s 被访问了,那状态 s 的访问数 N(s) 增加 1。 已经把一条轨迹跑完了,可以算每个状态实际的 return。没用 bootstrapping,因为它是根据实际的 return 来更新。

TD

 TD(0),每往前走一步,就做一步 bootstrapping,用得到的估计回报(estimated return)来更新上一时刻的值。【自举】一步一更新。

 之前是只往前走一步,即 one-step TD,TD(0)。可以调整步数,变成 n-step TD。比如 TD(2),即往前走两步,然后利用两步得到的 return,使用 bootstrapping 来更新状态的价值。

model-free control

   对于  未知  奖励R 和 状态转移P,无法使用 动态规划 (贝尔曼最优方程),所以 采用 Monte Carlo 的方式 去 估计 Q函数。

   为了确保 MC 方法能够有足够的探索,我们使用了ε-greedy   【超参数】exploration。策略会不断改变(epsilon  ε 会不断变小)

对比之前的 greedy ,增加 了 探索 到别的策略的可能性

 

 Q_learning  和  SARSA

  • Sarsa 是 Rt+1​+γQ(St+1​,At+1​) ;只有一个策略 policy π ,既用于 与环境交互 ,又用来 利用 ,要用到的 At+1 是下一步 step 一定 会去执行的 action 。 所以  在探索时 会相对保守 
  • Q-learning 是Rt+1​+γmaxa​Q(St+1​,a) 。有两个策略 ,一个 behavior policy  μ 可以是一个随机的 policy ,是一个 勇士 会进行 各种尝试 ,更新 Q-table ,另一个Target policy π 直接在 Q-table 上取 greedy ,选择最优的那一个 。

代码实践

import math

import gym
import numpy as np
import turtle
from collections import defaultdict

from matplotlib import pyplot as plt
import seaborn as sns



class QLearning(object):
    def __init__(self, n_states, n_actions, cfg):
        self.n_actions = n_actions
        self.lr = cfg.lr  # 学习率
        self.gamma = cfg.gamma
        self.epsilon = 0
        self.sample_count = 0
        self.epsilon_start = cfg.epsilon_start
        self.epsilon_end = cfg.epsilon_end
        self.epsilon_delay = cfg.epsilon_delay
        self.Q_table = defaultdict(lambda: np.zeros(n_actions)) # 用嵌套字典存放状态->动作->状态-动作值(Q值)的映射,即Q表
    def choose_action(self, state):
        self.sample_count += 1
        self.epsilon = self.epsilon_end + (self.epsilon_start - self.epsilon_end) * \
            math.exp(-1. * self.sample_count / self.epsilon_delay) # epsilon是会递减的,这里选择指数递减
        # e-greedy 策略
        if np.random.uniform(0, 1) > self.epsilon:
            action = np.argmax(self.Q_table[str(state)]) # 选择Q(s,a)最大对应的动作
        else:
            action = np.random.choice(self.n_actions) # 随机选择动作
        return action
    def predict(self,state):
        action = np.argmax(self.Q_table[str(state)])
        return action
    def update(self, state, action, reward, next_state, done):
        Q_predict = self.Q_table[str(state)][action]
        if done: # 终止状态
            Q_target = reward
        else:
            Q_target = reward + self.gamma * np.max(self.Q_table[str(next_state)])
        self.Q_table[str(state)][action] += self.lr * (Q_target - Q_predict)




class Config():
    def __init__(self):
        self.lr = 0.01
        self.gamma = 0.9
        self.epsilon_start = 0.95
        self.epsilon_end = 0.01
        self.epsilon_delay = 300
        self.train_episode = 50



def train(cfg,env,agent):  # 与环境交互
    print('开始训练!')

    rewards = []  # 记录奖励
    for i_ep in range(cfg.train_episode):
        ep_reward = 0  # 记录每个回合的奖励
        state = env.reset()  # 重置环境,即开始新的回合
        while True:
            action = agent.choose_action(state)  # 根据算法选择一个动作
            next_state, reward, done, _ = env.step(action)  # 与环境进行一次动作交互
            agent.update(state, action, reward, next_state, done)  # Q学习算法更新
            state = next_state  # 更新状态
            ep_reward += reward
            if done:
                break
        rewards.append(ep_reward)
        print("回合数:{}/{},奖励{:.1f}".format(i_ep+1, cfg.train_episode,ep_reward))
    print('完成训练!')
    return rewards

env = gym.make('CliffWalking-v0')  ## *定义环境
#env = CliffWalkingWapper(env)  ### !!! 2. 定义动作导致状态变化。。修饰环境。。
states = env.observation_space.n
actions = env.action_space.n
cfg = Config()
agent = QLearning(states, actions, cfg)
# print(f"state_number:{states},action_number:{actions}")

env.seed(10)

reward = train(cfg,env,agent)
plt.figure()
plt.plot(reward)
# plt.legend()
plt.show()

env.close()

注::(提醒自己!!)

  • += 是简写,a += 1就是a = a+1
  • =+并不是简写,a =+ a直接对a的赋值,±符号代表的是正负(完全可以省略不写),即a =+ b其实就是a = b。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值