【论文阅读】Learning to drive from a world on rails
引用与参考
代码地址:https://github.com/dotchen/WorldOnRails
论文地址:https://arxiv.org/abs/2105.00636
论文部分
- 已看完 写在ipad上了 正在进行中
摘要划重点:
- 视觉 只有视觉 → 所以关于加入激光点云的想法还是可以继续
- 行驶数据建立在model-based 使用车辆本身自行车模型 →
- world on rails的意思是:环境并不会随agent的行为而改变(很符合... Carla里的仿真了,车辆不会和你交互 只会按照自己的行程走 特别是在leaderboard测试的)
但是这一点在现实中,并不适用,现实中有车辆交互博弈学习等 → 这也正是用学习的原因
world on rails的假设后:简化学习问题、得知这个世界的动态信息?、自己的车低维度动作、状态空间
通过之前pre-recorded驾驶数据得出自己现在这步骤的影响
- 在已有的数据轨迹中学习世界的模型(learn world model)
- 对于所有pre-recorded轨迹预估action-value
- 训练RV policy,获得action-value function,从而获取所有动作的影响
理论方法总括
首先我们要学习的是一个能由传感器信息做出输入,输出动作的policy \(\pi(I)\)
在训练时的轨迹序列是:\(\tau=\left\{\left(\hat{I}_{1}, \hat{L}_{1}, \hat{a}_{1}\right),\left(\hat{I}_{2}, \hat{L}_{2}, \hat{a}_{2}\right), \ldots\right\}\)
- \(\hat{I}_{t}\) 传感器信息
- \(\hat{L}_{t}\) 驾驶数据,主要是自身车辆和其他参与者的位置、速度、朝向
- \(\hat{a}_{t}\) 做出的动作
戴帽的是从行驶数据中来的,普通的则是free or random变量
我们要利用这些驾驶数据学习的是:关于世界的forward model \(\mathcal{T}\) 和 action-value function \(Q\),整体过程就是 \(L_t\),\(a_t\) 通过 \(\mathcal{T}\) 预测得到\(L_{t+1}\),最后的agent对应的policy \(\pi(I_t)\)仅以传感器信息作为输入
整个算法流程 (公式请看下面定义)
3.1 Forward model分解
驾驶状态 \(L_t\) 和 forward model分成两个部分:
仅考虑自身车辆的控制:
\[L_{t+1}^{e g o}=\mathcal{T}^{e g o}\left(L_{t}^{e g o}, L_{t}^{\text {world }}, a_{t}\right)
\]建模剩下的世界模型:
\[L_{t+1}^{\text {world }}=\mathcal{T}^{\text {world }}\left(L_{t}^{\text {ego }}, L_{t}^{\text {world }}, a_{t}\right)
\]又因为假设的原因,world仅和自身有关,所以:\(L_{t+1}^{\text {world }}=\mathcal{T}^{\text {world }}\left(L_{t}^{\text {world }}\right)\),那么从一开始world状态就能知道整个world的模型
由以上,就只需建模对于自身车辆的forward model,这里使用L1进行回归训练 \(\mathcal{T}^{e g o}\):
\]
注意这里的自身车辆状态其实可以通过自行车模型来计算得来
实验处理
在收集到的subset轨迹上,训练自身车辆的forward model \(\mathcal{T}^{e g o}\),收集的数据保证在整个动作空间展开,例如:
- 转向从\([-1,1]\);油门从\([0,1]\);前两者都是均匀采样,刹车是只有\(\{0,1\}\)
正如前面提到的forward model \(\mathcal{T}^{e g o}\) 是由现在的\((x_t,y_t,\theta_t,v_t)\) 来预测下一个时刻车辆的状态:\((x_{t+1},y_{t+1},\theta_{t+1},v_{t+1})\)
在这里可以使用已知的自行车模型作为 \(\mathcal{T}^{e g o}\) 的结构先验:我们仅学习车辆的\(f_b,r_b\);从转向\(s\)到轮转向\(\phi\)的映射;油门和刹车到加速度的映射
这一条具体怎么做还需要看代码的实现方式,\(f_b,r_b\)这两者是车辆的基本参数吧?
详情见 代码阅读,是学习学到的这两个参数
3.2 Action-value function
这里我们想要的是一个给出行驶状态和动作,返回一个动作价值函数 [所以从这里可以知道对比lbc的方法 他是把鸟瞰图,或者说激活RGB图像的方式换成了RL里面对于动作价值的概念]
这里的公式就是Bellman基本公式,强化学习书里的,关于value function和q function的区别见:https://www.zhihu.com/question/59122948/answer/1899310296
\]
其中,\(\hat{L}_{t}^{\text {world }}\)是直接记录下来的周围环境(世界)的,不会对\(Q\)造成影响(是假设),所以这整个式子可以简化一下:
\]
其中的\(Q\)值计算由此可得:
\]
- 自身车辆的状态 \(L_{t}^{e g o}\) 由 (位置、朝向、速度) 组成;这样对每一个 \(V_{t}\left(L_{t}^{e g o}\right)\) 状态的价值我们都进行计算,在最后的eval过程中,线性拟合其值如果value falls between bins
实验处理
对于每个时间\(t\) 我们把vaule function弄成一个4D的tensor:\(N_H \times N_W\)是关于位置的;\(N_v\)是关于速度的;\(N_\theta\)是关于朝向的
实验中\(N_H=N_W=96, N_v=4, N_\theta=5\),每个点代表了物理的\(\frac{1}{3} \times \frac{1}{3} m^{2}\)区域,\(2m/s\)的速度范围和\(38°\)的朝向范围
\(\hat{L}_{t}^{e g o}=\left(x_{t}, y_{t}, v, \theta\right)\) 自身车辆的状态是处于整个离散化空间的中间的;对于value fall outside就直接为0
这里同样我们也离散化了我们的转向和油门 \(M_s \times M_t\),然后在转向或踩油门的时候,我们不进行刹车,那么当\(M_s=9,M_t=3\)。整个动作空间就是\(9\times3+1=28\)
reward的设计如下:
规定zero-speed area:比如遇到红灯、接近其他车辆/行人等
- +1:保持在目标车道
- 0:如果偏离了车道,但是+1到0直接的变化不是二值,而是线性拟合smoothly penalized
- +5:如果在zero-speed area里停下了
但是这里zero-speed只会给一次,不会累加了,以免出现车辆直接一直停下不走了
因为有了zero-speed区域,所以关于碰撞的惩罚也就不需要有了 - \(r_{stop}=0.01\) 以避免agent为了躲避而偏离车道 → 这一点我感觉只要不压实线,虚线变道应该是可以的吧 → 可能是对于leaderboard场景的trick设置
最后是通过high-level commands[左转、右转、直走、跟随路径、change right、 change left]来计算的整个动作价值函数
3.3 Policy Distillation
然后再使用 \(Q_{t}\left(\hat{L}_{t}^{e g o}, \cdot\right)\) 去监督学习VP(visuomotor policy) \(\pi(\hat I_t )\) ,所以呢 \(Q_{t}\left(\hat{L}_{t}^{e g o}, \cdot\right)\) 代表了车辆在那个状态下做出哪个动作是最优的,然后优化迭代我们直接通过期望:
\]
其中\(H\) 是entropy regularizer,\(\alpha\) 是温度超参数,这样的处理是为了拿到diverse output policy
实验处理
对于policy network的设计使用的是以RGB作为输入,ResNet34作为网络框架
- flatten ResNet features
- concatenating speed
- 喂到网络里去
- 输出动作空间的分布:categorical distribution over discretized action spaces
从图中应该比较明显可知:这个value map是限制在地图里的,也就是说如果换一个环境是需要重新再来的,从这一点上可能就没有lbc好?所以每个地图环境都是需要一个value map去对应的
看了代码知道了 不算是限制在地图里,而是因为读取了地图中的waypoint 来进行reward判断,就是需要沿着车道线行驶不能出界或者偏移 详情见reward的操作
关于加入value map其实有改进,针对lbc 的方法强化了正确动作的概率,类似于value map再做一层限制同样也是第二个agent的先验
4 实验部分处理
通过carla内的行为规划器 [5] Carla之全局规划follow 来收集数据 \(\pi_b\)
并没有使用行为规划器来进行,而是直接生成min-max的一系列动作,根据reward 选出最好的进行 做出动作
使用autopilot来添加转向的噪音
- 这一点还需细看是怎么加进去的
使用上面的数据去学习forward model,而不是直接去使用autopilot去做监督学习
对应每个我都直接放在上面的细节中了
- 所以还是行为规划器,Q action-value只是用来帮助激活RGB的某个部分,更或者是说保存整个地图信息在这个情况下怎样做是最好的;但是并没有去改善行为规划器的东西?而是从中学习得到value值
代码运行部分
Carla版本0.9.10.1,python版本3.7,已经在Planning主机上设置好了,
①打开termnial ②输入zsh
③输入carla_wor
运行结构主要由三个大过程组成,第一过程可以直接使用文件夹内的ego_model.th来
Rails系列代码阅读,后续传上来后再一个个贴吧
Stage 0: ego model
这一过程... 我暂时不知道是干啥的 因为按道理说第一过程才是开始收集train_scenario
的才对
- 待查明,这一过程ego的作用 → 训练得知车辆运动模型 train car dynamics
首先到config.yaml文件,修改ego_data和ego_model的储存位置
ego_data_dir: collection/phase0
ego_model_dir: collection/phase0
main_data_dir: collection
main_model_dir: collection
启动Carla,这里是写的sh文件来启动多个Carla窗口,注意一个carla本身就需要2G显存,正常6G显存电脑建议只启动2个即可
./scripts/launch_carla.sh 2 2000
# ./scripts/launch_carla.sh [NUM RUNNERS] [WORLD PORT]
启动收集data的脚本
- 咦?在这里就有收集数据的嘛??? → train dynamics
python -m rails.data_phase0 --num-runners=2 --port=2000
首先把 在这里我就没有运行下去了,主要是出现了pygame 然后它就自己也没报什么错误,也没保存什么文件就.. 就.. 就停止了
未知错误示意
大概探索了一下,从leaderboard_evaluator.py里出来的,但是因为没办法print所以不知道更具体为什么,猜测原因是ray.remote,为什么没办法print啊!!!真是的!!!
crash_message = "Agent couldn't be set up"
- 奇奇怪怪 为什么issue里没有人和我遇到一样的问题
被自己气死了!.... emmm 果然猜测是对的,改一下ray.init部分就可以显示了
ray.init(logging_level=40, local_mode=True, log_to_driver=False)
然后就显示wandb的,查一下
太绝了啊!这都是什么好东西!
有空查一下ray的东西
查完感觉!超棒!太爽了吧!
关于rails代码详细介绍请跳转吧,写在一起太长了,不过上面的步骤已经能让整个运行起来了:
但是运行过程中,前20个左右的frame可能是OK的,后面总是提示说,保存不了图片?但是为啥这个是和frame有关的呢?奇怪
错误示意:
Traceback (most recent call last):
File "/home/udi/KinZhang/WorldOnRails/leaderboard/leaderboard/scenarios/scenario_manager.py", line 152, in _tick_scenario
ego_action = self._agent()
File "/home/udi/KinZhang/WorldOnRails/leaderboard/leaderboard/autoagents/agent_wrapper.py", line 88, in __call__
return self._agent()
File "/home/udi/KinZhang/WorldOnRails/leaderboard/leaderboard/autoagents/autonomous_agent.py", line 115, in __call__
control = self.run_step(input_data, timestamp)
File "autoagents/collector_agents/random_collector.py", line 124, in run_step
self.flush_data()
File "autoagents/collector_agents/random_collector.py", line 67, in flush_data
'vid': wandb.Video(np.stack(self.rgbs).transpose((0,3,1,2)), fps=20, format='mp4')
File "<__array_function__ internals>", line 6, in stack
File "/home/udi/anaconda3/envs/carla_py37/lib/python3.7/site-packages/numpy/core/shape_base.py", line 423, in stack
raise ValueError('need at least one array to stack')
ValueError: need at least one array to stack During handling of the above exception, another exception occurred: Traceback (most recent call last):
File "/home/udi/KinZhang/WorldOnRails/leaderboard/leaderboard/leaderboard_evaluator.py", line 365, in _load_and_run_scenario
self.manager.run_scenario()
File "/home/udi/KinZhang/WorldOnRails/leaderboard/leaderboard/scenarios/scenario_manager.py", line 136, in run_scenario
self._tick_scenario(timestamp)
File "/home/udi/KinZhang/WorldOnRails/leaderboard/leaderboard/scenarios/scenario_manager.py", line 159, in _tick_scenario
raise AgentError(e)
leaderboard.autoagents.agent_wrapper.AgentError: need at least one array to stack
======[Agent] Wallclock_time = 2021-07-08 14:50:50.458292 / 6.338849 / Sim_time = 4.550000067800283 / 0.717682718910227x Stopping the route, the agent has crashed:
> need at least one array to stack
这里运行收集的数据是由随机动作得到的数据集,主要作用是用来训练车辆动力学
收集完后进行训练此收集数据
python -m rails.train_phase0 --data-dir=[EGO data DIR]
# 注意这里的[EGO data DIR] 需要和上面config里的ego_model_dir一致
Stage 1: Q-computation
Tips 前提知晓
- 这个阶段!真的很耗时!两块TiTan XP(和1080Ti差不多)训练10个epochs需要用4天
- 但是这个阶段更耗存储空间(如果要收集到作者有的数据集需要3.4TB in the lmdb format,详情见此issue:https://github.com/dotchen/WorldOnRails/issues/17#issuecomment-858148921)
- 收集数据如果因为空间不够,一定要记得删掉未完成的那一个part不然frame无法正确读取,计算q value的脚本会报错
- 记得提前对 config_nocrash.yaml 文件进行修改config 和 数据路径不然... 会报错的,详情见倒数第二部分可能出现的问题
- 此次使用会出现CUDA报错问题,详情见倒数第二部分可能出现的问题
收集数据
完成上面的车辆参数学习后,我们就可以把我们的动作(油门、方向盘、刹车)转成速度输出了,也就是上面理论部分提到的:
\(\hat{L}_{t}^{e g o}=\left(x_{t}, y_{t}, v, \theta\right)\) 自身车辆的状态是处于整个离散化空间的中间的;对于value fall outside就直接为0
这里主要是收集数据
# Open Carla
./scripts/launch_carla.sh [NUM RUNNERS] [WORLD PORT]
# 这一层设置你想要收集的数据
python -m rails.data_phase1 --scenario={train_scenario, nocrash_train_scenario} --num-runners=[NUM RUNNERS] --port=[WORLD PORT]
打开Carla
收集数据,
scenario
是指在哪个环境下,比如前者就是通过leaderboard来收集数据,后者可指定route在Town01下的4个不同的训练天气所以这个部分总结来看:在一个位置,根据已知的min, max的动作阈值,生成一张动作表,然后通过地图(其实也算是上帝视角)来给各个动作块附上reward,然后选取最大的。reward的标准呢在这里,不得不说一句这个作者代码是真的牛掰... 硬生生看来我好久才理解了
计算Q Value
等待上面数据收集完成后,就可以关闭Carla,运行Q value label的脚本
# Q-labeling
python -m rails.data_phase2 --num-runners=[NUM RUNNERS]
代码阅读:/
运行后可以从wandb上看到一些记录的细节:
大概可以看到即使只有1W(原作者数据集的1/1000都不到 也是花了1小时才做好的Q value label的过程)
为什么需要forward model呢,直接拿action来训练不行吗?比如 油门、方向盘、刹车去对应出value map,而且实际输出图片也看出来是这样的 (但是估计是通过forward反映射了?)
因为需要从油门、方向盘、刹车 → 速度 → 预测位置,最后一个预测位置也就是我们需要的state in the world
但是为什么不直接从定位GPS中读取呢?因为加了噪音,有误差嘛?
我忘记这个问题为什么问出来了,但是大概是这样的,首先做出的动作,并没有实际做出,而是根据地图的上帝因素进行判断,判断的前提是拿ego_model知晓了 这个动作做出后 位置大概在哪里,然后和地图waypoint偏移什么的来进行比较
但是实际上在 data_phase1的时候就有计算哪个动作的reward更高,通过论文中说到的标准来确定,所以这么看来动作是离散的 问题有点大 frame是20内
首先提出这个问题的时候,我还没意识到又是一次上帝视角去判断所有reward;第二动作确实是离散的,收集的频率为4Hz,也就是说动作为保持250ms直到下一次更新?
Stage 2: Image model training
python -m rails.train_phase2
可能会遇到的运行问题
ModuleNotFoundError: No module named 'leaderboard.leaderboard_evaluator'
原因:这是因为我下载了leaderboard后,结构是这样的leaderboard/leaderboard/code,
解决方案:
- 把leaderboard复制出来就好了
- 或者是在原主leaderboard下加一个空的__init__.py文件即可
> cuda runtime error (38) : no CUDA-capable device is detected at /opt/conda/conda-bld/pytorch_1579040055865/work/aten/src/THC/THCGeneral.cpp:50
运行第二阶段的数据收集时,也就是这行
python -m rails.data_phase1 --scenario={train_scenario, nocrash_train_scenario} --num-runners=[NUM RUNNERS] --port=[WORLD PORT]
原因:主要错误也指明了,是找不到cuda
解决方案:定位到在q_collector.py文件中device是没有指定哪一个的
参考:https://github.com/pytorch/pytorch/issues/5046
for key, value in config.items():
setattr(self, key, value)
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
device = torch.device('cuda') ego_model = EgoModel(1./FPS*(self.num_repeat+1)).to(device)感觉第二阶段的bug挺多的啊... 整个config中路径都没有被读入哎 emmm
我知道了,是我没有看清楚config.yaml,这个data_phase1读取的config是!!!! config_nocrash.yaml真是绝了,应该在readme里面说一声的
Debug小技巧
对于python来说,debug感觉上应该比C/C++轻松不少的,首先是我一开始设置了很久的launch因为这个不是直接运行一个py文件而是 -m脚本方式运行,所以launch中应该要加入其下的Python env但是我加了很久,怎么着都不行,所以就另辟蹊径走到了,直接开一个口进行监听的方式
具体参考:https://blog.csdn.net/m0_37991005/article/details/113342656
步骤:
配置launch.json文件
其中launch文件是这样的:注意第一个Debug是我当时设置了很久的环境 也没设对,所以第二个启动时注意选择好VScode界面
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "python",
// PYTHONPATH = ${CARLA_ROOT}/PythonAPI/carla/":"${SCENARIO_RUNNER_ROOT}":"${LEADERBOARD_ROOT}
//~/KinZhang/WorldOnRails/PythonAPI/carla/:~/KinZhang/WorldOnRails/leaderboard:~/KinZhang/WorldOnRails/scenario_runner
// "python.pythonPath": "~/KinZhang/WorldOnRails/PythonAPI/carla/",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"cwd": "${fileDirname}" },
{
"name": "Attach Debug",
"type": "python",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
}
}
]
}
配置后,首先运行python文件(注意看中间写的
debugpy --listen 5678 --wait-for-client
)python -m debugpy --listen 5678 --wait-for-client -m rails.data_phase1 --num-runners=1 --port=2000
然后是进入监听状态,再去VSCode里点击:首先选择好对应的那个Python文件,然后再选择好哪一个debug设置,最后点小绿就能debug上了
调试示意图:
同时可以到下面的debug terminal进行实时的调试测试(python可以 编译后的C/C++类型只能显示显示而已)
【论文阅读】Learning to drive from a world on rails的更多相关文章
- Deep Reinforcement Learning for Dialogue Generation 论文阅读
本文来自李纪为博士的论文 Deep Reinforcement Learning for Dialogue Generation. 1,概述 当前在闲聊机器人中的主要技术框架都是seq2seq模型.但 ...
- 论文阅读笔记 Improved Word Representation Learning with Sememes
论文阅读笔记 Improved Word Representation Learning with Sememes 一句话概括本文工作 使用词汇资源--知网--来提升词嵌入的表征能力,并提出了三种基于 ...
- 论文阅读:Face Recognition: From Traditional to Deep Learning Methods 《人脸识别综述:从传统方法到深度学习》
论文阅读:Face Recognition: From Traditional to Deep Learning Methods <人脸识别综述:从传统方法到深度学习> 一.引 ...
- 【论文阅读】Learning Dual Convolutional Neural Networks for Low-Level Vision
论文阅读([CVPR2018]Jinshan Pan - Learning Dual Convolutional Neural Networks for Low-Level Vision) 本文针对低 ...
- [论文阅读笔记] metapath2vec: Scalable Representation Learning for Heterogeneous Networks
[论文阅读笔记] metapath2vec: Scalable Representation Learning for Heterogeneous Networks 本文结构 解决问题 主要贡献 算法 ...
- [论文阅读笔记] node2vec Scalable Feature Learning for Networks
[论文阅读笔记] node2vec:Scalable Feature Learning for Networks 本文结构 解决问题 主要贡献 算法原理 参考文献 (1) 解决问题 由于DeepWal ...
- [论文阅读笔记] Adversarial Learning on Heterogeneous Information Networks
[论文阅读笔记] Adversarial Learning on Heterogeneous Information Networks 本文结构 解决问题 主要贡献 算法原理 参考文献 (1) 解决问 ...
- [论文阅读笔记] Adversarial Mutual Information Learning for Network Embedding
[论文阅读笔记] Adversarial Mutual Information Learning for Network Embedding 本文结构 解决问题 主要贡献 算法原理 实验结果 参考文献 ...
- 《Learning to warm up cold Item Embeddings for Cold-start Recommendation with Meta Scaling and Shifting Networks》论文阅读
<Learning to warm up cold Item Embeddings for Cold-start Recommendation with Meta Scaling and Shi ...
- Ensemble learning A survey 论文阅读
Ensemble learning A survey是2018年发表的一篇关于集成学习的综述性论文 发展 在Surowiecki的书中The Wisdom of Crowds,当符合以下标准时,大众的 ...
随机推荐
- 羽夏闲谈——TeeWorlds 中文问题
不久前 削微寒 园友发布了一篇博文 误入 GitHub 游戏区,意外地收获颇丰 ,看到了一个游戏 TeeWorlds .有一说一挺好玩的,下面是那个博客的原图: 官方的下载连接:https:/ ...
- 04 elasticsearch学习笔记-Rest风格说明
目录 Rest风格说明 关于文档的基本操作 添加数据PUT 查询 修改文档 删除索引或者文档 Rest风格说明 Rest风格说明 method url地址 描述 PUT localhost:9200/ ...
- ansible(2)--ansible的安装与配置文件管理
目录 1 ansible的安装 1.1 yum安装 1.2 pip安装 2 ansible相关文件 2.1 ansible配置文件 2.2 ansible配置文件的优先级 2.3 ansible的主机 ...
- vue2.0,把vform666、workFlow开源组件集成到vue-admin-template框架上心得体会
以上三个都是vue2版本的开源项目,有的已经有vue3版本了,我把他们集成到一起,是出于练习的目的,也是消磨时间. vue-admin-template是一个很基础简洁的后台管理系统框架:vform6 ...
- MyBatis两级缓存机制详解
缓存是提高软硬件系统性能的一种重要手段:硬件层面,现代先进CPU有三级缓存,而MyBatis也提供了缓存机制,通过缓存机制可以大大提高我们查询性能. 一级缓存 Mybatis对缓存提供支持,但是在 ...
- Javascript---时间加秒数得到新的时间
<script> // 当前时间:curTime var curTime = new Date("2023-12-10 17:32:46"); // 当前时间加上XXX ...
- WPF 设置第二次打开程序直接弹出第一次打开的程序
激活已经打开窗口函数[DllImport("user32.dll")]private static extern bool SetForegroundWindow(IntPtr h ...
- 011. jenkins 备份
Jenkins目录介绍 1. 主配置文件: /etc/sysconfig/jenkins 2. Jenkins主目录: /var/lib/jenkins/ [root@node1 plugins]# ...
- nginx接受请求连接事件模块流程
操作系统内核: 三次握手,当用户发来一个 SYN 报文时,系统内核会返回一个SYN+ACK确认给客户端,当客户端再次发送ACK来的时候,此时就已经建立了三次握手. 完成三次握手后,操作系统会根据系统内 ...
- js 检测文本是否溢出
自定义指令的方式 手写实现 /** * 检测文本是否溢出 * 参考 https://github.com/ElemeFE/element/blob/dev/packages/table/src/tab ...