加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

PyTorch最佳实践,奈何才气写出一手气魄威风凛凛美妙的代码

发布时间:2019-05-06 19:13:03 所属栏目:建站 来源:机器之心编译
导读:固然这是一个非官方的 PyTorch 指南,但本文总结了一年多行使 PyTorch 框架的履历,尤其是用它开拓深度进修相干事变的最优办理方案。请留意,我们分享的履历大多是从研究和实践角度出发的。 这是一个开拓的项目,接待其余读者改造该文档: https://github.

纵然 PyTorch 已经具有了大量尺度丧失函数,你偶然也也许必要建设本身的丧失函数。为了做到这一点,你必要建设一个独立的「losses.py」文件,而且通过扩展「nn.Module」建设你的自界说丧失函数:

  1. class CustomLoss(torch.nn.Module): 
  2.  
  3.     def __init__(self): 
  4.         super(CustomLoss,self).__init__() 
  5.  
  6.     def forward(self,x,y): 
  7.         loss = torch.mean((x - y)**2) 
  8.         return loss 

5. 实习模子的最佳代码布局

对付实习的最佳代码布局,我们必要行使以下两种模式:

  • 行使 prefetch_generator 中的 BackgroundGenerator 来加载下一个批量数据
  • 行使 tqdm 监控实习进程,并展示计较服从,这能辅佐我们找到数据加载流程中的瓶颈
  1. # import statements 
  2. import torch 
  3. import torch.nn as nn 
  4. from torch.utils import data 
  5. ... 
  6.  
  7. # set flags / seeds 
  8. torch.backends.cudnn.benchmark = True 
  9. np.random.seed(1) 
  10. torch.manual_seed(1) 
  11. torch.cuda.manual_seed(1) 
  12. ... 
  13.  
  14. # Start with main code 
  15. if __name__ == '__main__': 
  16.     # argparse for additional flags for experiment 
  17.     parser = argparse.ArgumentParser(description="Train a network for ...") 
  18.     ... 
  19.     opt = parser.parse_args()  
  20.  
  21.     # add code for datasets (we always use train and validation/ test set) 
  22.     data_transforms = transforms.Compose([ 
  23.         transforms.Resize((opt.img_size, opt.img_size)), 
  24.         transforms.RandomHorizontalFlip(), 
  25.         transforms.ToTensor(), 
  26.         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) 
  27.     ]) 
  28.  
  29.     train_dataset = datasets.ImageFolder( 
  30.         root=os.path.join(opt.path_to_data, "train"), 
  31.         transform=data_transforms) 
  32.     train_data_loader = data.DataLoader(train_dataset, ...) 
  33.  
  34.     test_dataset = datasets.ImageFolder( 
  35.         root=os.path.join(opt.path_to_data, "test"), 
  36.         transform=data_transforms) 
  37.     test_data_loader = data.DataLoader(test_dataset ...) 
  38.     ... 
  39.  
  40.     # instantiate network (which has been imported from *networks.py*) 
  41.     net = MyNetwork(...) 
  42.     ... 
  43.  
  44.     # create losses (criterion in pytorch) 
  45.     criterion_L1 = torch.nn.L1Loss() 
  46.     ... 
  47.  
  48.     # if running on GPU and we want to use cuda move model there 
  49.     use_cuda = torch.cuda.is_available() 
  50.     if use_cuda: 
  51.         netnet = net.cuda() 
  52.         ... 
  53.  
  54.     # create optimizers 
  55.     optim = torch.optim.Adam(net.parameters(), lr=opt.lr) 
  56.     ... 
  57.  
  58.     # load checkpoint if needed/ wanted 
  59.     start_n_iter = 0 
  60.     start_epoch = 0 
  61.     if opt.resume: 
  62.         ckpt = load_checkpoint(opt.path_to_checkpoint) # custom method for loading last checkpoint 
  63.         net.load_state_dict(ckpt['net']) 
  64.         start_epoch = ckpt['epoch'] 
  65.         start_n_iter = ckpt['n_iter'] 
  66.         optim.load_state_dict(ckpt['optim']) 
  67.         print("last checkpoint restored") 
  68.         ... 
  69.  
  70.     # if we want to run experiment on multiple GPUs we move the models there 
  71.     net = torch.nn.DataParallel(net) 
  72.     ... 
  73.  
  74.     # typically we use tensorboardX to keep track of experiments 
  75.     writer = SummaryWriter(...) 
  76.  
  77.     # now we start the main loop 
  78.     n_iter = start_n_iter 
  79.     for epoch in range(start_epoch, opt.epochs): 
  80.         # set models to train mode 
  81.         net.train() 
  82.         ... 
  83.  
  84.         # use prefetch_generator and tqdm for iterating through data 
  85.         pbar = tqdm(enumerate(BackgroundGenerator(train_data_loader, ...)), 
  86.                     total=len(train_data_loader)) 
  87.         start_time = time.time() 
  88.  
  89.         # for loop going through dataset 
  90.         for i, data in pbar: 
  91.             # data preparation 
  92.             img, label = data 
  93.             if use_cuda: 
  94.                 imgimg = img.cuda() 
  95.                 labellabel = label.cuda() 
  96.             ... 
  97.  
  98.             # It's very good practice to keep track of preparation time and computation time using tqdm to find any issues in your dataloader 
  99.             prepare_time = start_time-time.time() 
  100.  
  101.             # forward and backward pass 
  102.             optim.zero_grad() 
  103.             ... 
  104.             loss.backward() 
  105.             optim.step() 
  106.             ... 
  107.  
  108.             # udpate tensorboardX 
  109.             writer.add_scalar(..., n_iter) 
  110.             ... 
  111.  
  112.             # compute computation time and *compute_efficiency* 
  113.             process_time = start_time-time.time()-prepare_time 
  114.             pbar.set_description("Compute efficiency: {:.2f}, epoch: {}/{}:".format( 
  115.                 process_time/(process_time+prepare_time), epoch, opt.epochs)) 
  116.             start_time = time.time() 
  117.  
  118.         # maybe do a test pass every x epochs 
  119.         if epoch % x == x-1: 
  120.             # bring models to evaluation mode 
  121.             net.eval() 
  122.             ... 
  123.             #do some tests 
  124.             pbar = tqdm(enumerate(BackgroundGenerator(test_data_loader, ...)), 
  125.                     total=len(test_data_loader))  
  126.             for i, data in pbar: 
  127.                 ... 
  128.  
  129.             # save checkpoint if needed 
  130.             ... 

三、PyTorch 的多 GPU 实习

PyTorch 中有两种行使多 GPU 举办实习的模式。

按照我们的履历,这两种模式都是有用的。然而,第一种要领获得的功效更好、必要的代码更少。因为第二种要领中的 GPU 间的通讯更少,好像具有稍微的机能上风。

1. 对每个收集输入的 batch 举办切分

最常见的一种做法是直接将全部收集的输入切分为差异的批量数据,并分派给各个 GPU。

这样一来,在 1 个 GPU 上运行批量巨细为 64 的模子,在 2 个 GPU 上运行时,每个 batch 的巨细就酿成了 32。这个进程可以行使「nn.DataParallel(model)」包装器自动完成。

2. 将全部收集打包到一个超等收集中,并对输入 batch 举办切分

这种模式不太常用。下面的代码客栈向各人展示了 Nvidia 实现的 pix2pixHD,它有这种要领的实现。

地点:https://github.com/NVIDIA/pix2pixHD

四、PyTorch 中该做和不应做的

1. 在「nn.Module」的「forward」要领中停止行使 Numpy 代码

Numpy 是在 CPU 上运行的,它比 torch 的代码运行得要慢一些。因为 torch 的开拓思绪与 numpy 相似,以是大大都 Numpy 中的函数已经在 PyTorch 中获得了支持。

2. 将「DataLoader」从主措施的代码中疏散

载入数据的事变流程应该独立于你的主实习措施代码。PyTorch 行使「background」历程越发高效地载入数据,而不会滋扰到主实习历程。

3. 不要在每一步中都记录功效

凡是而言,我们要实习我们的模子好几千步。因此,为了减小计较开销,每隔 n 步对丧失和其余的计较功效举办记录就足够了。尤其是,在实习进程中将中间功效生涯成图像,这种开销长短常大的。

4. 行使呼吁行参数

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读