本文记录了博主阅读论文《Depth-Aware CNN for RGB-D Segmentation》代码的笔记的第一部分,train.py文件。更新于2019.03.21。
文章目录
train.py文件
import部分
import time
from tensorboardX import SummaryWriter
from collections import OrderedDict
from options.train_options import TrainOptions
从第4行开始调用的就是内部的包了,调用的是文件./options/train_options.py
。
from options.train_options import TrainOptions
这里调用的TrainOptions
中包括两部分,显示部分和训练部分。其中,显示部分包括的参数有:
display_freq
:在屏幕上显示训练结果的频率;print_freq
:在控制台(console)上显示训练结果的频率;save_latest_freq
:保存最新结果的频率;save_epoch_freq
:在一个epoch最后保存checkpoints的频率;no_html
:不向[opt.checkpoints_dir]/[opt.name]/web/
保存中间的训练结果;debug
:每次循环只进行一次epoch并显示。
训练部分包括的参数有:
loadfroms
:从32s或16s处加载,继续训练;continue_train
:加载最新的模型继续训练;use_softmax
:除非指定用softmax loss,否则使用log-softmax;phase
:train,val,test等;nepochs
:epoch的个数(默认100);iterSize
:初始学习率下的迭代次数(默认10,博主认为文件中这个注释写错了);maxbatchsize
:最大batchsize,默认-1;warmup_iters
:初始学习率下的迭代次数;beta1
:adam算法的动量;lr
:adam算法的初始学习率;lr_power
:学习率政策的指数;momentum
:sgd算法的动量;wd
:sgd的权重下降(weight decay)。
from data.data_loader import CreateDataLoader
调用的是文件./data/custom_dataset_data_loader.py
。允许的数据库模式有nyuv2
,voc
,sunrgbd
和stanfordindoor
。具体可以看./data
文件夹下对应的文件(如nyuv2_dataset.py
)
from models.models import create_model
可选择的模型类别有DeeplabVGG
,DeeplabVGG_HHA
和DeeplabResnet
。同样可以查看./models
下的对应文件。具体模型定义参见Deeplab.py文件部分和Deeplab_HHA.py文件部分。
import utils.util as util
调用的是文件./utils/utils.py
,其中包括了评估用的度量,包括_fast_hist
,label_accuracy_score
(返回accuracy score评估结果,包括overall accuracy,mean accuracy,mean IU和fwavacc)。
余下部分的代码来自于https://github.com/ycszen/pytorch-seg/blob/master/transform.py
,针对cityscape标注图颜色做了修改使其匹配。包括uint82bin
(返回整数
n
n
n的二进制,根据比特计数),labelcolormap
(针对cityscape有特殊的,否则用默认的),Colorize
,tensor2im
(将Tensor转成Numpy array),tensor2label
(将一个one-hot tensor转换成彩色label图),save_image
,mkdirs
和mkdir
。
from utils.visualizer import Visualizer
这一句加载的是文件./utils/visualizer.py
。其中包括display_current_results
(可以选择是显示图片还是保存,如果是tf_log
就在tensorboard输出显示图片,如果是use_html
就将图片保存成html文件),plot_current_errors
(错误标注和值得dictionary),print_current_errors
(格式与plotCurrentErros
中的errors
相同)和save_images
(将图片保存至磁盘)。
训练部分
训练设置部分:
opt = TrainOptions().parse() #从TrainOptions中读取参数
iter_path = os.path.join(opt.checkpoints_dir, opt.name, 'iter.txt') #合成路径,找到iter.txt文件存入iter_path
ioupath_path = os.path.join(opt.checkpoints_dir, opt.name, 'MIoU.txt') #合成路径,找到MIoU.txt文件存入路径ioupath_path
#如果继续训练
if opt.continue_train:
#尝试从iter.txt中读取start_epoch和epoch_iter;如果失败就将start_epoch设成1,epoch_iter设成0。
try:
start_epoch, epoch_iter = np.loadtxt(iter_path, delimiter=',', dtype=int)
except:
start_epoch, epoch_iter = 1, 0
# 尝试从MIoU.txt文件中读取best_iou,如果失败就将best_iou设成0。
try:
best_iou = np.loadtxt(ioupath_path, dtype=float)
except:
best_iou = 0.
# 显示从start_epoch的第epoch_iter开始恢复训练,之前的最优IoU为best_iou。
print('Resuming from epoch %d at iteration %d, previous best IoU %f' % (start_epoch, epoch_iter, best_iou))
# 否则(从头训练),start_epoch为1,epoch_iter为0,best_iou为0。
else:
start_epoch, epoch_iter = 1, 0
best_iou = 0.
加载数据:
data_loader = CreateDataLoader(opt)
dataset, dataset_val = data_loader.load_data()
dataset_size = len(dataset)
print('#training images = %d' % dataset_size)
模型创建及训练:
# 直接加载模型,允许的模型有DeeplabVGG,DeeplabVGG_HHA和DeeplabResnet
model = create_model(opt, dataset.dataset)
# print (model) 打印模型
visualizer = Visualizer(opt)
total_steps = (start_epoch - 1) * dataset_size + epoch_iter #一个epoch中的迭代次数
#在规定的epoch数内进行下面的过程
for epoch in range(start_epoch, opt.nepochs):
epoch_start_time = time.time() #记录开始时间
# 如果当前epoch不是初始epoch,将epoch_iter除以dataset_size取余数
if epoch != start_epoch:
epoch_iter = epoch_iter % dataset_size
# 网络训练
model.model.train()
for i, data in enumerate(dataset, start=epoch_iter):
iter_start_time = time.time()
total_steps += opt.batchSize
epoch_iter += opt.batchSize
############## Forward and Backward Pass 前向和后向传播 ######################
model.forward(data)
model.backward(total_steps, opt.nepochs * dataset.__len__() * opt.batchSize + 1)
############## update tensorboard and web images 更新tensorboard和web图片 ######################
if total_steps % opt.display_freq == 0: # 如果到了显示频率,就显示图片
visuals = model.get_visuals(total_steps) # 定义于Deeplab.py文件中,用于记录损失和可用于显示的结果
visualizer.display_current_results(visuals, epoch, total_steps) # 定义于visualizer.py文件中,用于显示或保存visuals中的结果
############## Save latest Model 保存最新的模型 ######################
if total_steps % opt.save_latest_freq == 0: # 如果到了保存频率就保存图片
print('saving the latest model (epoch %d, total_steps %d)' % (epoch, total_steps))
model.save('latest')
np.savetxt(iter_path, (epoch, epoch_iter), delimiter=',', fmt='%d')
# 可以输出训练消耗的时间
# print time.time()-iter_start_time
# end of epoch 结束当前epoch
# 开始模型评估
model.model.eval()
if dataset_val!=None: #如果有交叉验证集
label_trues, label_preds = [], []
for i, data in enumerate(dataset_val):
seggt, segpred = model.forward(data,False) # False进行测试,默认是True(训练)
# 将数据格式从CUDA Tensor转成numpy格式,不能直接转,需要先转成cpu float-tensor,再转成numpy。
# 数据转换的原因是,对tensor进行处理必须重新启动一个Session,否则无法对其重新赋值或判断。而转成numpy就好处理了。
# 另一个原因是,torch的tesnor和numpy的array会共享存储空间,修改一个另一个也会被修改。
# 不过博主的电脑上试验,可以直接转换成array,不知道是不是python版本的问题。博主电脑上try.cpu().numpy、try.numpy()和np.array(try)都可以实现将tensor try变成array。而且可以直接对tensor赋值。
seggt = seggt.data.cpu().numpy()
segpred = segpred.data.cpu().numpy()
label_trues.append(seggt)
label_preds.append(segpred)
# 返回正确率评估结果,包括overall accuracy(acc),mean accuracy(acc_cls),mean IU(mean_iu)和fwavacc(fwavacc)。
metrics = util.label_accuracy_score(
label_trues, label_preds, n_class=opt.label_nc)
# 将metrics的格式转换成numpy array。
metrics = np.array(metrics)
# 变成百分数
metrics *= 100
print('''\
Validation:
Accuracy: {0}
Accuracy Class: {1}
Mean IU: {2}
FWAV Accuracy: {3}'''.format(*metrics))
model.update_tensorboard(metrics,total_steps) # 更新显示界面
iter_end_time = time.time() # 记录迭代时间
print('End of epoch %d / %d \t Time Taken: %d sec' %
(epoch+1, opt.nepochs, time.time() - epoch_start_time))
# 如果当前的平均iou是最优的,那么保存这个模型作为best。
if metrics[2]>best_iou:
best_iou = metrics[2]
print('saving the model at the end of epoch %d, iters %d, loss %f' % (epoch, total_steps, model.trainingavgloss))
model.save('best')
### save model for this epoch 保存这个epoch下的模型
if epoch % opt.save_epoch_freq == 0:
print('saving the model at the end of epoch %d, iters %d, loss %f' % (epoch, total_steps, model.trainingavgloss))
model.save('latest')
model.save(epoch)
np.savetxt(iter_path, (epoch + 1, 0), delimiter=',', fmt='%d')
加入星球了解更多分割知识: