当前位置:   article > 正文

pytorch使用CNN实现MNIST手写体的识别_pytorch cnn mnist

pytorch cnn mnist

**MNIST数据集介绍:**MNIST数据集在torvision.datasets里面,可以自行加载,其中训练集有6W张,测试集有1W,都为灰度图,即channel为1,图片的大小都是28x28,下面图片就是一部分数据。
mnist数据集

导入工具包

import torch
from torch.autograd import Variable
import torch.nn as nn
import matplotlib.pyplot as plt
import torchvision
import torch.utils.data as Data
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

超参数设置

pyper parameter


"""
每次在训练集中提取64张图像进行批量化训练,目的是提高训练速度。
就好比搬砖,一次搬一块砖头的效率肯定要比一次能搬64块要低得多
"""
BATCH_SIZE = 64
#学习率,学习率一般为0.01,0.1等等较小的数,为了在梯度下降求解时避免错过最优解
LR = 0.001
"""
EPOCH 假如现在我有1000张训练图像,因为每次训练是64张,
每当我1000张图像训练完就是一个EPOCH,训练多少个EPOCH自己决定
"""
EPOCH = 1
"""
现在我要训练的训练集是系统自带的,需要先下载数据集,
当DOWNLOAD_MNIST为True是表示学要下载数据集,一但下载完,保存
然后这个参数就可以改为False,表示不用再次下载
"""
DOWNLOAD_MNIST = True
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

读取训练集

torchvision里面有许多的数据集,现在就要下载MNIST数据集,就是手写体数字

root表示下载到哪个目录下
train表示下载的是训练集,而不是测试集
tranform格式转换为tensor
download是否要下载


train_data = torchvision.datasets.MNIST(
    root='./mnist',
    train = True,
    transform=torchvision.transforms.ToTensor(),
    download=DOWNLOAD_MNIST
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

划分训练集

loader将训练集划分为n个64的集合,方便每次取64个,当最后不足64时,将剩下的归为一个集合里

datase需要划分的数据集
batch_size按多少划分
shuffle是否要打乱数据,一般打乱对结果有一个更好的影响
num_workers表示需要多少个核进行操作

train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True, num_workers=2 )
#每个batch_size的shape为[64, 1, 28, 28]

  • 1
  • 2
  • 3

测试集读取

#测试集操作和上面注释一样
test_data = torchvision.datasets.MNIST(
    root='./mnist',
    train = False,
)
  • 1
  • 2
  • 3
  • 4
  • 5

对测试集处理


test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), volatile=True).type(torch.FloatTensor)[:2000]/255.0
"""
test_data.test_data中的shape为[10000, 28, 28]代表1w张图像,都是28x28,当时并未表明channels,因此在unsqueeze在1方向想加一个维度,
则shape变为[10000, 1, 28, 28],然后转化为tensor的float32类型,取1w张中的2000张,并且将其图片进行归一化处理,避免图像几何变换的影响
"""
#标签取前2000
test_y = test_data.test_labels[:2000]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

定义网络结构

#定义网络结构
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        #前面都是规定结构
        #第一个卷积层,这里使用快速搭建发搭建网络
        self.conv1 = nn.Sequential(
            nn.Conv2d(
                in_channels=1,#灰度图,channel为一
                out_channels=16,#输出channels自己设定
                kernel_size=3,#卷积核大小
                stride=1,#步长
                padding=1#padding=(kernel_size-stride)/2   往下取整
            ),
            nn.ReLU(),#激活函数,线性转意识到非线性空间
            nn.MaxPool2d(kernel_size=2)#池化操作,降维,取其2x2窗口最大值代表此窗口,因此宽、高减半,channel不变
        )
        #此时shape为[16, 14, 14]
        self.conv2 = nn.Sequential(
            nn.Conv2d(
                in_channels=16,
                out_channels=32,
                kernel_size=3,
                stride=1,
                padding=1
            ),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)
        )
        #此时shape为[32, 7, 7]
        #定义全连接层,十分类,并且全连接接受两个参数,因此为[32*7*7, 10]
        self.prediction = nn.Linear(32*7*7, 10)
        #前向传播过程
    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)
        output = self.prediction(x)
        return output
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

实例化model,并且定义优化器以及损失函数

#创建网络
cnn = CNN()

#大数据常用Adam优化器,参数需要model的参数,以及学习率
optimizer = torch.optim.Adam(cnn.parameters(), LR)
#定义损失函数,交叉熵
loss_func = nn.CrossEntropyLoss()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

训练

#训练阶段
for epoch in range(EPOCH):
    #step,代表现在第几个batch_size
    #batch_x 训练集的图像
    #batch_y 训练集的标签
    for step, (batch_x, batch_y) in enumerate(train_loader):
        #model只接受Variable的数据,因此需要转化
        b_x = Variable(batch_x)
        b_y = Variable(batch_y)
        #将b_x输入到model得到返回值
        output = cnn(b_x)
        print(output)
        #计算误差
        loss = loss_func(output, b_y)
        #将梯度变为0
        optimizer.zero_grad()
        #反向传播
        loss.backward()
        #优化参数
        optimizer.step()
        #打印操作,用测试集检验是否预测准确
        if step%50 == 0:
            test_output = cnn(test_x)
            #squeeze将维度值为1的除去,例如[64, 1, 28, 28],变为[64, 28, 28]
            pre_y = torch.max(test_output, 1)[1].data.squeeze()
            #总预测对的数除总数就是对的概率
            accuracy = float((pre_y == test_y).sum()) / float(test_y.size(0))
            print("epoch:", epoch, "| train loss:%.4f" % loss.data, "|test accuracy:%.4f" %accuracy)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

到目前为止所有代码已经贴完,也就是一个完整的卷积神经网络已经实现,接下来就是与代码,等代结果。
是不是觉得很简单!
下面是我运行结果
在这里插入图片描述
可以看出来准确率可以达到97.65%,已经是一个很好结果了,目前为止所有过程都已经完成了。
下面我吧完整代码贴在后面

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

#pyper parameter
"""
每次在训练集中提取64张图像进行批量化训练,目的是提高训练速度。
就好比搬砖,一次搬一块砖头的效率肯定要比一次能搬64块要低得多
"""
BATCH_SIZE = 64
#学习率,学习率一般为0.01,0.1等等较小的数,为了在梯度下降求解时避免错过最优解
LR = 0.001
"""
EPOCH 假如现在我有1000张训练图像,因为每次训练是64张,
每当我1000张图像训练完就是一个EPOCH,训练多少个SEPOCH自己决定
"""
EPOCH = 1
"""
现在我要训练的训练集是系统自带的,需要先下载数据集,
当DOWNLOAD_MNIST为True是表示学要下载数据集,一但下载完,保存
然后这个参数就可以改为False,表示不用再次下载
"""
DOWNLOAD_MNIST = True

"""torchvision里面有许多的数据集,现在就要下载MNIST数据集,就是手写体数字"""
"""
root表示下载到哪个目录下
train表示下载的是训练集,而不是测试集
tranform格式转换为tensor
download是否要下载
"""
train_data = torchvision.datasets.MNIST(
    root='./mnist',
    train = True,
    transform=torchvision.transforms.ToTensor(),
    download=DOWNLOAD_MNIST
)
#loader将训练集划分为n个64的集合,方便每次取64个,当最后不足64时,将剩下的归为一个集合里
"""
datase需要划分的数据集
batch_size按多少划分
shuffle是否要打乱数据,一般打乱对结果有一个更好的影响
num_workers表示需要多少个核进行操作
"""
#每个batch_size的shape为[64, 1, 28, 28]
train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True, num_workers=2 )
#测试集操作和上面一样
test_data = torchvision.datasets.MNIST(
    root='./mnist',
    train = False,
)
#定义网络结构
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        #前面都是规定结构
        #第一个卷积层,这里使用快速搭建发搭建网络
        self.conv1 = nn.Sequential(
            nn.Conv2d(
                in_channels=1,#灰度图,channel为一
                out_channels=16,#输出channels自己设定
                kernel_size=3,#卷积核大小
                stride=1,#步长
                padding=1#padding=(kernel_size-stride)/2   往下取整
            ),
            nn.ReLU(),#激活函数,线性转意识到非线性空间
            nn.MaxPool2d(kernel_size=2)#池化操作,降维,取其2x2窗口最大值代表此窗口,因此宽、高减半,channel不变
        )
        #此时shape为[16, 14, 14]
        self.conv2 = nn.Sequential(
            nn.Conv2d(
                in_channels=16,
                out_channels=32,
                kernel_size=3,
                stride=1,
                padding=1
            ),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)
        )
        #此时shape为[32, 7, 7]
        #定义全连接层,十分类,并且全连接接受两个参数,因此为[32*7*7, 10]
        self.prediction = nn.Linear(32*7*7, 10)
        #前向传播过程
    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)
        output = self.prediction(x)
        return output
#创建网络
cnn = CNN()

#大数据常用Adam优化器,参数需要model的参数,以及学习率
optimizer = torch.optim.Adam(cnn.parameters(), LR)
#定义损失函数,交叉熵
loss_func = nn.CrossEntropyLoss()
#训练阶段
for epoch in range(EPOCH):
    #step,代表现在第几个batch_size
    #batch_x 训练集的图像
    #batch_y 训练集的标签
    for step, (batch_x, batch_y) in enumerate(train_loader):
        #model只接受Variable的数据,因此需要转化
        b_x = Variable(batch_x)
        b_y = Variable(batch_y)
        #将b_x输入到model得到返回值
        output = cnn(b_x)
        print(output)
        #计算误差
        loss = loss_func(output, b_y)
        #将梯度变为0
        optimizer.zero_grad()
        #反向传播
        loss.backward()
        #优化参数
        optimizer.step()
        #打印操作,用测试集检验是否预测准确
        if step%50 == 0:
            test_output = cnn(test_x)
            #squeeze将维度值为1的除去,例如[64, 1, 28, 28],变为[64, 28, 28]
            pre_y = torch.max(test_output, 1)[1].data.squeeze()
            #总预测对的数除总数就是对的概率
            accuracy = float((pre_y == test_y).sum()) / float(test_y.size(0))
            print("epoch:", epoch, "| train loss:%.4f" % loss.data, "|test accuracy:%.4f" %accuracy)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/214907
推荐阅读
相关标签
  

闽ICP备14008679号