Modèle de classification d'images de formation basé sur l'architecture réseau Resnet

Partie prétraitement des données :

  • Amélioration des données : Le module de transformations dans torchvision a ses propres fonctions, ce qui est plus pratique.
  • Prétraitement des données : les transformations dans torchvision sont également implémentées pour nous, il suffit de les appeler directement
  • Le module DataLoader lit directement les données par lots

Paramètres du module réseau :

  • Chargez le modèle pré-entraîné. Il existe de nombreuses architectures de réseau classiques dans torchvision, qui sont très pratiques à appeler. Vous pouvez également utiliser les paramètres de poids formés par d'autres pour continuer la formation, ce qu'on appelle l'apprentissage par transfert.
  • Il convient de noter que les tâches formées par d'autres ne sont pas exactement les mêmes que les nôtres : nous devons remplacer la dernière couche principale, qui est généralement la dernière couche entièrement connectée, par nos propres tâches.
  • Pendant l'entraînement, vous pouvez tout recommencer, ou vous ne pouvez entraîner que la dernière couche de notre tâche, car les premières couches sont toutes utilisées pour l'extraction de fonctionnalités et les objectifs essentiels de la tâche sont les mêmes.

Préservation et test du modèle de réseau

  • Le modèle peut être enregistré de manière sélective. Par exemple, si l'effet actuel est bon dans l'ensemble de validation, il sera enregistré.
  • Lire le modèle pour des tests réels
  • import os
    import matplotlib.pyplot as plt
    %matplotlib inline
    import numpy as np
    import torch
    from torch import nn
    import torch.optim as optim
    import torchvision
    #pip install torchvision
    from torchvision import transforms, models, datasets
    #https://pytorch.org/docs/stable/torchvision/index.html
    import imageio
    import time
    import warnings
    warnings.filterwarnings("ignore")
    import random
    import sys
    import copy
    import json
    from PIL import Image

    Opérations de lecture et de prétraitement des données

    data_dir = './flower_data/'
    train_dir = data_dir + '/train'
    valid_dir = data_dir + '/valid'

    Créez une bonne source de données :

  • Toutes les opérations de prétraitement d'image sont spécifiées dans data_transforms
  • ImageFolder suppose que tous les fichiers sont enregistrés dans des dossiers. Les images de la même catégorie sont stockées sous chaque dossier. Le nom du dossier est le nom de la catégorie.
    data_transforms = {
        'train': 
            transforms.Compose([
            transforms.Resize([96, 96]),
            transforms.RandomRotation(45),#随机旋转,-45到45度之间随机选
            transforms.CenterCrop(64),#从中心开始裁剪
            transforms.RandomHorizontalFlip(p=0.5),#随机水平翻转 选择一个概率概率
            transforms.RandomVerticalFlip(p=0.5),#随机垂直翻转
            transforms.ColorJitter(brightness=0.2, contrast=0.1, saturation=0.1, hue=0.1),#参数1为亮度,参数2为对比度,参数3为饱和度,参数4为色相
            transforms.RandomGrayscale(p=0.025),#概率转换成灰度率,3通道就是R=G=B
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])#均值,标准差
        ]),
        'valid': 
            transforms.Compose([
            transforms.Resize([64, 64]),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ]),
    }
    batch_size = 128
    
    image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'valid']}
    dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=batch_size, shuffle=True) for x in ['train', 'valid']}
    dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'valid']}
    class_names = image_datasets['train'].classes
    image_datasets
    {'train' : Dataset ImageFolder 
         Nombre de points de données : 6552 
         Emplacement racine : ./flower_data/train Transformation 
         StandardTransform
     : Compose( 
                    Resize(size=[96, 96], interpolation=bilinear, max_size=None, antialias=None) 
                    RandomRotation(degrés =[-45,0, 45,0], interpolation=le plus proche, expand=False, fill=0) 
                    CenterCrop(size=(64, 64)) 
                    RandomHorizontalFlip(p=0,5) 
                    RandomVerticalFlip(p=0,5) 
                    ColorJitter(luminosité=[0,8, 1,2 ], contraste=[0,9, 1,1], saturation=[0,9, 1,1], teinte=[-0,1, 0,1]) 
                    RandomGrayscale(p=0,025) 
                    ToTensor()
                    Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ) 
                , 'valid' : Dataset ImageFolder 
         Nombre de points de données : 818 
         Emplacement racine : ./flower_data/valid 
         StandardTransform 
     Transformation : Compose( 
                    Resize( size=[64, 64], interpolation=bilinéaire, max_size=Aucun, antialias=Aucun) 
                    ToTensor() 
                    Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ) 
                }
    dataloaders
    {'train' : <torch.utils.data.dataloader.DataLoader à 0x1e4c50b9400>, 
     'valide' : <torch.utils.data.dataloader.DataLoader à 0x1e4c51ad128>}
    dataset_sizes
    {'train' : 6552, 'valide' : 818}
  • Lire le nom réel correspondant au tag

    with open('cat_to_name.json', 'r') as f:
        cat_to_name = json.load(f)
    cat_to_name
    {'1' : 'primrose rose', 
     '10' : 'chardon globe', 
     '100' : 'fleur de couverture', 
     '101' : 'vigne trompette', 
     '102' : 'lys mûre', 
     '11' : 'muflier', 
     '12' : "pied de poulain", 
     '13' : 'roi protéa', 
     '14' : 'chardon-lance', 
     '15' : 'iris jaune', 
     '16' : 'globe-fleur', 
     '17' : 'échinacée pourpre', 
     '18' : 'lys péruvien', 
     '19' : 'fleur en ballon', 
     '2' : 'orchidée de poche à feuilles dures', 
     '20' : 'lys arum blanc géant',
     '21' : 'lys de feu', 
     '22' : 'fleur en coussinet', 
     '23' : 'fritillaire', 
     '24' : 'gingembre rouge', 
     '25' : 'jacinthe de raisin', 
     '26' : 'maïs coquelicot', 
     '27' : 'prince' de plumes de Pays de Galles',
     '28' : 'gentiane sans tige', 
     '29' : 'artichaut', 
     '3' : 'cloches de Canterbury', 
     '30' : 'sweet william', 
     '31' : 'œillet', ' 
     32' : 'phlox de jardin'. ', 
     '33' : 'l'amour dans la brume', 
     '34' : 'aster mexicain', 
     '35' : 'holly de mer alpin', 
     '36' : 'Cattleya aux lèvres rubis', 
     '37' : 'fleur du Cap ', 
     '38' : 'grande masterwort', 
     '39' : 'tulipe siam', 
     '4' : 'pois de senteur', 
     '40' : 'rose de carême', 
     '41' : 'marguerite barbeton', 
     '42' :'jonquille', 
     '43' : 'lys épée', 
     '44' : 'poinsettia', 
     '45' : 'boléro bleu profond', 
     '46' : 'giroflée', '48'  
     '47 ' : 'souci',
     : 'renoncule', 
     '49' : 'marguerite', 
     '5' : 'souci anglais', 
     '50' : 'pissenlit commun', 
     '51' : 'pétunia', 
     '52' : 'pensée sauvage', 
     '53' : 'primula' , 
     '54' : 'tournesol', 
     '55' : 'pélargonium', 
     '56' : 'évêque de llandaff', 
     '57' : 'gaura', 
     '58' : 'géranium', 
     '59' : 'dahlia orange ', 
     '6' : 'lys tigre', 
     '60' : 'dahlia rose-jaune', 
     '61' : 'cautleya spicata', 
     '62' : 'anémone du Japon', 
     '63' : 'susan aux yeux noirs' ,
     '64' : 'silverbush', 
     '65' : 'pavot de Californie', 
     '66' : 'osteospermum', 
     '67' : 'crocus printanier', 
     '68' : 'iris barbu', 
     '69' : 'windflower' ,
     '7' : 'orchidée lunaire', 
     '92' : 'baume d'abeille', 
     '70' : 'arbre coquelicot',
     '71' : 'gazania', 
     '72' : 'azalée', 
     '73' : 'nénuphar', 
     '74' : 'rose', 
     '75' : 'pomme épineuse', 
     '76' : 'gloire du matin' , 
     '77' : 'passiflore', 
     '78' : 'lotus lotus', 
     '79' : 'lys crapaud', 
     '8' : 'oiseau de paradis', 
     '80' : 'anthurium', 
     '81' : 'frangipanier', 
     '82' : 'clématite', 
     '83' : 'hibiscus', 
     '84' ​​: 'ancolie', 
     '85' : 'rose du désert', ' 
     86' : 'mauve', 
     '87' :'magnolia', 
     '88' : 'cyclamen', 
     '89' : 'cresson', 
     '9' : 'monkshood', 
     '90' : 'canna lily', 
     '91' : 'hippeastrum', 
     '93' : ' mousse en boule', 
     '94': 'digitale',
     '95' : 'bougainvillier', 
     '96' : 'camélia', 
     '97' : 'mauve', 
     '98' : 'pétunia mexicain', 
     '99' : 'bromélia'}
  • Chargez le modèle fourni dans models et utilisez directement les poids entraînés comme paramètres d'initialisation

  • La première exécution nécessite un téléchargement qui peut être lent, je vous fournirai une copie téléchargée qui pourra être directement placée dans le chemin correspondant.
    model_name = 'resnet'  #可选的比较多 ['resnet', 'alexnet', 'vgg', 'squeezenet', 'densenet', 'inception']
    #是否用人家训练好的特征来做
    feature_extract = True #都用人家特征,咱先不更新
    # 是否用GPU训练
    train_on_gpu = torch.cuda.is_available()
    
    if not train_on_gpu:
        print('CUDA is not available.  Training on CPU ...')
    else:
        print('CUDA is available!  Training on GPU ...')
        
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    CUDA n'est pas disponible. Formation sur CPU...
  • Les paramètres du modèle doivent-ils être mis à jour ?

  • Parfois, j'utilise les modèles d'autres personnes, et je continue à les utiliser, sans parler de les mettre à jour. Nous pouvons les personnaliser nous-mêmes.
    def set_parameter_requires_grad(model, feature_extracting):
        if feature_extracting:
            for param in model.parameters():
                param.requires_grad = False
    model_ft = models.resnet18()#18层的能快点,条件好点的也可以选152
    model_ft
    ResNet( 
      (conv1) : Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), biais=False) (bn1) : BatchNorm2d(64, eps 
      = 1e-05, momentum=0.1, affine=True, track_running_stats=True) 
      (relu) : ReLU(inplace=True) 
      (maxpool) : MaxPool2d(kernel_size=3, stride=2, padding=1, dilatation=1, ceil_mode= False) 
      (layer1) : Sequential( 
        (0) : BasicBlock( 
          (conv1) : Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais= Faux) 
          (bn1) : BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
        ) 
        (1) : BasicBlock( 
          (conv2) : Conv2d(64, 64, kernel_size= (3, 3), foulée=(1, 1), rembourrage=(1, 1), biais=False)
          (bn2) : BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (conv1) : Conv2d(64 
          , 64, kernel_size=(3, 3), stride=(1, 1 ), padding=(1, 1), biais=False) 
          (bn1) : BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) (bn2) : BatchNorm2d(64, eps= 
          1e- 05, momentum=0.1, affine=True, track_running_stats=True) 
        ) 
      ) 
      (layer2) : Sequential( 
        (0) : BasicBlock( 
          (conv1) : Conv2d(64, 128, kernel_size=(3, 3), stride=(2 , 2), remplissage=(1, 1), biais=Faux)
          (bn1) : BatchNorm2d(128, eps=1e-05, momentum=0,1, affine=True, track_running_stats=True) 
          relu) : ReLU(inplace=True)
          relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(128, 128, kernel_size= (3, 3), foulée=(1, 1), rembourrage=(1, 1), biais=False)
          (bn2) : BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          sous-échantillonnage) : Sequential( 
            (0) : Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), biais=False) 
            (1) : BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1) 
          : 
        BasicBlock 
        ( 
          (conv1) : Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) (bn1) : BatchNorm2d(128, eps=1e-05, momentum 
          = 0.1, affine=True, track_running_stats=True) 
          (conv2) : Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) ( 
          bn2 ) : BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 
        ( 
      0 
      )
        : BasicBlock( 
          (conv1) : Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), biais=False) (bn1) : BatchNorm2d(256, eps 
          = 1e-05, momentum=0.1, affine=True, track_running_stats=True) 
          (relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1 ), padding=(1, 1), biais=False) 
          (bn2) : BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (sous- 
          échantillonnage) : Séquentiel( 
            (0) : Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), biais=False)
            (1) : BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (conv1) : 
          Conv2d 
          (conv1) : Conv2d(256, 512, kernel_size=(3, 3), stride=( 2, 2), remplissage=(1, 1), biais=Faux)
        BasicBlock 
        (
          (conv1) : Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) (bn1) : BatchNorm2d(256, eps= 
          1e- 05, momentum=0.1, affine=True, track_running_stats=True) 
          (relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) 
          (bn2) : BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) ( 
        layer4 
      ) 
      : Séquentiel( 
        (0) : BasicBlock( 
          (bn1) : BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(512, 512, kernel_size= (3, 3), foulée=(1, 1), rembourrage=(1, 1), biais=False)
          (bn2) : BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          sous-échantillonnage) : Sequential( 
            (0) : Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), biais=False) 
            (1) : BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1) 
          : 
        BasicBlock 
        ( 
          (conv1) : Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) (bn1) : BatchNorm2d(512, eps=1e-05, momentum 
          = 0.1, affine=True, track_running_stats=True)
          bn2 ) : BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          relu) : ReLU(inplace=True)
          (conv2) : Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) ) ) (avgpool) : AdaptiveAvgPool2d(output_size 
        = 
      ( 
      1 , 1)) 
      (fc) : Linéaire (in_features=512, out_features=1000, biais=True)
  • Remplacez la couche de sortie du modèle par la vôtre

    def initialize_model(model_name, num_classes, feature_extract, use_pretrained=True):
        
        model_ft = models.resnet18(pretrained=use_pretrained)
        set_parameter_requires_grad(model_ft, feature_extract)
        
        num_ftrs = model_ft.fc.in_features
        model_ft.fc = nn.Linear(num_ftrs, 102)#类别数自己根据自己任务来
                                
        input_size = 64#输入大小根据自己配置来
    
        return model_ft, input_size

    Définir les couches qui doivent être entraînées

    model_ft, input_size = initialize_model(model_name, 102, feature_extract, use_pretrained=True)
    
    #GPU还是CPU计算
    model_ft = model_ft.to(device)
    
    # 模型保存,名字自己起
    filename='checkpoint.pth'
    
    # 是否训练所有层
    params_to_update = model_ft.parameters()
    print("Params to learn:")
    if feature_extract:
        params_to_update = []
        for name,param in model_ft.named_parameters():
            if param.requires_grad == True:
                params_to_update.append(param)
                print("\t",name)
    else:
        for name,param in model_ft.named_parameters():
            if param.requires_grad == True:
                print("\t",name)
    Paramètres à apprendre : 
    	 fc.weight 
    	 fc.bias
  • model_ft
    ResNet( 
      (conv1) : Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), biais=False) (bn1) : BatchNorm2d(64, eps 
      = 1e-05, momentum=0.1, affine=True, track_running_stats=True) 
      (relu) : ReLU(inplace=True) 
      (maxpool) : MaxPool2d(kernel_size=3, stride=2, padding=1, dilatation=1, ceil_mode= False) 
      (layer1) : Sequential( 
        (0) : BasicBlock( 
          (conv1) : Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais= Faux) 
          (bn1) : BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
        ) 
        (1) : BasicBlock( 
          (conv2) : Conv2d(64, 64, kernel_size= (3, 3), foulée=(1, 1), rembourrage=(1, 1), biais=False)
          (bn2) : BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (conv1) : Conv2d(64 
          , 64, kernel_size=(3, 3), stride=(1, 1 ), padding=(1, 1), biais=False) 
          (bn1) : BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) (bn2) : BatchNorm2d(64, eps= 
          1e- 05, momentum=0.1, affine=True, track_running_stats=True) 
        ) 
      ) 
      (layer2) : Sequential( 
        (0) : BasicBlock( 
          (conv1) : Conv2d(64, 128, kernel_size=(3, 3), stride=(2 , 2), remplissage=(1, 1), biais=Faux) 
          (bn1) : BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(128, 128, kernel_size= (3, 3), foulée=(1, 1), rembourrage=(1, 1), biais=False) 
          (bn2) : BatchNorm2d(128, eps=1e-05, momentum=0,1, affine=True, track_running_stats= True) 
          (sous-échantillonnage) : Sequential( 
            (0) : Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), biais=False) (1) : BatchNorm2d(128, eps= 
            1e- 05, momentum=0.1, affine=True, track_running_stats=True) 
          ) 
        ) 
        (1) : BasicBlock( 
          (conv1) : Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding= (1, 1), biais=False) 
          (bn1) : BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True)
          (conv2) : Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) ( 
          bn2 ) : BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        ) 
      ) 
      (layer3) : Sequential( 
        (0) : BasicBlock( 
          (conv1) : Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), biais= Faux) 
          (bn1) : BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(256, 256, kernel_size= (3, 3), foulée=(1, 1), padding=(1, 1), biais=False) 
          (bn2) : BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats= True) 
          (sous-échantillonnage) : Sequential(  
            (0) : Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), biais=False)
            (1) : BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1) 
          : 
        BasicBlock 
        (
          (conv1) : Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) (bn1) : BatchNorm2d(256, eps= 
          1e- 05, momentum=0.1, affine=True, track_running_stats=True) 
          (relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) 
          (bn2) : BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) ( 
        layer4 
      ) 
      : Séquentiel( 
        (0) : BasicBlock(  
          (conv1) : Conv2d(256, 512, kernel_size=(3, 3), stride=( 2, 2), remplissage=(1, 1), biais=Faux)
          (bn1) : BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(512, 512, kernel_size= (3, 3), foulée=(1, 1), rembourrage=(1, 1), biais=False) 
          (bn2) : BatchNorm2d(512, eps=1e-05, momentum=0,1, affine=True, track_running_stats= True) 
          (sous-échantillonnage) : Sequential( 
            (0) : Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), biais=False) (1) : BatchNorm2d(512, eps= 
            1e- 05, momentum=0.1, affine=True, track_running_stats=True) 
          ) 
        ) 
        (1) : BasicBlock( 
          (conv1) : Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding= (1, 1), biais=False) 
          (bn1) : BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ( 
          relu) : ReLU(inplace=True) 
          (conv2) : Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), biais=False) ( 
          bn2 ) : BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        ) 
      ) 
      (avgpool) : AdaptiveAvgPool2d(output_size=(1, 1)) 
      (fc) : Linéaire(in_features=512, out_features=102, biais=True) 
    )
  • Paramètres de l'optimiseur

    # 优化器设置
    optimizer_ft = optim.Adam(params_to_update, lr=1e-2)#要训练啥参数,你来定
    scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=10, gamma=0.1)#学习率每7个epoch衰减成原来的1/10
    criterion = nn.CrossEntropyLoss()

    module de formation

    def train_model(model, dataloaders, criterion, optimizer, num_epochs=25,filename='best.pt'):
        #咱们要算时间的
        since = time.time()
        #也要记录最好的那一次
        best_acc = 0
        #模型也得放到你的CPU或者GPU
        model.to(device)
        #训练过程中打印一堆损失和指标
        val_acc_history = []
        train_acc_history = []
        train_losses = []
        valid_losses = []
        #学习率
        LRs = [optimizer.param_groups[0]['lr']]
        #最好的那次模型,后续会变的,先初始化
        best_model_wts = copy.deepcopy(model.state_dict())
        #一个个epoch来遍历
        for epoch in range(num_epochs):
            print('Epoch {}/{}'.format(epoch, num_epochs - 1))
            print('-' * 10)
    
            # 训练和验证
            for phase in ['train', 'valid']:
                if phase == 'train':
                    model.train()  # 训练
                else:
                    model.eval()   # 验证
    
                running_loss = 0.0
                running_corrects = 0
    
                # 把数据都取个遍
                for inputs, labels in dataloaders[phase]:
                    inputs = inputs.to(device)#放到你的CPU或GPU
                    labels = labels.to(device)
    
                    # 清零
                    optimizer.zero_grad()
                    # 只有训练的时候计算和更新梯度
                    outputs = model(inputs)
                    loss = criterion(outputs, labels)
                    _, preds = torch.max(outputs, 1)
                    # 训练阶段更新权重
                    if phase == 'train':
                        loss.backward()
                        optimizer.step()
    
                    # 计算损失
                    running_loss += loss.item() * inputs.size(0)#0表示batch那个维度
                    running_corrects += torch.sum(preds == labels.data)#预测结果最大的和真实值是否一致
                    
                
                
                epoch_loss = running_loss / len(dataloaders[phase].dataset)#算平均
                epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset)
                
                time_elapsed = time.time() - since#一个epoch我浪费了多少时间
                print('Time elapsed {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
                print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))
                
    
                # 得到最好那次的模型
                if phase == 'valid' and epoch_acc > best_acc:
                    best_acc = epoch_acc
                    best_model_wts = copy.deepcopy(model.state_dict())
                    state = {
                      'state_dict': model.state_dict(),#字典里key就是各层的名字,值就是训练好的权重
                      'best_acc': best_acc,
                      'optimizer' : optimizer.state_dict(),
                    }
                    torch.save(state, filename)
                if phase == 'valid':
                    val_acc_history.append(epoch_acc)
                    valid_losses.append(epoch_loss)
                    #scheduler.step(epoch_loss)#学习率衰减
                if phase == 'train':
                    train_acc_history.append(epoch_acc)
                    train_losses.append(epoch_loss)
            
            print('Optimizer learning rate : {:.7f}'.format(optimizer.param_groups[0]['lr']))
            LRs.append(optimizer.param_groups[0]['lr'])
            print()
            scheduler.step()#学习率衰减
    
        time_elapsed = time.time() - since
        print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
        print('Best val Acc: {:4f}'.format(best_acc))
    
        # 训练完后用最好的一次当做模型最终的结果,等着一会测试
        model.load_state_dict(best_model_wts)
        return model, val_acc_history, train_acc_history, valid_losses, train_losses, LRs 

    Commence l'entraînement!

  • Nous formons désormais uniquement la couche de sortie
    model_ft, val_acc_history, train_acc_history, valid_losses, train_losses, LRs  = train_model(model_ft, dataloaders, criterion, optimizer_ft, num_epochs=20)
    Époque 0/19 
    ---------- 
    Temps écoulé 0m 39s 
    train Perte : 4.0874 Acc : 0.2355 
    Temps écoulé 0m 43s 
    valide Perte : 3.5746 Acc : 0.2531 
    Taux d'apprentissage de l'optimiseur : 0.0100000 
    
    Époque 1/19 
    ----- ----- 
    Temps écoulé 1m 22s 
    train Perte : 2,8185 Acc : 0,3953 
    Temps écoulé 1m 26s 
    valide Perte : 3,5450 Acc : 0,3142 
    Taux d'apprentissage de l'optimiseur : 0,0100000 
    
    Époque 2/19 
    ---------- 
    Temps écoulé 2m 5s 
    Perte du train : 2,7673 Acc : 0,4174 
    Temps écoulé 2m 9s 
    valide Perte : 3,9110 Acc : 0,2653 
    Taux d'apprentissage de l'optimiseur : 0,0100000 
    
    Époque 3/19 
    ----------  
    Temps écoulé 2m 48s
    Perte du train : 2,7962 Acc : 0,4255
    Temps écoulé 2m 52s 
    valide Perte : 3,6922 Acc : 0,3142 
    Taux d'apprentissage de l'optimiseur : 0,0100000 
    
    Époque 4/19 
    ---------- 
    Temps écoulé 3m 32s 
    train Perte : 2,7453 Acc : 0,4428 
    Temps écoulé 3m 36s 
    valide Perte : 3,9310 Acc : 0.3044 
    Taux d'apprentissage de l'optimiseur : 0.0100000 
    
    Époque 5/19 
    ---------- 
    Temps écoulé 4m 14s 
    train Perte : 2.2935 Acc : 0.5043 
    Temps écoulé 4m 18s 
    valide Perte : 3.3299 Acc : 0.3435 
    Taux d'apprentissage de l'optimiseur : 0.0010000 
    
    Époque 6 /19 
    ---------- 
    Temps écoulé 4m 57s 
    train Perte : 2.0654 Acc : 0.5258  
    Temps écoulé 5m 1s
    Perte valide : 3.2608 Acc : 0.3411 
    Taux d'apprentissage de l'optimiseur : 0.0010000
    
    Époque 7/19 
    ---------- 
    Temps écoulé 5m 40s 
    train Perte : 1,9603 Acc : 0,5369 
    Temps écoulé 5m 44s 
    valide Perte : 3,2618 Acc : 0,3472 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Époque 8/19 
    ----- ----- 
    Temps écoulé 6m 23s 
    train Perte : 1,9216 Acc : 0,5401 
    Temps écoulé 6m 27s 
    valide Perte : 3,1651 Acc : 0,3386 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Époque 9/19 
    ---------- 
    Temps écoulé 7m 5s 
    Perte du train : 1,9203 Acc : 0,5458 
    Temps écoulé 7m 9s 
    Perte valide : 3,0449 Acc : 0,3680 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Époque 10/19 
    Perte du train : 1,8366 Acc : 0,5553 
    ----------
    Temps écoulé 7m 48s 
    Temps écoulé 7m 52s 
    valide Perte : 3,0722 Acc : 0,3545 
    Taux d'apprentissage de l'optimiseur : 0,0001000 
    
    Époque 11/19 
    ---------- 
    Temps écoulé 8m 31s 
    train Perte : 1,8324 Acc : 0,5546 
    Temps écoulé 8m 35s 
    valide Perte : 3,0115 Acc : 0,3643 
    Taux d'apprentissage de l'optimiseur : 0,0001000 
    
    Époque 12/19 
    ---------- 
    Temps écoulé 9m 13s 
    train Perte : 1,8054 Acc : 0,5553 
    Temps écoulé 9m 17s 
    valide Perte : 3,0688 Acc : 0,3619 
    Taux d'apprentissage de l'optimiseur : 0.0001000 
    
    Époque 13/19 
    ---------- 
    Temps écoulé 9m 56s 
    train Perte : 1.8436 Acc : 0.5534 
    Temps écoulé 10m 0s
    Perte valide : 3,0100 Acc : 0,3631 
    ---------- 
    Taux d'apprentissage de l'optimiseur : 0.0001000
    
    Époque 14/19 
    ---------- 
    Temps écoulé 10m 39s 
    train Perte : 1.7417 Acc : 0.5614 
    Temps écoulé 10m 43s 
    valide Perte : 3.0129 Acc : 0.3655 
    Taux d'apprentissage de l'optimiseur : 0.0001000 
    
    Époque 15/19 
    ----- ----- 
    Temps écoulé 11m 22s 
    train Perte : 1.7610 Acc : 0.5672 
    Temps écoulé 11m 26s 
    valide Perte : 3.0220 Acc : 0.3606 
    Taux d'apprentissage de l'optimiseur : 0.0000100 
    
    Époque 16/19 
    ---------- 
    Temps écoulé 12m 6s 
    Perte du train : 1,7788 Acc : 0,5676 
    Temps écoulé 12m 10s 
    Perte valide : 3,0104 Acc : 0,3557 
    Taux d'apprentissage de l'optimiseur : 0,0000100 
    
    Époque 17/19 
    Temps écoulé 12m 49s 
    train Perte : 1.8033 Acc : 0.5638 
    Temps écoulé 12m 53s 
    valide Perte : 3.0428 Acc : 0.3606 
    Taux d'apprentissage de l'optimiseur : 0.0000100 
    
    Époque 18/19 
    ---------- 
    Temps écoulé 13m 33s 
    train Perte : 1.8294 Acc : 0.5568 
    Temps écoulé 13m 37s 
    valide Perte : 3.0307 Acc : 0.3509 
    Taux d'apprentissage de l'optimiseur : 0.0000100 
    
    Époque 19/19 
    ---------- 
    Temps écoulé 14m 16s 
    train Perte : 1.7949 Acc : 0.5612 
    Temps écoulé 14m 20s 
    valide Perte : 3,0396 Acc : 0,3643 
    Taux d'apprentissage de l'optimiseur : 0,0000100 
    
    Formation terminée en 14 min 20 s 
    Meilleur val Acc : 0,367971
  • Continuez ensuite à entraîner toutes les couches

    for param in model_ft.parameters():
        param.requires_grad = True
    
    # 再继续训练所有的参数,学习率调小一点
    optimizer = optim.Adam(model_ft.parameters(), lr=1e-3)
    scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)
    
    # 损失函数
    criterion = nn.CrossEntropyLoss()
    # 加载之前训练好的权重参数
    
    checkpoint = torch.load(filename)
    best_acc = checkpoint['best_acc']
    model_ft.load_state_dict(checkpoint['state_dict'])
    model_ft, val_acc_history, train_acc_history, valid_losses, train_losses, LRs  = train_model(model_ft, dataloaders, criterion, optimizer, num_epochs=10,)
    Époque 0/9 
    ---------- 
    Temps écoulé 1m 32s 
    train Perte : 2,2451 Acc : 0,4846 
    Temps écoulé 1m 36s 
    valide Perte : 2,3190 Acc : 0,4633 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Époque 1/9 
    ----- ----- 
    Temps écoulé 2m 54s 
    train Perte : 1.2920 Acc : 0.6505 
    Temps écoulé 2m 58s 
    valide Perte : 2.2263 Acc : 0.4670 
    Taux d'apprentissage de l'optimiseur : 0.0010000 
    
    Époque 2/9 
    ---------- 
    Temps écoulé 4m 15s 
    Perte du train : 1,1026 Acc : 0,6993 
    Temps écoulé 4m 19s 
    Perte valide : 1,8115 Acc : 0,5452 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Époque 3/9 
    ---------- 
    Temps écoulé 5m 35s
    Perte du train : 0,9062 Acc : 0,7515 
    Temps écoulé 9m 42s
    Temps écoulé 5m 39s 
    valide Perte : 2,0045 Acc : 0,5403 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Époque 4/9 
    ---------- 
    Temps écoulé 6m 56s 
    train Perte : 0,8392 Acc : 0,7643 
    Temps écoulé 7m 0s 
    valide Perte : 2,1381 Acc : 0.5171 
    Taux d'apprentissage de l'optimiseur : 0.0010000 
    
    Époque 5/9 
    ---------- 
    Temps écoulé 8m 17s 
    train Perte : 0.7081 Acc : 0.7953 
    Temps écoulé 8m 21s 
    valide Perte : 2.0461 Acc : 0.5599 
    Taux d'apprentissage de l'optimiseur : 0.0010000 
    
    Époque 6 /9 
    ---------- 
    Temps écoulé 9m 38s 
    train Perte : 0,6400 Acc : 0,8147 
    Perte valide : 2,2603 Acc : 0,5452 
    Taux d'apprentissage de l'optimiseur : 0,0010000
     
    Époque 7/9 
    ---------- 
    Temps écoulé 10m 59s 
    Train Perte : 0,6406 Acc : 0,8117 
    Temps écoulé 11m 3s 
    Perte valide : 1,4649 Acc : 0,6406 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Époque 8 /9 
    ---------- 
    Temps écoulé 12m 20s 
    train Perte : 0,5686 Acc : 0,8300 
    Temps écoulé 12m 24s 
    valide Perte : 1,7538 Acc : 0,6100 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Époque 9/9 
    ------- --- 
    Temps écoulé 13m 41s 
    train Perte : 0,5978 Acc : 0,8245 
    Temps écoulé 13m 45s 
    valide Perte : 1,6953 Acc : 0,6161 
    Taux d'apprentissage de l'optimiseur : 0,0010000 
    
    Entraînement terminé en 13m 45s
    Meilleur val Acc : 0,640587
  • Charger le modèle entraîné

    model_ft, input_size = initialize_model(model_name, 102, feature_extract, use_pretrained=True)
    
    # GPU模式
    model_ft = model_ft.to(device)
    
    # 保存文件的名字
    filename='best.pt'
    
    # 加载模型
    checkpoint = torch.load(filename)
    best_acc = checkpoint['best_acc']
    model_ft.load_state_dict(checkpoint['state_dict'])

    Prétraitement des données de test

  • La méthode de traitement des données de test doit être la même que lors de la formation.
  • Le but de l’opération de culture est de garantir que la taille des intrants est cohérente
  • Des opérations de normalisation sont également nécessaires. Utilisez la même moyenne et la même norme que les données d'entraînement. Cependant, il convient de noter que les données d'entraînement sont standardisées sur 0-1, donc les données de test doivent également être normalisées en premier.
  • Enfin, le canal de couleur dans PyTorch est la première dimension, qui est différente de nombreuses boîtes à outils et doit être convertie.
  • # 得到一个batch的测试数据
    dataiter = iter(dataloaders['valid'])
    images, labels = dataiter.next()
    
    model_ft.eval()
    
    if train_on_gpu:
        output = model_ft(images.cuda())
    else:
        output = model_ft(images)

    Le résultat représente la probabilité que chaque donnée d'un lot appartienne à chaque catégorie.

    output.shape

    Obtenez celui avec la probabilité la plus élevée

    _, preds_tensor = torch.max(output, 1)
    
    preds = np.squeeze(preds_tensor.numpy()) if not train_on_gpu else np.squeeze(preds_tensor.cpu().numpy())
    preds
    array([ 34,  49,  43,  54,  20,  14,  49,  43,  50,  20,  19, 100,  78,
            96,  96,  62,  62,  63,  32,  38,  82,  43,  88,  73,   6,  51,
            43,  89,  55,  75,  55,  11,  46,  82,  48,  82,  20, 100,  48,
            20,  24,  49,  76,  93,  49,  46,  90,  75,  89,  75,  76,  99,
            56,  48,  77,  66,  60,  72,  89,  97,  76,  73,  17,  48,  39,
            31,  19,  74,  61,  46,  93,  80,  27,  11,  91,  18,  23,  47,
            29,  54,  18,  93,   1,  50,  79,  96,  39,  53,  63,  60,  49,
            23,  23,  52,  99,  89,   3,  50,  64,  15,  19,  60,  19,  75,
            50,  78,  82,  18,  75,  18,  82,  53,   3,  52,  60,  38,  62,
            47,  21,  59,  81,  48,  89,  64,  60,  55, 100,  60], dtype=int64)

    Afficher les résultats de la prédiction

    def im_convert(tensor):
        """ 展示数据"""
        
        image = tensor.to("cpu").clone().detach()
        image = image.numpy().squeeze()
        image = image.transpose(1,2,0)
        image = image * np.array((0.229, 0.224, 0.225)) + np.array((0.485, 0.456, 0.406))
        image = image.clip(0, 1)
    
        return image
    fig=plt.figure(figsize=(20, 20))
    columns =4
    rows = 2
    
    for idx in range (columns*rows):
        ax = fig.add_subplot(rows, columns, idx+1, xticks=[], yticks=[])
        plt.imshow(im_convert(images[idx]))
        ax.set_title("{} ({})".format(cat_to_name[str(preds[idx])], cat_to_name[str(labels[idx].item())]),
                     color=("green" if cat_to_name[str(preds[idx])]==cat_to_name[str(labels[idx].item())] else "red"))
    plt.show()

Je suppose que tu aimes

Origine blog.csdn.net/qq_65838372/article/details/132745442
conseillé
Classement