龙空技术网

使用MNIST数据集训练第一个pytorch CNN手写数字识别神经网络

人工智能研究所 461

前言:

此刻大家对“pytorch卷积神经网络mnist”可能比较关注,朋友们都想要知道一些“pytorch卷积神经网络mnist”的相关资讯。那么小编在网上网罗了一些关于“pytorch卷积神经网络mnist””的相关内容,希望我们能喜欢,兄弟们快快来了解一下吧!

pytorch——人工智能的开源深度学习框架pytorch深度学习框架之tensor张量计算机视觉的基石——读懂 CNN卷积神经网络

本期文章的主要内容:

1、CNN卷积神经网络

2、torchvision.datasets

3、MINIST数据集

4、神经网络的训练

5、pytorch训练模型的保存

CNN

PyTorch 提供了许多预加载的数据集(例如 FashionMNIST),所有数据集都是torch.utils.data.Dataset 的子类,它们具有__getitem__和__len__实现的方法。因此,它们都可以传递给torch.utils.data.DataLoader 也可以使用torch.multiprocessing并行加载多个样本的数据 。例如:

以下是如何从 TorchVision加载Fashion-MNIST数据集的示例。Fashion-MNIST由 60,000 个训练示例和 10,000 个测试示例组成。每个示例都包含一个 28×28 灰度图像和来自 10 个类别之一的相关标签。

MINIST数据

MINIST的数据分为2个部分:55000份训练数据(mnist.train)和10000份测试数据(mnist.test)。这个划分有重要的象征意义,他展示了在机器学习中如何使用数据。在训练的过程中,我们必须单独保留一份没有用于机器训练的数据作为验证的数据,这才能确保训练的结果的可行性。

前面已经提到,每一份MINIST数据都由图片以及标签组成。我们将图片命名为“x”,将标记数字的标签命名为“y”。训练数据集和测试数据集都是同样的结构,例如:训练的图片名为 mnist.train.images 而训练的标签名为 mnist.train.labels。

每一个图片均为28×28像素,我们可以将其理解为一个二维数组的结构:

MNIST

我们使用以下参数加载MNIST 数据集:

root ( string ) – 数据集所在MNIST/processed/training.ptMNIST/processed/test.pt存在的根目录。train ( bool , optional ) – 如果为 True,则从 中创建数据集training.pt,否则从test.pt.download ( bool , optional ) – 如果为 true,则从 Internet 下载数据集并将其放在根目录中。如果数据集已经下载,则不会再次下载。transform ( callable , optional ) – 一个函数/转换,它接收一个 PIL 图像并返回一个转换后的版本。例如,transforms.RandomCroptarget_transform ( callable , optional ) – 一个接收目标并对其进行转换的函数/转换。

torchvision.datasets.MNIST( root: str ,                           train: bool = True ,                            transform: Optional[Callable] = None ,   target_transform: Optional[Callable] = None ,     download: bool = False )

所有数据集都有几乎相似的 API。它们都有两个共同的参数: transformtarget_transform,本期文章,我们基于MNIST数据集来写一个简单的神经网络,并进行神经网络的训练

下载数据集 torchvision.datasets

import torchimport torch.nn as nnimport torch.utils.data as Dataimport torchvision  # 数据库模块import matplotlib.pyplot as plt# torch.manual_seed(1)  # reproducibleEPOCH = 20  # 训练整批数据次数,训练次数越多,精度越高BATCH_SIZE = 50  # 每次训练的数据集个数LR = 0.001  # 学习效率DOWNLOAD_MNIST = False  # 如果你已经下载好了mnist数据就设置 False# Mnist 手写数字 训练集train_data = torchvision.datasets.MNIST(    root='./data/',  # 保存或者提取位置    train=True,  # this is training data    transform=torchvision.transforms.ToTensor(),  # 转换 PIL.Image or numpy.ndarray 成tensor    # torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间    download=DOWNLOAD_MNIST,  # 没下载就会自动下载数据集,当等于true)# Mnist 手写数字 测试集test_data = torchvision.datasets.MNIST(	root='./mnist/',	train=False, # this is training data)

通过以上代码,我们便在工程目录下的data文件夹下下载了MNIST的全部数据集,torchvision.datasets是pytorch为了方便研发者,进行了绝大部分的数据库的集合,通过torchvision.datasets可以很方便地下载使用其包含的数据集,其torchvision.datasets下面主要包含如下数据集,其他方面的数据集可以自行下载尝试

torchvision.datasetsCaltechCelebACIFARCityscapesCOCOEMNISTFakeDataFashion-MNISTFlickrHMDB51ImageNetKinetics-400KITTIKMNISTLSUNMNISTOmniglotPhotoTourPlaces365QMNISTSBDSBUSEMEIONSTL10SVHNUCF101USPSVOCWIDERFace
CNN卷积神经网络搭建

CNN

# 批训练 50samples, 1 channel, 28x28 (50, 1, 28, 28)train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)# 每一步 loader 释放50个数据用来学习# 为了演示, 我们测试时提取2000个数据先# shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1)test_x = torch.unsqueeze(test_data.data, dim=1).type(torch.FloatTensor)[:2000] / 255.  test_y = test_data.targets[:2000]#test_x = test_x.cuda() # 若有cuda环境,取消注释#test_y = test_y.cuda() # 若有cuda环境,取消注释# 定义神经网络class CNN(nn.Module):    def __init__(self):        super(CNN, self).__init__()        self.conv1 = nn.Sequential(  # input shape (1, 28, 28)            nn.Conv2d(                in_channels=1,  # 输入通道数                out_channels=16,  # 输出通道数                kernel_size=5,  # 卷积核大小                stride=1,  #卷积部数                padding=2,  # 如果想要 con2d 出来的图片长宽没有变化,                             # padding=(kernel_size-1)/2 当 stride=1            ),  # output shape (16, 28, 28)            nn.ReLU(),  # activation            nn.MaxPool2d(kernel_size=2),  # 在 2x2 空间里向下采样, output shape (16, 14, 14)        )        self.conv2 = nn.Sequential(  # input shape (16, 14, 14)            nn.Conv2d(16, 32, 5, 1, 2),  # output shape (32, 14, 14)            nn.ReLU(),  # activation            nn.MaxPool2d(2),  # output shape (32, 7, 7)        )        self.out = nn.Linear(32 * 7 * 7, 10)  # 全连接层,0-9一共10个类# 前向反馈    def forward(self, x):        x = self.conv1(x)        x = self.conv2(x)        x = x.view(x.size(0), -1)  # 展平多维的卷积图成 (batch_size, 32 * 7 * 7)        output = self.out(x)        return output

我们使用Data.DataLoader来加载我们下载好的MNIST数据集,并分开训练集与测试集

接下来我们建立一个CNN卷积神经网络:

第一层,我们输入minist的数据集,minist的数据图片是一维 28*28的图片,所以第一层的输入(1,28,28),高度为1,设置输出16通道,使用5*5的卷积核对图片进行卷积运算,每步移动一格,为了避免图片尺寸变化,设置pading为2,则经过第一层卷积就输出(16,28,28)数据格式

再经过relu与maxpooling (使用2*2卷积核)数据输出(16,14,14)

第二层卷积层是简化写法nn.Conv2d(16, 32, 5, 1, 2)的第一个参数为输入通道数in_channels=16,其第二个参数是输出通道数out_channels=32, # n_filters(输出通道数),第三个参数为卷积核大小,第四个参数为卷积步数,最后一个为pading,此参数为保证输入输出图片的尺寸大小一致

        self.conv2 = nn.Sequential(  # input shape (16, 14, 14)            nn.Conv2d(16, 32, 5, 1, 2),  # output shape (32, 14, 14)            nn.ReLU(),  # activation            nn.MaxPool2d(2),  # output shape (32, 7, 7)        )

全连接层,最后使用nn.linear()全连接层进行数据的全连接数据结构(32*7*7,10)以上便是整个卷积神经网络的结构,

大致为:input-卷积-Relu-pooling-卷积-Relu-pooling-linear-output

卷积神经网络建完后,使用forward()前向传播神经网络进行输入图片的训练

通过以上的神经网络的搭建,我们便建立一个神经网络,此神经网络类似MINIST的双隐藏层结构

神经网络的训练

神经网络搭建完成后,我们便可以进行神经网络的训练

cnn = CNN() # 创建CNN# cnn = cnn.cuda() # 若有cuda环境,取消注释optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)  loss_func = nn.CrossEntropyLoss() for epoch in range(EPOCH):    for step, (b_x, b_y) in enumerate(train_loader):  # 每一步 loader 释放50个数据用来学习        #b_x = b_x.cuda() # 若有cuda环境,取消注释        #b_y = b_y.cuda() # 若有cuda环境,取消注释        output = cnn(b_x)  # 输入一张图片进行神经网络训练        loss = loss_func(output, b_y)  # 计算神经网络的预测值与实际的误差        optimizer.zero_grad()  #将所有优化的torch.Tensors的梯度设置为零        loss.backward()  # 反向传播的梯度计算        optimizer.step()  # 执行单个优化步骤        if step % 50 == 0: # 我们每50步来查看一下神经网络训练的结果            test_output = cnn(test_x)            pred_y = torch.max(test_output, 1)[1].data.squeeze()            # 若有cuda环境,使用84行,注释82行            # pred_y = torch.max(test_output, 1)[1].cuda().data.squeeze()            accuracy = float((pred_y == test_y).sum()) / float(test_y.size(0))            print('Epoch: ', epoch, '| train loss: %.4f' % loss.data,             	'| test accuracy: %.2f' % accuracy)

首先我们使用CNN()函数进行神经网络的初始化,并建立一个神经网络模型,并利用optim.Adam优化函数建立一个optimizer神经网络优化器,torch.optim是一个实现各种优化算法的包。大部分常用的方法都已经支持,接口也足够通用,以后也可以轻松集成更复杂的方法。

常用的优化器主要有:OptimizerGradientDescentOptimizerAdadeltaOptimizerAdagradOptimizerAdagradDAOptimizerMomentumOptimizerAdamOptimizerFtrlOptimizerProximalGradientDescentOptimizerProximalAdagradOptimizerRMSPropOptimizer

然后建立一个损失函数,我们神经网络的目的就是使用损失函数使神经网络的训练loss越来越小。然后进行神经网络的训练,我们每50步打印一下神经网络的训练效果

测试神经网络的结果与保存神经网络

# test 神经网络test_output = cnn(test_x[:10])pred_y = torch.max(test_output, 1)[1].data.squeeze()# 若有cuda环境,使用92行,注释90行#pred_y = torch.max(test_output, 1)[1].cuda().data.squeeze()print(pred_y, 'prediction number')print(test_y[:10], 'real number')# save CNN# 仅保存CNN参数,速度较快torch.save(cnn.state_dict(), './model/CNN_NO1.pk')# 保存CNN整个结构#torch.save(cnn(), './model/CNN.pkl')

我们提取前10个MNIST的数据,并进行神经网络的预测,此时我们可以打印出来神经网络的预测值与实际值,最后并保存神经网络的模型,此模型我们可以直接使用来进行手写数字的识别

从训练结果可以看出,只训练了24*50个循环,神经网络的精度已经达到0.97

Epoch:  0 | train loss: 2.3018 | test accuracy: 0.18Epoch:  0 | train loss: 0.5784 | test accuracy: 0.82Epoch:  0 | train loss: 0.3423 | test accuracy: 0.89Epoch:  0 | train loss: 0.1502 | test accuracy: 0.92Epoch:  0 | train loss: 0.2063 | test accuracy: 0.93Epoch:  0 | train loss: 0.1348 | test accuracy: 0.92Epoch:  0 | train loss: 0.1209 | test accuracy: 0.95Epoch:  0 | train loss: 0.0577 | test accuracy: 0.95Epoch:  0 | train loss: 0.1297 | test accuracy: 0.95Epoch:  0 | train loss: 0.0237 | test accuracy: 0.96Epoch:  0 | train loss: 0.1275 | test accuracy: 0.97Epoch:  0 | train loss: 0.1364 | test accuracy: 0.97Epoch:  0 | train loss: 0.0728 | test accuracy: 0.97Epoch:  0 | train loss: 0.0752 | test accuracy: 0.98Epoch:  0 | train loss: 0.1444 | test accuracy: 0.97Epoch:  0 | train loss: 0.0597 | test accuracy: 0.97Epoch:  0 | train loss: 0.1162 | test accuracy: 0.97Epoch:  0 | train loss: 0.0260 | test accuracy: 0.97Epoch:  0 | train loss: 0.0830 | test accuracy: 0.97Epoch:  0 | train loss: 0.1918 | test accuracy: 0.97Epoch:  0 | train loss: 0.2217 | test accuracy: 0.97Epoch:  0 | train loss: 0.0767 | test accuracy: 0.97Epoch:  0 | train loss: 0.2015 | test accuracy: 0.97Epoch:  0 | train loss: 0.1214 | test accuracy: 0.97tensor([7, 2, 1, 0, 4, 1, 4, 9, 5, 9]) prediction numbertensor([7, 2, 1, 0, 4, 1, 4, 9, 5, 9]) real number

最后打印出来的前10个预测模型,完全一致

ok,本期我们分享了神经网络的搭建,并利用MNIST的数据集进行了神经网络的训练,并进行了神经网络的预测,下期文章我们利用训练好的模型进行神经网络的识别。

标签: #pytorch卷积神经网络mnist