思考

模型:智能体交互的环境模型,简单来说:就是状态转移函数和奖励函数进行建模。

回想一下:

基于模型的强化学习:动态规划(价值迭代、策略迭代)--事先知道的模型或者根据交互数据学习得到模型

无模型的强化学习:Sarsa,Q-learning ---交互数据进行,直接进行最优Q,V,\pi的估计

对于根据交互数据学习得到模型的算法:Dyna-Q算法

Dyna-Q算法-离散且确定的环境

(dynamic -Q动态Q算法)

 如上图所示:

智能体先与环境模型(一般都会事先给出,比如冰湖环境中的起点和终点和悬崖,比较简单,但是具体的状态转移函数和)交互,产生模拟数据,基于这些模拟数据进行强化学习。经过模拟学习的智能体与真实环境交互,产生经验数据。这些数据又可以反馈优化智能体。

具体来说:

Dyna-Q使用一种叫做Q-planing的方法来基于模型生成一些模拟数据,然后用模拟数据和真实数据一起改进策略。Q-planning每次选取一个曾经发放问过的状态s,采取一个曾经在该状态下执行过的动作a,通过环境模型得到转移后的状态s'以及奖励r,并根据这个模拟数据(s,a,r,s'),用Q-learning的方法来更新动作价值函数

伪代码

  • 初始化Q(s,a),初始化模型M(s,a)
  • for 序列e = 1 \rightarrow E do:
    • 得到初始状态s
    • for t = 1\rightarrowT do:
      • 用不完全贪婪策略根据Q选择当前状态s下的动作a
      • 得到环境反馈的r,s'
      • Q\left(s_t, a_t\right) \leftarrow Q\left(s_t, a_t\right)+\alpha\left[R_t+\gamma \max _a Q\left(s_{t+1}, a\right)-Q\left(s_t, a_t\right)\right]
      • M(s,a)\rightarrow r,s'       -----到现在环境交互完成,生成模拟环境模型M,后续该用这M使用Q-planning产生模拟数据,在下一个大循环中使用模拟数据和真实数据一起改进模型
      • for 次数 n =1 \rightarrow N do:
        • 随机选择一个曾经在状态s_{m}
        • 采取一个曾经在状态s_{m}下执行过的动作a_{m}
        • r_{m},s'_{m} \leftarrow M(s_{m},a_{m})
        • Q\left(s_m, a_m\right) \leftarrow Q\left(s_m, a_m\right)+\alpha\left[R_m+\gamma \max _a Q\left(s'_{m}, a'\right)-Q\left(s_m, a_m\right)\right]
      • end for 
      • s\leftarrow s'
    • end for 
  • end for

理解一下物理意义:

使用一种策略\pi,在t时刻的状态s下与环境交互后生成数据,然后计算该时刻下的价值,使用的就是max()方法了,等到这些都完成之后,下一个循环之前会使用这些数据的模拟环境模型去改进曾经访问过的状态(如果没有这一步,就是Q-learning),在下一个时刻的循环时,已经将之前的状态都更新完了

从伪代码看Q-learning 和 Dyna-Q的区别:

做n次Q-planning(他的方法其实就是Q-learning),n = 0时就是Q-learning了, n越大,收敛速度越快(一般情况下,并不是一定的 ),因为模拟环境模型越来越接近环境模型了。

代码

import matplotlib.pyplot as plt
import numpy as np
from tqdm import tqdm
import random
import time


class CliffWalkingEnv:
    def __init__(self, ncol, nrow):
        self.nrow = nrow
        self.ncol = ncol
        self.x = 0  # 记录当前智能体位置的横坐标
        self.y = self.nrow - 1  # 记录当前智能体位置的纵坐标

    def step(self, action):  # 外部调用这个函数来改变当前位置
        # 4种动作, change[0]:上, change[1]:下, change[2]:左, change[3]:右。坐标系原点(0,0)
        # 定义在左上角
        change = [[0, -1], [0, 1], [-1, 0], [1, 0]]
        self.x = min(self.ncol - 1, max(0, self.x + change[action][0]))
        self.y = min(self.nrow - 1, max(0, self.y + change[action][1]))
        next_state = self.y * self.ncol + self.x
        reward = -1
        done = False
        if self.y == self.nrow - 1 and self.x > 0:  # 下一个位置在悬崖或者目标
            done = True
            if self.x != self.ncol - 1:
                reward = -100
        return next_state, reward, done

    def reset(self):  # 回归初始状态,起点在左上角
        self.x = 0
        self.y = self.nrow - 1
        return self.y * self.ncol + self.x

修改Q-learning算法,加入model模型,字典的性质,重复数据不会添加多次

class DynaQ:
    """ Dyna-Q算法 """
    def __init__(self,
                 ncol,
                 nrow,
                 epsilon,
                 alpha,
                 gamma,
                 n_planning,
                 n_action=4):
        self.Q_table = np.zeros([nrow * ncol, n_action])  # 初始化Q(s,a)表格
        self.n_action = n_action  # 动作个数
        self.alpha = alpha  # 学习率
        self.gamma = gamma  # 折扣因子
        self.epsilon = epsilon  # epsilon-贪婪策略中的参数

        self.n_planning = n_planning  #执行Q-planning的次数, 对应1次Q-learning
        self.model = dict()  # 环境模型,键:状态动作对;值:奖励和下一个状态

    def take_action(self, state):  # 选取下一步的操作
        if np.random.random() < self.epsilon:
            action = np.random.randint(self.n_action)
        else:
            action = np.argmax(self.Q_table[state])
        return action

    def q_learning(self, s0, a0, r, s1):
        td_error = r + self.gamma * self.Q_table[s1].max(
        ) - self.Q_table[s0, a0]
        self.Q_table[s0, a0] += self.alpha * td_error

    def update(self, s0, a0, r, s1):
        self.q_learning(s0, a0, r, s1)
        self.model[(s0, a0)] = r, s1  # 将数据添加到模型中
        for _ in range(self.n_planning):  # Q-planning循环
            # 随机选择曾经遇到过的状态动作对
            (s, a), (r, s_) = random.choice(list(self.model.items()))
            self.q_learning(s, a, r, s_)

 运行

def DynaQ_CliffWalking(n_planning):
    ncol = 12
    nrow = 4
    env = CliffWalkingEnv(ncol, nrow)
    epsilon = 0.01
    alpha = 0.1
    gamma = 0.9
    agent = DynaQ(ncol, nrow, epsilon, alpha, gamma, n_planning)
    num_episodes = 300  # 智能体在环境中运行多少条序列

    return_list = []  # 记录每一条序列的回报
    for i in range(10):  # 显示10个进度条
        # tqdm的进度条功能
        with tqdm(total=int(num_episodes / 10),
                  desc='Iteration %d' % i) as pbar:
            for i_episode in range(int(num_episodes / 10)):  # 每个进度条的序列数
                episode_return = 0
                state = env.reset()
                done = False
                while not done:
                    action = agent.take_action(state)
                    next_state, reward, done = env.step(action)
                    episode_return += reward  # 这里回报的计算不进行折扣因子衰减
                    agent.update(state, action, reward, next_state)
                    state = next_state
                return_list.append(episode_return)
                if (i_episode + 1) % 10 == 0:  # 每10条序列打印一下这10条序列的平均回报
                    pbar.set_postfix({
                        'episode':
                        '%d' % (num_episodes / 10 * i + i_episode + 1),
                        'return':
                        '%.3f' % np.mean(return_list[-10:])
                    })
                pbar.update(1)
    return return_list
np.random.seed(0)
random.seed(0)
n_planning_list = [0, 2, 20]
for n_planning in n_planning_list:
    print('Q-planning步数为:%d' % n_planning)
    time.sleep(0.5)
    return_list = DynaQ_CliffWalking(n_planning)
    episodes_list = list(range(len(return_list)))
    plt.plot(episodes_list,
             return_list,
             label=str(n_planning) + ' planning steps')
plt.legend()
plt.xlabel('Episodes')
plt.ylabel('Returns')
plt.title('Dyna-Q on {}'.format('Cliff Walking'))
plt.show()

 总结

回顾一下学过的算法,我i们这里做一个图

首先说一个概念,大家可能会将奖励和奖励函数混为一谈,他们不是一个概念

奖励是在强化学习等场景中,环境对智能体所采取的动作给出的反馈信号,用于表示该动作的好坏程度,是一个数值。比如在机器人导航任务中,成功到达目标给予正奖励,碰到障碍给与负奖励。--------即时的反馈

奖励函数;是一个映射,将 智能体所处的状态s ,a, 下一个状态 s'   映射为一个奖励值,是一个数学函数,用于定义在不同情况下智能体应该获得的奖励。----决定学习目标和行为策略

以上前五节的算法都是关于离散空间的

下面就开始连续空间的了

记住伪代码的区别:

策略迭代

 价值迭代

Sarsa

 

 Q-learning

 Dyna-Q

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐