PaddlePaddle2.0构建LeNet-5模型进行MNIST手写数字分类

PaddlePaddle2.0构建LeNet-5模型进行MNIST手写数字分类

一、完整代码

import paddle
import paddle.nn.functional as F
from paddle.vision.transforms import Compose, Normalize

transform = Compose([Normalize(mean=[127.5],
                               std=[127.5],
                               data_format='CHW')])
#导入MNIST数据
train_dataset=paddle.vision.datasets.MNIST(mode="train", transform=transform)
val_dataset=paddle.vision.datasets.MNIST(mode="test", transform=transform)
#定义模型
class LeNetModel(paddle.nn.Layer):
    def __init__(self):
        super(LeNetModel, self).__init__()
        # 创建卷积和池化层块,每个卷积层后面接着2x2的池化层
        #卷积层L1
        self.conv1 = paddle.nn.Conv2D(in_channels=1,
                                      out_channels=6,
                                      kernel_size=5,
                                      stride=1)
        #池化层L2
        self.pool1 = paddle.nn.MaxPool2D(kernel_size=2,
                                         stride=2)
        #卷积层L3
        self.conv2 = paddle.nn.Conv2D(in_channels=6,
                                      out_channels=16,
                                      kernel_size=5,
                                      stride=1)
        #池化层L4
        self.pool2 = paddle.nn.MaxPool2D(kernel_size=2,
                                         stride=2)
        #线性层L5
        self.fc1=paddle.nn.Linear(256,120)
        #线性层L6
        self.fc2=paddle.nn.Linear(120,84)
        #线性层L7
        self.fc3=paddle.nn.Linear(84,10)

    #正向传播过程
    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.pool1(x)
        x = F.relu(x)
        x = self.conv2(x)
        x = self.pool2(x)
        x = paddle.flatten(x, start_axis=1,stop_axis=-1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = F.relu(x)
        out = self.fc3(x)
        return out

model=paddle.Model(LeNetModel())

model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
              paddle.nn.CrossEntropyLoss(),
              paddle.metric.Accuracy())

model.fit(train_dataset,
          epochs=5,
          batch_size=64,
          save_dir='my_model',
          verbose=1)
          
#获取测试集的第一个图片
val_data0, val_label_0 = val_dataset[0][0],val_dataset[0][1]
val_data0 = val_data0.reshape([28,28])
plt.figure(figsize=(2,2))
#展示测试集中的第一个图片
# print(plt.imshow(test_data0, cmap=plt.cm.binary))
plt.imshow(val_data0, cmap=plt.cm.binary)
print('val_data0 的标签为: ' + str(val_label_0))
#模型预测
result = model.predict(val_dataset, batch_size=1)
#打印模型预测的结果
print('val_data0 预测的数值为:%d' % np.argsort(result[0][0])[0][-1])

测试结果为:
PaddlePaddle2.0构建LeNet-5模型进行MNIST手写数字分类_第1张图片

二、LeNet-5结构

PaddlePaddle2.0构建LeNet-5模型进行MNIST手写数字分类_第2张图片
注:手写数字数据集MINST的驶入图片大小为28*28。
数据集中图片的可视化:

import matplotlib.pyplot as plt
#看看数据集中的图片是什么样子的
train_data0, train_label_0 = train_dataset[0][0],train_dataset[0][1]
train_data0 = train_data0.reshape([28,28])
plt.figure(figsize=(2,2))
plt.imshow(train_data0)
print('train_data0 的标签为: ' + str(train_label_0))

PaddlePaddle2.0构建LeNet-5模型进行MNIST手写数字分类_第3张图片

三、详细程序解释

import paddle
import paddle.nn.functional as F
from paddle.vision.transforms import Compose, Normalize

paddle 目录下包含tensor、device、framework相关API以及某些高层API。
paddle.nn 目录下包含飞桨框架支持的神经网络层和相关函数的相关API。
paddle.vision 目录是飞桨在视觉领域的高层API,其中transforms中的:
Compose将用于数据集预处理的接口以列表的方式进行组合;
Normalize用于图像归一化处理,支持两种方式:

  1. 用统一的均值和标准差值对图像的每个通道进行归一化处理;
  2. 对每个通道指定不同的均值和标准差值进行归一化处理。
    计算过程为:
output[channel] = (input[channel] - mean[channel]) / std[channel]

结果被限制在[-1,1]之间,将归一化后的图片像素数值可视化,可见(部分):
PaddlePaddle2.0构建LeNet-5模型进行MNIST手写数字分类_第4张图片

#导入MNIST数据
train_dataset=paddle.vision.datasets.MNIST(mode="train", transform=transform)
val_dataset=paddle.vision.datasets.MNIST(mode="test", transform=transform)

获取MINST数据分配给训练和测试两部分,并且将数据归一化。

self.conv1 = paddle.nn.Conv2D(in_channels=1,out_channels=6,kernel_size=5,stride=1)

表示输入是1组,输出是6组(也就是6组卷积核),卷积核的大小是5*5,每次移动的步长为1。

self.pool1 = paddle.nn.MaxPool2D(kernel_size=2,stride=2)

表示按照2*2的大小进行最大值池化,步长是2,也就是每次最大值池化没有重叠部分。

self.fc1=paddle.nn.Linear(256,120)

全连接层,输入是被展开成一列的16*(4*4),长度为256的tensor,输出为长度为120的tensor。
官方2.0版本的API后面是不接激活函数的,这样使用什么样的激活函数就比较灵活了,自己在方法中引用。

x = F.relu(x)

激活函数,用于增加网络的非线性。

model=paddle.Model(LeNetModel())

Model 对象是一个具备训练、测试、推理的神经网络。该对象同时支持静态图和动态图模式,飞桨框架默认为动态图模式,通过 paddle.enable_static() 来切换到静态图模式。需要注意的是,需要在实例化 Model 对象之前完成切换。

model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
              paddle.nn.CrossEntropyLoss(),
              paddle.metric.Accuracy())

在正式的训练之前定义优化器,损失函数,精确度度量形式。

model.fit(train_dataset,
          epochs=5,
          batch_size=64,
          save_dir='my_model',
          verbose=1)

verbose (int) 可视化的模型,必须为0,1,2。当设定为0时,不打印日志,设定为1时,使用进度条的方式打印日志,设定为2时,一行一行地打印日志。默认值:2。save_dir=‘my_model’,讲训练好的模型保存下来,方便之后的预测过程使用。

你可能感兴趣的:(一点一滴深度学习,深度学习,神经网络,python)