pytorch 基础用法汇总

Posted by HieDean on January 20, 2020

tensor的合并

cat会在原有维度上合并两个tensor

torch.cat([tensor1, tensor2], dim=0)

stack会增添一个新的维度

torch.stack([tensor1, tensor2], dim=0)

tensor的点乘

直接用*就可以了

GPU是否可用

torch.cuda.is_available()

有几块GPU

torch.cuda.device_count()

第0块GPU的名字

torch.cuda.get_device_name(0)

使用指定GPU

import os os.environ["CUDA_VISIBLE_DEVICES"] = "0"

使用GPU加速

# 将模型与损失函数转移至GPU
model = Model()
loss_fun = torch.nn.CrossEntropyLoss()
model = model.cuda()
loss_f = loss_fun.cuda()
# 输入的数据转移至GPU
x,y = x.cuda(),y.cuda()
# 最后结果转移回CPU
loss = loss.cpu()
# 注意优化器不需要进行这一步

打印模型的参数名与参数值

# 打印参数名
for x in model.state_dict():
    print(x)
# 打印参数名与参数值
for x in model.named_parameters():
    print(x)

为什么训练模型时显存占用没问题,但在测试模型时OOM?

在测试模型的时候一定要加上

with torch.no_grad(): 
# test_code

否则被测试的模型所占用的显存会越来越大最后出现OOM

torch.manual_seed()

设置GPU初始化时种子

nn.DataParallel(model, device_ids=device_ids)

多GPU并行运算使用

torch.nn.utils.clip_grad_norm(parameters, max_norm, norm_type=2)

用于限制梯度,防止梯度爆炸或消失

pytorch保存模型并继续训练

参考文章 https://www.jianshu.com/p/1cd6333128a1

如何把一个tensor复制给一个新的tensor

x_clone = x.clone()

注意:如果是x_clone = x这样写的话,那两个tensor是共享内存的,修改x_clone也会引起x的变化

x.detach()函数可以返回一个完全相同的tensor,新的tensor开辟与旧的tensor共享内存,新的tensor会脱离计算图

如何把梯度打印出来?

def print_grad(grad):
    print(grad)

tensor_x.register_hook(print_grad)
loss.backward()

tensor_x的梯度会在反向传播时被打印,为什么打印梯度这么奇怪呢?

现在Variabletensor已经区分不大了,至少我没怎么区分。一个Variable含有三部分:

  • data:前向传播的数据
  • grad:后向传播的梯度
  • grad_fn:梯度来自什么操作

在torch创造的动态图中,有的节点不可以求梯度、有的节点可以求梯度但不保存梯度、有的节点可以把求得的梯度保存下来

只要一个节点或者tensortensor_x.requires_grad属性为True,那这个节点就可以求梯度,并且与这个节点有关的其他所有节点都可求梯度

可以求梯度的节点,如果这个节点是叶节点(意思就是在网络中位于端点?可以使用tensor_x.is_leaf来判断是不是叶节点),那这个节点的梯度就可以被保留下来

可以求梯度的节点,如果不是叶节点,为了减少存储,所求的梯度会被删除为None,这些节点都是动态图中的中间节点。

那梯度爆炸的时候,如果想查看是哪个节点的梯度爆炸了,我们要如何获取中间节点的梯度呢?

这就需要tensor_x.register_hook(print_grad),括号里是一个函数的函数名

由于中间节点的梯度不会保留,所以我们只能在反向传播的过程中,该节点的梯度被求出的那一刻,用hook把梯度勾出来打印

ValueError: num_samples should be a positive integer value, but got num_samp=0

调用dataloader时注意参数:

self.train_dataloader = DataLoader(train_dataset, batch_size=TrainOption.train_batch_size, shuffle=TRUE, num_workers=TrainOption.data_load_worker_num)

因为已经有batch_sample了,就不需要shuffle来进行随机的sample了,所以在这里的shuffle应该设置为FALSE才对