Formación y construcción del modelo de red AlexNet

1. Explicación detallada de la red AlexNet

AlexNet es la red campeona de la competencia ISLVRC 2012 (Desafío de reconocimiento visual a gran escala de ImageNet) en 2012, y su precisión de clasificación ha aumentado del tradicional 70%+ a 80%+. Fue diseñado por Hinton y su alumno Alex Krizhevsky. También fue después de ese año que el aprendizaje profundo comenzó a desarrollarse rápidamente.

inserte la descripción de la imagen aquí

Los aspectos más destacados de la red son:

(1) Por primera vez, GPU se usa para entrenamiento de aceleración de red.

(2) La función de activación de ReLU se utiliza en lugar de la función de activación tradicional de Sigmoid y la función de activación de Tanh.

(3) Se utiliza la normalización de respuesta local LRN.

(4) La operación de neurona de desactivación aleatoria de abandono se utiliza en las dos primeras capas de la capa completamente conectada para reducir el sobreajuste.

1. Función de activación ReLU

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo de enlace antirrobo, se recomienda guardar la imagen y cargarla directamente (img-1gefuR8T-1648692034025) (marca de agua, type_ZmFuZ3poZW5naGVpdGk, shadow_10, text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxMjc 4OTA z, tamaño_16, color_FFFFFF ,t_70.png)]

Con el objetivo de resolver el problema de la convergencia de entrenamiento lenta causada por la saturación del gradiente sigmoide sigmoide, ReLU se introdujo en AlexNet. ReLU es una función lineal por partes, la salida es 0 si es menor o igual a 0; la salida es idéntica si es mayor que 0. En comparación con sigmoidsigmoid, ReLU tiene las siguientes ventajas:

  • La sobrecarga computacional es pequeña. La propagación hacia adelante de sigmoidsigmoid tiene una operación exponencial y una operación recíproca, y ReLu es una salida lineal; en la propagación hacia atrás, sigmoidsigmoid tiene una operación exponencial y ReLU tiene una parte de salida, y la derivada siempre es 1.
  • problema de saturación de gradiente
  • escasez Relu hará que la salida de algunas neuronas sea 0, lo que provoca la escasez de la red, reduce la interdependencia de los parámetros y alivia la aparición de problemas de sobreajuste.

2. Usar abandono

Sobreajuste : la causa raíz es que hay demasiadas dimensiones de características, suposiciones de modelos demasiado complejas, demasiados parámetros, muy pocos datos de entrenamiento y demasiado ruido, lo que lleva a la función de ajuste a predecir perfectamente el conjunto de entrenamiento, pero prediciendo el resultado de el conjunto de prueba de nuevos datos Diferencia. Sobreajustar los datos de entrenamiento sin tener en cuenta la generalización.

La introducción de Dropout es principalmente para evitar el sobreajuste. En la red neuronal, Dropout se realiza modificando la estructura de la propia red neuronal. Para una neurona de cierta capa, la neurona se establece en 0 por una probabilidad definida, y esta neurona no participa en la propagación hacia adelante y hacia atrás, solo como en la red se elimina, manteniendo el número de neuronas en la capa de entrada y la capa de salida sin cambios, y luego actualiza los parámetros de acuerdo con el método de aprendizaje de la red neuronal. En la siguiente iteración, algunas neuronas se eliminan aleatoriamente nuevamente (se establecen en 0) hasta el final del entrenamiento.
Dropout debe considerarse como una gran innovación en AlexNet, y ahora es una de las estructuras necesarias en las redes neuronales. La deserción también se puede considerar como una combinación de modelos. La estructura de red generada cada vez es diferente. Al combinar múltiples modelos, el sobreajuste se puede reducir de manera efectiva. La deserción solo necesita el doble del tiempo de entrenamiento para lograr la combinación de modelos (similar al efecto del promedio), muy eficiente.

[Transferencia de imagen de enlace externo falló, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y subirla directamente (img-UMVwFUoq-1648692034029)(image-20220330145132257.png)]

3. La fórmula de cálculo del tamaño de la matriz después de la convolución es:

norte = (W − F + 2P) / S + 1

① Tamaño de imagen de entrada ancho × ancho

② Tamaño de filtro F×F

③ Tamaño de paso S

④ Número de píxeles de relleno P

4. Explicación detallada de cada capa de red

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y cargarla directamente (img-UuJwtrKl-1648692034031)(image-20220330150550517.png)]

Conv1: Maxpool1: Conv2: Maxpool2: Conv3: Conv4:
núcleos: 96 núcleos: 256 granos:=384 núcleos: 384
tamaño_del_núcleo:11 kernel_size:3 tamaño_del_núcleo:5 kernel_size:3 kernel_size:3 kernel_size:3
relleno: [1, 2] página: 0 relleno: [2, 2] página: 0 relleno: [1, 1] relleno: [1, 1]
zancada: 4 zancada: 2 zancada: 1 zancada: 2 zancada: 1 zancada: 1
tamaño de salida: tamaño de salida: tamaño de salida: tamaño de salida: tamaño de salida: tamaño de salida:
[55, 55, 96] [27, 27, 96] [27, 27, 256] [13, 13, 256] [13, 13, 384] [13, 13, 384]
nombre_capa kernel_size kernel_num relleno paso
Conv1 11 96 [1, 2] 4
maxpool1 3 Ninguno 0 2
Conv2 5 256 [2, 2] 1
maxpool2 3 Ninguno 0 2
Conv3 3 384 [1, 1] 1
Conv4 3 384 [1, 1] 1
Conv5 3 256 [1, 1] 1
maxpool3 3 Ninguno 0 2
FC1 2048 Ninguno Ninguno Ninguno
FC2 2048 Ninguno Ninguno Ninguno
FC3 1000 Ninguno Ninguno Ninguno

2. Entrenamiento y pruebas

En primer lugar, este modelo utiliza un conjunto de datos de flores de 5 categorías, si lo desea, puede enviarme un mensaje privado

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y subirla directamente (img-pdoKbcWu-1648692034033)(image-20220330151020207.png)]

1. Escriba el código del modelo net.py

import torch
from torch import nn
import torch.nn.functional as F

class MyAlexNet(nn.Module):
    def __init__(self):
        super(MyAlexNet, self).__init__()
        self.c1 = nn.Conv2d(in_channels=3, out_channels=48, kernel_size=11, stride=4, padding=2)
        self.ReLU = nn.ReLU()
        self.c2 = nn.Conv2d(in_channels=48, out_channels=128, kernel_size=5, stride=1, padding=2)
        self.s2 = nn.MaxPool2d(2)
        self.c3 = nn.Conv2d(in_channels=128, out_channels=192, kernel_size=3, stride=1, padding=1)
        self.s3 = nn.MaxPool2d(2)
        self.c4 = nn.Conv2d(in_channels=192, out_channels=192, kernel_size=3, stride=1, padding=1)
        self.c5 = nn.Conv2d(in_channels=192, out_channels=128, kernel_size=3, stride=1, padding=1)
        self.s5 = nn.MaxPool2d(kernel_size=3, stride=2)
        self.flatten = nn.Flatten()
        self.f6 = nn.Linear(4608, 2048)
        self.f7 = nn.Linear(2048, 2048)
        self.f8 = nn.Linear(2048, 1000)
        self.f9 = nn.Linear(1000, 5)

    def forward(self, x):
        x = self.ReLU(self.c1(x))
        x = self.ReLU(self.c2(x))
        x = self.s2(x)
        x = self.ReLU(self.c3(x))
        x = self.s3(x)
        x = self.ReLU(self.c4(x))
        x = self.ReLU(self.c5(x))
        x = self.s5(x)
        x = self.flatten(x)
        x = self.f6(x)
        x = F.dropout(x, p=0.5)
        x = self.f7(x)
        x = F.dropout(x, p=0.5)
        x = self.f8(x)
        x = F.dropout(x, p=0.5)

        x = self.f9(x)
        return x

if __name__ == '__mian__':
    x = torch.rand([1, 3, 224, 224])
    model = MyAlexNet()
    y = model(x)

2. Escribe el modelo train.py

import os
import json

import torch
from PIL import Image
from torchvision import transforms

from model_v3 import mobilenet_v3_large


def main():
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    data_transform = transforms.Compose(
        [transforms.Resize(256),
         transforms.CenterCrop(224),
         transforms.ToTensor(),
         transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

    # load image
    # 指向需要遍历预测的图像文件夹
    imgs_root = r"D:/other/ClassicalModel/data/flower_datas/train/tulips"
    assert os.path.exists(imgs_root), f"file: '{
      
      imgs_root}' dose not exist."
    # 读取指定文件夹下所有jpg图像路径
    img_path_list = [os.path.join(imgs_root, i) for i in os.listdir(imgs_root) if i.endswith(".jpg")]

    # read class_indict
    json_path = r"D:/other/ClassicalModel/ResNet/class_indices.json"
    assert os.path.exists(json_path), f"file: '{
      
      json_path}' dose not exist."

    json_file = open(json_path, "r")
    class_indict = json.load(json_file)

    # create model
    model = mobilenet_v3_large(num_classes=5).to(device)

    # load model weights
    weights_path = r"D:/other/ClassicalModel/MobileNet/runs12/mobilenet_v3_large.pth"
    assert os.path.exists(weights_path), f"file: '{
      
      weights_path}' dose not exist."
    model.load_state_dict(torch.load(weights_path, map_location=device))

    #save predicted img
    filename = 'record.txt'
    save_path = 'detect'
    path_num = 1
    while os.path.exists(save_path + f'{
      
      path_num}'):
        path_num += 1
    os.mkdir(save_path + f'{
      
      path_num}')
    f = open(save_path + f'{
      
      path_num}/' + filename, 'w')
    f.write("imgs_root:"+imgs_root+"\n")
    f.write("weights_path:"+weights_path+"\n")

    actual_classes="tulips"
    acc_num=0
    all_num=len(img_path_list)
    # prediction
    model.eval()
    batch_size = 8  # 每次预测时将多少张图片打包成一个batch
    with torch.no_grad():
        for ids in range(0, len(img_path_list) // batch_size):
            img_list = []
            for img_path in img_path_list[ids * batch_size: (ids + 1) * batch_size]:
                assert os.path.exists(img_path), f"file: '{
      
      img_path}' dose not exist."
                img = Image.open(img_path)
                img = data_transform(img)
                img_list.append(img)

            # batch img
            # 将img_list列表中的所有图像打包成一个batch
            batch_img = torch.stack(img_list, dim=0)
            # predict class
            output = model(batch_img.to(device)).cpu()
            predict = torch.softmax(output, dim=1)
            probs, classes = torch.max(predict, dim=1)

            for idx, (pro, cla) in enumerate(zip(probs, classes)):
                print("image: {}  class: {}  prob: {:.3}".format(img_path_list[ids * batch_size + idx],
                                                                 class_indict[str(cla.numpy())],
                                                                 pro.numpy()))
                f.write("image: {}  class: {}  prob: {:.3}\n".format(img_path_list[ids * batch_size + idx],
                                                                 class_indict[str(cla.numpy())],
                                                                 pro.numpy()))
                if class_indict[str(cla.numpy())]==actual_classes:
                    acc_num+=1
    print("classes:{},acc_num:{:d},all_num:{:d},accuracy: {:.3f}".format(actual_classes,acc_num,all_num,acc_num/all_num))
    f.write("classes:{},acc_num:{:d},all_num:{:d},accuracy: {:.3f}".format(actual_classes,acc_num,all_num,acc_num/all_num))
    f.close()
if __name__ == '__main__':
    main()

Supongo que te gusta

Origin blog.csdn.net/qq_42076902/article/details/123864381
Recomendado
Clasificación