强化学习Q-learning实践

文摘   2023-06-10 19:04   江苏  







01


 引言



前篇文章介绍了强化学习系统中的基本概念和重要组成部分,并解释了Q-learning算法相关的理论知识。本文的目标是在Python3中实现该算法,并将其应用于实际的实验中。

闲话少说,我们直接开始吧!





02


Taxi-v3 Env

为了使本文具有实际具体的意义,特意选择了一个简单而基本的环境,可以让大家充分欣赏Q-learning算法的奥秘。我们选择的环境是OpenAI GymTaxi-v3,该环境简单明了,是强化学习RL领域的优秀入门样例。实际上Taxi-v3由一个grid map组成,如下图示:

其中,该环境下的agent是一名出租车司机,他必须接客户(图中绿色方块)并将其送到目的地(图中红色方块)。




03


States

一般来说,States的作用如下 (1) 确定action(2)计算执行action的奖励reward(3)计算到下一状态的转换所需的信息。

观察上图,我们的网格grid map的大小为5x5,所以出租车所有可能的选择有25个。除此之外,等待接车的乘客可以在四个可能的接车点(标记为Y、R、G、B)处等待当然也可以在出租车里,所以乘客所有可能的选择有(4+1)个;最后,乘客的目的地在(Y、R、G、B)四个中的一个,所以乘客的目的地共有4个选择,图示如下:

综上,我们用以下向量表示States

State = [x_pos_taxi, y_pos_taxi, pos_passenger, dest_passenger]

进而,我们agentStates一共有5X5X5X4=500个,可以被编码为0499之间的整数。其实,实际可用的状态的数量略小于500,例如,乘客将永远不会有相同的乘车点和目的地。由于建模的复杂性,我们通常关注完整的状态空间。





04


举个栗子

上述文字讲完后,有些同学还是有很多不理解的东东,那我们来找个中间过程来看看,如下:

上图中,STATE:(2,1,0,1)表示,当前出租车在grid map中的第二行第一列,同时乘客的状态选择为0表示位于乘客位于红色格子里等待乘车,同时乘客的目的地状态选择为1表示乘客的目的地为绿色格子。


进而,下图中的STATE:(3,4,4,0)表示,当前出租车在grid map中的第三行第四列,同时乘客的状态选择为4表示此时乘客位于出租车里,同时乘客的目的地状态选择为0 ,表示乘客的目的地为红色格子。

看到这里的童鞋,请仔细理解上述两个例子。




05


Action space

至于该环境Envagent的动作空间Action space,我们可以想象,代理agent可以使用以下离散动作来与环境交互:向前、向后、向右、向左、接乘客和送乘客。这使得总共有6个可能的动作,这些动作依次以0到5的数字编码,以便于编程。动作和数字之间的对应关系如下图所示。





06


Rewards

至于agent执行的每一步action所获得的奖励reward,做如下约定:

  • 移动:-1, 表示每一步都会受到一点惩罚,以鼓励从出发地到目的地走最短的路。

  • 错误运送:-10, 表示当乘客被送到到错误的位置时,乘客自然会不高兴,所以惩罚大一些是合适的。

  • 成功送达:20,表示出租车司机成功完成了任务,鼓励相应的行为,因此产生了正向的reward





07


Initialization

在数学上定义了这个问题之后,我们接着将着手用代码实现。首先,我们安装必要的库,然后导入它们。显然,我们需要安装gym 环境。除此之外,我们只需要一些可视化的东西和常见的数据处理库。

接着,我们使用以下代码来创建和渲染Taxi-v3环境。

结果如下:






08


测试随机agent

在上述环境Env按照预期开始工作后,此时我们可以随机让代理疯狂运行了。我们不妨让我们的agent在任何时刻都会采取随机行动,来看看会产生怎样的效果。

运行上述代码后,得到结果如下:

为什么要看完上述冗长的动画?好吧,上图展示一个未经训练的RL模型下的agent是如何表现的,以及需要多长时间才能获得有意义的reward




09


训练agent

接着,我们来尝试训练我们的agent,我们知道Q值是在进行观测之后使用以下等式进行更新的。

请注意,对于500个状态和6个动作,我们必须填写一个大小为500*6=3000的Q表,每个状态-动作二元组需要多次观察才能学到有用的知识。相应的训练代码如下:

"""Training the agent"""q_table = np.zeros([env.observation_space.n, env.action_space.n])
# Hyperparametersalpha = 0.1 # Learning rategamma = 1.0 # Discount rateepsilon = 0.1 # Exploration ratenum_episodes = 10000  # Number of episodes# Output for plotscum_rewards = np.zeros([num_episodes])total_epochs = np.zeros([num_episodes])
for episode in range(1, num_episodes+1): # Reset environment state, info = env.reset() epoch = 0 num_failed_dropoffs = 0 done = False cum_reward = 0
    while not done:        if random.uniform(0, 1) < epsilon:            action = env.action_space.sample() # Sample random action (exploration)        else:       action = np.argmax(q_table[state]) # Select best known action (exploitation)
        next_state, reward, done, _ , info = env.step(action)  cum_reward += reward
old_q_value = q_table[state, action]        next_max = np.max(q_table[next_state])        new_q_value = (1 - alpha) * old_q_value + alpha * (reward + gamma * next_max) q_table[state, action] = new_q_value
if reward == -10: num_failed_dropoffs += 1
state = next_state        epoch += 1  total_epochs[episode-1] = epoch cum_rewards[episode-1] = cum_reward
if episode % 100 == 0: clear_output(wait=True) print(f"Episode #: {episode}")
print("\n")print("===Training completed.===\n")

在2000个episode 之后,逐渐收敛,我们似乎学到了一个相当好的模型,如下:

上图图像中,横坐标表示我们一共训练了10000Episode,纵坐标表示每一个Episode下,出租车司机将乘客送达目的地所需要的移动步数epochs



10


验证训练效果

最后,让我们看看我们的模型学到了什么。根据我们所处的状态,我们在Q表中查找相应的Q值(即,每个状态对应于动作的六个值),并选择具有最高相关Q值的动作。代码如下:

"""Test policy performance after training"""num_epochs = 0total_failed_deliveries = 0num_episodes = 1experience_buffer = []store_gif = True
for episode in range(1, num_episodes+1):    # Initialize experience buffer my_env = env.reset() state = my_env[0] epoch = 1 num_failed_deliveries =0 cum_reward = 0 done = False
while not done: action = np.argmax(q_table[state]) state, reward, done, _, _ = env.step(action)        cum_reward += reward if reward == -10: num_failed_deliveries += 1
# Store rendered frame in animation dictionary experience_buffer.append({ 'frame': env.render(), 'episode': episode, 'epoch': epoch, 'state': state, 'action': action, 'reward': cum_reward } ) epoch += 1
total_failed_deliveries += num_failed_deliveries    num_epochs += epoch if store_gif:        store_episode_as_gif(experience_buffer)# Run animation and print outputrun_animation(experience_buffer)

结果如下:

可以看到,在执行了足够多的迭代训练之后,我们可以发现出租车总是直接驶向乘客,走最短的路到达目的地,并成功地将乘客放下。





11


 总结


本文通过具体的应用,来对前篇Q-learning的理论知识用代码进行了详细的说明,主要通过业内知名的Taxi-v3环境进行了讲解,并给出了完整的代码示例。


您学废了嘛?








点击上方小卡片关注我






寄语:

我们所听到的一切,都是一个观点,不是事实。

我们所看到的一切,都是一个视角,不是真相。

AI算法之道
一个专注于深度学习、计算机视觉和自动驾驶感知算法的公众号,涵盖视觉CV、神经网络、模式识别等方面,包括相应的硬件和软件配置,以及开源项目等。
 最新文章