当前位置:   article > 正文

Pytorch基础入门_pytorch入门

pytorch入门

一、Pytorch第一步 

1. 函数名后加"_"会修改Tensor本身,如加法的两种表达形式:y.add(x) 和 y.add_(x),前者不改变y的值,后者改变了y的值。

2. Tensor和Numpy的数组之间的互操作非常容易且快速,对于Tensor不支持的操作,可以先转化为Numpy数组尽力,之后再转回Tensor。且二者的对象共享内存,使得其转换很快,几乎不会消耗什么资源,但是这也意味着其中一个变了,另外一个也会随之改变。

  1. import torch as t
  2. import numpy as np
  3. a = np.ones(5)
  4. b = t.from_numpy(a)
  5. print(a)
  6. print(b)
  7. b.add_(1)
  8. print(a)
  9. print(b)

3. 获取某个元素的值可以使用scalar.item。直接使用Tensor[idx]得到的还是一个Tensor,而scalar一般是指0-dim的tensor。

  1. scalar = b[0]
  2. scalar
  3. scalar.size()
  4. scalar.item()
  5. tensor = t.tensor([2])
  6. tensor, scalar #二者的区别
  7. tensor.size(), scalar.size()
  8. tensor.item(), scalar.item() #只有一个元素的tensor也可以使用item

4. torch.tensor接口yunp.array类似

5. torch.tensor()和tensor.clone()总会拷贝数据,新的tensor和原来的数据不共享内存;而想要共享内存,可以使用torch.from_numpy()或者tensor.detach()。

  1. old_tensor = tensor
  2. new_tensor = old_tensor.clone()
  3. new_tensor[0] = 1111
  4. old_tensor, new_tensor
  5. new_tensor = old_tensor.detach()
  6. new_tensor[0] = 1111
  7. old_tensor, new_tensor

6. Tensor可以通过.cuda的方式转化为GPU的Tensor,从而来加速:

  1. device = t.device("cuda:0" if t.cuda.is_available() else "cpu)
  2. x = x.to(device)
  3. y = y.to(device)
  4. z = x+y

二、autograd:自动微分

1. 自动使用autograd功能,只需设置tensor.requires_grad=True。Variable主要包含三个属性:(1)data:保存Variable所包含的Tensor;(2)grad:保存data对应的梯度,它也是个Variable,而不是Tensor,与data的形状是一样的;(3)grad_fn:指向一个Function对象,这个Function用来反向传播计算输入的梯度。

  1. x = t.ones(2, 2, requires_grad=True)
  2. y = x.sum()
  3. y
  4. y.grad_fn
  5. y.backward() #反向传播,计算梯度,x内每个元素的梯度均为1
  6. x.grad

2. grad在反向传播的过程中是累加的,也就是说每一次运行反向传播,梯度都会累加之前的梯度,所以传播之前需要把梯度清零。

  1. y.backward()
  2. x.grad
  3. y.backward()
  4. x.grad
  5. x.grad.data.zero() #将x的梯度清零
  6. y.backward()
  7. x.grad

三、神经网络

1. torch.nn是专门为神经网络设计的模块化接口,建立在 Autograd之上。其中nn.Module是nn中最重要的类,可看成是一个网络的封装,包含网络各层定义以及forward方法,且只要在nn.Module的子类中定义了forward函数,backward函数就会自动被实现(利用autograd)

2. 定义网络:

(1)继承nn.Module模块,需要把网络中具有可学习参数的层放在__init__中,如果某一层不具有可学习的参数,则既可以放在构造函数中,也可以不放,建议不放如,而是在forward函数中使用nn.functional代替。

  1. #Lenet网络:
  2. import torch.nn as nn
  3. import torch.nn.functional as F
  4. class Net(nn.Module):
  5. def __init__(self):
  6. super(Net, self).__init__() # nn.Module子类的函数必须在构造函数中执行父类的构造函数,该式等价于nn.Module.__init__(self)
  7. self.conv1 = nn.Conv2d(1, 6, 5) # 卷积层 '1'表示输入图片为单通道, '6'表示输出通道数,'5'表示卷积核为5*5
  8. self.conv2 = nn.Conv2d(6, 16, 5)
  9. self.fc1 = nn.Linear(16*5*5, 120) # 仿射层/全连接层,y = Wx + b
  10. self.fc2 = nn.Linear(120, 84)
  11. self.fc3 = nn.Linear(84, 10)
  12. def forward(self, x): # 卷积 -> 激活 -> 池化
  13. x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
  14. x = F.max_pool2d(F.relu(self.conv2(x)), 2)
  15. x = x.view(x.size()[0], -1) # reshape,‘-1’表示自适应
  16. x = F.relu(self.fc1(x))
  17. x = F.relu(self.fc2(x))
  18. x = self.fc3(x)
  19. return x
  20. net = Net()
  21. print(net)

(2)网络的学习参数可通过net.parameters()返回,或者采用net.named_parameters可同时返回学习的参数及名称

  1. params = list(net.parameters())
  2. print(len(params))
  3. for name, parameters in net.named_parameters():
  4. print(name, ':', parameters.size())

(3)forward函数的输入和输出都是Tensor

  1. input = t.randn(1, 1, 32, 32)
  2. out = net(input)
  3. out.size()
  4. net.zero_grad()
  5. out.backward(t.ones(1, 10))

(4) torch.nn只支持mini_batches,不支持一次只输入一个样本,若只想输入一个样本,可以用input.unsqueeze()将batch_size设为1。例如nn.Conv2d输入必须是4维的:nSample*nChannels*Height*Width,可以变为1*nChannels*Height*Width

3. 损失函数:

(1)nn实现了神经网络大多数的损失函数,例如nn.MSELoss用来计算均方误差,nn.CrossEntropyLoss用来计算交叉熵损失

  1. output = net(input)
  2. target = t.arrange(0,10).view(1,10).float()
  3. criterion = nn.MSELoss()
  4. loss = criterion(output, target)
  5. loss

(2)调用backward时,会生成动态图并自动微分,也即会自动计算图中参数的导数

  1. net.zero_grad()
  2. print("反向传播之前 conv1.bias的梯度")
  3. print(net.conv1.bias.grad)
  4. loss.backward()
  5. print("反向传播之后 conv1.biad的梯度")
  6. print(net.conv1.bias.grad)

4. 优化器

(1)反向传播计算参数的梯度后,还需要使用优化方法来更新网络的梯度,例如随机梯度下降法的更新策略: weight = weight - learning_rate * gradient,手动实现为:

  1. learning_rate = 0.01
  2. for f in net.parameters():
  3. f.data.sub_(f.grad.data * learning_rate)# inplace 减法

(2)torch.optim中实现了深度学习中的绝大多数优化方法,例如RMSProp、Adam、SGD等

  1. import torch.optim as optim
  2. optimizer = optim.SGD(net.parameters(), lr = 0.01)
  3. optimizer.zero_grad()
  4. output = net(input)
  5. loss = criterion(output, target)
  6. loss.backward
  7. optimizer.step()

四、CIFAR-10分类

1. 数据加载与预处理:torchvision实现了常用的图像数据加载功能,例如Imagenet、CIFAR10、MINIST,以及常用的数据转换操作,可极大地方便数据加载,并且代码具有可重用性。

  1. import torchvision as tv
  2. import torchvision.transforms as transforms
  3. from torchvision.transforms import ToPILImage
  4. show = ToPILImage() # 可以把Tensor转成Image,方便可视化
  5. # 定义对数据的预处理
  6. transform = transforms.Compose([
  7. transforms.ToTensor(), # 转为Tensor
  8. transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # 归一化
  9. ])
  10. # 训练集
  11. trainset = tv.datasets.CIFAR10(
  12. root='/home/cy/tmp/data/',
  13. train=True,
  14. download=True,
  15. transform=transform)
  16. trainloader = t.utils.data.DataLoader(
  17. trainset,
  18. batch_size=4,
  19. shuffle=True,
  20. num_workers=2)
  21. # 测试集
  22. testset = tv.datasets.CIFAR10(
  23. '/home/cy/tmp/data/',
  24. train=False,
  25. download=True,
  26. transform=transform)
  27. testloader = t.utils.data.DataLoader(
  28. testset,
  29. batch_size=4,
  30. shuffle=False,
  31. num_workers=2)
  32. classes = ('plane', 'car', 'bird', 'cat',
  33. 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

2. 定义网络

  1. import torch.nn as nn
  2. import torch.nn.functional as F
  3. class Net(nn.Module):
  4. def __init__(self):
  5. super(Net, self).__init__()
  6. self.conv1 = nn.Conv2d(3, 6, 5)
  7. self.conv2 = nn.Conv2d(6, 16, 5)
  8. self.fc1 = nn.Linear(16*5*5, 120)
  9. self.fc2 = nn.Linear(120, 84)
  10. self.fc3 = nn.Linear(84, 10)
  11. def forward(self, x):
  12. x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
  13. x = F.max_pool2d(F.relu(self.conv2(x)), 2)
  14. x = x.view(x.size()[0], -1)
  15. x = F.relu(self.fc1(x))
  16. x = F.relu(self.fc2(x))
  17. x = self.fc3(x)
  18. return x
  19. net = Net()
  20. print(net)

3. 定义损失函数和优化器:

  1. from torch import optim
  2. criterion = nn.CrossEntropyLoss() # 交叉熵损失函数
  3. optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

 4. 训练网络:

  1. t.set_num_threads(8)
  2. for epoch in range(2):
  3. running_loss = 0.0
  4. for i, data in enumerate(trainloader, 0):
  5. inputs, labels = data;
  6. optimizer.zero_grad()
  7. output = net(inputs)
  8. loss = criterion(outputs, labels)
  9. loss.backward()
  10. optimizer.step()
  11. running_loss += loss.item()
  12. if i % 2000 == 1999:
  13. print('[%d, %5d] loss: %.3f' %(epoch+1, i+1, running_loss / 2000))
  14. running_loss = 0.0
  15. print('Finished Training')

5. 查看效果:

  1. dataiter = iter(testloader)
  2. images, labels = dataiter.next()
  3. print('实际的label:', ' '.join('%08s'%classes[labels[j]] for j in range(4)))
  4. show(tv.utils.make_grid(images / 2 - 0.5)).resize((400,100))
  5. outputs = net(images)
  6. _, predicted = t.max(outputs.data, 1)
  7. print('预测结果:'' '.join('%5s'%classes[predicted[j]] for j in range(4)))

6. 在这个测试集上的效果 

  1. correct = 0 #预测正确的图片数
  2. total = 0 #总共的图片数
  3. with t.no_grad():
  4. for data in testloader:
  5. images, labels = data
  6. outputs = net(images)
  7. _, predicted = t.max(outputs, 1)
  8. total += labels.size(0)
  9. correct += (predicted == labels).sum()
  10. print('10000张测试集中的准确率为: %d %%' %(100 * correct / total))

7. 在GPU上训练:

  1. device = t.device('cuda;0' if t.cuda.is_available() else "cpu")
  2. net.to(device)
  3. images = images.to(device)
  4. labels = labels.to(device)
  5. output = net(images)
  6. loss = criterion(output, labelss)
  7. loss

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号