美文网首页Pytorch
Pytorch实现AlexNet解决自定义数据集(cifar10

Pytorch实现AlexNet解决自定义数据集(cifar10

作者: Lornatang | 来源:发表于2019-03-16 10:48 被阅读11次

    AlexNet

    代码地址

    Why AlexNet very good?

    1. 为什么Alexnet能在图2012 ImageNet LSVRC-2012 像识别(分类) competition取得这么好的成绩
    2. Alexnet的网络结构以及,参数数量的计算
    3. 为了避免过拟合使用的技巧:Data Augmentation(数据增强),正则化Relu以及dropout,局部响应归一化LRN。
    4. 对比了多个小的卷积核和大的卷积核的区别(前面BAT面试题)。
    5. Alexnet取得成功的原因,主要三条:
      大量数据,Deep Learning领域应该感谢李飞飞团队搞出来如此大的标注数据集合ImageNet;

    GPU,这种高度并行的计算神器确实助了洪荒之力,没有神器在手,Alex估计不敢搞太复杂的模型;

    算法的改进,包括网络变深、数据增强、ReLU、Dropout等。

    1. Alexnet网络结构以及参数数量的计算
      Alexnet网络的大体结构如下(论文以及一般的blog都是如下这个图,但是看起来很不直观):
    image

    下面给出两个更好理解的结构图,5个卷积层+3个全连接层:

    image image

    来源:stackoverflow
    https://www.learnopencv.com/understanding-alexnet/

    各层的参数计算如下,下图为5个卷积层的参数:

    image

    全连接层如下:

    image

    可以看到:卷积层的参数明显少于全连接层的参数。其中,网络大概有62.3 million parameters,其中卷积层占比约6%,单占比95%的计算。

    1. 为了避免过拟合使用的技巧:Data Augmentation(数据增强),正则化Relu以及dropout
    2. 1 Data Augmentation(数据增强)
      数据增强简单的办法如,图片翻转Mirroring,随机裁剪Random Crops。
    image image
    1. 2 使用ReLU非线性激活函数
      使用ReLU非线性激活函数而不选择sigmoid或tanh函数,ReLU优势在于:

    速度快 和sigmoid函数需要计算指数和倒数相比,relu函数其实就是一个max(0,x),计算代价小很多。

    减轻梯度消失问题,从而可以训练更深的网络。

    稀疏性 通过对大脑的研究发现,大脑在工作的时候只有大约5%的神经元是激活的,而采用sigmoid激活函数的人工神经网络,其激活率大约是50%。有论文声称人工神经网络在15%-30%的激活率时是比较理想的。因为relu函数在输入小于0时是完全不激活的,因此可以获得一个更低的激活率.

    1. 3 使用Dropout(只在最后几个全连接层做)
    image image

    为什么Dropout有效?

    Dropout背后理念和集成模型很相似。在Drpout层,不同的神经元组合被关闭,这代表了一种不同的结构,所有这些不同的结构使用一个的子数据集并行地带权重训练,而权重总和为1。如果Dropout层有 n 个神经元,那么会形成 2^{n} 个不同的子结构。在预测时,相当于集成这些模型并取均值。这种结构化的模型正则化技术有利于避免过拟合。Dropout有效的另外一个视点是:由于神经元是随机选择的,所以可以减少神经元之间的相互依赖,从而确保提取出相互独立的重要特征。

    1. 4 局部响应归一化LRN(Local Response Normalization)
      提出了LRN层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
    image

    补充
    2个33的卷积层和一个55卷积层的区别?(某BAT的一个面试题,也可以理解为多个小的卷积层和一个大的卷积层的区别),问题来源:stackoverflow,VGG中给出了答案,如下:

    多个卷积层可以增加网络的深度,从而学习更复杂的特征
    2个33的卷积层的参数少于一个55卷积层的参数

    code:

    import os
    import time
    
    import torch
    import torchvision
    from torch import nn, optim
    from torch.utils import data
    from torchvision import transforms
    
    # Device configuration
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    
    WORK_DIR = '/tmp/cifar10'
    NUM_EPOCHS = 10
    BATCH_SIZE = 128
    LEARNING_RATE = 1e-4
    NUM_CLASSES = 10
    
    MODEL_PATH = './models'
    MODEL_NAME = 'AlexNet.pth'
    
    # Create model
    if not os.path.exists(MODEL_PATH):
      os.makedirs(MODEL_PATH)
    
    transform = transforms.Compose([
      transforms.RandomCrop(36, padding=4),
      transforms.RandomResizedCrop(32),
      transforms.RandomHorizontalFlip(),
      transforms.ToTensor(),
      transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
    ])
    
    # Load data
    train_dataset = torchvision.datasets.ImageFolder(root=WORK_DIR + '/' + 'train',
                                                     transform=transform)
    
    train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                               batch_size=BATCH_SIZE,
                                               shuffle=True)
    
    
    class AlexNet(nn.Module):
      
      def __init__(self, num_classes=NUM_CLASSES):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
          nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
          nn.ReLU(inplace=True),
          nn.MaxPool2d(kernel_size=3, stride=2),
          nn.Conv2d(64, 192, kernel_size=5, padding=2),
          nn.ReLU(inplace=True),
          # net.MaxPool2d(kernel_size=3, stride=2),
          nn.Conv2d(192, 384, kernel_size=3, padding=1),
          nn.ReLU(inplace=True),
          nn.Conv2d(384, 256, kernel_size=3, padding=1),
          nn.ReLU(inplace=True),
          nn.Conv2d(256, 256, kernel_size=3, padding=1),
          nn.ReLU(inplace=True),
          # net.MaxPool2d(kernel_size=3, stride=2),
        )
        self.classifier = nn.Sequential(
          nn.Dropout(),
          nn.Linear(256 * 3 * 3, 4096),
          nn.ReLU(inplace=True),
          nn.Dropout(),
          nn.Linear(4096, 4096),
          nn.ReLU(inplace=True),
          nn.Linear(4096, num_classes),
        )
      
      def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        x = self.classifier(x)
        return x
    
    
    def main():
      print(f"Train numbers:{len(train_dataset)}")
      
      # load model
      model = AlexNet().to(device)
      # cast
      cast = nn.CrossEntropyLoss().to(device)
      # Optimization
      optimizer = optim.Adam(
        model.parameters(),
        lr=LEARNING_RATE,
        weight_decay=1e-8)
      step = 1
      for epoch in range(1, NUM_EPOCHS + 1):
        model.train()
        
        # cal one epoch time
        start = time.time()
        
        for images, labels in train_loader:
          images = images.to(device)
          labels = labels.to(device)
          
          # Forward pass
          outputs = model(images)
          loss = cast(outputs, labels)
          
          # Backward and optimize
          optimizer.zero_grad()
          loss.backward()
          optimizer.step()
          
          print(f"Step [{step * BATCH_SIZE}/{NUM_EPOCHS * len(train_dataset)}], "
                f"Loss: {loss.item():.8f}.")
          step += 1
        
        # cal train one epoch time
        end = time.time()
        print(f"Epoch [{epoch}/{NUM_EPOCHS}], "
              f"time: {end - start} sec!")
        
        # Save the model checkpoint
        torch.save(model, MODEL_PATH + '/' + MODEL_NAME)
      print(f"Model save to {MODEL_PATH + '/' + MODEL_NAME}.")
    
    
    if __name__ == '__main__':
      main()
    
    

    文章引用于 FishBear_move_on
    编辑 Lornatang
    校准 Lornatang

    相关文章

      网友评论

        本文标题:Pytorch实现AlexNet解决自定义数据集(cifar10

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