LaserNet README批注


LaserNet是 Gregory P. Meyer博士供职于Uber期间,在 CVPR2019CVPRW2019的两篇论文中提出的三维识别神经网络框架,前者是激光雷达三维识别,后者(称为LaserNet++)是图像+激光雷达融合三维识别。作者本人并没有开源代码,但是github上 atyshka复现了 LaserNet,本文面阐述对象就是这篇复现的代码。

LaserNet in Tensorflow 2.0

  In this project I’ve done my best to implement the work from Uber ATG on LaserNet. LaserNet is a 3D object detector for autonomous driving, with 3 distinguishing factors: range-view, low-latency, and probabilistic detection. See here for the original paper. The original paper uses Uber’s proprietary dataset, and overfits on the small KITTI dataset, so for this project I am using Waymo Open Dataset.

1. 环境配置

参考运行LaserNet前的环境配置

2. Instructions:

2.1 Run save_ds.py

2.1.1 数据下载

  to save the dataset to disk from the cloud bucket and perform initial preprocessing
注:
  save_ds.py,其中ds应为dataset缩写,使用save_ds.py下载数据容易出现数据中断的情况,建议使用下载工具进行下载。参考该程序可以发现其25行为数据集所在位置:gs://waymo_open_dataset_v_1_2_0_individual_files/validation/*.tfrecord。可以使用gsutil进行下载,如遇到问题可以参考《gsutil的安装与文件下载注意事项》。另外使用该工具进行下载的时候有时也会遇到中断的情况,此时可以观察已经下载的文件的扩展名,找出下载失败的文件,重新编辑下载指令,对这些下载失败的文件再次下载,详情可以参考《gsutil下载失败如何恢复下载》。
  若你采用的是自己下载数据,那么因为下载下来数据集是“tfrecord”格式,你仍然需要使用save_ds.py对文件进行处理,该程序第139行/home/alex/full_validation指出了数据下载后存储的位置。在处理之前你需要将25行和139行的路径修改到你自己的对应路径。同时因为数据量过大,你需要确保保存目录有足够的存储空间。

python3 ${你的工程路径}/save_ds.py

  运行之后你会看到终端最后打印出如下信息,光标在闪烁。此时说明程序正在处理数据集,打开系统监视器,可以看到CPU被高占用,一个python3的进程各项资源占据都很高。

...
2022-05-01 13:54:35.683364: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:116] None of the MLIR optimization passes are enabled (registered 2)
2022-05-01 13:54:35.701035: I tensorflow/core/platform/profile_utils/cpu_utils.cc:112] CPU Frequency: 2499950000 Hz
2.1.2 MLIR信息

运行程序会打印如下信息

None of the MLIR optimization passes are enabled (registered 2)

导致这个问题的原因可能跟TFRecord格式有关,详细原因可以参考下面,但是该信息不影响程序运行。
None of the MLIR Optimization Passes are enabled is a bit misleading as it refers to very particular workflow. But it is benign and has no effect - it just means a user didn’t opt in to a specific pass (which is not enabled by default), so it doesn’t indicate any error and was rather used as signal for developers. But seeing this, it is causing more confusion. I’ll go and update the message.

This is expected as in TF 2.3, the MLIR based implementation is still being developed and proven, so end users are generally not expected to use the MLIR implementation and are instead expected to use the non-MLIR feature complete implementation.

2.1.3 内存溢出

当程序运行一段时间之后,会报错已杀死killed,通过终端中运行dmesg可以看到如下打印信息,可以看到进程9214(就是你运行的python)是因为内存溢出导致的。

[ 4805.772780] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice,task=python,pid=9214,uid=1000
[ 4805.772903] Out of memory: Killed process 9214 (python) total-vm:45467964kB, anon-rss:12459308kB, file-rss:71512kB, shmem-rss:0kB, UID:1000 pgtables:54764kB oom_score_adj:0
[ 4806.483925] oom_reaper: reaped process 9214 (python), now anon-rss:0kB, file-rss:74732kB, shmem-rss:0kB

各参数的意思是(参考这里

参数全称意义
total-vmtotal virtual memory进程使用的总的虚拟内存
rss:resident set size驻留集大小。驻留集是指进程已装入内存的页面的集合。
anon-rssanonymous rss匿名驻留集。比如malloc出来的就是匿名的。
file-rss映射到设备和文件上的内存页面。
shmem-rss大概是shared memory rss?

解决方案

  1. 减少内存使用,将程序139行的代码map_py_function_to_dataset的函数的第三个参数64改为2减少并行处理数量,就可以减少内存的使用。
tensor_ds = map_py_function_to_dataset(record_ds, parse_frame_parallel, 2, (tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float64))
  1. 增加内存或swap交换分区,内存溢出电脑的内存和swap分区都是16G。
2.1.4 使用CPU计算

根据程序中类PyMapper的注释内容,该程序仅使用CPU计算没有使用GPU。

2.2 Run split_shards.py

   (注:原文使用的为shard_ds.py,但应该时程序更新README没有更新导致)
   上面程序等待大约2个小时,文件会处理完,接下来 to split the dataset into shards. This is not strictly necessary but improves results by performing an out-of-memory shuffle Run train.py to train on the dataset。即如果不运行该程序,那么在运行训练程序train.py的时候,就要同时进行shuffle洗牌操作,将会导致内存溢出。

2.2.1 修改split_shards.py

  split_shards.py在使用之前需要修改第7、19行的加载数据集路径和保存数据集路径。

2.2.2 内存溢出

再该程序的for循环批处理数量过大,导致shuffle缓存过大,也会出现内存溢出的情况,如下报错信息。

[47408.858780] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice,task=python,pid=16746,uid=1000
[47408.858833] Out of memory: Killed process 16746 (python) total-vm:39273812kB, anon-rss:14727308kB, file-rss:72024kB, shmem-rss:0kB, UID:1000 pgtables:58676kB oom_score_adj:0
[47409.316770] oom_reaper: reaped process 16746 (python), now anon-rss:0kB, file-rss:74732kB, shmem-rss:0kB

经过实验16G内存设置num_batch=1482是可以胜任的,代码修改如下:

i = 0
num_batch = 1482 # 单次批处理的元素数量,取决于内存大小,这个值16GB内存可以 #7904
while( ds.cardinality().numpy() >  0):
    print("the %d loop processing"%i,", remain elements=",ds.cardinality().numpy(),"/39987")
    shard = ds.take(num_batch) 
    shard = shard.shuffle(num_batch)
    tf.data.experimental.save(shard, '/media/bit/Elements1/waymo_open_dataset_v_1_2_0_individual_files_for_LaserNet_split/shard_%d'%i, compression='GZIP')
    ds = ds.skip(num_batch)
    i = i + 1

训练模型,加载数据一般有两种[文献]:直接全部加载到内存中, 使用 placeholder 占位符;使用 queue / tf.data (更推荐这种方式) 读硬盘中的数据。

此程序在进入后期的for循环之后,存在一个问题,在每次循环,貌似程序都要对硬盘中的所有数据读取一边,一找到skip后的文件位置,但这个过程会随着循环次数的增加而需要更长的时间找到目标文件,最后几次寻址的时间已经非常长。故,若直接使用tfrecord格式的文件可能不会出现这个问题。

对最后的for循环进行了一下修改,增加了一个单次本纪电脑所能处理的最大批量的变量,用户可以根据自己的计算机情况进行调整,笔者使用的是16G内存。并且引入全体元素个数,处理完成后即可自动退出。

2.3 训练

经过测试train.py需要使用随机分块之后的训练集数据和压缩之后的验证集数据;train_from_saved.py直接使用压缩之后的数据,但是经过测试该程序报错如下信息,故我们这里使用train.py进行训练。

ImportError: cannot import name 'LaserNetLoss' from 'src.loss' (/home/.../Lasernet/src/loss.py)
2.3.1 修改程序

修改对应的数据集的路径指向自己的数据集存放路径

2.3.2 运行train.py
  1. GPU报错
failed to create cublas handle: CUBLAS_STATUS_NOT_INITIALIZED

原因: 在创建session时没有使用想让它用的GPU[文献]。另外还有几种方法解决【123官网
解决方法:设置 CUDA_VISIBLE_DEVICES,在python程序前部添加如下语句

gpus= tf.config.list_physical_devices('GPU') 
print(gpus)
tf.config.experimental.set_memory_growth(gpus[0], True)
  1. 超出系统空间
    再次运行报出警告如下
Allocation of 230481920 exceeds 10% of free system memory.

解决方案:
有人通过修改keras模型的batch_size解决【参考该博客】;还有人通过扩充系统硬盘生于空间解决【参考该博客】。我试了一下第二种方案有效。

  1. 显存报错
    再次运行程序显存溢出,报出如下错误
.../cuda_driver.cc:789] failed to allocate 4.00G (4294967296 bytes) from device: CUDA_ERROR_OUT_OF_MEMORY: out of memory

将两处batch_size由16改为1,可以解决该问题,程序不会死,显卡可以正常工作,否则显卡最终会崩。显存报错还有很多博客讲述【12345678】,总结起来就是batch_size控制着显卡批处理数量,也就是显卡需要加载的模型参数批量,那么该值越大,显卡加载的数量也就越多,超出硬件显存,自然程序要崩溃。经过测试单个RTX 3090 显卡LaserNet支持Batchsize是3,可以支持到4但是显存会报OMM但是可以运行。双卡RTX1080Ti可以设置为4,设置到6显存会报OMM但是可以运行。

  1. 内存溢出报错
oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice,task=python,pid=13342,uid=1000
[38860.408573] Out of memory: Killed process 13342 (python) total-vm:35989456kB, anon-rss:14924192kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:59592kB oom_score_adj:0
[38860.966108] oom_reaper: reaped process 13342 (python), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

这两篇博客【12】给出了分析及一些解决思路。就本程序而言,猜测还是加载shuffle缓存导致的,也就是.sample_from_datasets(datasets).shuffle(500)导致的,加载数据解压填充到缓存,逐渐填满了内存,由于我们之前已经使用split_shards.py进行洗牌,故该程序可以修改为.sample_from_datasets(datasets),就不会出现内存溢出的情况了。

3. What works:

Basic implementation of the architecture for vehicles, pedestrians, and cyclists

4. What’s still not done:

  • Parameterize the scripts (yeah I was lazy and used hard-coded paths)
  • Mean-shift cluster (coming soon)
  • Adaptive NMS
  • Multi-modal distriutions for vehicles
  • Integration with Waymo Dataset evaluation metrics (also coming soon)

5. Example Results

top_image_2

6 其他看考资料

论文阅读:LaserNet: An Efficient Probabilistic 3D Object Detector for Autonomous Driving
LaserNet
LaserNet:一种用于自动驾驶的高效三维目标概率检测器
LaserNet:一种高效的自动驾驶概率三维目标探测器

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值