PV-RCNN:paper,code
1. train 在tools/train.py
中找到以下表示开始训练的代码
# -----------------------start training---------------------------
logger.info('**********************Start training %s/%s(%s)**********************'
% (cfg.EXP_GROUP_PATH, cfg.TAG, args.extra_tag))
train_model(
model, optimizer, train_loader, model_func=model_fn_decorator(),
lr_scheduler=lr_scheduler, optim_cfg=cfg.OPTIMIZATION,
start_epoch=start_epoch, total_epochs=args.epochs,
start_iter=it, rank=cfg.LOCAL_RANK, tb_log=tb_log,
ckpt_save_dir=ckpt_dir, train_sampler=train_sampler,
lr_warmup_scheduler=lr_warmup_scheduler,
ckpt_save_interval=args.ckpt_save_interval,
max_ckpt_save_num=args.max_ckpt_save_num,
merge_all_iters_to_one_epoch=args.merge_all_iters_to_one_epoch
)
train_model
定位在头文件中的tools/train_utils/train_utils.py
中其关键信息的框架为
for key in epochs:
train_one_epoch #训练一个epoch
save_trained_model #储存训练好的模型
找到
train_model
中的train_one_epoch()
accumulated_iter = train_one_epoch(
model, optimizer, train_loader, model_func,
lr_scheduler=cur_scheduler,
accumulated_iter=accumulated_iter, optim_cfg=optim_cfg,
rank=rank, tbar=tbar, tb_log=tb_log,
leave_pbar=(cur_epoch + 1 == total_epochs),
total_it_each_epoch=total_it_each_epoch,
dataloader_iter=dataloader_iter
)
train_one_epoch
函数的定义在同一py
文件中,其关键信息为def train_one_epoch(model, optimizer, train_loader, model_func, lr_scheduler, accumulated_iter, optim_cfg,
rank, tbar, total_it_each_epoch, dataloader_iter, tb_log=None, leave_pbar=False):
#找到表示训练和梯度优化等的关键函数
model.train() #一个固定语句
optimizer.zero_grad() #梯度清零
loss, tb_dict, disp_dict = model_func(model, batch) #求loss
loss.backward() #反向传播
clip_grad_norm_(model.parameters(), optim_cfg.GRAD_NORM_CLIP) #梯度裁剪
optimizer.step() #更新
用到了几个
Pytorch
自带的函数:model.train()
:在训练模型时都会在前面加上
model.train()
在测试模型时都会在前面加上
model.eval()
如果不写这两个程序也可以运行,这两个方法是针对在训练和测试时采用不同方式的情况,比如
Batch Normalization
和 Dropout
。详细介绍。clip_grad_norm_()
:功能是梯度裁剪。即为了防止梯度爆炸,当梯度超过阈值
optim_cfg
时将其设置为阈值。详细介绍。optimizer.step()
:功能是根据网络反向传播的梯度信息,更新网络的参数,以降低loss。详细介绍。
训练结束之后
info
logger.info('**********************End training %s/%s(%s)**********************\n\n\n'
% (cfg.EXP_GROUP_PATH, cfg.TAG, args.extra_tag))
2. test 接下来程序会自动执行测试过程
logger.info('**********************Start evaluation %s/%s(%s)**********************' %
(cfg.EXP_GROUP_PATH, cfg.TAG, args.extra_tag))
test_set, test_loader, sampler = build_dataloader(
dataset_cfg=cfg.DATA_CONFIG,
class_names=cfg.CLASS_NAMES,
batch_size=args.batch_size,
dist=dist_train, workers=args.workers, logger=logger, training=False
) # test_loader为一个batch_size大小的Tensoreval_output_dir = output_dir / 'eval' / 'eval_with_train' #输出路径
eval_output_dir.mkdir(parents=True, exist_ok=True)
args.start_epoch = max(args.epochs - 10, 0)# Only evaluate the last 10 epochs
# args.start_epoch = max(args.epochs - 1, 0)# Only evaluate the last epochrepeat_eval_ckpt( #测试训练好的模型
model.module if dist_train else model,
test_loader, args, eval_output_dir, logger, ckpt_dir,
dist_test=dist_train
)
【PV-RCNN|PV-RCNN代码解读——train & test】
built_dataloader()
:dataloader
是PyTorch
中数据读取的一个重要接口,功能是将自定义的Dataset
封装成一个batch_size
大小的Tensor
,用于后面的训练。repeat_eval_ckpt()
:在
tools/test
中定义的函数,其关键部分为def repeat_eval_ckpt(model, test_loader, args, eval_output_dir, logger, ckpt_dir, dist_test=False):
# 加载数据
model.load_params_from_file(filename=cur_ckpt, logger=logger, to_cpu=dist_test)
model.cuda()
# 测试结果的储存路径
cur_result_dir = eval_output_dir / ('epoch_%s' % cur_epoch_id) / cfg.DATA_CONFIG.DATA_SPLIT['test']
# 测试一个epoch
tb_dict = eval_utils.eval_one_epoch(
cfg, model, test_loader, cur_epoch_id, logger, dist_test=dist_test,
result_dir=cur_result_dir, save_to_file=args.save_to_file
)
# 储存这个测试过的epoch
with open(ckpt_record_file, 'a') as f:
print('%s' % cur_epoch_id, file=f)
logger.info('Epoch %s has been evaluated' % cur_epoch_id)
eval_one_epoch()
的定义在tools/eval_utils/eval_utils.py
中,其关键部分为def eval_one_epoch(cfg, model, dataloader, epoch_id, logger, dist_test=False, save_to_file=False, result_dir=None): # 储存路径
result_dir.mkdir(parents=True, exist_ok=True)
final_output_dir = result_dir / 'final_result' / 'data'
if save_to_file:
final_output_dir.mkdir(parents=True, exist_ok=True) # 开始测试
logger.info('*************** EPOCH %s EVALUATION *****************' % epoch_id)
'''
这里省略了把资源分配给多个GPU的代码,详见源码
''' # 对于dataloader中的每一个batch_dict产生预测值和反馈值
start_time = time.time()
for i, batch_dict in enumerate(dataloader):
load_data_to_gpu(batch_dict)
with torch.no_grad():
pred_dicts, ret_dict = model(batch_dict)
disp_dict = {}#产生预测值,对于kitti数据引用的函数定义在pcdet/datasets/kitti/kitti_dataset.py
statistics_info(cfg, ret_dict, metric, disp_dict)
annos = dataset.generate_prediction_dicts(
batch_dict, pred_dicts, class_names,
output_path=final_output_dir if save_to_file else None
)
det_annos += annos#显示进度条
if cfg.LOCAL_RANK == 0:
progress_bar.set_postfix(disp_dict)
progress_bar.update()if cfg.LOCAL_RANK == 0:
progress_bar.close()'''
这里省略了显示进度条&打印测试结果的语句,详见源码
'''
# 得到测试结果,evaluation()函数我会详细写一个博客写
result_str, result_dict = dataset.evaluation(
det_annos, class_names,
eval_metric=cfg.MODEL.POST_PROCESSING.EVAL_METRIC,
output_path=final_output_dir
) # 更新结果,打印日志,测试结束
logger.info(result_str)
ret_dict.update(result_dict)
logger.info('Result is save to %s' % result_dir)
logger.info('****************Evaluation done.*****************')
return ret_dict
evaluation函数详解
我的其他
PV-RCNN
代码解读系列文章,如果对你有帮助的话,请给我点赞哦~PV-RCNN代码解读——输入参数介绍
PV-RCNN代码解读——TP,FP,TN,FN的计算
PV-RCNN代码解读——eval.py
PV-RCNN代码解读——计算iou
PV-RCNN代码解读——数据初始化
PV-RCNN代码解读——从点云到输入神经网络的数据处理
推荐阅读
- 机器学习|从Python入门人工智能指南
- python|可以给AI减轻负担的Python AI库有哪些()
- Something|《Python深度学习》之卷积神经网络可视化
- Pytorch教程|Pytorch教程[01]张量操作
- Pytorch教程|Pytorch教程[02]DataLoader与Dataset
- Pytorch教程|Pytorch教程[04]torch.nn---Containers
- DEEP|什么是端到端神经网络()
- Python基础|快速傅里叶变换及python代码实现
- 问答系统|简单问答系统实现原理 - 基于机器学习的