Aprendizaje profundo: reconocimiento de dígitos escritos a mano por el MNIST mediante una red neuronal convolucional CNN

introducción

Este proyecto construye una red neuronal de aprendizaje profundo basada en pytorch. La red incluye una capa convolucional, una capa de agrupación y una capa totalmente conectada. A través de esta red, se realiza el reconocimiento de números escritos a mano en el conjunto de datos MINST. A través del código de este proyecto, los números escritos a mano se pueden entender en principio.Todo el proceso de reconocimiento, incluida la retropropagación, el descenso de gradiente, etc.

1 Introducción a las Redes Neuronales Convolucionales

1.1 ¿Qué es una red neuronal convolucional?

Una red neuronal convolucional es una red neuronal de alimentación hacia adelante de múltiples capas. Funcionalmente, se puede dividir en dos etapas, etapa de extracción de características y etapa de reconocimiento de clasificación.

La etapa de extracción de características puede extraer automáticamente las características de los datos de entrada como base para la clasificación. Se compone de múltiples capas de características apiladas, y cada capa de características se compone de una capa convolucional y una capa de agrupación. La capa de características en el frente captura la información de los detalles locales en la imagen, mientras que la capa de características en la parte posterior puede capturar la información abstracta y de nivel superior en la imagen.

1.1.1 Núcleo de convolución

En una capa convolucional de una red neuronal convolucional, una neurona solo está conectada a algunas neuronas en capas vecinas. En una capa convolucional de CNN, generalmente contiene varios mapas de características (featureMap), cada mapa de características está compuesto por algunas neuronas dispuestas en un rectángulo, y las neuronas del mismo mapa de características comparten pesos, y los pesos compartidos aquí son volúmenes. . El kernel de convolución generalmente se inicializa en forma de una matriz decimal aleatoria, y el kernel de convolución aprenderá a obtener pesos razonables durante el proceso de entrenamiento de la red. El beneficio directo de compartir pesos (núcleos de convolución) es reducir las conexiones entre las capas de la red y al mismo tiempo reducir el riesgo de sobreajuste.

1.1.2 Campo receptivo

Definición: En la red neuronal convolucional, los puntos de píxel en el mapa de características (mapa de características) generado por cada capa de la red neuronal convolucional asignan el tamaño del área en la imagen de entrada. En una estructura CNN típica, el valor de cada nodo de salida de la capa FC depende de todas las entradas de la capa FC, mientras que el valor de cada nodo de salida de la capa CONV solo depende de un área de la entrada de la CONV La capa y otros valores de entrada fuera de esta área no afectarán el valor de salida, y esta área es el campo receptivo. La siguiente figura es un diagrama esquemático del campo receptivo:

 

Cuando usamos núcleos de convolución con diferentes tamaños, la mayor diferencia es que el tamaño del campo receptivo es diferente, por lo que a menudo usamos varias capas de núcleos de convolución pequeños para reemplazar una capa de núcleos de convolución grandes y reducir los parámetros manteniendo los campos receptivos. el mismo volumen y cómputo. Por ejemplo, es muy común usar dos capas de núcleos de convolución de 3*3 para reemplazar una capa de núcleos de convolución de 5*5.

 1.3 Estandarización (normalización por lotes)

Antes de la introducción de BN, el entrenamiento del modelo anterior tenía algunos problemas sistemáticos, lo que provocó que muchos algoritmos convergieran muy lentamente, o incluso que no funcionaran en absoluto, especialmente cuando se usaba la función de activación sigmoidea. En el aprendizaje automático, generalmente estandarizamos o normalizamos las características de entrada, porque las dimensiones de cada dimensión de los datos de entrada directa pueden ser diferentes y los valores pueden variar mucho, lo que hace que el modelo no pueda aprender bien de cada característica. . Cuando el valor de salida de la capa anterior es demasiado grande o demasiado pequeño, caerá en la región de saturación cuando pase por la función de activación sigmoidea, y la retropropagación tendrá el problema de la desaparición del gradiente.
Normalización por lotes : estandarice un pequeño lote de datos (lote). Ajuste los datos a una distribución con una media de 0 y una desviación estándar de 1.

La capa de normalización por lotes generalmente se agrega entre cada capa de red neuronal y la capa de activación, unifica y ajusta la salida de distribución de datos de la capa de red neuronal y la convierte en una distribución normal estándar con una media de 0 y una varianza de 1, que resuelve el problema de la desaparición del gradiente en la red neuronal.El problema de hacer la salida en el área no saturada de la capa de activación logra el efecto de acelerar la convergencia.

1.1.4 Capa Pooling (Pooling)

La agrupación se utiliza para reducir la dimensión del mapa de características (mapa de características) en la red neuronal. En las redes neuronales convolucionales, la operación de agrupación suele ir seguida de la operación de convolución para reducir el tamaño espacial del mapa de características. La idea básica de la operación de agrupación es dividir el mapa de características en varias subregiones (generalmente rectangulares) y realizar un resumen estadístico para cada subregión. La agrupación generalmente tiene dos formas: agrupación media y agrupación máxima. La agrupación puede verse como un proceso de convolución especial. La convolución y la agrupación simplifican en gran medida la complejidad del modelo y reducen los parámetros del modelo.

  • La agrupación máxima puede extraer la textura de la imagen
  • La agrupación media conserva las características de fondo

 

1.2 Proceso de cálculo de la convolución

Supongamos que ingresamos una imagen de 5*5*1, y el 3*3*1 en el medio es un núcleo de convolución que definimos (en términos simples, puede considerarse como un operador de matriz), a través de la imagen de entrada original y la convolución. El resultado de la parte verde se puede obtener mediante la operación central ¿Qué tipo de operación? En realidad es muy simple. Miramos la parte oscura en la imagen de la izquierda. El número en el medio es el píxel de la imagen, y el número en la esquina inferior derecha es el número de nuestro kernel de convolución. Simplemente multiplique y agregue el números correspondientes para obtener el resultado. Por ejemplo, '3*0+1*1+2*2+2*2+0*2+0*0+2*0+0*1+0*2=9' en la imagen

El proceso de cálculo es el siguiente:

 Las tres matrices de entrada en el extremo izquierdo de la figura son nuestra entrada equivalente d=3 cuando hay tres mapas de canales. Cada mapa de canales tiene un núcleo de convolución que pertenece a su propio canal. Podemos ver que solo hay dos salidas (salida) Un mapa de características significa que configuramos la salida d=2, y hay varias capas de núcleos de convolución con varios canales de salida (por ejemplo, hay FilterW0 y FilterW1 en la figura), lo que significa que el número de nuestros núcleos de convolución es el número de entrada d El número multiplicado por el número de salida d (en la figura es 2*3=6), donde el cálculo de cada capa del mapa de canales es el mismo que el cálculo de la capa mencionada anteriormente, y luego agregue el salida de cada salida de canal Ese es el número de salida verde.

Tamaño de paso: el tamaño de cada movimiento del kernel de convolución

Cálculo del tamaño de la característica de salida : después de comprender todo el proceso de cálculo de convolución en la red neuronal, se puede calcular el tamaño del mapa de características de salida. Como se muestra en la siguiente figura, el tamaño de la característica de salida de una imagen de 5×5 es 3×3 después del cálculo de convolución con un kernel de convolución de tamaño 3×3.

cero relleno

Cuando el tamaño del kernel de convolución es mayor que 1, el tamaño del mapa de características de salida será más pequeño que el tamaño de la imagen de entrada. Después de varias circunvoluciones, el tamaño de la imagen de salida seguirá disminuyendo. Para evitar que el tamaño de la imagen se reduzca después de la convolución, el relleno generalmente se realiza en la periferia de la imagen, como se muestra en la figura a continuación.

Relleno con todos los ceros (relleno): para mantener el tamaño de la imagen de salida consistente con la imagen de entrada, a menudo se realiza un relleno con todos los ceros alrededor de la imagen de entrada, como se muestra a continuación, si se llena con 0 alrededor de la imagen de entrada de 5 × 5, la salida el tamaño de la función también es de 5 × 5.

 

Cuando padding=1 y paadding=2, como se muestra en la siguiente figura:

2 Uso de CNN para realizar el reconocimiento de dígitos escritos a mano del MNIST

El proceso de reconocimiento de imagen de la máquina: el reconocimiento de imagen de la máquina no reconoce completamente una imagen compleja a la vez, sino que divide una imagen completa en muchas partes pequeñas, extrae las características de cada parte pequeña y luego Las características de estas partes pequeñas se suman para completar el reconocimiento de la máquina de la imagen completa.

2.1 Introducción a los datos MNIST

El conjunto de datos MNIST es una gran base de datos de dígitos escritos a mano recopilados por el Instituto Nacional de Estándares y Tecnología, que incluye un conjunto de capacitación de 60 000 ejemplos y un conjunto de prueba de 10 000 ejemplos. El tamaño de la imagen es 28*28. Los datos muestreados se muestran de la siguiente manera:

2.2 Implementación de código basada en pytorch

import torch
import torch.nn as nn
import torchvision.datasets as dataset
import torchvision.transforms as transforms
import torch.utils.data as data_utils
import matplotlib.pyplot as plt
import numpy as np


#获取数据集
train_data=dataset.MNIST(root="./data",
                         train=True,
                         transform=transforms.ToTensor(),
                         download=True
                         )
test_data=dataset.MNIST(root="./data",
                         train=False,
                         transform=transforms.ToTensor(),
                         download=False
                         )
train_loader=data_utils.DataLoader(dataset=train_data, batch_size=64, shuffle=True)
test_loader=data_utils.DataLoader(dataset=test_data, batch_size=64, shuffle=True)

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

#创建网络
class Net(torch.nn.Module):
   def __init__(self):
        super().__init__()
        self.conv=nn.Conv2d(1, 32, kernel_size=5, padding=2)
        self.bat2d=nn.BatchNorm2d(32)
        self.relu=nn.ReLU()
        self.pool=nn.MaxPool2d(2)
        self.linear=nn.Linear(14 * 14 * 32, 70)
        self.tanh=nn.Tanh()
        self.linear1=nn.Linear(70,30)
        self.linear2=nn.Linear(30, 10)
   def forward(self,x):
        y=self.conv(x)
        y=self.bat2d(y)
        y=self.relu(y)
        y=self.pool(y)
        y=y.view(y.size()[0],-1)
        y=self.linear(y)
        y=self.tanh(y)
        y=self.linear1(y)
        y=self.tanh(y)
        y=self.linear2(y)
        return y
cnn=Net()
cnn = cnn.to(device)

#损失函数
los=torch.nn.CrossEntropyLoss()

#优化函数
optime=torch.optim.Adam(cnn.parameters(), lr=0.001)

#训练模型
accuracy_rate = [0]
num_epochs = 10
for epo in range(num_epochs):
    for i, (images,lab) in enumerate(train_loader):
        images=images.to(device)
        lab=lab.to(device)
        out = cnn(images)
        loss=los(out,lab)
        optime.zero_grad()
        loss.backward()
        optime.step()
    print("epo:{},i:{},loss:{}".format(epo+1,i,loss))

    #测试模型
    loss_test=0
    accuracy=0
    with torch.no_grad():
        for j, (images_test,lab_test) in enumerate(test_loader):
            images_test = images_test.to(device)
            lab_test=lab_test.to(device)
            out1 = cnn(images_test)
            loss_test+=los(out1,lab_test)
            loss_test=loss_test/(len(test_data)//100)
            _,p=out1.max(1)
            accuracy += (p==lab_test).sum().item()

        accuracy=accuracy/len(test_data)
        accuracy_rate.append(accuracy)
        print("loss_test:{},accuracy:{}".format(loss_test,accuracy))


accuracy_rate = np.array(accuracy_rate)
times = np.linspace(0, num_epochs, num_epochs+1)
plt.xlabel('times')
plt.ylabel('accuracy rate')
plt.plot(times, accuracy_rate)
plt.show()

resultado de la operación:

epo:1,i:937,loss:0.2277517020702362
loss_test:0.0017883364344015718,accuracy:0.9729
epo:2,i:937,loss:0.01490325853228569
loss_test:9.064914047485217e-05,accuracy:0.9773
epo:3,i:937,loss:0.0903361514210701
loss_test:0.0003304268466308713,accuracy:0.9791
epo:4,i:937,loss:0.003910894505679607
loss_test:0.00019427068764343858,accuracy:0.9845
epo:5,i:937,loss:0.011963552795350552
loss_test:3.232352901250124e-05,accuracy:0.983
epo:6,i:937,loss:0.04549657553434372
loss_test:0.0001462855434510857,accuracy:0.9859
epo:7,i:937,loss:0.02365218661725521
loss_test:3.670657861221116e-06,accuracy:0.9867
epo:8,i:937,loss:0.00040980291669256985
loss_test:1.4913265658833552e-05,accuracy:0.9872
epo:9,i:937,loss:0.024399513378739357
loss_test:7.590289897052571e-05,accuracy:0.9865
epo:10,i:937,loss:0.0012365489965304732
loss_test:0.00014759502664674073,accuracy:0.9869

 

 

3 Resumen

Este artículo presenta los conceptos clave en la red neuronal convolucional, incluido el kernel de convolución, la agrupación, la estandarización, el campo receptivo, etc., y en base al conjunto de datos MNIST, se construye un modelo de reconocimiento de red neuronal convolucional. Después de 10 épocas de entrenamiento, la tasa de precisión alcanza 98%, demostrando plenamente el papel de las redes neuronales convolucionales en el reconocimiento de imágenes.

Supongo que te gusta

Origin blog.csdn.net/lsb2002/article/details/132124598
Recomendado
Clasificación