深入浅出pytorch-02 pytorch深度学习框架简介

Pytorch框架

  • 学习链接
  • 前言总结:
    • 常用库函数概览
    • Pytorch 的计算图概览
  • 计算图CG
  • 自动差分引擎torch.autograd
  • Pytorch主要模块
  • torch的辅助工具模块
  • 张量Tensor
  • 张量的创建和修改
  • pytorch数据输入和预处理
    • 数据载入类
  • 模型保存方式
    • 检查点checkpoint设置!

学习链接

奇客谷
2
3

前言总结:

常用库函数概览

转换成张量 torch.tensor
运算torch.mm(matrix1,matrix2)
并行torch.CUDA
网络torch.nn

  • torch.nn.functional 激活函数和池化
  • torch.nn.Linear | torch.nn.conv2d 线性和卷积
  • torch.MSELoss | torch.CrossEntropyLoss 损失函数
  • torch.nn.init 网络初始化
  • torch.nn.Parameters 张量网络参数化

优化器torch.optim

  • torch.optim.SGD
  • torch.optim.lr_scheduler

辅助模块torch.utils

  • torch.utils.data
    • toch.utils.data.Dataset
    • torch.utils.data.DataLoader
  • torch.utils.tensorboard

存储载入

  • torch.load()
  • torch.save()
  • torch.load_state_dict()

Pytorch 的计算图概览

动态图

pytorch使用动态计算图,在计算过程中构建图(结点是运算符)。

前向构建图的时候同时构建反向计算图,输出张量绑定反向梯度函数,到了最终损失函数后,开始沿着反向图,调用反向梯度函数。权重张量绑定梯度张量,优化器这个工具人来进行优化更新权重张量。

三个主人公和工具人:

  • 输出张量
  • 权重张量
  • 梯度张量
  • 优化器(工具人)

+表示绑定

  • 优化器+权重张量
  • 输出张量+反向梯度函数
  • 优化器 ---->权重张量<------ (梯度张量)

工具人 优化器

LMS (online 更新) ⇒ SGD(考虑单次批次梯度信息) ⇒ Momentum(不够,再考虑之前的批次信息)⇒ AdaGrad(考虑过去所有的梯度平方和,用NLMS类似手法)⇒ RMSProp(用指数记忆过去平方梯度信息,再类似NLMS) ⇒ Adam(结合RMSProp和Momentum)

SGD, Momentum, AdaGrad, Rmsprop, Adam

  • SGD : 批次随机梯度下降

  • Momentum: w t + 1 = w t − m t \bold w_{t+1} = \bold w_t - \bold m_t wt+1=wtmt
    m t = γ . m t − 1 + α d L d w t \bold m_t = \gamma.\bold m_{t-1} + \alpha\frac{dL}{d \bold w_t} mt=γ.mt1+αdwtdL

  • AdaGrad: 类似于NLMS, 记忆梯度平方
    G t = ∑ i = 1 t ( d L d w i ) 2 \bold{G_t }= \sum_{i=1}^{t}(\frac{dL}{d\bold w_i})^2 Gt=i=1t(dwidL)2
    w t + 1 = w t − α d L d w t G t + ϵ \bold w_{t+1} = \bold w_t - \frac{\alpha \frac{dL}{d\bold w_t}}{\sqrt{\bold G_{\bold t}+\epsilon}} wt+1=wtGt+ϵ αdwtdL

  • RMSprop: 不用全部记忆,用移动指数平均。
    v t v_t vt代替AdaGrad中的 G t G_t Gt
    v t = γ v t − 1 + ( 1 − γ ) ( d L d w i ) 2 \bold{v_t} = \gamma \bold{v_{t-1}}+(1-\gamma)(\frac{dL}{d\bold w_i})^2 vt=γvt1+(1γ)(dwidL)2
    w t + 1 = w t − α d L d w t v t + ϵ \bold w_{t+1} = \bold w_t - \frac{\alpha \frac{dL}{d\bold w_t}}{\sqrt{\bold v_{\bold t}+\epsilon}} wt+1=wtvt+ϵ αdwtdL

  • Adam:结合动量和速度


计算图CG

计算图举例
神经网络记录计算图, 结点为运算操作(operator),边为张量。(记忆:树结构,父节点是+号)
静态图(static graph):以前的TensorFlow ,caffe
动态图: Pytorch

张量
运算符
运算符

静态图:先引擎构建图并且可以进行优化,然后不在过程中更改。然后进行正向,反向传播。缺点在于不灵活,不能在传播过程中debug。


自动差分引擎torch.autograd

静态图

  • 计算图构建完成时候,反向传播路径也同时完成。

动态图

  • 构建前向计算图的时候给每个输出张量绑定一个反向传播的梯度计算函数,当计算图到达最终损失函数张量的时候,直接调用这个张量的反向传播函数,并不断地递归反向传播函数。(记忆:前向绑定梯度,遇最终损失函数,反向传播调用梯度)

动态计算图

  • 优化器 先和 权重张量 绑定。反向传播完成后,权重张量又和对应的梯度张量绑定,然后优化器根据绑定的梯度张量更新权重张量。

让我们理一理:

+表示绑定
优化器+权重张量
输出张量+反向梯度函数
优化器 ---->权重张量<------ (梯度张量)


Pytorch主要模块

torch模块包含了本身常使用的激活函数,torch.sigmoid, torch.relu, torch.tanh以及矩阵的乘法torch.mm,张量元素的选择torch.select。

  • torch.Tensor 模块
    任何方法后缀带了_的函数都是直接修改本身数据,即in-place方法。
    torch.Storage 负责torch.Tensor的底层数据存储

  • torch.sparse
    稀疏表达

  • torch.CUDA
    GPU有关

  • torch.nn
    非常重要!!!
    一般用来继承它。

import torch.nn as nn
nn.Linear
nn.Conv1d
nn.Conv2d
nn.Conv3d
torch.nn.MSELoss
torch.nn.CrossEntropyLoss
  • torch.nn.functional
    激活函数和池化函数

  • torch.nn.init
    神经网络初始化
    torch.nn.init.uniform_
    torch.nn.init.normal_

  • torch.optim
    优化器 update weight tensor

torch.optim.SGD
torch.optim.AdaGrad
torch.optim.RMSprop
torch.optim.Adam

torch.optim.lr_scheduler #学习率衰减子模块
torch.optim.lr_scheduler.StepLR #阶梯下降
torch.optim.lr_scheduler.CosineAnnealingLR #余弦退火
  • torch.autograd
    torch.autograd.backward

  • torch.onnx
    ONNX格式存在是为了方便不同框架之间的模型交换


torch的辅助工具模块

  • torch.utils.bottleneck
    检查模块运行时间,找到导致性能瓶颈的模块。

  • torch.utils.checkpoint
    节约内存
    时间换空间内存,丢弃中间数据,只记录计算过程。

  • torch.utils.data
    引入了Dataset 和 DataLoader,得到shuffle 和 sample 后的迷你小批次数据集。

  • torch.utils.tensorboard
    数据可视化工具,可视化中间张量,损失函数,张量权重的直方图,一节中间文本,视频,图像。



张量Tensor

  • 张量的使用和Numpy中的ndarrays很类似, 区别在于张量可以在GPU或其它专用硬件上运行, 这样可以得到更快的加速效果。

  • 张量如何存储?
    (记忆:最里面的,最深层的的,最后的维度,最先储存)

k维度张量,维度为 ( n 1 , n 2 , . . . , n k ) (n_1, n_2,...,n_k) (n1,n2,...,nk)
存储顺序是一般从 n k n_k nk开始,:
先填满 n k , n k − 1 , n k − 1 , . . . , n 1 n_k, n_{k-1}, n_{k-1}, ..., n_1 nknk1,nk1,...,n1
一个元素张量中的下标为 ( i 1 , i 2 , i 3 , . . . , i k ) (i_1, i_2, i_3, ..., i_k) (i1,i2,i3,...,ik), 那么它在内存中是第 ( i k ) + ( i k − 1 ∗ n k ) + . . . + ( i 1 ∗ ( n 2 ∗ n 3 . . . ∗ n k ) ) (i_k)+(i_{k-1}*n_k) +...+ (i_1*(n_2*n_3...*n_k)) ik+(ik1nk)+...+i1(n2n3...nk)

张量的创建和修改

  • 张量的初始化
    PyTorch教程

    • 直接生成张量
    import torch
    data = [[1, 2], [3, 4]]
    x_data = torch.tensor(data)
    
    • 通过Numpy数组来生成张量
    import numpy as np
    np_array = np.array(data)
    x_np = torch.from_numpy(np_array)
    
    • 通过已有的张量来生成新的张量
    x_ones = torch.ones_like(x_data)   # 保留 x_data 的属性
    print(f"Ones Tensor: \n {x_ones} \n")
    x_rand = torch.rand_like(x_data, dtype=torch.float)   # 重写 x_data 的数据类型int -> float                                            
    print(f"Random Tensor: \n {x_rand} \n")
    
    • 通过指定数据维度来生成张量
    shape = (2,3,)
    rand_tensor = torch.rand(shape)
    ones_tensor = torch.ones(shape)
    zeros_tensor = torch.zeros(shape)
    
    print(f"Random Tensor: \n {rand_tensor} \n")
    print(f"Ones Tensor: \n {ones_tensor} \n")
    print(f"Zeros Tensor: \n {zeros_tensor}")
    
  • 张量类型转换

import torch
torch.tensor(a, dtype = torch.float32) #或者
torch.tensor(a).to(torch.float32)
  • 张量存储设备
    device = ‘cpu’
    device = ‘cuda:0’
    n个GPU设备编号 cuda:0. … cuda:n-1
    torch.tensor(a, device = 'cuda:3')

GPU->CPU

设备之间的转移可以用to、xx.cpu()

torch.ones_like(a, device="cuda:4")**.cpu()**
torch.ones_like(a, device = 'cuda:4').**to**('cuda:0')
  • view +contiguous == reshape
    t = torch.tensor(a)
    t.view(-1,3)
    view函数不改变底层数据存储,只改变维度步长信息。
    如果需要复制数据,需要调用contiguous()。

  • 张量拼接与分割
    拼接不会增加维度
    但是stack会增加维度

t1 =  torch.rand(3,4)
#Returns a tensor filled with random numbers from a uniform distribution
t2 =  torch.rand(3,4)
t3 =  torch.rand(3,4)
t.cat([t1,t2,t3, t4], -1) 
#3*(4+4+4)
t.stack([t1 ,t2, t3], -1)
#3*4*3

  • 张量的扩张与压缩
t = torch.randn(3,4)
t.unsqueeze(-1).shape
# 3*4*1
t = torch.rand(1,3,4,1)
torch.squeeze()
#压缩所有为1 的维度
  • 张量的广播
    必须有相同维度
    3 1 4 + 3 3 4
    第二维度复制3遍,然后一一相加

简单模型初始化化要把 tensor张量变成Parameter才能被optim优化器访问到!

Pytorch优化器直接接收模型的参数生成器作为函数的参数。

self.weight = nn.Parameter( torch.rand(n_dim,1) )

model.named_parameters()

model.parameters()

张量绑定的梯度张量不清空的话,会一直逐渐积累,因此要在反向传播之前optim.zero_grad()

import torch
from torch import nn

learning_rate = 0.01
model = LinearModel(..) # 初始化模型
criterion = nn.MSELoss() # 初始化损失函数criterion
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

for step in range(..):
	predict = model(x) # 预测
	loss = criterion(preict, target) # 损失函数
	optimizer.zero_grad()#优化器清空之前反向传播的梯度
	loss.backward() #损失函数反向传播
	optimizer.step()# 优化器进行梯度下降优化


pytorch数据输入和预处理

数据载入类

  • torch.utils.data.DataLoader
DataLoader(dataset, batch_size =1, shuffle = False, sampler = None, batch_sampler =None, num_workers =0, collate_fn = None, pin_memory = False, drop_last = False, timeout =0, worker_init_fn = None)
  • 要想使用DataLoader,必须要获得对应的dataset

模型保存方式

  • 保存模型实例
import torch
torch.save()
  • 保存模型状态字典
model.state_dict()
model.load_state_dict(t)

检查点checkpoint设置!

save_info = {#保存的信息
"iter_num": iter_num, #迭代步数
"optimizer": optimizer.state_dict(),   #优化器状态字典
"model": model.state_dict()  # 模型状态字典
}
torch.save(save_info, save_path)

save_info = torch.load(save_info)

optimizer.load_state_dict(save_indo["optimizer"])
model.load_state_dict(save_indo["model"])

你可能感兴趣的:(机器学习,神经网络,人工智能,深度学习,神经网络)