pytorch入门细讲

目录

一、pytorch数据加载及其预处理

二、模型创建

三、完整模型的训练迭代

四、模型保存及加载

五、pytorch GPU加速

六、pytorch与tensorflow区别

 

一、pytorch数据加载及其预处理

1.torchvision库

torchvision是独立于pytorch的关于图像操作的一些方便工具库。

torchvision主要包括一下几个包:

  • vision.datasets : 几个常用视觉数据集,可以下载和加载(如:MNISTFashion-MNIST、COCOCIFARVOC),这里主要的高级用法就是可以看源码如何自己写自己的Dataset的子类
  • vision.models : 流行的模型,例如 AlexNet, VGG, ResNet 和 Densenet 以及 与训练好的参数。
  • vision.transforms : 常用的图像操作,例如:随机切割,旋转,数据类型转换,图像到tensor ,numpy 数组到tensor , tensor 到 图像等。
  • vision.utils : 用于把形似 (3 x H x W) 的张量保存到硬盘中,给一个mini-batch的图像可以产生一个图像格网

1)加载torchvision提供的数据集

      对于这一类数据集,就是PyTorch已经帮我们做好了所有的事情,连数据源都不需要自己下载。         Imagenet,CIFAR10,MNIST等等PyTorch都提供了数据加载的功能,所以可以先看看你要用的数据集是不是这种情况。

import torch
import torchvision
import torchvision.transforms as transforms
 
transform = transforms.Compose(
    [transforms.ToTensor(), # 归一化到(0,1),直接除以255 
     transforms.Normalize(std=(0.5, 0.5, 0.5), mean=(0.5, 0.5, 0.5))# 归一化到(-1,1),channel=(channel-mean)/std
    ]
)
train_set = torchvision.datasets.CIFAR10(root='./data', train=True, download=False, transform=transform)
train_loader = torch.utils.data.DataLoader(dataset=train_set, batch_size=4, shuffle=True, num_workers=2)
 
test_set = torchvision.datasets.CIFAR10(root='./data', train=False, download=False, transform=transform)
test_loader = torch.utils.data.DataLoader(dataset=test_set, batch_size=4, shuffle=False, num_workers=2)

2)对于特定结构的数据集

这种情况就是不在上述PyTorch提供数据库之列,但是满足下面的形式:

 root/ants/xxx.png
 root/ants/xxy.jpeg
 root/ants/xxz.png
.
.
.
root/bees/123.jpg
root/bees/nsdf3.png
root/bees/asd932_.png

那么就可以通过torchvision中的通用数据集ImageFolder来完成加载。具体例子如下:

import torch
from torchvision import transforms, datasets
 
data_transform = transforms.Compose([
        transforms.RandomSizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ])
hymenoptera_dataset = datasets.ImageFolder(root='hymenoptera_data/train',
                                           transform=data_transform)
dataset_loader = torch.utils.data.DataLoader(hymenoptera_dataset,
                                             batch_size=4, shuffle=True,
                                             num_workers=4)

3)对于最普通的数据集

最后一种情况是既不是自带数据集,又不满足ImageFolder,这种时候就自己进行处理。定义数据集的类(myDataset),这个类要继承dataset这个抽象类,并实现__len__以及__getitem__这两个函数,通常情况还包括初始函数__init__.

class myDataset(Dataset): # 继承Dataset
 
    def __init__(self, csv_file, root_dir, transform=None):
        """
        Args:
            csv_file (string): Path to the csv file with annotations.
            root_dir (string): Directory with all the images.
            transform (callable, optional): Optional transform to be applied on a sample.
        """
 
    def __len__(self): # __len__返回数据集的大小,用法:len(dataset)
        return len(...)
 
    def __getitem__(self, idx):# 支持整数idx索引,范围从0到len(self),用法:dataset[i]得到索引为i的样本及标签
 
 
        if self.transform:
            sample = self.transform(sample)  # 可以实现裁剪缩放等数据转换(transform类是有__call__方法的)
                                             # 所以就可以利用函数形式transform(sample)来进行变换
        return sample

二、模型创建

1)torchvision中带模型加载

import torchvision.models as models
resnet18 = models.resnet18(pretrained=True)
alexnet = models.alexnet(pretrained=True)
squeezenet = models.squeezenet1_0(pretrained=True)
vgg16 = models.vgg16(pretrained=True)
densenet = models.densenet161(pretrained=True)
inception = models.inception_v3(pretrained=True)
googlenet = models.googlenet(pretrained=True)
shufflenet = models.shufflenet_v2_x1_0(pretrained=True)
mobilenet = models.mobilenet_v2(pretrained=True)
resnext50_32x4d = models.resnext50_32x4d(pretrained=True)
wide_resnet50_2 = models.wide_resnet50_2(pretrained=True)
mnasnet = models.mnasnet1_0(pretrained=True)
pretrained=True表示加载预训练参数,Fale表示只搭建模型框架随机初始化参数。

2)搭建系列化神经网络

import torch
	
net2 = torch.nn.Sequential(
    torch.nn.Linear(1, 10),
    torch.nn.ReLU(),
    torch.nn.Linear(10, 1)
)

print(net2)

"""
Sequential (
  (0): Linear (1 -> 10)
  (1): ReLU ()
  (2): Linear (10 -> 1)
)
"""

3)继承torch.nn.Module

import torch

class Net(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_feature, n_hidden)
        self.predict = torch.nn.Linear(n_hidden, n_output)
 
    def forward(self, x):
        x = F.relu(self.hidden(x))
        x = self.predict(x)
        return x
 
net1 = Net(1, 10, 1) 

print(net1)
"""
Net (
  (hidden): Linear (1 -> 10)
  (predict): Linear (10 -> 1)
)
"""

三、完整模型的训练迭代

import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
import torchvision

# 超参数
EPOCH = 10
BATCH_SIZE = 64
LR = 0.005
DOWNLOAD_MNIST = True   # 下过数据的话, 就可以设置成 False
N_TEST_IMG = 5          # 到时候显示 5张图片看效果, 如上图一

# Mnist digits dataset
train_data = torchvision.datasets.MNIST(
    root='./mnist/',
    train=True,                                     # this is training data
    transform=torchvision.transforms.ToTensor(),    # Converts a PIL.Image or numpy.ndarray to
                                                    # torch.FloatTensor of shape (C x H x W) and normalize in the range [0.0, 1.0]
    download=DOWNLOAD_MNIST,                        # download it if you don\'t have it
)



class AutoEncoder(nn.Module):
    def __init__(self):
        super(AutoEncoder, self).__init__()

        # 压缩
        self.encoder = nn.Sequential(
            nn.Linear(28*28, 128),
            nn.Tanh(),
            nn.Linear(128, 64),
            nn.Tanh(),
            nn.Linear(64, 12),
            nn.Tanh(),
            nn.Linear(12, 3),   # 压缩成3个特征, 进行 3D 图像可视化
        )
        # 解压
        self.decoder = nn.Sequential(
            nn.Linear(3, 12),
            nn.Tanh(),
            nn.Linear(12, 64),
            nn.Tanh(),
            nn.Linear(64, 128),
            nn.Tanh(),
            nn.Linear(128, 28*28),
            nn.Sigmoid(),       # 激励函数让输出值在 (0, 1)
        )

    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded, decoded

autoencoder = AutoEncoder()

optimizer = torch.optim.Adam(autoencoder.parameters(), lr=LR)
loss_func = nn.MSELoss()

for epoch in range(EPOCH):
    for step, (x, y) in enumerate(train_loader):
        b_x = Variable(x.view(-1, 28*28))   # batch x, shape (batch, 28*28)
        b_y = Variable(x.view(-1, 28*28))   # batch y, shape (batch, 28*28)
        b_label = Variable(y)               # batch label

        encoded, decoded = autoencoder(b_x)

        loss = loss_func(decoded, b_y)      # mean square error
        optimizer.zero_grad()               # clear gradients for this training step
        loss.backward()                     # backpropagation, compute gradients
        optimizer.step() 

四、模型保存及加载

1)两种途径来保存

torch.save(net1, \'net.pkl\')  # 保存整个网络
torch.save(net1.state_dict(), \'net_params.pkl\')   # 只保存网络中的参数 (速度快, 占内存少)

2)提取网络

#这种方式将会提取整个神经网络, 网络大的时候可能会比较慢.

def restore_net():
    # restore entire net1 to net2
    net2 = torch.load(\'net.pkl\')
    prediction = net2(x)

3)只提取网络参数

#这种方式将会提取所有的参数, 然后再放到你的新建网络中.
	
def restore_params():
    # 新建 net3
    net3 = torch.nn.Sequential(
        torch.nn.Linear(1, 10),
        torch.nn.ReLU(),
        torch.nn.Linear(10, 1)
    )
 
    # 将保存的参数复制到 net3
    net3.load_state_dict(torch.load(\'net_params.pkl\'))
    prediction = net3(x)

五、pytorch GPU加速

 使用GPU之前,需要确保GPU是可以使用,可通过torch.cuda.is_available()的返回值来进行判断。返回True则具有能够使用的GPU。通过torch.cuda.device_count()可以获得能够使用的GPU数量。

1)单GPU加速

把数据从内存转移到GPU,一般针对张量(我们需要的数据)和模型。 对张量(类型为FloatTensor或者是LongTensor等),一律直接使用方法.to(device)或.cuda()即可。

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#或device = torch.device("cuda:0")
device1 = torch.device("cuda:1")  
for batch_idx, (img, label) in enumerate(train_loader):
    img=img.to(device)
    label=label.to(device)

对于模型来说,也是同样的方式,使用.to(device)或.cuda来将网络放到GPU显存。

#实例化网络
model = Net()
model.to(device)   #使用序号为0的GPU
#或model.to(device1) #使用序号为1的GPU

 

2)多GPU加速

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#实例化网络
model = Net1(13, 16, 32, 1)
if torch.cuda.device_count() > 1:
    print("Let's use", torch.cuda.device_count(), "GPUs")
    # dim = 0 [64, xxx] -> [32, ...], [32, ...] on 2GPUs
    model = nn.DataParallel(model)#单主机多GPU,多主机多GPU用DistributedParallel
model.to(device)

六、pytorch与tensorflow区别

1)动态静态之分

Tensorflow 就是最典型的静态计算模块,也就是说, 大部分时候, 用 Tensorflow 是先搭建好这样一个计算系统, 一旦搭建好了, 就不能改动了 (也有例外, 比如 dynamic_rnn() , 但是总体来说他还是运用了一个静态思维), 所有的计算都会在这种图中流动, 当然很多情况, 这样就够了, 我们不需要改动什么结构. 不动结构当然可以提高效率. 但是一旦计算流程不是静态的, 计算图要变动。

2)GPU的使用

PyTorch 和 TensorFlow 的一个主要差异特点是数据并行化。PyTorch 优化性能的方式是利用 Python 对异步执行的本地支持。而用 TensorFlow 时,你必须手动编写代码,并微调要在特定设备上运行的每个操作,以实现分布式训练。但是,你可以将 PyTorch 中的所有功能都复现到 TensorFlow 中,但这需要做很多工作。

3)可视化

在训练过程的可视化方面,TensorFlow 更有优势。可视化能帮助开发者跟踪训练过程以及实现更方便的调试。TensorFlow 的可视化库名为 TensorBoard。PyTorch 开发者则使用 Visdom,但是 Visdom 提供的功能很简单且有限,所以 TensorBoard 在训练过程可视化方面更好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值