Affinement :
l'entraînement conjoint du classificateur nouvellement ajouté et de certaines ou de toutes les couches convolutives nous permet d'affiner les représentations des caractéristiques d'ordre élevé dans le modèle de base car elles sont pertinentes pour la tâche spécifique.
Ce n'est que lorsque le classificateur est entraîné (c'est-à-dire la couche linéaire) que la base de convolution peut être affinée, sinon l'erreur d'apprentissage sera très importante au début et ce qui a été appris dans la couche de convolution avant le réglage fin sera détruit.
Étapes :
1. Ajoutez une couche personnalisée à la base de convolution pré-entraînée
2. Gelez la base de convolution
3. Entraînez la couche de classification ajoutée
4. Dégelez une partie ou la totalité de la base de convolution (dégelez généralement la base de convolution proche de la sortie partie)
5. Former conjointement l'ensemble du modèle
Étapes générales pour l'apprentissage par transfert :
Code:
"""Utilisez le modèle Resnet pour pré-entraîner le modèle + réglage fin""" import torch.cuda import torchvision from torch import nn import os from torchvision import transforms # import matplotlib.pyplot as plt #Preprocess data base_dir = r'. /dataset/4weather ' train_dir = os.path.join(base_dir,'train') test_dir = os.path.join(base_dir,'test') train_transformer = torchvision.transforms.Compose( [ transforms.Resize((224,224)) , transforms.RandomCrop ((192,192)), transforms.ColorJitter(luminosité=0,4), transforms.RandomHorizontalFlip(0,2), transforms.ColorJitter(contrast=4), transforms.ToTensor(), transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]) ] ) test_transformer = torchvision.transforms.Compose([ transforms.Resize((192,192)), transforms.ToTensor(), transforms.Normalize(mean=[0.5,0.5,0.5],std=[0.5,0.5,0.5])]) #创建dataset train_ds = torchvision.datasets.ImageFolder( train_dir, transform = train_transformer ) test_ds = torchvision.datasets.ImageFolder ( test_dir, transform =test_transformer ) #创建dataloader batch = 8 train_dl =torch .utils.data.DataLoader( train_ds, batch_size = batch, shuffle = True ) test_dl = torch.utils.data .DataLoader ( test_ds, batch_size = lot) imgs,labels =next(iter(train_dl)) #Charger le modèle de périphérique = 'cuda' si torch.cuda. is_available() else 'cpu' model = torchvision.models.resnet18().to(device) for param in model.parameters(): param.requires_grad = False #Seul le nombre de catégories de classification dans la couche de liaison complète doit être modifié in_f= model .fc.in_features #Le remplacement de la couche entièrement liée est un model.fc = nn.Linear(in_f, 4) #L'optimiseur n'a besoin d'optimiser que la dernière couche optim =torch .optim.Adam(model.fc .parameters() ,lr =0.001) #Fonction de perte loss_fn = nn.CrossEntropyLoss() #训练函数fit 必须要指定 model.train,model.eval Resnet中有BN层 def fit(epoch,model,trainloader,testloader) : correct = 0 total = 0 epoch_loss = running_loss/len(trainloader.dataset) running_loss =0 model.train() #Indiquez qu'il s'agit du mode train et qu'il nécessite bn et laisse tomber pour x,y dans le chargeur de train : si torch.cuda.is_available() : x,y =x.to('cuda'),y.to('cuda') y_pred =model(x) loss = loss_fn(y_pred,y ) optim.zero_grad() loss.backward() optim.step() avec torch.no_grad() : y_pred = torch.argmax(y_pred,dim=1) correct +=(y_pred==y).sum().item () total += y.size(0) running_loss += loss.item() model.eval() avec torch.no_grad() : epoch_acc =correct/total test_correct = 0 test_total = 0 test_running_loss =0 print('epoch',epoch,'loss',round(epoch_loss,3), pour x,y dans le chargeur de test : if torch.cuda.is_available() : x,y = x.to('cuda'),y.to('cuda') y_pred =model(x) loss = loss_fn(y_pred,y ) y_pred = torch.argmax(y_pred,dim=1) test_correct +=(y_pred==y).sum().item() test_total +=y.size(0) test_running_loss +=loss.item() epoch_tst_loss =test_running_loss /len(testloader.dataset) epoch_tst_acc = test_correct/test_total return epoch_loss ,époque_acc,époque_tst_loss,époque_tst_acc 'acc:',round(epoch_acc,3), 'test_loss:',round(epoch_tst_loss,3), 'test_acc:',round(epoch_tst_acc,3)) # époques =5 # train_loss =[] # train_acc =[] # test_loss =[] # test_acc=[] # # pour l'époque dans la plage (époques) : # epoch_loss,epoch_acc,epoch_tst_loss,epoch_tst_acc =fit(epoch,model,train_dl,test_dl) # train_loss.append(epoch_loss) # train_acc.append (epoch_acc) # test_loss.append(epoch_tst_loss) # test_acc.append(epoch_tst_acc) #绘制图像: # plt.plot(range(1,epochs+1),train_loss,label='train_loss') # plt.plot(range( 1,époques+1),test_loss,étiquette = 'test_loss' ) # plt.legend() # plt.show() # #Réglage précis des paramètres dans model.parameters() : param.requires_grad=True extend_epoch =8 #Le taux d'apprentissage doit être plus faible lors du réglage fin optimiseur = torch.optim .Adam( model.parameters(),lr=0.00001) # # #Processus de formation train_loss =[] train_acc =[] test_loss =[] test_acc=[] pour l'époque dans la plage (extend_epoch) : epoch_loss,epoch_acc,epoch_tst_loss,epoch_tst_acc =fit(epoch,model,train_dl,test_dl) train_loss.append(epoch_loss) train_acc.append(epoch_acc) test_loss.append(epoch_tst_loss) test_acc.append(epoch_tst_acc)