Construction et formation du modèle de réseau AlexNet

1. Explication détaillée du réseau AlexNet

AlexNet est le réseau champion du concours ISLVRC 2012 (ImageNet Large Scale Visual Recognition Challenge) en 2012, et sa précision de classification est passée du traditionnel 70%+ à 80%+. Il a été conçu par Hinton et son élève Alex Krizhevsky. C'est également après cette année que l'apprentissage en profondeur a commencé à se développer rapidement.

insérez la description de l'image ici

Les points forts du réseau sont :

(1) Pour la première fois, le GPU est utilisé pour l'entraînement à l'accélération du réseau.

(2) La fonction d'activation ReLU est utilisée à la place de la fonction d'activation Sigmoïde traditionnelle et de la fonction d'activation Tanh.

(3) La normalisation de la réponse locale LRN est utilisée.

(4) Le fonctionnement du neurone de désactivation aléatoire d'abandon est utilisé dans les deux premières couches de la couche entièrement connectée pour réduire le surajustement.

1. Fonction d'activation ReLU

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme de lien antivol, il est recommandé d'enregistrer l'image et de la télécharger directement (img-1gefuR8T-1648692034025) (filigrane, type_ZmFuZ3poZW5naGVpdGk, shadow_10, text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxM jc4OTA z,size_16,color_FFFFFF ,t_70.png)]

Visant le problème de la convergence lente de la formation causée par la saturation du gradient sigmoïde sigmoïde, ReLU a été introduit dans AlexNet. ReLU est une fonction linéaire par morceaux, la sortie est 0 si elle est inférieure ou égale à 0 ; la sortie est identique si elle est supérieure à 0. Par rapport au sigmoïde-sigmoïde, ReLU présente les avantages suivants :

  • La surcharge de calcul est faible. La propagation vers l'avant de sigmoidsigmoid a un fonctionnement exponentiel et un fonctionnement réciproque, et ReLu est une sortie linéaire ; en rétropropagation, sigmoidsigmoid a un fonctionnement exponentiel, et ReLU a une partie de sortie, et la dérivée est toujours 1.
  • problème de saturation du gradient
  • parcimonie. Relu rendra la sortie de certains neurones 0, ce qui provoque la parcimonie du réseau, réduit l'interdépendance des paramètres et atténue l'apparition de problèmes de surajustement.

2. Utilisez le décrochage

Sur-ajustement : la cause principale est qu'il y a trop de dimensions d'entités, des hypothèses de modèle trop complexes, trop de paramètres, trop peu de données d'apprentissage et trop de bruit, ce qui conduit la fonction d'ajustement à prédire parfaitement l'ensemble d'apprentissage, mais à prédire le résultat de l'ensemble de test de nouvelles données Différence. Surajustement des données d'entraînement sans tenir compte de la généralisation.

L'introduction de Dropout vise principalement à éviter le surajustement. Dans le réseau de neurones, Dropout est réalisé en modifiant la structure du réseau de neurones lui-même.Pour un neurone d'une certaine couche, le neurone est mis à 0 par une probabilité définie, et ce neurone ne participe pas à la propagation avant et arrière, juste comme dans le réseau est supprimé, tout en gardant inchangé le nombre de neurones dans la couche d'entrée et la couche de sortie, puis mettre à jour les paramètres selon la méthode d'apprentissage du réseau de neurones. À l'itération suivante, certains neurones sont à nouveau supprimés de manière aléatoire (mis à 0) jusqu'à la fin de l'apprentissage.
Le décrochage doit être considéré comme une grande innovation dans AlexNet, et c'est maintenant l'une des structures nécessaires dans les réseaux de neurones. L'abandon peut également être considéré comme une combinaison de modèles. La structure de réseau générée à chaque fois est différente. En combinant plusieurs modèles, le surajustement peut être efficacement réduit. L'abandon n'a besoin que de deux fois plus de temps de formation pour obtenir une combinaison de modèles (similaire à l'effet de la moyenne), très efficace.

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-UMVwFUoq-1648692034029)(image-20220330145132257.png)]

3. La formule de calcul de la taille de la matrice après convolution est :

N = (W - F + 2P ) / S + 1

① Taille de l'image d'entrée L×L

② Taille du filtre F×F

③ Pas de taille S

④ Nombre de pixels de rembourrage P

4. Explication détaillée de chaque couche de réseau

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-UuJwtrKl-1648692034031)(image-20220330150550517.png)]

Conv1 : Maxpool1 : Conv2 : Maxpool2 : Conv3 : Conv4 :
noyaux : 96 noyaux : 256 noyaux :=384 noyaux : 384
taille_noyau : 11 taille_noyau : 3 kernel_size:5 taille_noyau : 3 taille_noyau : 3 taille_noyau : 3
rembourrage : [1, 2] pages : 0 rembourrage : [2, 2] pages : 0 rembourrage : [1, 1] rembourrage : [1, 1]
foulée : 4 foulée : 2 foulée : 1 foulée : 2 foulée : 1 foulée : 1
taille_sortie : taille_sortie : taille_sortie : taille_sortie : taille_sortie : taille_sortie :
[55, 55, 96] [27, 27, 96] [27, 27, 256] [13, 13, 256] [13, 13, 384] [13, 13, 384]
nom_couche taille_noyau kernel_num rembourrage foulée
Conv1 11 96 [1, 2] 4
Maxpool1 3 Aucun 0 2
Conv2 5 256 [2, 2] 1
Maxpool2 3 Aucun 0 2
Conv3 3 384 [1, 1] 1
Conv4 3 384 [1, 1] 1
Conv5 3 256 [1, 1] 1
Maxpool3 3 Aucun 0 2
FC1 2048 Aucun Aucun Aucun
FC2 2048 Aucun Aucun Aucun
FC3 1000 Aucun Aucun Aucun

2. Formation et tests

Tout d'abord, ce modèle utilise un ensemble de données de fleurs à 5 catégories, si vous le souhaitez, vous pouvez m'envoyer un message privé

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-pdoKbcWu-1648692034033)(image-20220330151020207.png)]

1. Écrivez le code du modèle 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. Écrivez le modèle 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()

Je suppose que tu aimes

Origine blog.csdn.net/qq_42076902/article/details/123864381
conseillé
Classement