Red neuronal convolucional (LENET)

Parte de las notas de estudio de "Practica Pytorch de aprendizaje profundo" es solo para tu propia revisión.

Red neuronal convolucional (LENET)

Realización del perceptrón multicapa desde cero Construimos un modelo de perceptrón multicapa con una sola capa oculta para clasificar las imágenes en el conjunto de datos Fashion-MNIST. Cada imagen tiene 28 píxeles de alto y ancho. Expandimos los píxeles de la imagen uno por uno para obtener un vector con un grado de 784 y lo ingresamos en la capa completamente conectada . Sin embargo, este método de clasificación tiene ciertas limitaciones.

1. Los píxeles de la misma imagen 列 adyacente pueden estar muy separados en esta dirección. Los patrones que constituyen pueden ser difíciles de reconocer por el modelo.
2. Para imágenes de entrada a gran escala, el uso de la capacidad de capa completamente conectada 易 hace que el modelo sea demasiado grande. Suponga que la entrada es una foto en color (incluidos 3 canales) con una altura y un ancho de 1000 píxeles. Incluso si el número de salidas de la capa completamente conectada sigue siendo 256, la forma del parámetro de peso de esta capa es 3000000 × 256: ocupa aproximadamente 3 GB de memoria o memoria de video. Esto ha traído modelos complicados y gastos de almacenamiento excesivos.

La capa convolucional intenta resolver estos dos problemas.

  • Por un lado, la capa convolucional retiene la forma de entrada , de modo que la correlación de los píxeles de la imagen tanto en la dirección de la altura como en la de la anchura puede reconocerse eficazmente.
  • Por otro lado, la capa convolucional recalcula la entrada del mismo núcleo convolucional y la misma posición a través de la ventana deslizante, evitando así que el tamaño del parámetro sea demasiado grande. 

Las redes neuronales convolucionales son redes con capas convolucionales. En esta sección, presentaremos una red neuronal convolucional temprana utilizada para reconocer imágenes digitales escritas a mano: LeNet . El nombre proviene de Yann LeCun, el primer autor de LeNet. LeNet demostró que entrenar redes neuronales convolucionales a través del descenso de gradientes puede lograr los resultados más avanzados de reconocimiento de dígitos escritos a mano en ese momento. Este trabajo fundamental es la primera vez que se pone en escena la red neuronal convolucional y es bien conocido en el mundo. La estructura de red de LeNet se muestra en la siguiente figura. 

 Modelo LENET 

LeNet se divide en dos partes: bloque de capa convolucional y bloque de capa completamente conectado.

La unidad básica del bloque de capa convolucional es la capa convolucional seguida de la capa de agrupación máxima :

La capa convolucional se usa para reconocer el patrón espacial de la imagen, como líneas y partes de objetos, y la capa de agrupación máxima posterior se usa para reducir la sensibilidad de la capa convolucional a la posición . El bloque de capas convolucionales se compone de dos de estas unidades básicas apiladas repetidamente. En el bloque de la capa convolucional, cada capa convolucional usa una ventana de 5 × 5 y usa una función de activación sigmoidea en la salida . El número de canales de salida de la primera capa convolucional es 6 y el número de canales de salida de la segunda capa convolucional se incrementa a 16. Esto se debe a que la altura y el ancho de la entrada de la segunda capa convolucional son más pequeños que los de la primera capa convolucional, por lo que aumentar el canal de salida hace que los tamaños de los parámetros de las dos capas convolucionales sean similares. La forma de la ventana de las dos capas agrupadas más grandes del bloque de capas convolucionales es 2 × 2, y la zancada es 2. Dado que la ventana de agrupación tiene la misma forma que la zancada, el área cubierta por cada deslizamiento de la ventana de agrupación en la entrada no se superpone entre sí.

La forma de salida del bloque de capa convolucional es (tamaño de lote, canal, altura, ancho). Cuando la salida del bloque de capa convolucional se pasa al bloque de capa completamente conectado, el bloque de capa completamente conectado aplanará cada muestra en el lote pequeño. En otras palabras, la forma de entrada de la capa completamente conectada se volverá bidimensional, donde la primera dimensión son las muestras en el mini-lote, y la segunda dimensión es la representación vectorial después de que se aplana cada muestra , y la dirección es el canal y la altura. Y el producto de ancho. El bloque de capas completamente conectado contiene 3 capas completamente conectadas. Sus números de salida son 120, 84 y 10 respectivamente, donde 10 es el número de categorías de salida.

El modelo LeNet es implementado por la clase secuencial a continuación .

import time
import torch
from torch import nn, optim
import sys
sys.path.append("..")
import d2lzh_pytorch as d2l
device = torch.device('cuda' if torch.cuda.is_available() else
'cpu')
class LeNet(nn.Module):
    def __init__(self):
        # 初始化
        super(LeNet, self).__init__()
        # 卷积层 in_channels, out_channels,kernel_size
        self.conv = nn.Sequential(nn.Conv2d(1, 6, 5), 
        nn.Sigmoid(),
        # kernel_size, stride
        nn.MaxPool2d(2, 2), 

        nn.Conv2d(6, 16, 5),
        nn.Sigmoid(),
        nn.MaxPool2d(2, 2)
        )
        # 全连接层 
        self.fc = nn.Sequential(
        nn.Linear(16*4*4, 120),
        nn.Sigmoid(),
        nn.Linear(120, 84),
        nn.Sigmoid(),
        nn.Linear(84, 10)
        )
        # 前向传播
    def forward(self, img):
        feature = self.conv(img)
        output = self.fc(feature.view(img.shape[0], -1))
        return output

Comprueba la forma de cada capa.

net = LeNet()
print(net)

Salida:

LeNet ((conv): Sequential (
(0): Conv2d (1, 6, kernel_size = (5, 5), stride = (1, 1))
(1): Sigmoid ()
(2): MaxPool2d (kernel_size = 2 , stride = 2, padding = 0, dilatación = 1,
ceil_mode = False)
(3): Conv2d (6, 16, kernel_size = (5, 5), stride = (1, 1))
(4): Sigmoid ()
(5): MaxPool2d (kernel_size = 2, stride = 2, padding = 0, dilatación = 1,
ceil_mode = False)
)
(fc): Sequential (
(0): Linear (in_features = 256, out_features = 120, bias = True )
(1): Sigmoide ()
(2): Lineal (in_features = 120, out_features = 84, sesgo = verdadero)
(3): Sigmoide ()
(4): Lineal (in_features = 84, out_features = 10, sesgo = verdadero )))

Puede verse que la altura y el ancho de la entrada en el bloque de capas convolucionales disminuyen capa por capa. Dado que la capa convolucional utiliza un núcleo de convolución con una altura y un ancho de 5, la altura y el ancho se reducen en 4 respectivamente, mientras que la capa de agrupación reduce a la mitad la altura y el ancho, pero el número de canales aumenta de 1 a 16. La capa completamente conectada reduce el número de salidas capa por capa hasta que el número de categorías de imágenes es 10.

Obtenga datos y entrene modelos

Modelo experimental de LeNet. En el experimento, todavía usamos Fashion-MNIST como el conjunto de datos de entrenamiento.

batch_size = 256
# 载入输数据集
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)

Debido a que los cálculos de redes neuronales convolucionales son más complejos que los perceptrones multicapa, se recomienda utilizar GPU para acelerar los cálculos. Por lo tanto, modificamos ligeramente la función evalu_accuracy descrita en la implementación de la regresión softmax desde cero para admitir la computación con GPU.

# 本函数已保存在d2lzh_pytorch包中方便以后使用。
def evaluate_accuracy(data_iter, net, device=None):
    if device is None and isinstance(net, torch.nn.Module):
        # 如果没指定device就使用net的device
        device = list(net.parameters())[0].device
    acc_sum, n = 0.0, 0
    with torch.no_grad():
        for X, y in data_iter:
            if isinstance(net, torch.nn.Module):
                net.eval() # 评估模式, 这会关闭dropout
                acc_sum += (net(X.to(device)).argmax(dim=1) == y.to(device)).float().sum().cpu().item()
                net.train() # 改回训练模式
            else: # 自定义的模型, 不考虑GPU
                if('is_training' in net.__code__.co_varnames): # 如果有is_training这个参数
                    # 将is_training设置成False
                    acc_sum += (net(X, is_training=False).argmax(dim=1) == y).float().sum().item() 
                else:
                    acc_sum += (net(X).argmax(dim=1) == y).float().sum().item() 
            n += y.shape[0]
    return acc_sum / n

Realice pequeños cambios en la función train_ch3 definida para asegurarse de que los datos y el modelo utilizados para el cálculo estén en la misma memoria o memoria de video.

# 本函数已保存在d2lzh_pytorch包中方便以后使用
def train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs):
    net = net.to(device)
    print("training on ", device)
    # 交叉熵损失函数
    loss = torch.nn.CrossEntropyLoss()
    batch_count = 0
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n, start = 0.0, 0.0, 0, time.time()
        for X, y in train_iter:
            X = X.to(device)
            y = y.to(device)
            y_hat = net(X)
            l = loss(y_hat, y)
            optimizer.zero_grad()
            l.backward()
            optimizer.step()
            train_l_sum += l.cpu().item()
            train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()
            n += y.shape[0]
            batch_count += 1
        test_acc = evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec'
              % (epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start))

 

# 学习率采⽤0.001
lr, num_epochs = 0.001, 5
# 训练算法使用Adam算法
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
train_ch5(net, train_iter, test_iter, batch_size, optimizer, device,num_epochs)

Salida:

entrenamiento en cuda
epoch 1, pérdida 0.0072, train acc 0.322, test acc 0.584, time 3.7 sec
epoch 2, loss 0.0037, train acc 0.649, test acc 0.699, time 1.8 sec
epoch 3, loss 0.0030, train acc 0.718, test acc 0.724 , tiempo 1.7 seg
época 4, pérdida 0.0027, tren acc 0.741, prueba acc 0.746, tiempo 1.6 sec
época 5, pérdida 0.0024, tren acc 0.759, prueba acc 0.759, tiempo 1.7 seg

resumen

  • Las redes neuronales convolucionales son redes con capas convolucionales.
  • LeNet utiliza alternativamente una capa convolucional y una capa de agrupación máxima seguida de una capa completamente conectada para la clasificación de imágenes.

Supongo que te gusta

Origin blog.csdn.net/dujuancao11/article/details/108571642
Recomendado
Clasificación