Pytroch利用GPU训练模型以及固定随机种子

一、Pytroch利用GPU训练模型

Pytroch利用GPU训练模型需要将设计好的模型数据放入指定的GPU上,至于损失函数个人认为不需要放到GPU上,至于原因引用知乎高赞回答(当然把损失函数放到GPU上也不会报错):

通常不需要。简单地说,损失函数接收一个或多个输入tensor,如果输入tensor本身就是在gpu上,则输出tensor自然就在gpu上。构建网络时,需要主动to或cuda的包括模型输入tensor,以及对应的Module(网络模型)对象。模型输入tensor是数据不用多说,Module对象使用.cuda是为了将模型内部的数据(即每个子叶Module的Parameter或Buffer成员变量)递归地传入gpu。再进一步,如CrossEntropyCriterion等pytorch自带的loss类(或称loss layer)虽然也是Module的子类,但是这些类的成员变量不含Parameter对象或Buffer对象,所以无需to或cuda处理。Module对象是否持有数据,在设计上也是区分network layer和loss layer的关键。

1.判断设备是否支持GPU

if torch.cuda.is_available():
    print('gpu is available !')
    print('gpu数量:',torch.cuda.device_count())

2.利用.cuda()将模型和数据放到GPU上
网上有人说使用.cuda()不能指定GPU,但经过本人实践是可以指定GPU的。具体方法如下。

if torch.cuda.is_available():
    model.cuda() # model为模型
	model.cuda(1) # 指定显卡1训练
	model.cuda('cuda:1') # 和model.cuda(1)等价,指定显卡1训练
	model.cuda('cuda:1,2') # 使用多张显卡
if torch.cuda.is_available():
     data = data.cuda()
     label = label.cuda()
	 # data为训练数据,label为标签,和model一样可以使用.cuda(gpu_id)和.cuda('cuda:gpu_id')来指定GPU进行训练

3.利用.to将模型和数据放到指定的GPU上
使用该方法方便之处是便于选择GPU还是NPU来训练代码,不需要改太多。

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 如果可以用GPU则设备指向GPU,如果不能使用GPU则使用CPU
# 同样如果已经知道可以使用的GPU如卡0,则可以直接指定GPU
device = torch.device("cuda:0")

接下来把模型和数据放到GPU上就简单多了,便于代码的修改。

model.to(device)
data.to(device)
label.to(device)

4.os.environ[“CUDA_VISIBLE_DEVICES”]详解
os.environ[“CUDA_VISIBLE_DEVICES”]使用该命令可以指定使用的GPU,同时修改pytorch感受的设备编号。

CUDA_VISIBLE_DEVICES 表示当前可以被python环境程序检测到的显卡
os.environ["CUDA_VISIBLE_DEVICES"] = '1,2'
进行指定使用设备,这样会修改pytorch感受的设备编号,pytorch感知的编号还是从device:0开始。如上则把1号显卡改为device:0,2号显卡改为device:1。

# 在代码中直接指定,==建议把这段代码放在开头,否则会报错!!!一定要注意这段代码放置的位置。==
import os 
os.environ['CUDA_VISIBLE_DEVICES'] = gpu_ids 
# 在命令行中执行代码时指定
CUDA_VISIBLE_DEVICES=gpu_ids python3 train.py
# 利用该代码来指定使用设备
print(torch.cuda.device_count()) # 输出结果为3,一共有三张显卡分别是0,1,2

import os 
os.environ['CUDA_VISIBLE_DEVICES'] = '0, 1' 
print(torch.cuda.device_count()) # 输出结果为2,此时已经指定了卡0和卡1

二、固定随机种子

在训练过程中,若相同的数据数据集,相同的训练集、测试集划分方式,相同的权重初始化,但是每次训练结果不同,可能有以下几个原因:

1.Dropout的存在 ;
2. PyTorch、Python、Numpy中的随机种子没有固定;
3. 数据预处理、增强方式采用了概率,若没有设置固定的随机种子,结果可能不同。例如常用数据增强库albumentations就采用了Python的随机产生器;
4.训练数据集被随机打乱了顺序;
5. 向上采样和插值函数/类的向后是不确定的(PyTorch的问题)

在测试过程中,相同的权重,相同的测试数据集,结果不同,可能有以下几个原因:

1.未设定eval()模式,因为模型中的Dropout和Batchnorm存在,导致结果不固定;
2.PyTorch、Python、Numpy中的随机种子没有固定,可能运行时依赖的一些第三方库;
3.有随机性 数据预处理方式中含有概率;
4.向上采样和插值函数/类的向后是不确定的(Pytorch的问题)

seed = 1029
torch.manual_seed(seed) # 为CPU设置随机种子
torch.cuda.manual_seed(seed) # 为当前GPU设置随机种子
torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU,为所有GPU设置随机种子
np.random.seed(seed)  # Numpy module.
random.seed(seed)  # Python random module.	
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True

当 向上采样和插值函数/类的向后是不确定的(BACKWARD of upsampling and interpolation functionals/classes is non-deterministic)。这意味着,如果你在训练图中使用这样的模块,无论你做什么,都永远不会得到确定性的结果。torch.nn.ConvTranspose2d函数是不确定的,除非你使用torch.backends.cudnn.deterministic = True(原文中说you can try to make the operation deterministic … by setting torch.backends.cudnn.deterministic = True,所以这样做是否能够得到正确结果也是待定的)。

PyTorch固定随机数种子这篇博客写的太好了,固定随机种子均摘抄于这篇博客。

三、参考文献

pytorch训练时指定显卡
pytorch指定GPU训练
PyTorch固定随机数种子
本篇博客是上述三篇博客加自己理解的总结。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值