防坑指南 | pytorch常见的坑汇总

点击上方AI算法与图像处理”,选择加"星标"或“置顶”

重磅干货,每天 8:25 送达640?wx_fmt=jpeg

来源:知乎 郁振波

编辑:AI算法与图像处理

链接:https://zhuanlan.zhihu.com/p/77952356

已授权转载,禁止二次转载

640?wx_fmt=png

1. 没有比较高效的数据存储,tensorflow有tfrecord, caffe有lmdb,cv.imread在网络训练过程中实属浪费时间。这里感谢一下小智大神 

智天成

解决方案:

当时看到了一个还不错的github链接,

https://github.com/Lyken17/Efficient-PyTorch

主要是讲如何使用lmdb,h5py,pth,lmdb,n5等数据存储方式皆可以。

个人的感受是,h5在数据调用上比较快,但是如果要使用多线程读写,就尽量不要使用h5,因为h5的多线程读写好像比较麻烦。

http://docs.h5py.org/en/stable/mpi.html

这里贴一下h5数据的读写代码(主要需要注意的是字符串的读写需要encode,decode,最好用create_dataset,直接写的话读的时候会报错):

写:	
    imagenametotal_.append(os.path.join('images', imagenametotal).encode())	
    with h5py.File(outfile) as f:	
        f.create_dataset('imagename', data=imagenametotal_)	
        f['part'] = parts_	
        f['S'] = Ss_	
        f['image'] = cvimgs	
读:	
with h5py.File(outfile) as f:	
    imagename = [x.decode() for x in f['imagename']]	
    kp2ds = np.array(f['part'])	
    kp3ds = np.array(f['S'])	
    cvimgs = np.array(f['image'])

2. gpu imbalance,这里感谢一下张航学长 

张航

老生常谈的问题,第一个GPU显存占用多一点。

张航学长Hang Zhang (张航)提了一个开源的gpu balance的工具--PyTorch-Encoding。

https://github.com/zhanghang1989/PyTorch-Encoding

使用方法还是比较便捷的,如下所示

from balanced_parallel import DataParallelModel, DataParallelCriterion	
model = DataParallelModel(model, device_ids=gpus).cuda()	
criterion = loss_fn().cuda()

这里其实有2个注意点,第一,测试的时候需要手动将gpu合并,代码如下:

from torch.nn.parallel.scatter_gather import gather	
preds = gather(preds, 0)

第二,当loss函数有多个组成的时候,比如 loss = loss1 + loss2 + loss3

那么需要把这三个loss写到一个class中,然后再forward里面将其加起来。

其次,我们还可以用另外一个函数distributedDataParallel来解决gpu imbalance的问题.

使用方法如下:(注:此方法好像无法和h5数据同时使用)

from torch.utils.data.distributed import DistributedSampler	
from torch.nn.parallel import DistributedDataParallel	

	
torch.distributed.init_process_group(backend="nccl")	
# 配置每个进程的gpu	
local_rank = torch.distributed.get_rank()	
torch.cuda.set_device(local_rank)	
device = torch.device("cuda", local_rank)	

	
#封装之前要把模型移到对应的gpu	
model.to(device)	
model = torch.nn.parallel.DistributedDataParallel(model,device_ids=[local_rank],	
                                                   output_device=local_rank)	

	
#原有的dataloader上面加一个数据sample	
train_loader = torch.utils.data.DataLoader(	
        train_dataset,	
        sampler=DistributedSampler(train_dataset)	
    )

3.gpu利用率不高+gpu现存占用浪费

常用配置: 

1主函数前面加:(这个会牺牲一点点现存提高模型精度)

cudnn.benchmark = True
torch.backends.cudnn.deterministic = False
torch.backends.cudnn.enabled = True	

2 训练时,epoch前面加:(定期清空模型,效果感觉不明显)

torch.cuda.empty_cache()	

3 无用变量前面加:(同上,效果某些操作上还挺明显的)

del xxx(变量名)

4 dataloader的长度_len_设置:(dataloader会间歇式出现卡顿,设置成这样会避免不少)

def __len__(self):
    return self.images.shape[0]

5 dataloader的预加载设置:(会在模型训练的时候加载数据,提高一点点gpu利用率)

train_loader = torch.utils.data.DataLoader(
        train_dataset,
        pin_memory=True,
    )

6 网络设计很重要,外加不要初始化任何用不到的变量,因为pyroch的初始化和forward是分开的,他不会因为你不去使用,而不去初始化。

7 最后放一张目前依旧困扰我的图片:

防坑指南 | pytorch常见的坑汇总_第1张图片

可以看到,每个epoch刚开始训练数据的时候,第一个iteration时间会占用的非常多,pytorch这里就做的很糟糕,并不是一个动态分配的过程,我也看到了一个看上去比较靠谱的解决方案,解决方案如下 

风车车: https://zhuanlan.zhihu.com/p/77633542

640?

有热门推荐?

1.

2.

3.干货!PyTorch资源分享——你需要的可能都在这里

4.
5. GitHub趋势榜第一:TensorFlow+PyTorch深度学习资源大汇总
6.

加群交流

640?wx_fmt=png
你点的每个“在看”,我都认真当成了喜欢

你可能感兴趣的:(防坑指南 | pytorch常见的坑汇总)