跟我一起学PyTorch-06:卷积神经网络CNN

以全连接层为基础的深度神经网络DNN是整个深度学习的基石。要说应用最广、影响最大的深度神经网络,那就是卷积神经网络(Convolutional Neural Network,CNN)。卷积神经网络虽然发布的时间较早,但直到2006年Hilton解决深度神经网络的训练问题后才焕发生机。卷积神经网络现在几乎是图像识别研究的标配。

简单回顾卷积神经网络的发展历程。日本科学家福岛邦彦在1986年提出了Neocognitron(神经认知机),直接启发了后来的卷积神经网络。Yann LeCun于1998年提出的卷积神经LeNet,首次提出了多层级联的卷积结构,可对手写数字进行有效识别。2012年,Alex依靠卷积神经网络AlexNet夺得ILSVRC 2012比赛的冠军,吹响了卷积神经网络研究的号角。AlexNet成功应用了ReLU、Dropout、最大池化、LRN(Local Response Normalization,局部响应归一化)、GPU加速等新技术,启发了后续更多的技术创新,加速了卷积神经网络和深度学习的研究。从此,深度学习研究进入了蓬勃发展的新阶段。2014年Google提出的GoogleNet,运用Inception Module这个可以反复堆叠、高效的卷积神经结构,获得了当年ImageNet ILSVRC比赛的冠军,同年的亚军VGGNet全程使用3*3的卷积,成功训练了深度达19层的网络。2015年,微软提出了ResNet,包含残差学习模块,成功训练了152层的网络,一举拿下当年的ILSVRC比赛的冠军。

卷积神经网络技术的发展风起云涌,尽管卷积神经网络最初是为了解决计算机视觉等问题设计的,现在其应用范围不仅仅局限于图像和视频领域,也可用于时间序列信号,比如音频信号等。本章主要通过卷积神经网络在计算机视觉上的应用来介绍卷积神经网络的原理以及如何使用PyTorch实现卷积神经网络。

本章首先介绍人类视觉和计算机的基本原理,以及计算机视觉中特征的提取和选择;然后介绍卷积神经网络的主体思想和整体结构,并将详细讲解卷积层和池化层的网络结构、PyTorch对这些网络的支持、如何设置每一层神经网络的配置,以及更加复杂的卷积神经网络结构,如AlexNet、VGGNet、ResNet等;最后再MNIST数据集上通过PyTorch使用卷积神经网络实现突破分类。

1.计算机视觉

1.人类视觉和计算机视觉
2.特征提取
3.数据集

2.卷积神经网络

1.卷积层

2.池化层

3.经典卷积神经网络

3.MNIST数据集上的卷积神经网络的实现

本节介绍如何使用PyTorch实现一个简单的卷积神经网络,使用的数据集是MNIST,预期可以达到97.5%左右的准确率。该神经网络由2个卷积层和3个全连接层构成。通过这个例子我们可以账务设计卷积神经网络的特征以及参数的配置。

1.配置库和配置参数
import torch
from torch import nn,optim
import torch.nn.functional as F
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms,datasets
# 配置参数
torch.manual_seed(1)    # 设置随机种子,确保结果可重复
batch_size = 128        # 批处理大小
learning_rate = 1e-2    # 学习率
num_epoches = 10        # 训练次数
2.加载MNIST数据集
# 下载训练集MNIST(手写数字数据)
train_dataset = datasets.MNIST(root='./data',                    # 数据集保存路径
                               train=True,                       # 训练数据集
                               transform=transforms.ToTensor(),  # 转为Tensor
                               download=True)                    # 下载数据
test_dataset = datasets.MNIST(root='./data',
                               train=False,                      # 测试数据集
                               transform=transforms.ToTensor())
# 训练数据的加载方式:每次从train_dataset中随机(shuffle=True)选择batch_size个样本作为一个批次返回,因此所选择的数据可能会重复
train_loader = DataLoader(train_dataset,batch_size=batch_size,shuffle=True)
# 测试数据的加载方式:每次从test_dataset中选择batch_size个不同的样本作为一个批次返回,要覆盖到所有测试样本
test_loader = DataLoader(test_dataset,batch_size=batch_size,shuffle=False)
3.创建CNN模型
class Cnn(nn.Module):
    def __init__(self,in_dim,n_class): # 28*28*1
        super(Cnn,self).__init__()
        # 定义卷积层
        self.conv = nn.Sequential(
            nn.Conv2d(in_dim,6,3,stride=1,padding=1),  # 28*28
            nn.ReLU(True),
            nn.MaxPool2d(2,2),  # 14*14
            nn.Conv2d(6,16,5,stride=1,padding=0),  # 10*10*16
            nn.ReLU(True),
            nn.MaxPool2d(2,2))   # 5*5*16
        # 定义全连接层
        self.fc = nn.Sequential(
            nn.Linear(400,120),  # 400 = 5*5*16
            nn.Linear(120,84),   
            nn.Linear(84,n_class))
    # 前向传播
    def forward(self,x):
        out = self.conv(x)
        out = out.view(out.size(0),400)  # 400 = 5*5*16
        out = self.fc(out)
        return out
    
model = Cnn(1,10)   # 图片大小是28*28,10是数据的种类
print(model)

输出如下:

Cnn(
  (conv): Sequential(
    (0): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace)
    (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (3): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
    (4): ReLU(inplace)
    (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (fc): Sequential(
    (0): Linear(in_features=400, out_features=120, bias=True)
    (1): Linear(in_features=120, out_features=84, bias=True)
    (2): Linear(in_features=84, out_features=10, bias=True)
  )
)
4.训练模型
# 定义损失:交叉熵损失
criterion = nn.CrossEntropyLoss() 
# 定义优化器:随机梯度下降SGD
optimizer = optim.SGD(model.parameters(),lr=learning_rate)
# 共训练num_epoches轮
for epoch in range(num_epoches): 
    running_loss = 0.0  # 当前损失 
    running_acc = 0.0   # 当前准确度
    # 训练集:60000,批处理:128
    for i,data in enumerate(train_loader,1): 
        img,label = data 
        img = Variable(img) 
        label = Variable(label) 
        out = model(img)                              # 前向传播
        loss = criterion(out,label)                   # 这个损失是当前批次的平均损失
        running_loss += loss.item() * label.size(0)   # 累计损失大小,乘积表示当前批次的总损失
        _,pred=torch.max(out,1)                       # 多分类问题的类别取概率最大的类别
        num_correct = (pred == label).sum()           # 当前批次预测正确的个数
        running_acc += num_correct.item()             # 累计预测正确的个数
        optimizer.zero_grad()                         # 梯度清零
        loss.backward()                               # 误差反向传播
        optimizer.step()                              # 梯度更新
    # 每训练一轮,打印一次信息
    print('Train {} epoch, Loss: {:.6f}, Acc: {:.6f}'.format(epoch+1,running_loss/(len(train_dataset)),running_acc/(len(train_dataset))))

输出如下:

Train 1 epoch, Loss: 1.366457, Acc: 0.626950
Train 2 epoch, Loss: 0.411538, Acc: 0.877867
Train 3 epoch, Loss: 0.294756, Acc: 0.911117
Train 4 epoch, Loss: 0.232250, Acc: 0.930517
Train 5 epoch, Loss: 0.188249, Acc: 0.943533
Train 6 epoch, Loss: 0.159317, Acc: 0.952500
Train 7 epoch, Loss: 0.139562, Acc: 0.957750
Train 8 epoch, Loss: 0.125770, Acc: 0.962000
Train 9 epoch, Loss: 0.115610, Acc: 0.964783
Train 10 epoch, Loss: 0.108309, Acc: 0.966983
5.评估模型
# 由于训练和测试的BatchNorm,Drop等配置不同,所以需要说明是模型评估
model.eval()
eval_loss = 0
eval_acc = 0
for data in test_loader:
    img,label = data
    img = Variable(img)
    # 测试不需要 label = Variable(label)
    out = model(img)                             # 前向传播
    loss = criterion(out,label)                  # 当前批次的平均损失
    eval_loss += loss.item() * label.size(0)     # 累计损失
    _,pred = torch.max(out,1)                    # 多分类问题的类别取概率最大的类别
    num_correct = (pred==label).sum()            # 当前批次预测正确的个数
    eval_acc += num_correct.item()               # 累计预测正确的个数
# 打印测试集上的评估结果 
print('Test Loss: {:.6f}, Acc: {:.6f}'.format(eval_loss/(len(test_dataset)),eval_acc * 1.0 / (len(test_dataset))))

输出如下:

Test Loss: 0.091677, Acc: 0.972800

你或许想:《去原作者写文章的地方

转载请注明:Python量化投资 » 跟我一起学PyTorch-06:卷积神经网络CNN

喜欢 (0)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址