pytorch学习笔记

pytorch学习笔记

文章目录

  • pytorch学习笔记
    • 第一部分:pytorch入门
      • 1.1介绍pytorch
      • 1.2 安装
      • 1.3张量
      • 1.4自动求导机制
      • 1.5神经网络包nn和优化器optm
      • 1.6 数据的加载与预处理

第一部分:pytorch入门

1.1介绍pytorch

PyTorch是一个基于Torch的Python开源机器学习库,用于自然语言处理等应用程序。它主要由Facebook的人工智能研究小组开发。Uber的“ Pyro”也是使用的这个库。基于Python的科学计算包,服务于以下两种场景:

  • 作为NumPy的替代品,可以使用GPU的强大计算能力

  • 提供最大的灵活性和高速的深度学习研究平台

PyTorch是一个Python包,提供两个高级功能:

  • 具有强大的GPU加速的张量计算(如NumPy)

  • 包含自动求导系统的的深度神经网络

1.2 安装

pip install torch===1.4.0 torchvision===0.5.0 -f https://download.pytorch.org/whl/torch_stable.html

1.3张量

Tensors(张量)

Tensors与Numpy中的 ndarrays类似,但是在PyTorch中 Tensors 可以使用GPU进行计算.。
创建一个tensor:

from __future__ import print_function
import torch
x = torch.tensor([5.5, 3])
print(x)
x = torch.rand(5, 3)#随机生成5*3的矩阵
print(x)

pytorch学习笔记_第1张图片
加法:

result = torch.empty(5, 3)
x = torch.rand(5, 3)
y = torch.rand(5, 3)
torch.add(x, y, out=result)
print(result)

NumPy Array 转化成 Torch Tensor

使用from_numpy自动转化

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)

Torch Tensor转numpy:

a = torch.ones(5)
print(a)
b = a.numpy()
print(b)

CUDA张量将张量放入指定的设备中去:

# is_available 函数判断是否有cuda可以使用
# ``torch.device``将张量移动到指定的设备中
if torch.cuda.is_available():
    device = torch.device("cuda")          # a CUDA 设备对象
    y = torch.ones_like(x, device=device)  # 直接从GPU创建张量
    x = x.to(device)                       # 或者直接使用``.to("cuda")``将张量移动到cuda中
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))       # ``.to`` 也会对变量的类型做更改

pytorch学习笔记_第2张图片

1.4自动求导机制

PyTorch 中所有神经网络的核心是 autograd 包。
我们先简单介绍一下这个包,然后训练第一个简单的神经网络。

autograd包为张量上的所有操作提供了自动求导。
它是一个在运行时定义的框架,这意味着反向传播是根据你的代码来确定如何运行,并且每次迭代可以是不同的。

torch.Tensor是这个包的核心类。如果设置
.requires_gradTrue,那么将会追踪所有对于该张量的操作。
当完成计算后通过调用 .backward(),自动计算所有的梯度,
这个张量的所有梯度将会自动积累到 .grad 属性。

要阻止张量跟踪历史记录,可以调用.detach()方法将其与计算历史记录分离,并禁止跟踪它将来的计算记录。

为了防止跟踪历史记录(和使用内存),可以将代码块包装在with torch.no_grad():中。
在评估模型时特别有用,因为模型可能具有requires_grad = True的可训练参数,但是我们不需要梯度计算。

在自动梯度计算中还有另外一个重要的类Function.
TensorFunction互相连接并生成一个非循环图,它表示和存储了完整的计算历史。
每个张量都有一个.grad_fn属性,这个属性引用了一个创建了TensorFunction(除非这个张量是用户手动创建的,即,这个张量的
grad_fnNone)。

如果需要计算导数,你可以在Tensor上调用.backward()
如果Tensor是一个标量(即它包含一个元素数据)则不需要为backward()指定任何参数,
但是如果它有更多的元素,你需要指定一个gradient 参数来匹配张量的形状。

例子:

x = torch.ones(2, 2, requires_grad=True) #创建一个张量并设置 requires_grad=True 用来追踪他的计算历史
print(x)
y = x + 2  #对张量进行操作
print(y)
print(y.grad_fn)#结果y已经被计算出来了,所以,grad_fn已经被自动生成了。
z = y * y * 3
out = z.mean()

print(z, out)
out.backward() #反向传播 因为 out是一个纯量(scalar),out.backward() 等于out.backward(torch.tensor(1))。
print(x.grad)# 显示out对x的反向传播梯度

pytorch学习笔记_第3张图片
原理:
得到矩阵 4.5.调用 out
Tensor o o o”.

得到 o = 1 4 ∑ i z i o = \frac{1}{4}\sum_i z_i o=41izi,
z i = 3 ( x i + 2 ) 2 z_i = 3(x_i+2)^2 zi=3(xi+2)2 and z i ∣ x i = 1 = 27 z_i\bigr\rvert_{x_i=1} = 27 zixi=1=27.

因此,
∂ o ∂ x i = 3 2 ( x i + 2 ) \frac{\partial o}{\partial x_i} = \frac{3}{2}(x_i+2) xio=23(xi+2), hence
∂ o ∂ x i ∣ x i = 1 = 9 2 = 4.5 \frac{\partial o}{\partial x_i}\bigr\rvert_{x_i=1} = \frac{9}{2} = 4.5 xioxi=1=29=4.5.
第二个例子:

x = torch.randn(3, requires_grad=True)

y = x * 2
while y.data.norm() < 1000:
    y = y * 2

print(y)
gradients = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)#输入x的值求梯度
y.backward(gradients)

print(x.grad)

1.5神经网络包nn和优化器optm

使用torch.nn包来构建神经网络。nn包依赖autograd包来定义模型并求导。 一个nn.Module包含各个层和一个forward(input)方法,该方法返回output。
神经网络的典型训练过程如下:

  1. 定义包含一些可学习的参数(或者叫权重)神经网络模型;
  2. 在数据集上迭代;
  3. 通过神经网络处理输入;
  4. 计算损失(输出结果和正确值的差值大小);
  5. 将梯度反向传播回网络的参数;
  6. 更新网络的参数,主要使用如下简单的更新原则:
    weight = weight - learning_rate * gradient
    下面我们使用pytorch定义一个网络:
# 首先要引入相关的包
import torch
# 引入torch.nn并指定别名
import torch.nn as nn
#打印一下版本
torch.__version__
import torch.nn.functional as F
class Net(nn.Module):
    def __init__(self):
        # nn.Module子类的函数必须在构造函数中执行父类的构造函数
        super(Net, self).__init__()
        
        # 卷积层 '1'表示输入图片为单通道, '6'表示输出通道数,'3'表示卷积核为3*3
        self.conv1 = nn.Conv2d(1, 6, 3) 
        #线性层,输入1350个特征,输出10个特征
        self.fc1   = nn.Linear(1350, 10)  #这里的1350是如何计算的呢?这就要看后面的forward函数
    #正向传播 
    def forward(self, x): 
        print(x.size()) # 结果:[1, 1, 32, 32]
        # 卷积 -> 激活 -> 池化 
        x = self.conv1(x) #根据卷积的尺寸计算公式,计算结果是30,具体计算公式后面第二章第四节 卷积神经网络 有详细介绍。
        x = F.relu(x)
        print(x.size()) # 结果:[1, 6, 30, 30]
        x = F.max_pool2d(x, (2, 2)) #我们使用池化层,计算结果是15
        x = F.relu(x)
        print(x.size()) # 结果:[1, 6, 15, 15]
        # reshape,‘-1’表示自适应
        #这里做的就是压扁的操作 就是把后面的[1, 6, 15, 15]压扁,变为 [1, 1350]
        x = x.view(x.size()[0], -1) 
        print(x.size()) # 这里就是fc1层的的输入1350 
        x = self.fc1(x)        
        return x

net = Net()
print(net)

输出:
在这里插入图片描述
网络的可学习参数通过net.parameters()返回

for parameters in net.parameters():
    print(parameters)

pytorch学习笔记_第4张图片
forward函数的输入和输出都是Tensor,执行下面代码打印每个层的输出格式:

input = torch.randn(1, 1, 32, 32) # 这里的对应前面fforward的输入是32
out = net(input)
out.size()

在反向传播前,先要将所有参数的梯度清零:

net.zero_grad() 
out.backward(torch.ones(1,10)) # 反向传播的实现是PyTorch自动实现的,我们只要调用这个函数即可

损失函数:
在nn中PyTorch还预制了常用的损失函数,下面我们用MSELoss用来计算均方误差

y = torch.arange(0,10).view(1,10).float()
criterion = nn.MSELoss()
loss = criterion(out, y)
#loss是个scalar,我们可以直接用item获取到他的python类型的数值
print(loss.item()) 

优化器:
在反向传播计算完所有参数的梯度后,还需要使用优化方法来更新网络的权重和参数,例如随机梯度下降法(SGD)的更新策略如下:

weight = weight - learning_rate * gradient

在torch.optim中实现大多数的优化方法,例如RMSProp、Adam、SGD等,下面我们使用SGD做个简单的样例

out = net(input) # 这里调用的时候会打印出我们在forword函数中打印的x的大小
criterion = nn.MSELoss()
loss = criterion(out, y)
#新建一个优化器,SGD只需要要调整的参数和学习率
optimizer = torch.optim.SGD(net.parameters(), lr = 0.01)
# 先梯度清零(与net.zero_grad()效果一样)
optimizer.zero_grad() 
loss.backward()

#更新参数
optimizer.step()

以上步骤我们实现了盛景网络的数据完整传播步骤。

1.6 数据的加载与预处理

PyTorch通过torch.utils.data对一般常用的数据加载进行了封装,可以很容易地实现多线程数据预读和批量加载。 并且torchvision已经预先实现了常用图像数据集,包括前面使用过的CIFAR-10,ImageNet、COCO、MNIST、LSUN等数据集,可通过torchvision.datasets方便的调用
Dataset
Dataset是一个抽象类,为了能够方便的读取,需要将要使用的数据包装为Dataset类。
自定义的Dataset需要继承它并且实现两个成员方法:

  1. __getitem__() 该方法定义用索引(0len(self))获取一条数据或一个样本
  2. __len__() 该方法返回数据集的总长度

自定义数据类方法:

# 首先要引入相关的包
import torch
#打印一下版本
torch.__version__

#引用
from torch.utils.data import Dataset
import pandas as pd
#定义一个数据集
class BulldozerDataset(Dataset):
    """ 数据集演示 """
    def __init__(self, csv_file):
        """实现初始化方法,在初始化的时候将数据读载入"""
        self.df=pd.read_csv(csv_file)
    def __len__(self):
        '''
        返回df的长度
        '''
        return len(self.df)
    def __getitem__(self, idx):
        '''
        根据 idx 返回一行数据
        '''
        return self.df.iloc[idx].SalePrice

ds_demo= BulldozerDataset('median_benchmark.csv')# 从https://www.kaggle.com/c/bluebook-for-bulldozers/data下载median_benchmark.csv数据集放入当前目录
#实现了 __len__ 方法所以可以直接使用len获取数据总数
len(ds_demo)
#用索引可以直接访问对应的数据,对应 __getitem__ 方法
ds_demo[0]

定义好数据集类之后使用dataloader加载数据:

dl = torch.utils.data.DataLoader(ds_demo, batch_size=10, shuffle=True, num_workers=0)
# DataLoader为我们提供了对Dataset的读取操作,常用参数有:batch_size(每个batch的大小)、 shuffle(是否进行shuffle操作)、 
# num_workers(加载数据的时候使用几个子进程)。下面做一个简单的操作
idata=iter(dl)#DataLoader返回的是一个可迭代对象,我们可以使用迭代器分次获取数据
print(next(idata))

我们已经可以通过dataset定义数据集,并使用Datalorder载入和遍历数据集,除了这些以外,PyTorch还提供能torcvision的计算机视觉扩展包,里面封装了

torchvision 包
torchvision 是PyTorch中专门用来处理图像的库,PyTorch官网的安装教程中最后的pip install torchvision 就是安装这个包。
torchvision.datasets
torchvision.datasets 可以理解为PyTorch团队自定义的dataset,这些dataset帮我们提前处理好了很多的图片数据集,我们拿来就可以直接使用:

  • MNIST
  • COCO
  • Captions
  • Detection
  • LSUN
  • ImageFolder
  • Imagenet-12
  • CIFAR
  • STL10
  • SVHN
  • PhotoTour
    我们可以直接使用,示例如下:
import torchvision.datasets as datasets
trainset = datasets.MNIST(root='./data', # 表示 MNIST 数据的加载的目录
                                      train=True,  # 表示是否加载数据库的训练集,false的时候加载测试集
                                      download=True, # 表示是否自动下载 MNIST 数据集
                                      transform=None) # 表示是否需要对数据进行预处理,none为不进行预处理

torchvision.models
torchvision不仅提供了常用图片数据集,还提供了训练好的模型,可以加载之后,直接使用,或者在进行迁移学习
torchvision.models模块的 子模块中包含以下模型结构。

  • AlexNet
  • VGG
  • ResNet
  • SqueezeNet
  • DenseNet
    torchvision.transforms
    transforms 模块提供了一般的图像转换操作类,用作数据处理和数据增强

你可能感兴趣的:(paper)