欢迎来到机器学习工程师纳米学位的第四个项目!在这个notebook文件中,模板代码已经提供给你,有助于你对智能出租车的分析和实现学习算法。你无须改动已包含的代码,除非另有要求。 你需要回答notebook文件中给出的与项目或可视化相关的问题。每一个你要回答的问题前都会冠以'问题 X'。仔细阅读每个问题,并在后面'回答'文本框内给出完整的回答。你提交的项目会根据你对于每个问题的回答以及提交的agent.py
的实现来进行评分。
提示: Code 和 Markdown 单元格可通过 Shift + Enter 快捷键来执行。此外,Markdown可以通过双击进入编辑模式。
开始
在这个项目中,你将构建一个优化的Q-Learning驾驶代理程序,它会操纵智能出租车 通过它的周边环境到达目的地。因为人们期望智能出租车要将乘客从一个地方载到另一个地方,驾驶代理程序会以两个非常重要的指标来评价:安全性和可靠性。驾驶代理程序在红灯亮时仍然让智能出租车行驶往目的地或者勉强避开事故会被认为是不安全的。类似的,驾驶代理程序频繁地不能适时地到达目的地会被认为不可靠。最大化驾驶代理程序的安全性和可靠性保证了智能出租车会在交通行业获得长期的地位。
安全性和可靠性用字母等级来评估,如下:
等级 | 安全性 | 可靠性 |
---|---|---|
A+ | 代理程序没有任何妨害交通的行为, 并且总是能选择正确的行动。 | 代理程序在合理时间内到达目的地的次数 占行驶次数的100%。 |
A | 代理程序有很少的轻微妨害交通的行为, 如绿灯时未能移动。 | 代理程序在合理时间内到达目的地的次数 占行驶次数的90%。 |
B | 代理程序频繁地有轻微妨害交通行为, 如绿灯时未能移动。 | 代理程序在合理时间内到达目的地的次数 占行驶次数的80%。 |
C | 代理程序有至少一次重大的妨害交通行为, 如闯红灯。 | 代理程序在合理时间内到达目的地的次数 占行驶次数的70%。 |
D | 代理程序造成了至少一次轻微事故, 如绿灯时在对面有车辆情况下左转。 | 代理程序在合理时间内到达目的地的次数 占行驶次数的60%。 |
F | 代理程序造成了至少一次重大事故, 如有交叉车流时闯红灯。 | 代理程序在合理时间内到达目的地的次数 未能达到行驶次数的60%。 |
为了协助评估这些重要的指标,你会需要加载可视化模块的代码,会在之后的项目中用到。运行下面的代码格来导入这个代码,你的分析中会需要它。
# 检查你的Python版本
from sys import version_info
if version_info.major != 2 and version_info.minor != 7:
raise Exception('请使用Python 2.7来完成此项目')
# Import the visualization code
import visuals as vs
# Pretty display for notebooks
%matplotlib inline
回答:没有移动,每一次trail都失败了。驾驶代理获得的奖励与交通灯颜色相关,当面向红灯时,为正奖励,一般在【0,3】之间;当绿灯时,为负奖励一般在[-4,-6]之间。因为奖励的目标是希望他红灯停,绿灯行。
回答:update_delay:每一个动作的持续时间;display:是否现实图形界面;log_metrics将模拟结果记录下logs目录下。 调用environment类的act函数。 render_text()函数在模拟程序不输出图形界面时,提供终端的文字输出,提高模拟运行的效率;render()函数则会渲染图形GUI界面,输出智能小车和其他小车的运行界面。 先考虑东西方向再考虑南北方向。
基本代理程序模拟结果
要从最初的模拟程序获得结果,你需要调整下面的标志:
'enforce_deadline'
- 将此标志设定为True
来强制驾驶代理程序捕获它是否在合理时间内到达目的地。'update_delay'
- 将此标志设定为较小数值(比如0.01
)来减少每次试验中每步之间的时间。'log_metrics'
- 将此标志设定为True
将模拟结果记录为在/logs/
目录下的.csv
文件。'n_test'
- 将此标志设定为'10'
则执行10次测试试验。
可选的,你还可以通过将'display'
标志设定为False
来禁用可视化模拟(可以使得试验跑得更快)。调试时,设定的标志会返回到他们的默认设定。重要的是要理解每个标志以及它们如何影响到模拟。
你成功完成了最初的模拟后(有20个训练试验和10个测试试验),运行下面的代码单元格来使结果可视化。注意运行同样的模拟时,日志文件会被覆写,所以留意被载入的日志文件!在 projects/smartcab 下运行 agent.py 文件。
# Load the 'sim_no-learning' log file from the initial simulation results
vs.plot_trials('sim_no-learning.csv')
答案: 驾驶程序在20轮的训练中,错误决策频率达到了0.34-0.44之间,大约有0.2左右的决策造成了事故; 随机驾驶的可靠率在20轮训练中始终为0,不合理。 代理程序对于行动受到的回报大部分处于-4到-6之间,这说明大部分是负奖励,也就是说在训练过程中受到了严重的惩罚; 随着实验次数增加,结果数据并未发现重大变化,因为行动是完全随机的; 这个智能出租车对于乘客而言,不是安全的,因为事故率太高,而且没有一次能够准时到达终点。
回答:waypoint;与效率相关性最高;inputs的四个特征与安全相关性最高;因为如果waypoint规划的最够好,对inputs数据又能正确处理,则肯定能够到达目的地,相反,对于deadline特征,对于安全性影响不明显,只要规划的路线保证到达目的地时剩余动作数目大于0即可。
定义状态空间
当定义一系列代理程序会处于的状态,必需考虑状态空间的大小。就是说,如果你期望驾驶代理程序针对每个状态都学习一个策略,你会需要对于每一个代理状态都有一个最优的动作。如果所有可能状态的数量非常大,最后会变成这样的状况,驾驶代理程序对于某些状态学不到如何行动,会导致未学习过的决策。例如,考虑用下面的特征定义智能出租车的状态的情况:
('is_raining', 'is_foggy', 'is_red_light', 'turn_left', 'no_traffic', 'previous_turn_left', 'time_of_day')
. 发生如(False, True, True, True, False, False, '3AM')
的状态的频次如何?没有近乎无限数量的训练,很怀疑代理程序会学到一个合适的动作!
回答: 应当是32444=384.经过合理训练后,能够学到一个较好的策略。 waypoint: forward , left , right inputs: light:red, green left:none,forward,left,right right:none,forward,left,right oncoming:none,forward,left,right 3/2/4/4/4求积得到384. 下一步动作包括:none,forward,left,right;故Qtable大小为1536.
实现Q-Learning驾驶代理程序
创建一个优化Q-Learning的驾驶代理程序的第三步,是开始实现Q-Learning自身的功能。Q-Learning的概念相当直接:每个访问的状态,为所有可用的状态-行动配对在Q-table里创建一条记录。然后,当代理程序遇到一个状态并执行了一个动作,基于获得的奖励和设定的相互的更新规则,来更新关联的状态-动作配对的Q-value。当然,Q-Learning还带来其他的收益,如此我们可以让代理程序根据每个可能的状态-动作配对的Q-values,来为每个状态选择最佳动作。在这个项目里,你会实现一个衰减 ϵϵ -贪心 的Q-learning算法,不含折扣因子。遵从每个代理程序函数的TODO下的实现指导。
注意代理程序的属性self.Q
是一个字典:这就是Q-table的构成。每个状态是self.Q
字典的键,每个值是另一个字典,包含了action和Q-value。这里是个样例:
{ 'state-1': {
'action-1' : Qvalue-1,
'action-2' : Qvalue-2,
...
},
'state-2': {
'action-1' : Qvalue-1,
...
},
...
}
此外,注意你要求利用一个衰减ϵϵ(探索)因子。因此,随着试验的增加,ϵϵ会向0减小。这是因为,代理程序会从它的行为中学习,然后根据习得的行为行动。而且当ϵϵ达到特定阈值后(默认阈值为0.01),代理程序被以它所学到的东西来作检测。作为初始的Q-Learning实现,你将实现一个线性衰减ϵϵ的函数。
Q-Learning模拟结果
要从最初的Q-learning程序获得结果,你需要调整下面的标志和设置:
'enforce_deadline'
- 将此标志设定为True
来强制驾驶代理程序捕获它是否在合理时间内到达目的地。'update_delay'
- 将此标志设定为较小数值(比如0.01
)来减少每次试验中每步之间的时间。'log_metrics'
- 将此标志设定为True
将模拟结果记录为在/logs/
目录下的.csv
文件,Q-table存为.txt
文件。'n_test'
- 将此标志设定为'10'
则执行10次测试试验。'learning'
- 将此标志设定为'True'
来告诉驾驶代理使用你的Q-Learning实现。
此外,使用下面的ϵϵ衰减函数:
如果你在实施时遇到困难,尝试把'verbose'
标志设为True
来调试。调试时,在这里设定的标志会返回到它们的默认设定。重要的是你要理解每个标志做什么并且解释它们怎么影响模拟!
当你成功完成初始的Q-Learning模拟程序后,运行下面代码单元格来使结果可视化。注意当相同的模拟运行时,log文件会被覆写,所以要留意载入的log文件!
# Load the 'sim_default-learning' file from the default Q-Learning simulation
vs.plot_trials('sim_default-learning.csv')
回答:和之前驾驶相比,Q-Learning取得了很大的进步,违反交通规则和交通事故的行为都降低了,意外事故也减少了,错误驾驶的事故率下降到了0.4左右。测试之前,代理要做20次训练,每次下降0.05,20次正好从1下降到0; 衰减函数能够准确在参数面板中显示。 不良动作的数目没有明显减少,平均奖励也没有明显增加。 与初始的代理程序相比,安全性上升到了B,但可靠性没有变化。
改进Q-Learning驾驶代理程序
创建一个优化Q-Learning的驾驶代理程序的第三步,是执行优化!现在Q-Learning算法已经实现并且驾驶代理程序已经成功学习了,需要调整设定、调节参数让驾驶代理程序学习安全性和效率。通常这一步需要很多试验和错误,因为某些设定必定会造成更糟糕的学习。要记住的一件事是学习的行为本身和需要的时间:理论上,我们可以允许代理程序用非常非常长的时间来学习;然而,Q-Learning另一个目的是将没有习得行为的试验试验变为有习得行为的行动。例如,训练中总让代理程序执行随机动作(如果ϵ=1ϵ=1并且永不衰减)当然可以使它学习,但是不会让它行动。当改进你的Q-Learning实现时,要考虑做一个特定的调整的意义,以及它是否逻辑上是否合理。
改进Q-Learning的模拟结果
要从最初的Q-learning程序获得结果,你需要调整下面的标志和设置:
'enforce_deadline'
- 将此标志设定为True
来强制驾驶代理程序捕获它是否在合理时间内到达目的地。'update_delay'
- 将此标志设定为较小数值(比如0.01
)来减少每次试验中每步之间的时间。'log_metrics'
- 将此标志设定为True
将模拟结果记录为在/logs/
目录下的.csv
文件,Q-table存为.txt
文件。'learning'
- 将此标志设定为'True'
来告诉驾驶代理使用你的Q-Learning实现。'optimized'
- 将此标志设定为'True'
来告诉驾驶代理你在执行一个优化版本的Q-Learning实现。
优化Q-Learning代理程序可以调整的额外的标志:
'n_test'
- 将此标志设定为某个正数(之前是10)来执行那么多次测试试验。'alpha'
- 将此标志设定为0 - 1之间的实数来调整Q-Learning算法的学习率。'epsilon'
- 将此标志设定为0 - 1之间的实数来调整Q-Learning算法的起始探索因子。'tolerance'
- 将此标志设定为某个较小的大于0的值(默认是0.05)来设定测试的epsilon阈值。
此外,使用一个你选择的ϵϵ (探索因子)衰减函数。注意无论你用哪个函数,一定要以合理的速率衰减到'tolerance'
。Q-Learning代理程序到此才可以开始测试。某个衰减函数的例子(tt是试验的数目):
如果你想的话,你也可以使用αα (学习率) 的衰减函数,当然这通常比较少见。如果你这么做了,确保它满足不等式0≤α≤10≤α≤1。 如果你在实施时遇到困难,尝试把'verbose'
标志设为True
来调试。调试时,在这里设定的标志会返回到它们的默认设定。重要的是你要理解每个标志做什么并且解释它们怎么影响模拟!
当你成功完成初始的Q-Learning模拟程序后,运行下面代码单元格来使结果可视化,请注意为了达到项目要求你需要在安全性和可靠性上获得至少都为A的评分。注意当相同的模拟运行时,log文件会被覆写,所以要留意载入的log文件!
# Load the 'sim_improved-learning' file from the improved Q-Learning simulation
vs.plot_trials('sim_improved-learning.csv')
回答:使用了ϵ=e −at ,for 0<a<1衰减函数。 在测试之前做了大约8000次训练试验; 使用的epsilon-tolerance大约为0.005,alpha =0.5;第一个参数对训练次数有影响;第二个参数控制agent的遗忘程度; 改进很多,安全性达到了A+,可靠性达到了A 驾驶代理成功的学习到了一个合适的策略。 对评分满意。
回答: 最佳策略就是在保证安全性的情况下用最少的步骤到达目的地。对于给定的状态,策略基本都是正确的。但是对于有些状态,有更优策略,因为距离目的地的剩余步数未作为训练特征,因此当有些情况出现时,可能会采用一些相对低效的到达目的地的策略。如当遇到红灯时,如果目的地就在前面时,最优策略应当是none,而不是左转或者右转。 ('forward', 'red', 'forward', None, 'right') -- forward : 0.00 -- right : 0.00 -- None : 1.98 -- left : -19.60 上面的状态表示:应当直行,红灯,左侧的要直行,右侧的车不动,对面来车要右转。所以说,直行、右转的奖励为0,最优策略是停止不动,而左转会发生交通事故,因此为reward最低为负。
选做:未来奖励 - 折扣因子 'gamma'
也许你会好奇,作为Q-Learning算法的一部分,之前要求你在实现中不要使用折扣引子'gamma'
。在算法中包含未来奖励能有助于在未来状态回溯到当前状态时的反向正面奖励。本质上,如果给予驾驶代理程序执行若干动作到达不同状态的选择,包含未来奖励会是代理程序偏向可以得到更多奖励的状态。一个例子是驶向目的的驾驶代理程序:所有行动和奖励都相等,那么理论上如果到达目的地会有额外奖励,驶向目的会获得更好的奖励。然而,即使在这个项目里,驾驶代理程序也要在规定的时间里到达目的地,包含未来奖励不会有益于代理程序。实际上,如果代理程序给予多次试验学习,它甚至会给Q-value带来负面影响!
回答:一个是限定了智能出租车本身并不知道距离目的地有多远,在状态中使用剩余步数信息,使用折扣因子的目的是将最终到达目的地的奖励向前回溯传递,如果在本项目中使用折扣因子使Q值包含未来奖励,那么最终迭代的Q值可能会导致发散,Q值越来越大,而永远不会到达目的地,因为最终奖励会向当前奖励传递。 另外一个原因是起点和终点不固定,每次训练都是随机的,目的地的奖励无法传递到起点。