[强化学习实战]出租车调度-Q learning & SARSA


代码链接

案例分析

本节考虑Gym库里出租车调度问题(Taxi-v2):在一个5×5方格表示的地图上,有4个出租车停靠点。在每个回合开始时,有一个乘客会随机出现在4个出租车停靠点中的一个,并想在任意一个出租车停靠点下车。出租车会随机出现在25个位置的任意一个位置。出租车需要通过移动自己的位置,到达乘客所在的位置,并将乘客接上车,然后移动到乘客想下车的位置,再让乘客下车。出租车只能在地图范围内上下左右移动一格,并且在有竖线阻拦地方不能横向移动。出租车完成一次任务可以得到20个奖励,每次试图移动得到-1个奖励,不合理地邀请乘客上车(例如目前车和乘客不在同一位置,或乘客已经上车)或让乘客下车(例如车不在目的地,或车上没有乘客)得到-10个奖励。希望调度出租车让总奖励的期望最大。
其中B、G、R、Y是4个上下车点

实验环境使用

Gym库的Taxi-v2环境实现了出租车调度问题的环境。导入环境后,可以用env.reset()来初始化环境,用env.step()来执行一步,用env.render()来显示当前局势。env.render()会打印出的局势图,其中乘客的位置、目的地会用彩色字母显示,出租车的位置会高亮显示。具体而言,如果乘客不在车上,乘客等待地点(位置)的字母会显示为蓝色。目的地所在的字母会显示为洋红色。如果乘客不在车上,出租车所在的位置会用黄色高亮;如果乘客在车上,出租车所在的位置会用绿色高亮。
在这里插入图片描述
这个环境中的观测是一个范围为[0,500)的int型数值。这个数值实际上唯一表示了整个环境的状态。我们可以用env.decode()函数将这个int数值转化为长度为4的元组(taxirow,taxicol,passloc,desti dx),其各元素含义如下:
·taxirow和taxicol是取值为{0,1,2,3,4}的int型变量,表示当前出租车的位置;
·passloc是取值为{0,1,2,3,4}的int型数值,表示乘客的位置,其中0~3表示乘客在表1中对应的位置等待,4表示乘客在车上;
·destidx是取值为{0,1,2,3}的int型数值,表示目的地,目的地的位置由表5-1给出。全部的状态总数为(5×5)×5×4=500。
在这里插入图片描述
这个问题中的动作是取自{0,1,2,3,4,5}的int型数值,其含义下表所示。表中还给出了对应的env.render()函数给出的文字提示以及执行动作后可能得到的奖励值。
在这里插入图片描述
代码清单给出了初始化环境并玩一步的代码。初始化后,借助env.decode()获得了出租车、乘客和目的地的位置,并将地图显示出来,接着试图玩了一步。

import gym
env = gym.make('Taxi-v2')
state = env.reset()
taxirow, taxicol, passloc, destidx = env.unwrapped.decode(state)
print(taxirow, taxicol, passloc, destidx)
print('出租车位置 = {}'.format((taxirow, taxicol)))
print('乘客位置 = {}'.format(env.unwrapped.locs[passloc]))
print('目标位置 = {}'.format(env.unwrapped.locs[destidx]))
env.render()
env.step(1)

至此,我们已经会使用这个环境了。

同策时序差分学习调度

本节我们使用SARSA算法和期望SARSA算法来学习策略。
首先我们来看SARSA算法。以下代码中的SARSAAgent类play_sarsa()函数共同实现了SARSA算法。其中,SARSAAgent类包括了智能体的学习逻辑和判决逻辑,是智能体类;play_sarsa()函数实现了智能体和环境交互的逻辑。play_sarsa()函数有两个bool类型的参数,参数train表示是否对智能体进行训练,参数render表示是否用对人类友好的方式显示当前环境。这里把SARSA算法拆分成一个智能体类和一个描述智能体和环境交互的函数,是为了能够更加清晰地将智能体的学习和决策过程隔离开来。智能体和环境的交互过程可以为许多类似的智能体重复使用。例如,play_sarsa()函数不仅在SARSA算法中被使用,还会被本章后续的SARSA(λ)算法使用,甚至被后续章节使用。

class SARSAAgent:
    def __init__(self, env, gamma=0.9, learning_rate=0.2, epsilon=.01):
        self.gamma = gamma
        self.learning_rate = learning_rate
        self.epsilon = epsilon
        self.action_n = env.action_space.n
        self.q = np.zeros((env.observation_space.n, env.action_space.n))
        
    def decide(self, state):
        if np.random.uniform() > self.epsilon:
            action = self.q[state].argmax()
        else:
            action = np.random.randint(self.action_n)
        return action
    
    def learn(self, state, action, reward, next_state, done, next_action):
        u = reward + self.gamma * \
                self.q[next_state, next_action] * (1. - done)
        td_error = u - self.q[state, action]
        self.q[state,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值