两类深度学习框架的优缺点

动态图(PyTorch)
计算图的进行与代码的运行时同时进行的。
静态图(Tensorflow <2.0)

自建命名体系
自建时序控制
难以介入

使用深度学习框架的优点

GPU 加速  (cuda)
自动求导
常用网络层的API

PyTorch 的特点

支持 GPU
动态神经网络
Python 优先
命令式体验
轻松扩展



1.Pytorch简介
Pytorch是Facebook 的 AI 研究团队发布了一个基于 Python的科学计算包,旨在服务两类场合:

替代numpy发挥GPU潜能(在线环境暂时不支持GPU)
一个提供了高度灵活性和效率的深度学习实验性平台
2.Pytorch特点及优势
2.1 Pytorch特点
PyTorch 提供了运行在 GPU/CPU 之上、基础的张量操作库;
可以内置的神经网络库;
提供模型训练功能;
支持共享内存的多进程并发(multiprocessing )库等;
2.2 Pytorch特点
处于机器学习第一大语言 Python 的生态圈之中,使得开发者能使用广大的 Python 库和软件;如 NumPy、SciPy 和 Cython(为了速度把 Python 编译成 C 语言);
(最大优势)改进现有的神经网络,提供了更快速的方法——不需要从头重新构建整个网络,这是由于 PyTorch 采用了动态计算图(dynamic computational graph)结构,而不是大多数开源框架(TensorFlow、Caffe、CNTK、Theano 等)采用的静态计算图;
提供工具包,如torch 、torch.nn、torch.optim等;
3.Pytorch常用工具包
torch :类似 NumPy 的张量库,强 GPU 支持 ;
torch.autograd :基于 tape 的自动区别库,支持 torch 之中的所有可区分张量运行;
torch.nn :为最大化灵活性未涉及、与 autograd 深度整合的神经网络库;
torch.optim:与 torch.nn 一起使用的优化包,包含 SGD、RMSProp、LBFGS、Adam 等标准优化方式;
torch.multiprocessing: python 多进程并发,进程之间 torch Tensors 的内存共享;
torch.utils:数据载入器。具有训练器和其他便利功能;
torch.legacy(.nn/.optim) :处于向后兼容性考虑,从 Torch 移植来的 legacy 代码;


pytorch 入门指南 
 
 
 

     
 
 
 

   1. pytorch 概述 
 
 
 

   pytorch是facebook 开发的torch(Lua语言)的python版本,于2017年引爆学术界 
  
官方宣传pytorch侧重两类用户:numpy的gpu版、深度学习研究平台 
  
pytorch使用动态图机制,相比于tensorflow最开始的静态图,更为灵活 
  
当前pytorch支持的系统包括:win,linux,macos 
  
 

     
 
 
 

   2. pytorch基本库 
 
 
 

   常用的pytorch基本库主要包括: 
 
 
 
 
  
torch: 内含一些常用方法,与numpy比较像 
  
torch.Tensor:内含一些操作tensor的方法,可通过tensor.xx()进行调用 
  
torch.nn:内含一些常用模型,如rnn,cnn等 
  
torch.nn.functional:内含一些常用方法,如sigmoid,softmax等 
  
torch.optim:内含一些优化算法,如sgd,adam等 
  
torch.utils.data:内含一些数据迭代方法 
  
 
 
  
3. 基本操作 
  
 

     
 
 
 

   a. tensor操作 
 
 
 

     
 
 
 

   # 初始化空向量 
  
torch.empty(3,4) 
  
 

   # 随机初始化数组 
  
torch.rand(4,3) 
  
 

   # 初始化零向量 
  
torch.zeros(4,3, dtype=torch.int) 
  
 

   # 从数据构建数组 
  
x = torch.tensor([3,4],dtype=torch.float) 
  
x = torch.IntTensor([3,4]) 
  
 

   # 获取tensor的尺寸,元组 
  
x.shape 
  
x.size() 
  
 

   # _在方法中的意义:表示对自身的改变 
  
x = torch.ones(3,4) 
  
# 以下三个式子 含义相同 
  
x = x + x 
  
x = torch.add(x, x) 
  
x.add_(x) 
  
 

   # 索引,像操作numpy一样 
  
x[:,1] 
  
 

   # 改变形状 
  
x.view(-1) 
  
x.view(4,3) 
  
 

   # 如果只包含一个元素值,获取 
  
x = torch.randn(1) 
  
x.item() 
  
 

   # 增加一维 
  
input = torch.randn(32, 32) 
  
input = input.unsqueeze(0) 
  
input.size() 
  
 

   # tensor的data还是tensor,但是requires_grad=False 
  
x.data.requires_grad 
  
 

   # 改变类型 
  
x.type(torch.LongTensor)123456789101112131415161718192021222324252627282930313233343536373839404142434445 
  
 

     
 
 
 

   b. numpy 与 tensor的转换 
 
 
 

     
 
 
 

   # 转换, 共享内存 
  
a= numpy.array([1,2,3]) 
  
a = torch.from_numpy(a) 
  
a.numpy()1234 
  
 

     
 
 
 

   c. 调用gpu 
 
 
 

     
 
 
 

   # gpu是否可用 
  
torch.cuda.is_available() 
  
# 调用设备 
  
device = torch.device('cpu') # cuda or cpu 
  
a = torch.tensor([1,2,3], device='cuda')  # 直接在gpu上创建 
  
a = a.to(device) # 上传 
  
a = a.to('cpu') # 上传, cpu or cuda 
  
a = a.cuda()  # 上传cuda12345678 
  
 

     
 
 
 

   d. 梯度 
 
 
 
 
  
.requires_grad ,决定是否可微(梯度) 
  
.backward(), 计算梯度;如果单独一个值则不需指定参数,否则需传入权重(尺寸与tensor的size同) 
  
.grad, 用于存储梯度累计值。 只有tensor有梯度值,计算节点没有 
  
.detach(), 相当于新建了一个变量,历史的计算图无效 
  
with torch.no_grad():, 评估模型时可用到,不计算梯度 
  
.grad_fn, 节点是如何产生的;用户创造的tensor([1,2,3]).grad_fn 为None 
  
.data(), tensor值,requires_grad=False 
  
 

     
 
 
 
 
  
# 创建可微的tensor 
  
x = torch.ones(2,3,requires_grad=True) 
  
 

   # 改变可微性 
  
x.requires_grad_(False) 
  
 

   # 获得梯度值 
  
x = torch.ones(2, 2, requires_grad=True) 
  
y = x +2 
  
z = y * y *3 
  
out = torch.sum(z) 
  
out.backward() 
  
x.grad 
  
 

   # 无梯度, 报错 
  
with torch.no_grad(): 
  
    x = torch.ones(2, 2, requires_grad=True) 
  
    y = x +2 
  
    z = y * y *3 
  
    out = torch.sum(z) 
  
    out.backward() 
  
    x.grad12345678910111213141516171819202122 
  
 

     
 
 
 

   e. 定义模型 
 
 
 

   两种定义方式 
 
 
 
 
  
class定义 
  
Sequential定义 
  
 
 
  
# 通过class定义 
  
class Net(nn.Module): 
  
    def __init__(self): 
  
        super(Net, self).__init__() 
  
        # 下面通过实例变量的形式声明模型内需要学习的参数 
  
        self.fc1 = nn.Linear(5, 10) 
  
        self.fc2 = nn.Linear(10,20) 
  
 

       def forward(self, x): 
  
        # 下面定义计算图 
  
        x = self.fc1(x) 
  
        x = nn.functional.relu(x) 
  
        x = self.fc2(x) 
  
        return x 
  
net = Net() 
  
 

   # 通过Sequential定义 
  
net = Sequential( 
  
    nn.Linear(5, 10), 
  
    nn.Relu(), 
  
    nn.Linear(10, 20) 
  
)12345678910111213141516171819202122 
  
 

     
 
 
 

   f. 模型参数操作 
 
 
 

     
 
 
 

   # 获取模型参数 
  
net.parameters() #可用for 迭代 
  
 

   # 模型内参数梯度清零 
  
net.zero_grad()12345 
  
 

     
 
 
 

   g. 定义损失函数 
 
 
 

     
 
 
 

   loss = nn.CrossEntropyLoss()1 
 
 
 

     
 
 
 

   h. 定义优化算子 
 
 
 

     
 
 
 

   optimizer = optim.SGD(net.parameters(), lr=0.01)1 
 
 
 

     
 
 
 

   i. 训练 
 
 
 

     
 
 
 

   optimizer.zero_grad()   # zero the gradient buffers 
  
output = net(input) 
  
loss = criterion(output, target) 
  
loss.backward() 
  
optimizer.step() 12345 
  
 

     
 
 
 

   j. 测试 
 
 
 

     
 
 
 

   # 测试 
  
with torch.no_grad(): 
  
    output = net(input)123 
  
 

     
 
 
 

   k. 保存与载入 
 
 
 

     
 
 
 

   # 模型 
  
torch.save(net, file) 
  
net = torch.load(file) 
  
 

   # 参数 
  
torch.save(model.state_dict(), file) 
  
net = Model() 
  
net.load_state_dict(file)12345678 
  
 

     
 
 
 

   4. 一个完整的机器学习流程 
 
 
 
 
  
数据 
  
载入数据 
  
数据处理 
  
构建迭代器 
  
模型 
  
loss 
  
optimizer 
  
新建/载入模型 
  
新建 
  
载入 
  
直接载入模型 
  
载入参数 
  
新建模型 
  
载入模型参数(对于adam等优化器,其参数也需载入) 
  
训练 
  
 

   batch训练 
 
 
 

   for i, batch in enumerate(dataloader): 
  
     x_batch, y_batch = batch 
  
     outputs = net(x_batch) 
  
     loss = criterion(output, target) 
  
     optimizer.zero_grad() 
  
     loss.backward() 
  
     optimizer.step()1234567 
  
每隔一段时间,打印验证集loss 
  
每隔一段时间,存储模型 
  
测试 
  
 

   载入测试数据 
  
数据处理 
  
构建迭代器(可选) 
  
放入模型,输出结果 
  
计算accuracy