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
的梯度会在反向传播时被打印,为什么打印梯度这么奇怪呢?
现在Variable
和tensor
已经区分不大了,至少我没怎么区分。一个Variable
含有三部分:
data
:前向传播的数据grad
:后向传播的梯度grad_fn
:梯度来自什么操作
在torch创造的动态图中,有的节点不可以求梯度、有的节点可以求梯度但不保存梯度、有的节点可以把求得的梯度保存下来
只要一个节点或者tensor
的tensor_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
才对