四个重要的包
torch.Torch
torch.autograd
torch.nn
torch.optim
一、tensor转化到gpu上运算:
默认情况下不允许跨 GPU 操作,除了 copy_()和 其他具有类似复制功能的方法,例如to()和cuda()。除非您启用点对点内存访问,否则任何在跨不同设备的张量上启动操作的尝试都会引发错误。
cuda = torch.device('cuda') # Default CUDA device
cuda0 = torch.device('cuda:0')
cuda2 = torch.device('cuda:2') # GPU 2 (these are 0-indexed)
#1. 直接参数设置
x = torch.tensor([1., 2.], device=cuda0)
# x.device is device(type='cuda', index=0)
#2. .cuda()
y = torch.tensor([1., 2.]).cuda()
# y.device is device(type='cuda', index=0)
3. .to(torch.device("cuda")
y=torch.tensor(1.,2.]).to(cuda)
# y.device is device(type='cuda', index=0)
二、修改tensor的requires_grad属性
x.requires_grad_(True)
x.requires_grad=True
三、model.zero_grad()和optimizer.zero_grad()和param.grad.zero_()
pytorch之object.grad.zero_()
【PyTorch】PyTorch中的model.zero_grad()和optimizer.zero_grad()使用
在用pytorch训练神经网络时,可以先用:
model.zero_grad()
optimizer.zero_grad()
这两种方式都是把模型中的参数的梯度设为0。
常用
for i in range(epoch):
for j,(data,target) in tqdm(enumerate(train_loader)):
logit = transfer_layer(resnet18(data.to(device)))
# print (logit.shape)
# print (target.shape)
loss = torch.nn.functional.cross_entropy(logit.to(device),target.to(device))
loss.backward()
for param in transfer_layer.parameters():
if param.grad is not None:
param.grad.zero_()
optimizer.step()
中的
"""Sets gradients of all model parameters to zero."""
for p in self.parameters():
if p.grad is not None:
p.grad.data.zero_()
将参数的梯度清零,否则参数梯度会叠加,这样相当于所有batch在一起使用了,比如每两次清一次零就相当于将两个batch合并成一个batch进行计算了。
四、pytorch完整训练神经网络过程
import torch
import torchvision
import torchvision.models as models
import torchvision.transforms as transforms
resnet18 = models.resnet18(pretrained = True)
# 得到对象 PIL.Image.Image image mode=RGB size=32x32 at 0x7FEECE0EEC50
# 如果需要对图像进行reshape或者归一化等操作,可以使用transforms.lambda(lambda x:---)进行定义
train_dataset = torchvision.datasets.CIFAR10('./data' ,train = True ,download=True, transform = transforms.Compose([transforms.ToTensor(),]))
test_dataset = torchvision.datasets.CIFAR10('./data' ,train = True ,download=False, transform = transforms.Compose([transforms.ToTensor(),]))
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=10,shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset,batch_size=10,shuffle=True)
from tqdm import tqdm
epoch = 1
learning_rate = 0.001
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
category_list = ['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']
resnet18 = resnet18.to(device)
transfer_layer = torch.nn.Linear(1000,10).to(device)
# 联合参数进行优化需使用如下方式。key只能是params
optimizer = torch.optim.SGD([{'params':transfer_layer.parameters()},{'params':resnet18.conv1.parameters()}],lr = learning_rate)
def train():
for i in range(epoch):
for j,(data,target) in tqdm(enumerate(train_loader)):
logit = transfer_layer(resnet18(data.to(device)))
# print (logit.shape)
# print (target.shape)
loss = torch.nn.functional.cross_entropy(logit.to(device),target.to(device))
loss.backward()
for param in transfer_layer.parameters():
if param.grad is not None:
param.grad.zero_()
optimizer.step()
# 上下两种优化网络参数方式都行。
# for param in transfer_layer.parameters():
# param = (param - learning_rate*param.grad).detach().requires_grad_()
if j % 500 == 0:
print ('第{}次迭代,loss值为{}'.format(j*10,loss))
def test():
correct_num = torch.tensor(0).to(device)
for j,(data,target) in tqdm(enumerate(test_loader)):
data = data.to(device)
target = target.to(device)
logit = transfer_layer(resnet18(data))
pred = logit.max(1)[1]
num = torch.sum(pred==target)
correct_num = correct_num + num
print (correct_num)
print ('\n correct rate is {}'.format(correct_num/10000))
train()
test()
五、pytorch搭建模型
可以用model.parameters访问网络模型参数或者某层的参数
可以用print(model)访问网络模型
参考链接
pytorch基础入门教程/一小时学会pytorch
pytorch官方文档
pytorch中文文档
#coding=utf-8
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
class Net(nn.Module):
#定义Net的初始化函数,这个函数定义了该神经网络的基本结构
def __init__(self):
super(Net, self).__init__() #复制并使用Net的父类的初始化方法,即先运行nn.Module的初始化函数
self.conv1 = nn.Conv2d(1, 6, 5) # 定义conv1函数的是卷积函数:输入为图像(1个频道,即灰度图),输出为 6张特征图(feature map), 卷积核为5x5正方形
self.conv2 = nn.Conv2d(6, 16, 5) # 定义conv2函数的是卷积函数:输入为6张特征图(feature map),输出为16张特征图(feature map), 卷积核为5x5正方形
self.fc1 = nn.Linear(16*5*5, 120) # 定义fc1(fullconnect)全连接函数1为线性函数:y = Wx + b,并将16*5*5个节点连接到120个节点上。
self.fc2 = nn.Linear(120, 84) #定义fc2(fullconnect)全连接函数2为线性函数:y = Wx + b,并将120个节点连接到84个节点上。
self.fc3 = nn.Linear(84, 10) #定义fc3(fullconnect)全连接函数3为线性函数:y = Wx + b,并将84个节点连接到10个节点上。
#定义该神经网络的向前传播函数,该函数必须定义,一旦定义成功,向后传播函数也会自动生成(autograd)
def forward(self, x):
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) #输入x经过卷积conv1之后,经过激活函数ReLU(原来这个词是激活函数的意思),使用2x2的窗口进行最大池化Max pooling,然后更新到x。
x = F.max_pool2d(F.relu(self.conv2(x)), 2) #输入x经过卷积conv2之后,经过激活函数ReLU,使用2x2的窗口进行最大池化Max pooling,然后更新到x。
x = x.view(-1, self.num_flat_features(x)) #view函数将张量x变形成一维的向量形式,总特征数并不改变,为接下来的全连接作准备。
x = F.relu(self.fc1(x)) #输入x经过全连接fc1,再经过ReLU激活函数,然后更新x
x = F.relu(self.fc2(x)) #输入x经过全连接fc2,再经过ReLU激活函数,然后更新x
x = self.fc3(x) #输入x经过全连接3,然后更新x
return x
#使用num_flat_features函数计算张量x的总特征量(把每个数字都看出是一个特征,即特征总量),比如x是4*2*2的张量,那么它的特征总量就是16。
def num_flat_features(self, x):
size = x.size()[1:] # 这里为什么要使用[1:],是因为pytorch只接受批输入,也就是说一次性输入好几张图片,那么输入数据张量的维度自然上升到了4维。【1:】让我们把注意力放在后3维上面
num_features = 1
for s in size:
num_features *= s
return num_features
################
net = Net()
# 以下代码是为了看一下我们需要训练的参数的数量
print (net)
params = list(net.parameters())
k=0
for i in params:
l =1
print "该层的结构:"+str(list(i.size()))
for j in i.size():
l *= j
print "参数和:"+str(l)
k = k+l
print "总参数和:"+ str(k)