RL实践3——为Agent添加Policy

2020-09-07 15:02:07 浏览数 (1)

参考自知乎(叶强)

Introduction

在实践2中,介绍了gym环境的定义和使用方法。 在实践1中,介绍了 动态规划DP 求解 价值函数 并没有形成一个策略Policy(pi)来指导agent的动作选取,本节将利用SARSA(0)的学习方法,帮助agent学习到价值函数(表),指导(epsilon)-greedy策略选取动作。

Agent的写法

Agent的三要素是:价值函数、策略、模型 Sarsa(0)是不基于模型的控制,其动作选择策略是(epsilon)-greedy,根据价值函数选择动作。

对于一般问题,Agent包括如下功能

  • 对环境的引用
  • 自身变量:Q值,状态值的记忆
  • 策略方法
  • 动作执行方法
  • 学习方法:改进策略,这部分是关键
代码语言:javascript复制
class Agent():
    def __init__(self, env: Env):
        self.env = env      # 个体持有环境的引用
        self.Q = {}         # 个体维护一张行为价值表Q
        self.state = None   # 个体当前的观测,最好写成obs.

    def performPolicy(self, state): pass # 执行一个策略

    def act(self, a):       # 执行一个行为
        return self.env.step(a)

    def learning(self): pass   # 学习过程

Agent方法

SARSA(0)的伪算法流程如下:

核心方法:learning

代码语言:javascript复制
def learning(self, gamma, alpha, max_episode_num):
    # self.Position_t_name, self.reward_t1 = self.observe(env)
    total_time, time_in_episode, num_episode = 0, 0, 0
    while num_episode < max_episode_num: # 设置终止条件
        self.state = self.env.reset()    # 环境初始化
        s0 = self._get_state_name(self.state) # 获取个体对于观测的命名
        self.env.render()                # 显示UI界面
        a0 = self.performPolicy(s0, num_episode, use_epsilon = True)

        time_in_episode = 0
        is_done = False
        while not is_done:               # 针对一个Episode内部
            # a0 = self.performPolicy(s0, num_episode)
            s1, r1, is_done, info = self.act(a0) # 执行行为
            self.env.render()            # 更新UI界面
            s1 = self._get_state_name(s1)# 获取个体对于新状态的命名
            self._assert_state_in_Q(s1, randomized = True)
            # 获得A'
            a1 = self.performPolicy(s1, num_episode, use_epsilon=True)
            old_q = self._get_Q(s0, a0)  
            q_prime = self._get_Q(s1, a1)
            td_target = r1   gamma * q_prime  
            #alpha = alpha / num_episode
            new_q = old_q   alpha * (td_target - old_q)
            self._set_Q(s0, a0, new_q)

            if num_episode == max_episode_num: # 终端显示最后Episode的信息
                print("t:{0:>2}: s:{1}, a:{2:2}, s1:{3}".
                    format(time_in_episode, s0, a0, s1))

            s0, a0 = s1, a1
            time_in_episode  = 1

        print("Episode {0} takes {1} steps.".format(
            num_episode, time_in_episode)) # 显示每一个Episode花费了多少步
        total_time  = time_in_episode
        num_episode  = 1
    return

策略方法:performPolicy

通过改变use_epsilon参数,可以切换SARSA 和 Q-learning 相同在于:

  • 都用(epsilon)-greedy策略进行了探索

区别在于:

  • Q-learning:更激进,最优更新
    • update: (greedy)策略,评估过程的A'没有实际执行
    • control:(epsilon-greedy)策略
  • SARSA:更新和执行都用(epsilon-greedy)策略
代码语言:javascript复制
def performPolicy(self, s, episode_num, use_epsilon):
    epsilon = 1.00 / (episode_num 1)
    Q_s = self.Q[s]
    str_act = "unknown"
    rand_value = random()
    action = None
    if use_epsilon and rand_value < epsilon:  
        action = self.env.action_space.sample()
    else:
        str_act = max(Q_s, key=Q_s.get)
        action = int(str_act)
    return action    

0 人点赞