PyTorch上路
PyTorch
torch.autograd模块
- 深度学习的算法本质上是通过反向传播求导数, PyTorch的autograd模块实现了此功能, 在Tensor上的所有操作, autograd都会为它们自动提供微分, 避免手动计算导数的复杂过程。
- autograd.Variable是autograd的核心类, 它简单封装了Tensor(最新版PyTorch已经将Variable和Tensor的API合并, 以后直接使用Tensor即可, 不要使用Variable了)
- backward: 一个Scalar变量调用backward方法可以实现反向传播, 计算出各个变量的梯度
- data: 数据
- grad: 梯度
- grad_fn: 计算梯度的函数
- 注意:
- 方向传播backward中grad的值是累加的, 第二次反向传播的梯度就加上第一次反向传播的梯度, 这不是我们期望的, 所以进行了一次反向传播之后应该清空梯度, 使用grad.data.zero_()
 
 
torch.nn模块
- torch.autograd提供了反向传播的功能, 已经可以仅仅通过torch.autograd来写深度学习代码了, 但是在大多数情况下还是略显麻烦, torch.nn提供了神经网络设计的模块化接口, torch.nn模块是以torch.autograd为基础的。 
- torch.nn.Module是torch.nn模块的核心类 - 使用torch.nn.Module搭建LeNet
 
 #!/usr/bin/env python
 # -*- coding: utf-8 -*- import torch as t
 from torch.autograd import Variable
 import torch.optim as optim
 import torch.nn as nn
 import torch.nn.functional as F class LeNet(nn.Module): def __init__(self):
 super(LeNet, self).__init__()
 # 需要学习的参数要写在__init__()中, 并且作为属性
 # 在__init__()并不是定义图, 是在设置要学习的参数(进行初始化), nn.Conv2d这么多的参数就是在确定卷积核的维度而已
 # 接着随机初始化参数W与b
 self.conv1 = nn.Conv2d(1, 6, 5)
 self.conv2 = nn.Conv2d(6, 16, 5)
 self.fc1 = nn.Linear(16 * 5 * 5, 120)
 self.fc2 = nn.Linear(120, 84)
 self.fc3 = nn.Linear(84, 10) def forward(self, x):
 # 这里才是搭建网络的步骤
 net = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
 net = F.max_pool2d(F.relu(self.conv2(net)), 2)
 net = net.view(net.size()[0], -1)
 net = F.relu(self.fc1(net))
 net = F.relu(self.fc2(net))
 net = self.fc3(net)
 return net def main(argv=None):
 # 创建网络
 lenet = LeNet()
 # PyTorch中维度是通道优先, 与TensorFlow不同
 # 伪造数据
 x = Variable(t.randn(1, 1, 32, 32))
 labels = Variable(t.arange(0, 10).type(t.FloatTensor)) # 前向传播
 out = lenet(x)
 # 定义损失函数
 criterion = nn.MSELoss()
 # 计算损失
 loss = criterion(out, labels)
 # 反向传播前先清空grad
 lenet.zero_grad() loss.backward()
 """
 # 手动实现SGD(最简单的优化策略)
 learning_rate = 0.01
 for f in lenet.parameters():
 f.data.sub_(f.data * learning_rate)
 """
 # 使用PyTorch提供的SGD
 optimizer = optim.SGD(lenet.parameters(), lr=0.01)
 optimizer.step() if __name__ == '__main__':
 main()
- 扩展PyTorch中的函数 - 可以选择继承PyTorch中的Function对象, 实现Function的staticmethod, 分别为forward, backward
- 上面的方法需要计算函数的反向传播, 其实也可以向TensorFlow一样, 直接写前向传播公式, PyTorch会通过自动求微分autograd机制实现反向传播
- 方法一和方法二的区别, 方法一, 采用的是面向对象的思维, 如果要自定义一个新的函数, 需要继承Function对象; 方法二, 一般定义的是一个函数。他们关系就像是PyTorch中的nn.ReLU和nn.funcional.relu一样
 
- torchvision模块 - 提供已经预训练的网络模型(AlexNet, VGG, ResNet等), 在torchvision.models中
- 提供常用的数据集(MSCOCO, MNIST, CIFAR等), 在torchvision.datasets中
- 图像预处理模块, torchvision.transform
- CenterCrop
- ToTensor
- ToPILImage
- RandomHorizontalFlip
- Resize
- Normalize
- Compose用于将多个操作何为一个Sequence
 
- 工具模块, torchvision.utils
- make_grid, 将图像拼进去指定的网格中
- save_image, 将Tensor转为Image并保存到磁盘中
 
 
- 自定义数据集 
import os
import numpy as np
import torch as t
import torch.nn as nn
import PIL
from PIL import Image
from torch.utils.data.dataset import Dataset
from torch.utils.data.dataloader import default_collate
from torch.utils.data import DataLoader
from torchvision import Transform as T
class BaseCatVsDogDataset(Dataset):
    def __init__(self, root, transform=None):
        ims = os.listdir(root)
        self.ims = [os.path.join(root, im) for im in ims]
        self.transform = transform
    def __getitem__(self, idx):
        im_path = self.ims[idx]
        label = 1 if 'dog' in os.split('/')[0] else 0
        im = Image.open(im_path)
        if self.transform:
            data = self.transform(im)
        else:
            data = t.Tensor(np.asarray(im))
        return data, label
    def __len__(self):
        return len(self.ims)
class CatVsDogDataset(BaseCatVsDogDataset):
    """
    Notes
    -----
    Subclass ``CatVsDogDataset`` are used to prevent abnormal exit of program caused by abnormal data
    """
    def __init__(self, root, transform=None):
        super(CatVsDogDataset, self).__init__(root, transform=transform)
    def __getitem__(self, idx):
        try:
            return super(CatVsDogDataset, self).__getitem__(idx)
        except:
            # An exception returns to None
            return None, None
def collate_fn(batch):
    """
    Parameters
    ----------
    batch : list
        At this point, batch hasn't been integrated into [batch_size, C, H, W],
        and each image is placed in a list [(im, label), (im, label), ...]
    """
    # Filter out None values
    batch = filter(lambda x: x[0] is not None, batch)
    # Splice the values in batch whose type is ``list`` into a matrix
    return default_collate(batch)
def main():
    transform = T.Compose([T.Resize(224), T.CenterCrop(224), T.RandomHorizontalFlip(), T.ToTensor(), T.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])])
    dataset = CatVsDogDataset('./data', transform=transform)
    dataloader = DataLoader(dataset, shuffle=True, batch_size=64, drop_last=False, collate_fn=collate_fn)
    for ims, labels in dataloader:
        print(ims.size(), labels.size())
if __name__ == '__main__':
    main()
- visdom工具 - 先启动守护进程, nohup python -m visdom.server &
- 创建vis对象, vis = visdom.Visdom(env='test'), env为环境名称
- 绘制标量变化, vis.line(X=x, Y=y, win='sin', opts={'title': 'This is a title'}), win是窗口名称, opts提供额外的属性, title为标题
- 绘制分布图, vis.histogram(X=x, Y=y, win='test', opts={'title': 'This is a new title'})
 
- 先启动守护进程, 
- PyTorch规范 - 目录结构
 - .
 ├── README.md
 ├── checkpoints: 保存训练好的权重
 ├── config.py: 配置信息, 里面是一个DefaultConfig类, 还有一个parse方法, 用于解析命令行参数来覆盖DefaultConfig中的默认配置
 ├── data: 处理数据集
 │ ├── __init__.py
 │ └── dataset.py: 里面定义了一个数据集名称的类
 ├── dataset: 存放训练和测试的数据
 ├── main.py: 启动文件, 包含有train, val, test三个函数, 其中train会调用val在训练中进行交叉验证, test需要用户另外再启动一个进程执行
 ├── models: 存放网络模型
 │ ├── __init__.py: 在文件中导入模型, 方便在main.py中导入
 │ ├── basemodule.py: 扩展了nn.Module, 主要添加了load和save模型的方法
 │ └── resnet34.py: 不继承nn.Module, 而是继承BaseModule
 ├── requirements.txt: 程序依赖说明文件
 ├── tmp: 临时目录, 如果在该目录下创建一个debug文件, 则程序进入debug模式
 └── utils: 工具
 ├── __init__.py
 └── visualize.py: 封装了visdom的可视化
 - config.py中一般配置
- num_workers
- use_gpu
- lr
- max_epoch
- batch_size
- save_path
- env
- debug_file
- data_root
 
 
- 试手项目 - DogVsCat
- FastNeuralStyle
- RNN写诗
 
- 可能用到的函数 - torch.bmm: batch matmul
- nn.ReflectionPad2d(size): 镜像padding
- clamp(min, max): if x < min: min, if x > max: max, else x
- torchvision.transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])是现将图片归一化到0-1, 在减去均值除以标准差, 所以要可视化的话要乘以标准差, 加上均值
- with torch.no_grad(): 类似于之前版本中的volatile=True, 比requires_grad优先级要高
 
- 其他 - 转置卷积维度计算公式
- \(H_{out}=(H_{in}-1)\times{stride}-2\times{padding}+ksize\)
 
- 研究表明, 几乎所有神经网络的第一层学习到的都是关于线条和颜色的信息, 直观理解就是像素组成颜色, 点组成线, 这与人眼的感知特征十分相像, 在往上层, 神经网络开始关注一些复杂的特征, 例如拐角或者某些特殊的形状, 这些特征可以看成是低层次的特征组合, 随着深度的加深, 神经网络关注的信息逐渐抽象, 例如有一些卷积核关注的是这张图中有个鼻子, 或者是图中有张人脸, 以及对象之间的空间关系, 例如鼻子在人脸的中间等(这不是我说的, 是唐进民作者说的)
- 取patch像素中的值并累加就会抛弃空间信息, 因为一张图片的像素随机打乱得到的累加也是一样的, 但是亮度信息还保留, 因此还会有纹理信息, 色彩信息等
- PyTorch中网络中的__init__方法中定义了self.left = nn.Conv2d(in_ch, out_ch, 3, 1)等, 此时就会在使用的optimizer中会有一个param_group, PyTorch支持分层设置学习率, 使用
 for param_group in optimizer.param_groups:
 param_group['lr'] = lr * lr_decay
 
- PyTorch中, 对于Scalar的Tensor, 使用item()可是直接返回里面的数值
- torchnet.meter对象直接不能直接相加, 需要调用value()[0]获取里面的tensor才能相加, value()返回的是元组, [0]是我们期望的元素, [1]是Inf
- visdom.line参数一般是这样设置的
vis.line(X=np.array([x]), Y=np.array([y]), win=name, opts={'title': name}, update=None if not x else 'append')
 
 
- 转置卷积维度计算公式
PyTorch上路的更多相关文章
- php大力力 [001节]2015-08-21.php在百度文库的几个基础教程新手上路日记 大力力php 大力同学 2015-08-21 15:28
		php大力力 [001节]2015-08-21.php在百度文库的几个基础教程新手上路日记 大力力php 大力同学 2015-08-21 15:28 话说,嗯嗯,就是我自己说,做事认真要用表格,学习技 ... 
- 负重前行的婚纱线上路 - i天下网商-最具深度的电商知识媒体
		负重前行的婚纱线上路 - i天下网商-最具深度的电商知识媒体 负重前行的婚纱线上路 
- Mybatis上路_05-使用命令行自动生成【转】
		http://my.oschina.net/vigiles/blog/125127 Mybatis上路_05-使用命令行自动生成 1人收藏此文章, 我要收藏 发表于1个月前(2013-04-24 ... 
- Mybatis上路_06-使用Java自动生成[转]
		Mybatis上路_06-使用Java自动生成 11人收藏此文章, 我要收藏发表于1个月前(2013-04-24 23:05) , 已有151次阅读 ,共0个评论 目录:[ - ] 1.编写Gener ... 
- OpenGL教程之新手上路
		Jeff Molofee(NeHe)的OpenGL教程- 新手上路 译者的话:NeHe的教程一共同拥有30多课,内容翔实,而且不断更新 .国内的站点实在应该向他们学习.令人吃惊的是,NeHe提供的例程 ... 
- Unity 4.3 2D 教程:新手上路
		这篇文章译自 Christopher LaPollo 先生的 Unity 4.3 2D 教程的第一部分 Unity 4.3 2D Tutorial: Getting Started 感谢这套优秀教程的 ... 
- Ubutnu16.04安装pytorch
		1.下载Anaconda3 首先需要去Anaconda官网下载最新版本Anaconda3(https://www.continuum.io/downloads),我下载是是带有python3.6的An ... 
- 解决运行pytorch程序多线程问题
		当我使用pycharm运行 (https://github.com/Joyce94/cnn-text-classification-pytorch ) pytorch程序的时候,在Linux服务器 ... 
- 基于pytorch实现word2vec
		一.介绍 word2vec是Google于2013年推出的开源的获取词向量word2vec的工具包.它包括了一组用于word embedding的模型,这些模型通常都是用浅层(两层)神经网络训练词向量 ... 
随机推荐
- 数据可视化之DAX篇(二十七)半累加度量,在Power BI 中轻松处理
			https://zhuanlan.zhihu.com/p/96823622 开始半累加的计算之前,我们先看看什么是累加.半累加以及不可累加数据. 在含有大量行的数据表中,各种数据处理语言,包括DAX ... 
- Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归
			Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归 目录 Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归 内容纲要 1.函数名的第一类对象及使用 2.f ... 
- RocketMQ在面试中那些常见问题及答案+汇总
			0.汇总 RocketMQ入门到入土(一)新手也能看懂的原理和实战! RocketMQ入门到入土(二)事务消息&顺序消息 从入门到入土(三)RocketMQ 怎么保证的消息不丢失? Rocke ... 
- 【Python学习笔记五】re.findall()方法中,正则的"()"效果
			在笔记四中,使用正则去筛选数据时,使用了findall()这个方法,在使用时正则表达式中使用了到了"()",最初以为只是强调执行优先级,后来发现正则表达式中的每一个(),在find ... 
- javascript : 递归遍历数组
			我们假设有一个对象数组. 这个对象数组里的对象,有一个叫children的key,value也是一个对象数组. 这个数组里面可能还有children... 现在我们想递归遍历它. 上代码. test_ ... 
- 搭建mysql NDB集群
			NDB群集安装 介绍 https://dev.mysql.com/doc/refman/8.0/en/mysql-cluster-basics.html NDBCLUSTER (也称为NDB)是一种内 ... 
- 网络流(EK算法)
			poj1273 #include <iostream> #include <cstdio> #include <cstring> #include <queu ... 
- Spring Security 实战干货:图解用户是如何登录的
			1. 前言 欢迎阅读Spring Security 实战干货系列文章,在集成Spring Security安全框架的时候我们最先处理的可能就是根据我们项目的实际需要来定制注册登录了,尤其是Http登录 ... 
- Go 中读取命令参数的几种方法总结
			前言 对于一名初学者来说,想要尽快熟悉 Go 语言特性,所以以操作式的学习方法为主,比如编写一个简单的数学计算器,读取命令行参数,进行数学运算. 本文讲述使用三种方式讲述 Go 语言如何接受命令行参数 ... 
- PHPSTORM  Live-Templates变量速查表
			camelCase(String) 返回字符串作为参数传递,转换为驼峰式大小写.例如, my-text-file/my text file/my_text_file将转化为 myTextFile. c ... 
