当前位置: 代码迷 >> 综合 >> pytorch tutorials
  详细解决方案

pytorch tutorials

热度:88   发布时间:2024-01-26 07:55:41.0

pytorch 1.4.0版本的tutorials提供了三个大块的教程:

  • deep learning with pytorch: a 60 minute blitz
  • writing custom datasets, dataloaders and transforms
  • visualizing models, data and training with tensorboard

根据个人所需将其分为五个篇章,作为pytorch的入门(假设你已经有了一定的tensorflow和深度学习基础):

第一篇章 tensor

tensor是pytorch核心的数据结构,和numpy中的ndarray的区别是,它可以在GPU上实现加速。

tensor需要了解的就是两个部分的内容:(为表述方便,用t表示某个具体的tensor)

tensor的属性

  • t.shape/t.size()

创建tensor

创建tensor有很多种方法,和tensorflow中的tensor差不多

  • 构造方法:tensor()
  • 特殊张量:ones()/ones_like()
  • 随机函数:randn()

tensor运算

tensor的计算(包括算术计算、代数运算、维度计算),太多了,和tensorflow几乎没什么两样。

  • t.view():改变tensor的shape并返回
  • t.item():如果tensor只有一个元素,直接获取python数字,如果不是请使用tolist()
  • t.tolist():直接将tensor转化为python原生的嵌套list

以加法为例,既可以从torch的角度执行:torch.add(t1, t2),也可以从tensor的角度去执行:t1.add(t2),还可以原地执行t1.add_(t2)

原地执行的好处是不用重新赋值。

第二篇章 自动微分

自动微分的这个机制完全吊打tensorflow,只需要设置tensor的requires_grad参数为True,便可以追踪该tensor的计算,最后可以通过loss调用loss.backward()自动计算所有被追踪的tensor的梯度值。

除了requires_grad每个tensor还有grad属性和grad_fn属性,前者是记录了梯度值,后者是梯度函数。

避免追踪

  • requires_grad设置为False:t.requires_grad_(False)
  • detach()

第三篇章 神经网络

自定义的模型需要继承nn.module(类似keras的自定义模型必须继承keras.Model),然后__init__()中定义层结构,在forward(inputs)中定义前向传播的过程,最后返回output即可。

在开始正式的模型之前,需要了解下:

  • torch.nn.Conv2d(in_channels, out_channels, kernel_size):创建的卷积层在接受参数的时候,图像的shape是 n S a m p l e s ? n C h a n n e l s ? H e i g h t ? W i d t h nSamples*nChannels*Height*Width
  • torch.nn.Linear(in_features, out_features)

接下来看下模型结构:

import torch
import torch.nn as nn
import torch.nn.functional as Fclass Net(nn.module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 6, 3)self.conv2 = nn.Conv2d(6, 16, 3)self.fc1 = nn.Linear(16 * 6 * 6, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 10)def forward(self, x):x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))x = F.max_pool2d(F.relu(self.conv2(x)), 2)x = x.view(-1, self.num_flat_features(x))x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.fc3(x)return xdef num_flat_features(self, x):size = x.size()[1:]num_features = 1for s in size:num_features *= sreturn num_featuresnet = Net()
print(net)

可以通过net.parameters()查看所有的参数。

损失函数和优化器

和tensorflow一样,损失函数有很多,比如MSELoss().

由于每次求梯度值都会累加,所以需要在一开始进行清零:net.zeros_grad(),然后在计算出loss之后通过loss.backward()计算。

求出梯度,需要对参数进行更新,最简单的方法是使用梯度下降:

for f in net.parameters():f.data.sub_(f.grad.data * learning_rate)

除此之外,还有很多种其他的优化器:SGD、Nesterous-SGD、Adam、Rmsprop等,都封装到torch.optim中去了。

所以,一般通过优化器来将参数的梯度值清零:optimizer.zeros_grad()

将以上的过程总结为下面的三个步骤:

  1. 使用优化器将参数的梯度值清零:optimizer.zero_grad()
  2. 根据损失值来计算损失值:loss.backward()
  3. 使用优化器来更新参数:optimizer.step()

第四篇 训练一个分类器

模型的保存分为两种:(1)仅保存参数;(2)保存整个模型

仅保存参数

torch.save(model.state_dict(), PATH)  # PATH是某个具体路径
the_model = Model()
the_model.load_state_dict(torch.load(PATH))

保存整个模型

torch.save(the_mode, PATH)
the_model = torch.load(PATH)

如何在GPU上实现训练?

每个tensor都有一个device参数,如果将一个cpu上的tensor转化成gpu上的tensor,只需要t = t.device('cuda:0'),但是在此之前需要检测cuda是否存在,否则代码在没有cuda上的机器上不能运行:

# generate the device
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")model = model.to(device)

这样模型就可以在显卡上运行了,只不过,输入input和正确答案target也要转一下:input.to(device)target.to(device)

除此之外还可以通过torch.cuda.device_count()来查看显卡的数量,从而实现分布式训练:

model = nn.DataParallel(model)

第五篇章 通过tensorboard进行可视化

tensorboard是一个独立的工具,为了对模型训练进行可视化,需要将summary写到指定目录中去(默认为logdir=runs),然后开启本地服务器tensorboard --logdir=xxx,并在浏览器中(https://localhost:6006)查看。

写入tensorboard需要创建一个SummaryWriter类对象:

from torch.utils.tensorboard import SummaryWriterwriter = SummaryWriter('runs/fashion_mnist_experiment_1')

第一个部分:图像(images)

对图像不感兴趣,所以这里不深究,通过add_image()添加图像,并借助make_grid()来画图。

img_grid = torchvision.utils.make_grid(images)  # create grid of images
matplotlib_imshow(img_grid, one_channel=True)  # show images
writer.add_image('four_fashion_mnist_images', img_grid)

第二个部分:计算图(graphs)

通过add_graph()将整个模型写入目录中,可以查看模型结构。

writer.add_graph(net, images)
writer.close()

第三个部分:数据(projector)

通过add_embedding()来将某个张量加入到tensorboard中去,当然高维数据都会通过降维成低维数据查看。

features = images.view(-1, 28 * 28)
writer.add_embedding(features, metadata=class_labels, label_img=images.unsequeeze(1))
writer.close()

第四个部分:添加标量(scalars)

将损失值等标量值加入到tensorboard中去

# writer down each 1000 batchs, running_loss is the total loss of 1000 batchs
writer.add_scalar('training_loss', running_loss/1000, epoch*len(trainloader)+i))

还可以画个figure上去

writer.add_figure('predictions vs actuals',plot_classes_preds(net, inputs, labels),global_step=epoch*len(trainloader)+i)

除此之外还有几个其他的画图方法,这个后面再慢慢加。