代码学习-CVPR2020非监督域内自适应语义分割:Intra-ADVENT

1.官方readme.md

Step 1. 通过训练ADVENT进行跨领域适应: ADVENT:

$ cd <root_dir>/ADVENT/advent/scripts
$ python train.py --cfg ./config/advent.yml 
$ python train.py --cfg ./config/advent.yml --tensorboard % using tensorboard

经过域间训练后,需要通过运行test.py得到最佳IoU迭代:

$ cd <root_dir>/ADVENT/advent/scripts
$ python test.py --cfg ./config/advent.yml

最佳IoU迭代BEST_ID将是Step 2的一个参数
Step 2. 基于熵的排序将Cityscapes训练集划分为易分割和难分割:

$ cd <root_dir>/entropy_rank
$ python entropy.py --best_iter BEST_ID --normalize False --lambda1 0.67 

您将看到生成的伪标签 color_masks, 容易分割文件名称在 easy_split.txt, 难分割文件名称在 hard_split.txt.
Step 3. 通过运行以下代码进行域内适配:

$ cd <root_dir>/intrada
$ python train.py --cfg ./intrada.yml
$ python train.py --cfg ./intrada.yml --tensorboard % using tensorboard

Testing
测试性能,请运行:

$ cd <root_dir>/intrada
$ python test.py --cfg ./intrada.yml

2.代码文件编排

在这里插入图片描述

3.部分代码注释

3.1.ADVENT

3.1.1.advent/domain_adaptation/train_UDA.py

主函数train_domain_adaptation,根据所选择的方法进行域间适应:

train_domain_adaptation(model, trainloader, targetloader, cfg):
    if cfg.TRAIN.DA_METHOD == 'MinEnt':
        train_minent(model, trainloader, targetloader, cfg)
    elif cfg.TRAIN.DA_METHOD == 'AdvEnt':
        train_advent(model, trainloader, targetloader, cfg)

train_minent :根据minent方法进行域间适应训练:

train_minent(model, trainloader, targetloader, cfg):
	#先通过有标记的源图像最小化交叉熵损失,监督训练Ginter    
	pred_src_aux, pred_src_main =model(images_source.cuda(device))    
	loss_seg_src_aux = loss_calc(pred_src_aux, labels, device)    
	loss_seg_src_main = loss_calc(pred_src_main, labels, device)    
	loss = (cfg.TRAIN.LAMBDA_SEG_MAIN * loss_seg_src_main+ cfg.TRAIN.LAMBDA_SEG_AUX * loss_seg_src_aux)   
	loss.backward()#通过最小化模型预测目标图像的熵损失,优化Ginter    
	pred_trg_aux, pred_trg_main = model(images.cuda(device))    
	pred_trg_aux = interp_target(pred_trg_aux);
	pred_trg_main = interp_target(pred_trg_main)    
	pred_prob_trg_aux = F.softmax(pred_trg_aux);pred_prob_trg_main = F.softmax(pred_trg_main)    
	loss_target_entp_aux = entropy_loss(pred_prob_trg_aux)    
	loss_target_entp_main = entropy_loss(pred_prob_trg_main)    
	loss = (cfg.TRAIN.LAMBDA_ENT_AUX * loss_target_entp_aux+ cfg.TRAIN.LAMBDA_ENT_MAIN * loss_target_entp_main)    
	loss.backward()    
	optimizer.step()

train_advent:根据ADVENT方法进行域间适应性训练:

train_advent(model, trainloader, targetloader, cfg):
	#discriminator是作用于熵图的
	d_aux = get_fc_discriminator(num_classes=num_classes);
	d_main = get_fc_discriminator(num_classes=num_classes)
	interp = nn.Upsample(size=(input_size_source[1], input_size_source[0]))
	interp_target = nn.Upsample(size=(input_size_target[1], input_size_target[0]))
	source_label = 0;target_label = 1    
	# UDA Training:#先使用源和源标记监督训练分割网络    
	pred_src_aux, pred_src_main = model(images_source.cuda(device))    
	pred_src_aux = interp(pred_src_aux);
	loss_seg_src_aux = loss_calc(pred_src_aux, labels, device)    
	pred_src_main = interp(pred_src_main);
	loss_seg_src_main = loss_calc(pred_src_main, labels, device)    
	loss = (cfg.TRAIN.LAMBDA_SEG_MAIN * loss_seg_src_main + cfg.TRAIN.LAMBDA_SEG_AUX * loss_seg_src_aux)    
	loss.backward() 
	#对抗训练,训练model,希望model足够好,好到可以让discriminator无法分辨图像来自哪个域,这里固定不训练discriminator    
	pred_trg_aux, pred_trg_main = model(images.cuda(device))
	#生成目标的伪软分割图,后面生成伪标签    
	pred_trg_aux = interp_target(pred_trg_aux)    
	d_out_aux = d_aux(prob_2_entropy(F.softmax(pred_trg_aux)))
	loss_adv_trg_aux = bce_loss(d_out_aux, source_label)
	pred_trg_main = interp_target(pred_trg_main)
	d_out_main = d_main(prob_2_entropy(F.softmax(pred_trg_main)))
	loss_adv_trg_main = bce_loss(d_out_main, source_label)    
	loss = (cfg.TRAIN.LAMBDA_ADV_MAIN * loss_adv_trg_main+ cfg.TRAIN.LAMBDA_ADV_AUX * loss_adv_trg_aux)    
	loss = loss;
	loss.backward()
	#训练discriminator,使用源图的熵图,通过最小化discriminator对源预测出是源还是目标所产生的损失        
	pred_src_aux = pred_src_aux.detach()
	d_out_aux = d_aux(prob_2_entropy(F.softmax(pred_src_aux)))        
	loss_d_aux = bce_loss(d_out_aux, source_label)
	loss_d_aux = loss_d_aux / 2;loss_d_aux.backward()        
	pred_src_main = pred_src_main.detach()        
	d_out_main = d_main(prob_2_entropy(F.softmax(pred_src_main)))        
	loss_d_main = bce_loss(d_out_main, source_label);
	loss_d_main = loss_d_main / 2;
	loss_d_main.backward()
	# 训练discriminator,使用目标图像的熵图,通过最小化discriminator对目标预测出是源还是目标所产生的损失        
	pred_trg_aux = pred_trg_aux.detach();
	 d_out_aux = d_aux(prob_2_entropy(F.softmax(pred_trg_aux)))        
	 loss_d_aux = bce_loss(d_out_aux, target_label); 
	 loss_d_aux = loss_d_aux / 2;loss_d_aux.backward()        
	 pred_trg_main = pred_trg_main.detach()        
	 d_out_main = d_main(prob_2_entropy(F.softmax(pred_trg_main)))        
	 loss_d_main = bce_loss(d_out_main, target_label);
	 loss_d_main = loss_d_main / 2
	 loss_d_main.backward()

3.1.2.advent/domain_adaptation/eval_UDA.py

验证模型的精度,输出对应结果的IoU
主函数evaluate_domain_adaptation:根据模式进行相关的模型验证

evaluate_domain_adaptation( models, test_loader, cfg,fixed_test_size=True,verbose=True):
    if cfg.TEST.MODE == 'single':        
    	eval_single(cfg, models,device, test_loader, interp, fixed_test_size,verbose)    
    elif cfg.TEST.MODE == 'best':
        eval_best(cfg, models,device, test_loader, interp, fixed_test_size,verbose)

eval_single验证单个模型的性能:

eval_single(cfg, models,device, test_loader, interp,fixed_test_size, verbose):
	#计算IOU    
	hist = np.zeros((cfg.NUM_CLASSES, cfg.NUM_CLASSES))    
	hist += fast_hist(label.flatten(), output.flatten(), cfg.NUM_CLASSES)
	#输出每一类的IoU
	inters_over_union_classes = per_class_iu(hist)

eval_best验证所有模型,输出最好的那个:

eval_best(cfg, models,device, test_loader, interp,fixed_test_size, verbose):
	for i_iter in range(start_iter, max_iter + 1, step):
		hist += fast_hist(label.flatten(), output.flatten(), cfg.NUM_CLASSES)    
		inters_over_union_classes = per_class_iu(hist)    
		all_res[i_iter] = inters_over_union_classes    
		pickle_dump(all_res, cache_path)
		#计算每一类的mIoU,保存最好的那个    
		computed_miou = round(np.nanmean(inters_over_union_classes) * 100, 2)        
		if cur_best_miou < computed_miou:            
			cur_best_miou = computed_miou            
			cur_best_model = restore_from

3.2.entropy_rank

3.2.1.entropy.py

对目标图像按经过生成器后的熵进行排序分为难分割和易分割
主函数main:

main(arg):    
	model_gen = get_deeplab_v2
	load_checkpoint_for_evaluation(model_gen, restore_from, device)    
	_, pred_trg_main = model_gen(image.cuda(device))    
	pred_trg_main    = interp_target(pred_trg_main)    p
	red_trg_entropy = prob_2_entropy(F.softmax(pred_trg_main))    
	entropy_list.append((name[0], pred_trg_entropy.mean().item() * normalizor))    
	##将预测的mask和转换成指定色彩的彩色图存下来
	colorize_save(pred_trg_main, name[0])  
	#根据entropy_list排序将easy和hard图像的名字写入对应的txt文件
	cluster_subdomain(entropy_list, args.lambda1)

3.3.intrada

3.3.1.train.py

进行域内适配训练
主函数main

main():  
	model = get_deeplab_v2(num_classes=cfg.NUM_CLASSES, multi_level=cfg.TRAIN.MULTI_LEVEL)  
	saved_state_dict = torch.load(cfg.TRAIN.RESTORE_FROM)  
	#根据之前存下来的easy的图像的名单加载数据
	easy_dataset = CityscapesDataSet_easy(root=cfg.DATA_DIRECTORY_SOURCE);
	easy_loader = data.DataLoader(easy_dataset)  
	#根据之前存下来的hard的图像的名单加载数据
	hard_dataset = CityscapesDataSet_easy(root=cfg.DATA_DIRECTORY_TARGET);
	hard_loader = data.DataLoader(hard_dataset)  
	#将easy作为源hard作为目标。进行域内适应训练,训练结构和域间一样
	train_domain_adaptation(model, easy_loader, hard_loader, cfg)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值