Reconocimiento de dígitos escritos a mano MNIST: la primera red neuronal convolucional de grado comercial de Lenet-5

        La razón por la que el conjunto de datos MNIST se ha convertido en un conjunto de datos introductorio para el aprendizaje profundo es por el nacimiento de la red LeNet-5. El efecto de reconocimiento de dígitos escritos a mano de esta red puede alcanzar el nivel comercial. Es la primera red neuronal profunda que realmente ha alcanzado un uso comercial y es ampliamente utilizado para el reconocimiento de cheques escritos a mano.

        Las redes neuronales convolucionales se utilizan principalmente en tareas de clasificación de imágenes. Utiliza una estructura en capas para extraer características de las imágenes y se compone de una serie de capas de red apiladas, como capas convolucionales, capas de agrupación, capas de activación, etc.

En este caso, Lenet-5 se utilizará para realizar el reconocimiento de dígitos escritos a mano.

1. Cargue y procese el conjunto de datos

        Dado que la red neuronal convolucional requiere más memoria de video durante el entrenamiento, es imposible cargar las 60 000 muestras del reconocimiento de dígitos completo en el entrenamiento al mismo tiempo, por lo que es necesario cargar el conjunto de entrenamiento en lotes para el entrenamiento.

import os
import sys
import moxing as mox

datasets_dir = '../datasets'
if not os.path.exists(datasets_dir):
    os.makedirs(datasets_dir)
    
if not os.path.exists(os.path.join(datasets_dir, 'MNIST_Data.zip')):
    mox.file.copy('obs://modelarts-labs-bj4-v2/course/hwc_edu/python_module_framework/datasets/mindspore_data/MNIST_Data.zip', 
                  os.path.join(datasets_dir, 'MNIST_Data.zip'))
    os.system('cd %s; unzip MNIST_Data.zip' % (datasets_dir))
    
sys.path.insert(0, os.path.join(os.getcwd(), '../datasets/MNIST_Data'))
from load_data_all import load_data_all
from process_dataset import process_dataset

mnist_ds_train, mnist_ds_test, train_len, test_len = load_data_all(datasets_dir)  # 加载数据集
mnist_ds_train = process_dataset(mnist_ds_train, batch_size= 32, resize= 32)  # 处理训练集,分批加载
mnist_ds_test = process_dataset(mnist_ds_test, batch_size= 32, resize= 32)  # 处理测试集,分批加载

Tamaño del conjunto de entrenamiento: 60000, tamaño del conjunto de prueba: 10000 

 

2. Construcción de la red LeNet-5 y función de evaluación

        LeNet-5 tiene una red de 5 capas, que son la capa convolucional 1, la capa convolucional 2, la capa 1 completamente conectada, la capa 2 completamente conectada y la capa 3 completamente conectada. La estructura de la red se muestra en la siguiente figura: 

import mindspore
import mindspore.nn as nn
import mindspore.ops as ops
from mindspore.common.initializer import Normal

class Network(nn.Cell):
    """Lenet network structure."""
    # define the operator required
    def __init__(self, num_class=10, num_channel=1):
        super(Network, self).__init__()
        self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')  
        self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')  
        self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))
        self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02))
        self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02))
        self.relu = nn.ReLU()
        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
        self.flatten = nn.Flatten()  # 输入到全连接层之前需要将16个5*5大小的特性矩阵拉成一个一维向量

    # use the preceding operators to construct networks
    def construct(self, x):
        x = self.max_pool2d(self.relu(self.conv1(x)))
        x = self.max_pool2d(self.relu(self.conv2(x)))
        x = self.flatten(x)
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    
def evaluate(pred_y, true_y): 
    pred_labels = ops.Argmax(output_type=mindspore.int32)(pred_y)
    correct_num = (pred_labels == true_y).asnumpy().sum().item()
    return correct_num

3. Definir la función de pérdida de entropía cruzada y el optimizador

# 损失函数
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')

# 创建网络
network = Network(28*28)  
lr = 0.01
momentum = 0.9

# 优化器
net_opt = nn.Momentum(network.trainable_params(), lr, momentum)

4. Implementar la función de formación

def train(network, mnist_ds_train, max_epochs= 50):
    net = WithLossCell(network, net_loss)
    net = TrainOneStepCell(net, net_opt)
    network.set_train()
    for epoch in range(1, max_epochs + 1):
        train_correct_num = 0.0
        test_correct_num = 0.0
        for inputs_train in mnist_ds_train:
            output = net(*inputs_train)
            train_x = inputs_train[0]
            train_y = inputs_train[1]
            pred_y_train = network.construct(train_x)  # 前向传播
            train_correct_num += evaluate(pred_y_train, train_y)
        train_acc = float(train_correct_num) / train_len

        for inputs_test in mnist_ds_test:
            test_x = inputs_test[0]
            test_y = inputs_test[1]
            pred_y_test = network.construct(test_x)
            test_correct_num += evaluate(pred_y_test, test_y)
        test_acc = float(test_correct_num) / test_len
        if (epoch == 1) or (epoch % 10 == 0):
            print("epoch: {0}/{1}, train_losses: {2:.4f}, tain_acc: {3:.4f}, test_acc: {4:.4f}".format(epoch, max_epochs, output.asnumpy(), train_acc, test_acc, cflush=True))

 5. Configurar la información de ejecución

from mindspore import context
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")  # device_target 可选 CPU/GPU, 当选择GPU时mindspore规格也需要切换到GPU

6. Empieza a entrenar

El entrenamiento para 50 épocas toma alrededor de 11 minutos

import time
from mindspore.nn import WithLossCell, TrainOneStepCell

max_epochs = 50
start_time = time.time()
print("*"*10 + "开始训练" + "*"*10)
train(network, mnist_ds_train, max_epochs= max_epochs)
print("*"*10 + "训练完成" + "*"*10)
cost_time = round(time.time() - start_time, 1)
print("训练总耗时: %.1f s" % cost_time)
**********开始训练*********** 

época: 1/50, train_losses: 2.3162, tain_acc: 0.1095, test_acc: 0.1027 

época: 10/50, train_losses: 0.0008, tain_acc : 0.9942, test_acc: 0.9846 

época: 20/50, train_losses: 0.0001, tain_acc: 0.9984, test_acc: 0.9832 época: 30/50, train_losses: 0.1701, tain_acc: 0.9996, test_acc 

: 0.98 39 época: 

40/50, train_losses: 0.0000, 
tain_acc : 1.0000, test_acc: 0.9861 

época: 50/50, train_losses: 0.0000, tain_acc: 1.0000, test_acc: 

0.9864 
: 686.4 s 

Se puede ver que al usar la red LeNet-5 para entrenar durante 11 minutos y después de 50 épocas, la tasa de precisión de la prueba alcanza el 98,6 %. 

Supongo que te gusta

Origin blog.csdn.net/m0_54776464/article/details/126073321
Recomendado
Clasificación