赞
踩
Q-learning是一种经典的强化学习算法,用于解决马尔可夫决策过程(Markov Decision Process,MDP)中的控制问题。它是基于值迭代(Value Iteration)的思想,通过估计每个状态动作对的价值函数Q值来指导智能体在每个状态下选择最佳的动作。
其算法的基本思想跟主要优势如下:
Q-Learning
是强化学习算法中value-based的算法,Q即为Q(s,a),就是在某一个时刻的state
状态下,采取动作a能够获得收益的期望,环境会根据agent
的动作反馈相应的reward
奖赏,所以算法的主要思想就是将state
和action
构建成一张Q_table
表来存储Q值,然后根据Q值来选取能够获得最大收益的动作。
Q-learning的主要优势就是使用了时间差分法(融合了蒙特卡洛和动态规划)能够进行off-policy的学习,使用贝尔曼方程可以对马尔科夫过程求解最优策略.
(这里引用https://zhuanlan.zhihu.com/p/74225549这篇文章的图片)
我们做事情都会有自己的一个行为准则,比如小时候爸妈常说“不写完作业就不准看电视”。所以我们在写作业的状态(state)下,好的行为就是继续写作业,直到写完它,我们还可以得到奖励(reward),不好的行为就是没写完作业就跑去看电视了,被爸妈发现就会被惩罚,这种事情做的多了,也变成了我们不可磨灭的记忆,这其实就是一个Q-learning的决策过程。
首先这张图片我们可以看到s1,a2,s2代表写作业,a1代表看电视,Q表中的值代表着在某一状态下做某一件事能够得到的奖赏reward,我们可以随意设置Q表中的数值,但是我们会发现Q(s1,a1)=-2要小于Q(s1,a2)=1,所以我们判断要选择a2写作业作为我们的下一个行为。现在我们的状态更新成s2,我们还是有两个同样的选择,重复上面的过程,在行为准则Q-table中寻找Q(s2,a1)Q(s2,s2)的值,并比较他们的大小,选取较大的一个。接着根据a2我们到达s3并重复上述的决策过程,Q-learning的方法就是这样抉择的。那我们的Q-table这张行为决策表又是如何决策的呢?我们来看看。
回到之前,根据Q表的估计,因为在s1中,a2的值比较大,通过之前的决策方法我们在s1选择了a2,并到达s2,这时我们开始更新用于决策的Q表,接着我们并没有在实际中采取任何行为,而是在想象自己在s2上采取了a1,a2两个行为,分别看看两种行为哪一个的Q值大,比如说Q(s2,a2)的值比Q(s2,a1)的大,所以我们把大的Q(s2,a2)乘上一个衰减值gamma(eg 0.9)并加上到达s2时所获得的奖励Reward(这里没有获取到我们的棒棒糖,所以奖励为0),因为会获取实实在在的奖励Reward,所以我们将这个作为我们现实中Q(s1,a2)的值,但是我们之前是根据Q表估计Q(s1,a2)的值。所以有了现实值和估计值,我们就可以更新Q(s1,a2)的值,变成新的值。但时刻记住,我们虽然用maxQ(s2)估算了一下s2的状态,但还没有在S2做出任何行为,s2的行为决策要等到更新完了以后再重新另外做,这就是off-policy的Q-learning是如何决策和学习优化决策过程。
Epsilon greedy
:是用在决策上的一个策略,以概率ε选择随机动作,以概率1-ε选择当前最优动作,比如epsilon = 0.9的时候,就说明百分之90的情况我会按照Q表的最优值选择行为,百分之10的时间随机选择行为。
alpha
:学习率,决定这次的误差有多少是要被学习的。
学习率控制着每次更新Q值时所采用的步长。较大的学习率会导致Q值函数的快速更新,可能会使算法更快地收敛,但也可能导致不稳定性和震荡。
如果学习率过大,会导致Q值函数不稳定,可能会导致算法无法收敛或者在局部最优解处震荡。
如果学习率过小,会导致算法收敛速度变慢,可能需要更多的迭代次数才能达到收敛。
gamma
:对未来reward的衰减值。gamma越接近1,机器对未来的reward越敏感
这个算法公式也形象的说出了Q表的更新过程,总而言之四句话
(来自对http://mnemstudio.org/path-finding-q-learning-tutorial.htm 的翻译)
import numpy as np import os import random def random_action(V): # 找出V中非负元素对应的索引 index_list = [] for index, s in enumerate(list(V)): if s >= 0: index_list.append(index) # 从索引列表中随机选择一个索引作为动作 return random.choice(index_list) def reward_setting(state_num, action_num): # 定义奖励矩阵R R = -1 * np.ones((state_num , action_num)) # 设置特定状态的奖励 R[0,4] = 0 # 当前状态为0,动作为4时的奖励 R[1,3] = 0 # 当前状态为1,动作为3时的奖励 R[1,5] = 100 # 当前状态为1,动作为5时的奖励 R[2,3] = 0 # 当前状态为2,动作为3时的奖励 R[3,1] = 0 # 当前状态为3,动作为1时的奖励 R[3,2] = 0 # 当前状态为3,动作为2时的奖励 R[3,4] = 0 # 当前状态为3,动作为4时的奖励 R[4,0] = 0 # 当前状态为4,动作为0时的奖励 R[4,3] = 0 # 当前状态为4,动作为3时的奖励 R[4,5] = 100 # 当前状态为4,动作为5时的奖励 R[5,1] = 0 # 当前状态为5,动作为1时的奖励 R[5,4] = 0 # 当前状态为5,动作为4时的奖励 R[5,5] = 100 # 当前状态为5,动作为5时的奖励 return R if __name__ == '__main__': action_num = 6 # 动作数量 state_num = 6 # 状态数量 gamma = 0.8 # 折现因子 epoch_number = 200 # 迭代轮数 condition_stop = 5 # 终止条件 Q = np.zeros((state_num , action_num)) # 初始化Q值矩阵 R = reward_setting(state_num , action_num) # 初始化奖励矩阵 for epoch in range(epoch_number): for s in range(state_num): loop = True while loop: # 获取随机动作a a = random_action(R[s,:]) # 计算最大Q值 q_max = np.max(Q[a,:]) # 使用Bellman最优迭代方程更新Q值 Q[s,a] = R[s,a] + gamma * q_max s = a if s == condition_stop: loop = False # 将Q值除以5并转换为整数类型,以便显示 Q = (Q / 5).astype(int) print(Q)
实验结果如下所示,大约训练200轮之后Q 矩阵就可以收敛到理论值,并且理论推导与实验结果一致。
此博客仅用于学习使用,并无其他用途
参考:https://zhuanlan.zhihu.com/p/74225549
https://zhuanlan.zhihu.com/p/643431408
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。