pytorch demo 实践

作者: Moonsmile | 来源:发表于2018-03-27 16:46 被阅读116次

    相关环境

    python
    opencv
    pytorch
    ubuntu 14.04

    pytorch 基本内容

    60分钟快速入门,参考:https://blog.csdn.net/u014630987/article/details/78669051
    需要学习的内容包括

       1、基本概念Tensors、Variable、Numpy等
       2、如何搭建神经网络模型(包括卷积神经网络)
       3、如何定义损失函数和优化器(包括不同分类器和优化器的含义)
       4、如何训练(包括如何读取数据、如何在GPU上训练)
       5、如何测试(定义好评价指标,比如准确率和loss)
    
    网络( 参考[1])
    网络结构
    对应代码(直接执行就行,有一个下载数据的过程,可能有一点耗时 参考[1])
    #coding=utf-8
    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    import torch.optim as optim
    from torchvision import datasets, transforms
    from torch.autograd import Variable
    
    # Training settings
    batch_size = 64
    
    # MNIST Dataset
    train_dataset = datasets.MNIST(root='./mnist_data/',
                                   train=True,
                                   transform=transforms.ToTensor(),
                                   download=True)
    
    test_dataset = datasets.MNIST(root='./mnist_data/',
                                  train=False,
                                  transform=transforms.ToTensor())
    
    # Data Loader (Input Pipeline)
    train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                               batch_size=batch_size,
                                               shuffle=True)
    
    test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                              batch_size=batch_size,
                                              shuffle=False)
    
    
    class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.l1 = nn.Linear(784, 520)
            self.l2 = nn.Linear(520, 320)
            self.l3 = nn.Linear(320, 240)
            self.l4 = nn.Linear(240, 120)
            self.l5 = nn.Linear(120, 10)Variable
    
        def forward(self, x):
            # Flatten the data (n, 1, 28, 28) --> (n, 784)
            x = x.view(-1, 784)
            x = F.relu(self.l1(x))
            x = F.relu(self.l2(x))
            x = F.relu(self.l3(x))
            x = F.relu(self.l4(x))
            return F.log_softmax(self.l5(x))
            #return self.l5(x)
    
    model = Net()
    
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    
    def train(epoch):
        # 每次输入barch_idx个数据
        for batch_idx, (data, target) in enumerate(train_loader):
            data, target = Variable(data), Variable(target)
    
            optimizer.zero_grad()
            output = model(data)
            # loss
            loss = F.nll_loss(output, target)
            loss.backward()
            # update
            optimizer.step()
            if batch_idx % 100 == 0:
                print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                    epoch, batch_idx * len(data), len(train_loader.dataset),
                    100. * batch_idx / len(train_loader), loss.data[0]))
    
    def test():
        test_loss = 0
        correct = 0
        # 测试集
        for data, target in test_loader:
            data, target = Variable(data, volatile=True), Variable(target)
            output = model(data)
            # sum up batch loss
            test_loss += F.nll_loss(output, target).data[0]
            # get the index of the max
            #pred = output.data.max(1, keepdim=True)[1]
            pred = output.data.max(1)[1]
            correct += pred.eq(target.data.view_as(pred)).cpu().sum()
    
        test_loss /= len(test_loader.dataset)
        print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
            test_loss, correct, len(test_loader.dataset),
            100. * correct / len(test_loader.dataset)))
    
    for epoch in range(1,6):
        train(epoch)
        test()
    
    亲自验证代码可行
    运行结果

    使用GPU

    使用GPU计算这是核心

    官方参考代码

    由于我只有一块GPU,所以将这一行代码
    if torch.cuda.device_count() > 1:改成了
    if torch.cuda.device_count() >= 1:

    """
    Optional: Data Parallelism
    ==========================
    **Authors**: `Sung Kim <https://github.com/hunkim>`_ and `Jenny Kang <https://github.com/jennykang>`_
    
    In this tutorial, we will learn how to use multiple GPUs using ``DataParallel``.
    
    It's very easy to use GPUs with PyTorch. You can put the model on a GPU:
    
    .. code:: python
    
        model.gpu()
    
    Then, you can copy all your tensors to the GPU:
    
    .. code:: python
    
        mytensor = my_tensor.gpu()
    
    Please note that just calling ``mytensor.gpu()`` won't copy the tensor
    to the GPU. You need to assign it to a new tensor and use that tensor on the GPU.
    
    It's natural to execute your forward, backward propagations on multiple GPUs. 
    However, Pytorch will only use one GPU by default. You can easily run your 
    operations on multiple GPUs by making your model run parallelly using 
    ``DataParallel``:
    
    .. code:: python
    
        model = nn.DataParallel(model)
    
    That's the core behind this tutorial. We will explore it in more detail below.
    """
    
    
    ######################################################################
    # Imports and parameters
    # ----------------------
    # 
    # Import PyTorch modules and define parameters.
    # 
    
    import torch
    import torch.nn as nn
    from torch.autograd import Variable
    from torch.utils.data import Dataset, DataLoader
    
    # Parameters and DataLoaders
    input_size = 5
    output_size = 2
    
    batch_size = 30
    data_size = 100
    
    
    ######################################################################
    # Dummy DataSet
    # -------------
    # 
    # Make a dummy (random) dataset. You just need to implement the
    # getitem 
    #
    
    class RandomDataset(Dataset):
    
        def __init__(self, size, length):
            self.len = length
            self.data = torch.randn(length, size)
    
        def __getitem__(self, index):
            return self.data[index]
    
        def __len__(self):
            return self.len
    
    rand_loader = DataLoader(dataset=RandomDataset(input_size, 100),
                             batch_size=batch_size, shuffle=True)
    
    
    ######################################################################
    # Simple Model
    # ------------
    # 
    # For the demo, our model just gets an input, performs a linear operation, and 
    # gives an output. However, you can use ``DataParallel`` on any model (CNN, RNN,
    # Capsule Net etc.) 
    #
    # We've placed a print statement inside the model to monitor the size of input
    # and output tensors. 
    # Please pay attention to what is printed at batch rank 0.
    # 
    
    class Model(nn.Module):
        # Our model
    
        def __init__(self, input_size, output_size):
            super(Model, self).__init__()
            self.fc = nn.Linear(input_size, output_size)
    
        def forward(self, input):
            output = self.fc(input)
            print("  In Model: input size", input.size(), 
                  "output size", output.size())
    
            return output
    
    
    ######################################################################
    # Create Model and DataParallel
    # -----------------------------
    # 
    # This is the core part of the tutorial. First, we need to make a model instance
    # and check if we have multiple GPUs. If we have multiple GPUs, we can wrap 
    # our model using ``nn.DataParallel``. Then we can put our model on GPUs by
    # ``model.gpu()`` 
    # 
    
    model = Model(input_size, output_size)
    if torch.cuda.device_count() >= 1:
      print("Let's use", torch.cuda.device_count(), "GPUs!")
      # dim = 0 [30, xxx] -> [10, ...], [10, ...], [10, ...] on 3 GPUs
      model = nn.DataParallel(model)
    
    if torch.cuda.is_available():
       print "cuda cuda cuda"
       model.cuda()
    
    
    ######################################################################
    # Run the Model
    # -------------
    # 
    # Now we can see the sizes of input and output tensors.
    # 
    
    for data in rand_loader:
        if torch.cuda.is_available():
            input_var = Variable(data.cuda())
        else:
            input_var = Variable(data)
    
        output = model(input_var)
        print("Outside: input size", input_var.size(),
              "output_size", output.size())
    
    
    ######################################################################
    # Results
    # -------
    # 
    # When we batch 30 inputs and 30 outputs, the model gets 30 and outputs 30 as
    # expected. But if you have GPUs, then you can get results like this.
    # 
    # 2 GPUs
    # ~~~~~~
    #
    # If you have 2, you will see:
    # 
    # .. code:: bash
    # 
    #     # on 2 GPUs
    #     Let's use 2 GPUs!
    #         In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
    #         In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
    #         In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
    #         In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([5, 5]) output size torch.Size([5, 2])
    #         In Model: input size torch.Size([5, 5]) output size torch.Size([5, 2])
    #     Outside: input size torch.Size([10, 5]) output_size torch.Size([10, 2])
    # 
    # 3 GPUs
    # ~~~~~~
    # 
    # If you have 3 GPUs, you will see:
    # 
    # .. code:: bash
    # 
    #     Let's use 3 GPUs!
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #         In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #     Outside: input size torch.Size([10, 5]) output_size torch.Size([10, 2])
    # 
    # 8 GPUs
    # ~~~~~~~~~~~~~~
    # 
    # If you have 8, you will see:
    # 
    # .. code:: bash
    # 
    #     Let's use 8 GPUs!
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #     Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #         In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
    #     Outside: input size torch.Size([10, 5]) output_size torch.Size([10, 2])
    # 
    
    
    ######################################################################
    # Summary
    # -------
    # 
    # DataParallel splits your data automatically and sends job orders to multiple
    # models on several GPUs. After each model finishes their job, DataParallel
    # collects and merges the results before returning it to you.
    # 
    # For more information, please check out
    # http://pytorch.org/tutorials/beginner/former\_torchies/parallelism\_tutorial.html.
    # 
    

    如果运行遇到了这个问题

    RuntimeError: cublas runtime error : library not initialized at /b/wheel/pytorch-src/torch/lib/THC/THCGeneral.c:387
    

    解决办法

    尝试执行 sudo rm -rf ~/.nv 
    
    执行结果
    执行结果

    Pytorch 的几种数据读取方式介绍

    1、torchvision.datasets的使用 参考[2]

    上边的minist实战的数据读取就是用这种方式

    对于常用数据集,可以使用torchvision.datasets直接进行读取。torchvision.dataset是torch.utils.data.Dataset的实现,该包提供了以下数据集的读取。

    torchvision.dataset和torch.utils.data.Dataloader的代码实现

    参考https://zhuanlan.zhihu.com/p/28200166

    包含的数据集如下
    MNIST
    COCO (Captioning and Detection)
    LSUN Classification
    ImageFolder
    Imagenet-12
    CIFAR10 and CIFAR100
    STL10
    

    将该种方式读取的数据打印出来看看,是一些Tensor。

    #coding=utf-8
    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    import torch.optim as optim
    from torchvision import datasets, transforms
    import torchvision
    from torch.autograd import Vari上边的minist实战的数据读取就是用这种方式able
    import matplotlib.pyplot as plt
    import numpy as np
    import cv2
    # Training settings
    batch_size = 2
    
    # MNIST Dataset
    train_dataset = datasets.MNIST(root='./mnist_data/',
                                   train=True,
                                   transform=transforms.ToTensor(),
                                   download=True)
    
    test_dataset = datasets.MNIST(root='./mnist_data/',
                                  transform=transforms.ToTensor())
    
    # Data Loader (Input Pipeline)
    train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                               batch_size=batch_size,
                                               shuffle=True)
    
    test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                              batch_size=batch_size,
                                              shuffle=False)
    
    dataiter = iter(train_loader)
    image,lables = dataiter.next()
    
    print image[0] #打印第一张图片的矩阵
    print lables[0] #打印第一张图片的标签值
    
    #分别用opencv matlabplot读取和显示本地图片
    im = cv2.imread("1.jpg")
    win = cv2.namedWindow('opencv test win', flags=0)
    cv2.imshow("opencv test win",im)
    cv2.waitKey(5)
    plt.imshow(im)
    plt.show("matplotlib")
    #plt.imshow(image.reshape(image.shape[0], image.shape[1]), cmap=plt.cm.Greys)
    
    结果

    2、自定义标签数据集的读取(参考文献[2])
    比如现在有文件text.txt, 格式如下,第一个是文件名,后边的数字是标签

    0.jpg  1 2 3 4 5 6
    1.jpg  2 3 4 5 6 7
    2.jpg  6 7 8 9 0 1
    

    第一步:继承torch.utils.data.Dataset类,完成图像及标签的读取,图像存在某个目录下,比如..../images

    代码来源文献[2]
    import os  
    import torch  
    import torch.utils.data as data  
    from PIL import Image  
      
    def default_loader(path):  
        return Image.open(path).convert('RGB')  
      
    class myImageFloder(data.Dataset):  
        def __init__(self, root, label, transform = None, target_transform=None, loader=default_loader):  
            fh = open(label)  
            c=0  
            imgs=[]  
            class_names=[]  
            for line in  fh.readlines():  
                if c==0:  
                    class_names=[n.strip() for n in line.rstrip().split('   ')]  
                else:  
                    cls = line.split()   
                    fn = cls.pop(0)  
                    if os.path.isfile(os.path.join(root, fn)):  
                        imgs.append((fn, tuple([float(v) for v in cls])))  
                c=c+1  
            self.root = root  
            self.imgs = imgs  
            self.classes = class_names  
            self.transform = transform  
            self.target_transform = target_transform  
            self.loader = loader  
      
        def __getitem__(self, index):  
            fn, label = self.imgs[index]  
            img = self.loader(os.path.join(self.root, fn))  
            if self.transform is not None:  
                img = self.transform(img)  
            return img, torch.Tensor(label)  
      
        def __len__(self):  
            return len(self.imgs)  
          
        def getName(self):  
            return self.classes 
    

    第二步:实例化torch.utils.data.DataLoader
    获取到实例,就能获得data跟label,就能扔到模型训练或者测试啦。

        mytransform = transforms.Compose([  
            transforms.ToTensor()  
            ]  
        )  
          
        # torch.utils.data.DataLoader  
        imgLoader = torch.utils.data.DataLoader(  
                 myFloder.myImageFloder(root = "../data/testImages/images", label = "../data/testImages/test.txt", transform = mytransform ),   
                 batch_size= 2, shuffle= False, num_workers= 2)  
          
        for i, data in enumerate(imgLoader, 0):  
            print(data[i][0])  
            # opencv  
            img2 = data[i][0].numpy()*255  
            img2 = img2.astype('uint8')  
            img2 = np.transpose(img2, (1,2,0))  
            img2=img2[:,:,::-1]#RGB->BGR  
            cv2.imshow('img2', img2)  
            cv2.waitKey()  
            break  
    
    感谢以下博客大神们的文章,本文在多人的博客和论文基础上总结而来,如有侵权或者内容不妥,请简书私信联系作者。

    参考文献

    1.https://blog.csdn.net/m0_37306360/article/details/79309849
    2.https://blog.csdn.net/tfygg/article/details/73354235
    3.https://zhuanlan.zhihu.com/p/28200166
    4.https://blog.csdn.net/m0_37306360/article/details/79309849
    5.https://translate.google.com.hk/translate?hl=zh-CN&sl=en&u=https://github.com/torch/cutorch/issues/677&prev=search

    相关文章

      网友评论

        本文标题:pytorch demo 实践

        本文链接:https://www.haomeiwen.com/subject/ozqscftx.html