电脑公司网站建设模板,平面设计和网站运营,广告设计公司网页,十大保洁公司pytorch使用技巧 1. 指定GPU编号
设置当前使用的GPU设备仅为0号设备#xff0c;设备名称为 /gpu:0os.environ[CUDA_VISIBLE_DEVICES] 0
设置当前使用的GPU设备为0, 1号两个设备#xff0c;名称依次为 /gpu:0、/gpu:1#xff1a; os.environ[设备名称为 /gpu:0os.environ[CUDA_VISIBLE_DEVICES] 0
设置当前使用的GPU设备为0, 1号两个设备名称依次为 /gpu:0、/gpu:1 os.environ[CUDA_VISIBLE_DEVICES] 0,1 根据顺序表示优先使用0号设备,然后使用1号设备。
2. 查看模型每层输出详情
Keras有一个简洁的API来查看模型的每一层输出尺寸这在调试网络时非常有用。现在在PyTorch中也可以实现这个功能。
from torchsummary import summarysummary(your_model, input_size(channels, H, W))
input_size 是根据你自己的网络模型的输入尺寸进行设置。
https://github.com/sksq96/pytorch-summary
3. 梯度裁剪Gradient Clipping
import torch.nn as nn
outputs model(data)loss loss_fn(outputs, target)optimizer.zero_grad()loss.backward()nn.utils.clip_grad_norm_(model.parameters(), max_norm20, norm_type2)optimizer.step()
nn.utils.clip_grad_norm_ 的参数 parameters – 一个基于变量的迭代器会进行梯度归一化 max_norm – 梯度的最大范数 norm_type – 规定范数的类型默认为L2
4. 扩展单张图片维度
因为在训练时的数据维度一般都是 (batch_size, c, h, w)而在测试时只输入一张图片所以需要扩展维度扩展维度有多个方法
import cv2import torch
image cv2.imread(img_path)image torch.tensor(image)print(image.size())
img image.view(1, *image.size())print(img.size())
# output:# torch.Size([h, w, c])# torch.Size([1, h, w, c])
或
import cv2import numpy as np
image cv2.imread(img_path)print(image.shape)img image[np.newaxis, :, :, :]print(img.shape)
# output:# (h, w, c)# (1, h, w, c)
import cv2import torch
image cv2.imread(img_path)image torch.tensor(image)print(image.size())
img image.unsqueeze(dim0) print(img.size())
img img.squeeze(dim0)print(img.size())
# output:# torch.Size([(h, w, c)])# torch.Size([1, h, w, c])# torch.Size([h, w, c])
tensor.unsqueeze(dim)扩展维度dim指定扩展哪个维度。
tensor.squeeze(dim)去除dim指定的且size为1的维度维度大于1时squeeze()不起作用不指定dim时去除所有size为1的维度。
5. 独热编码
在PyTorch中使用交叉熵损失函数的时候会自动把label转化成onehot所以不用手动转化而使用MSE需要手动转化成onehot编码。 import torchclass_num 8batch_size 4
def one_hot(label): 将一维列表转换为独热编码 label label.resize_(batch_size, 1) m_zeros torch.zeros(batch_size, class_num) # 从 value 中取值然后根据 dim 和 index 给相应位置赋值 onehot m_zeros.scatter_(1, label, 1) # (dim,index,value)return onehot.numpy() # Tensor - Numpy
label torch.LongTensor(batch_size).random_() % class_num # 对随机数取余print(one_hot(label))
# output:[[0. 0. 0. 1. 0. 0. 0. 0.] [0. 0. 0. 0. 1. 0. 0. 0.] [0. 0. 1. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0.]]
6. 防止验证模型时爆显存
验证模型时不需要求导即不需要梯度计算关闭autograd可以提高速度节约内存。如果不关闭可能会爆显存。
with torch.no_grad(): # 使用model进行预测的代码 pass
意思就是PyTorch的缓存分配器会事先分配一些固定的显存即使实际上tensors并没有使用完这些显存这些显存也不能被其他应用使用。这个分配过程由第一次CUDA内存访问触发的。
而 torch.cuda.empty_cache() 的作用就是释放缓存分配器当前持有的且未占用的缓存显存以便这些显存可以被其他GPU应用程序中使用并且通过 nvidia-smi命令可见。注意使用此命令不会释放tensors占用的显存。
对于不用的数据变量Pytorch 可以自动进行回收从而释放相应的显存。
7. 学习率衰减
import torch.optim as optimfrom torch.optim import lr_scheduler
# 训练前的初始化optimizer optim.Adam(net.parameters(), lr0.001)scheduler lr_scheduler.StepLR(optimizer, 10, 0.1) # # 每过10个epoch学习率乘以0.1
# 训练过程中for n in n_epoch: scheduler.step() ...
8. 冻结某些层的参数
参考Pytorch 冻结预训练模型的某一层 https://www.zhihu.com/question/311095447/answer/589307812
在加载预训练模型的时候我们有时想冻结前面几层使其参数在训练过程中不发生变化。
我们需要先知道每一层的名字通过如下代码打印
net Network() # 获取自定义网络结构for name, value in net.named_parameters(): print(name: {0},\t grad: {1}.format(name, value.requires_grad))
name: cnn.VGG_16.convolution1_1.weight, grad: Truename: cnn.VGG_16.convolution1_1.bias, grad: Truename: cnn.VGG_16.convolution1_2.weight, grad: Truename: cnn.VGG_16.convolution1_2.bias, grad: Truename: cnn.VGG_16.convolution2_1.weight, grad: Truename: cnn.VGG_16.convolution2_1.bias, grad: Truename: cnn.VGG_16.convolution2_2.weight, grad: Truename: cnn.VGG_16.convolution2_2.bias, grad: True
后面的True表示该层的参数可训练然后我们定义一个要冻结的层的列表
no_grad [ cnn.VGG_16.convolution1_1.weight, cnn.VGG_16.convolution1_1.bias, cnn.VGG_16.convolution1_2.weight, cnn.VGG_16.convolution1_2.bias]
net Net.CTPN() # 获取网络结构for name, value in net.named_parameters(): if name in no_grad: value.requires_grad False else: value.requires_grad True
name: cnn.VGG_16.convolution1_1.weight, grad: Falsename: cnn.VGG_16.convolution1_1.bias, grad: Falsename: cnn.VGG_16.convolution1_2.weight, grad: Falsename: cnn.VGG_16.convolution1_2.bias, grad: Falsename: cnn.VGG_16.convolution2_1.weight, grad: Truename: cnn.VGG_16.convolution2_1.bias, grad: Truename: cnn.VGG_16.convolution2_2.weight, grad: Truename: cnn.VGG_16.convolution2_2.bias, grad: True
可以看到前两层的weight和bias的requires_grad都为False表示它们不可训练。
最后在定义优化器时只对requires_grad为True的层的参数进行更新。
optimizer optim.Adam(filter(lambda p: p.requires_grad, net.parameters()), lr0.01)
9. 对不同层使用不同学习率
net Network() # 获取自定义网络结构for name, value in net.named_parameters(): print(name: {}.format(name))
# 输出# name: cnn.VGG_16.convolution1_1.weight# name: cnn.VGG_16.convolution1_1.bias# name: cnn.VGG_16.convolution1_2.weight# name: cnn.VGG_16.convolution1_2.bias# name: cnn.VGG_16.convolution2_1.weight# name: cnn.VGG_16.convolution2_1.bias# name: cnn.VGG_16.convolution2_2.weight# name: cnn.VGG_16.convolution2_2.bias
对 convolution1 和 convolution2 设置不同的学习率首先将它们分开即放到不同的列表里
conv1_params []conv2_params []
for name, parms in net.named_parameters(): if convolution1 in name: conv1_params [parms] else: conv2_params [parms]
# 然后在优化器中进行如下操作optimizer optim.Adam( [ {params: conv1_params, lr: 0.01}, {params: conv2_params, lr: 0.001}, ], weight_decay1e-3,)
我们将模型划分为两部分存放到一个列表里每部分就对应上面的一个字典在字典里设置不同的学习率。当这两部分有相同的其他参数时就将该参数放到列表外面作为全局参数如上面的weight_decay。
也可以在列表外设置一个全局学习率当各部分字典里设置了局部学习率时就使用该学习率否则就使用列表外的全局学习率。