Pytorch笔记·60分钟速成

学习自60分钟速成pytorch


第一章 What is pytorch?

初始化

torch.empty(3,4)

生成未初始化的tensor

torch.rand(5,3)

随机初始化

torch.zeros(3,4)

用0初始化

torch.tensor([3,4,5])

从list初始化

torch.from_numpy(arr)

从numpy初始化

x.new_ones(5, 3, dtype=torch.double)

从已有的tensor全一初始化,继承x的所有属性,包括device,dtype等

x = torch.randn_like(x, dtype=torch.float)

从已有的tensor随机初始化,shape同x

tensor基本操作

x.size()

查看shape

torch.add(x, y)

加法

torch.add(x, y, out=result)

把结果保存到result,result可能需要提前用empty或其他方式声明

y.add_(x)

加法,注意,所有 a.操作() 的方法都有一个_后缀

x.view(-1, 8)

pytorch中的resize

x.item()

查看x的具体数值

a.numpy()

把tensor转换成numpy.array
注意! 无论是numpy转tensor还是tensor转Numpy,他们都共享地址,变更一个的值另外一个也会跟着变!

第二章 AUTOGRAD: AUTOMATIC DIFFERENTIATION

tensor的一些属性

requires_grad=True

设置tensor是否自动求导,为true的话会自动搜集求导需要的信息
如果全都不需要反向传播(比如测试的时候),可以用with torch.no_grad():关闭所有的
也可以通过**a.requires_grad_(True)**来改变一个tensor的属性(默认是False)

grad_fn

只要tensor是由一个操作比如加减法得到的,就有grad_fn属性,指明了得到tensor的方法,比如grad_fn=<AddBackward0>

out.backward()

对out进行后向传播,同时out所涉及到的tensor的梯度会被记录在其grad属性中,如x.grad
backward的参数问题参考https://www.cnblogs.com/JeasonIsCoding/p/10164948.html
结论是参数维度应该与out维度相同,同时把参数看做一个行向量arg,最终其他tensor的雅克比矩阵就为( arg * Jacobi )T

第三章 NEURAL NETWORKS

Define the network

CLASS torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=‘zeros’)
nn.Conv2d()定义一个卷积层,eg.self.conv2 = nn.Conv2d(6, 16, 3)
Conv2d()是二维卷积,就是对图像的卷积,而Conv1d是一维卷积,是对文本数据的卷积。
CLASS torch.nn.Linear(in_features, out_features, bias=True)
nn.Linear()定义一个线性层,eg.self.fc1 = nn.Linear(16 * 6 * 6, 120)
torch.nn与torch.nn.functional之间的区别和联系
参考https://blog.csdn.net/GZHermit/article/details/78730856
与https://blog.csdn.net/xiaohuihui1994/article/details/89207534
结论是nn.Conv2d是建立一个类,建立时weight,bias等变量(Variable)已经定义好了,不用再手动去定义,同时由于是class,需要先在init中实例化,才能在forward中使用,于是如果层内有Variable(如全链接层,卷积层),那么用nn定义,反之(如pooling,relu),则用nn.functional定义,同时nn定义的层都是写在init里的
看下面代码中的中文注释

import torch
import torch.nn as nn
import torch.nn.functional as F


class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 3x3 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 3)#先实例化一个Conv2d类
        self.conv2 = nn.Conv2d(6, 16, 3)#再实例化一个Conv2d类
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 6 * 6, 120)  # 6*6 from image dimensio
        #卷积输出大小=[(输入大小-卷积核(过滤器)大小+2*P)/步长]+1
        #池化输出大小=[(输入大小-卷积核(过滤器)大小)/步长]+1
        
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))#conv1->relu->maxpool这行语句定义了三层网络
        # If the size is a square you can only specify a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)#再经过一个conv->relu->maxpool层
        x = x.view(-1, self.num_flat_features(x))#改变上层输出的shape,保留第一个维度的值,把x变为2维的,因为全连接层必须要2维的输入?
        x = F.relu(self.fc1(x))#经过一个全链接层
        x = F.relu(self.fc2(x))#又一个全链接层
        x = self.fc3(x)#最后一个全连接层,输出
        return x

    def num_flat_features(self, x):
        size = x.size()[1:]  # all dimensions except the batch dimension  x.size()得到的是一个list,x的shape,[1:]即将list切片,不要第一个数
        num_features = 1
        for s in size:#遍历list
            num_features *= s
        return num_features


net = Net()
print(net)

Note: 为什么Conv2d是一个类,但是却可以当做函数使用呢?:self.conv1(x)
答:Conv2d的顶级父类定义了__call__()函数,这样就可以把类当函数使用了
net.parameters()返回网络的所有参数,包括每层的weight,bias等
另外注意,net(input),input默认是4维的,也就是个数*channels*w*h,如果你只有一个样本,那么就要用input.unsqueeze(0)去增加一个维度

Loss Function

criterion = nn.MSELoss()#先实例化均方误差类
loss = criterion(output, target)#得到Loss

Backprop

在后向传播之前,要先清除掉之前的梯度值
net.zero_grad()
然后直接loss.backward()就好(把各个参数求导后的梯度值赋给他们的grad)

Update the weights

方法一:直接遍历所有的参数,用它自己减去学习率*梯度值

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

方法二:用torch.optim建立优化器来优化
CLASS torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)
eg.

import torch.optim as optim
# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)#优化器包含所有参数,设置学习率
optimizer.zero_grad()   # zero the gradient buffers同样要把梯度置0
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()    # Does the update 更新优化所有参数

第四章 TRAINING A CLASSIFIER


前言
对于cv,pytorch有专门的包torchvision可以处理常见的数据集,如Imagenet, CIFAR10, MNIST, etc,比如torchvision.datasetstorch.utils.data.DataLoader
除此之外,也可以用其他的python包来处理,
对于image,可以用Pillow,OpenCV; 音频audio可以用scipy and librosa; 文本用其他的……


Loading and normalizing CIFAR10

首先设置好要进行的处理
torch.transforms

transform = transforms.Compose(
    [transforms.ToTensor(),#ToTensor是把PIL image或者numpy array转换成tensor
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])#torchvision.transforms.Normalize(mean, std, inplace=False)
     #因为有三个通道所以有三个mean\std?
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
#这里的获取的trainset不是numpy也不是tensor,是单独的一个CIFAR类

Train the network

主要说一下网络训练这一部分的代码

for epoch in range(2):  # loop over the dataset multiple times

   running_loss = 0.0
   for i, data in enumerate(trainloader, 0):
       #这里dataloader被enumerate之后,i就是index,data为一个list,包含x和y,也就是inputs和labels
       #每次迭代抛出一个iteration的数据?也就是说i是iteration的index,每个iteration用一个batch的数据
       # get the inputs; data is a list of [inputs, labels]
       inputs, labels = data

       # zero the parameter gradients
       optimizer.zero_grad()

       # forward + backward + optimize
       outputs = net(inputs)#输入数据得到输出
       loss = criterion(outputs, labels)计算损失函数
       loss.backward()#梯度后向传播
       optimizer.step()#优化

       # print statistics
       running_loss += loss.item()
       if i % 2000 == 1999:    # print every 2000 mini-batches
           print('[%d, %5d] loss: %.3f' %
                 (epoch + 1, i + 1, running_loss / 2000))
           running_loss = 0.0

print('Finished Training')

CLASS torchvision.transforms.Compose(transforms)
Compose就是把很多种transforms集合在一起,参数为transorms类的list,比如上面示例中的transforms.ToTensor和transforms.Normalize
torchvision.utils.make_grid(imagelist)
把多个图像做成一个表格tensor

iter()与enumerate()函数

iter()

生成迭代器,返回迭代器对象
迭代器可以用.next()返回下一个,也可以用for循环遍历
eg.

for i in iter(lst):
     print(i)

enumerate()

将一个可遍历的数据对象变为(索引,对象)的序列
eg.

>>>seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))       # 下标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

因为有索引,所以用for遍历时要for i,element in enumerate(seq)

torch.max()

(1)torch.max(tensor)
返回tensor中的最大值
(2)torch.max(tensor,dim)
返回tensor中的最大值及他们对应的index
eg.

>> a

0.0692  0.3142  1.2513 -0.5428
0.9288  0.8552 -0.2073  0.6409
1.0695 -0.0101 -2.4507 -1.2230
0.7426 -0.7666  0.4862 -0.6628
torch.FloatTensor of size 4x4]

>>> torch.max(a, 1)
(
 1.2513
 0.9288
 1.0695
 0.7426
[torch.FloatTensor of size 4x1]#每行的最大值
,
 2
 0
 0
 0
[torch.LongTensor of size 4x1]#最大值对应的索引
)

torch.squeeze(input, dim=None, out=None)

将tensor的shape中的1去除,比如输入形状为: (A×1×B), squeeze(input, 0) 将会保持张量不变,只有用 squeeze(input, 1),形状会变成 (A×B)。

第五章 DATA PARALLELISM

如何让模型使用多GPU

model = nn.DataParallel(model)
这是最基本的用法

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值