微調整:
新しく追加された分類器と一部またはすべての畳み込み層を共同トレーニングすることで、特定のタスクに関連する基本モデル内の高次の特徴表現を微調整できます。
分類器 (つまり、線形層) がトレーニングされている場合にのみ、畳み込みベースを微調整できます。そうでない場合、トレーニング エラーは最初に非常に大きくなり、微調整前に畳み込み層で学習された内容は、破壊されました。
手順:
1. 事前トレーニングされた畳み込みベースにカスタム層を追加します
。 2. 畳み込みベースをフリーズします
。 3. 追加された分類層をトレーニングします。
4. 畳み込みベースの一部または全体をフリーズ解除します (通常、出力に近い畳み込みベースをフリーズ解除します)パート)
5. モデル全体を共同トレーニングする
転移学習の一般的な手順:
コード:
"""Resnet モデルを使用してモデルを事前トレーニング + 微調整します""" import torch.cuda import torchvision from torch import nn import os from torchvision importtransforms # import matplotlib.pyplot as plt #Preprocess database_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(brightness=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]) ] #创建dataloader バッチ = 8 train_dl =torch .utils.data.DataLoader( ] ) 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 ) train_ds,batch_size =バッチ, shuffle = True ) test_dl = torch.utils.data .DataLoader( test_ds、 batch_size = バッチ) imgs,labels =next(iter(train_dl)) # torch.cuda の場合 、モデル デバイス = 'cuda' をロードします。 is_available() else 'cpu' model = torchvision.models.resnet18().to(device) for param in model.parameters(): param.requires_grad = False #完全なリンク層内の分類カテゴリの数のみが必要です変更されました in_f= model .fc.in_features #完全にリンクされた層の置換はトレーニング可能な model.fc = nn.Linear(in_f, 4) #オプティマイザは最後の層を最適化するだけで済みます optim =torch .optim.Adam(model.fc .parameters() ,lr =0.001) #損失関数 loss_fn = nn.CrossEntropyLoss() #训练関数数fit 必ず指定するmodel.train、model.eval Resnet中にあるBN层 def fit(epoch,model,trainloader,testloader): 正しい = 0 total = 0 running_loss =0 model.train() #これが train モードであり、bn が必要であることを示しますそしてドロップします for x,y in trainloader: if 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() と torch.no_grad(): y_pred = torch.argmax(y_pred,dim=1) 正しい +=(y_pred==y).sum().item() 合計 += y.size(0) running_loss + = loss.item() epoch_loss = running_loss/len(trainloader.dataset) epoch_acc =正しい/合計 test_correct = 0 test_total = 0 test_running_loss =0 print('epoch',epoch,'loss',round(epoch_loss,3), torch.no_grad( ) を使用した model.eval (): テストローダーの x,y の場合: 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 、epoch_acc、epoch_tst_loss、epoch_tst_acc 'acc:',round(epoch_acc,3), 'test_loss:',round(epoch_tst_loss,3), 'test_acc:',round(epoch_tst_acc,3)) # エポック =5 # train_loss =[] # train_acc =[] # test_loss =[] # test_acc=[] # # range(epochs) 内のエポックの場合: # 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,epochs+1),test_loss,label = 'test_loss' ) # plt.legend() # plt.show() # # param の 微調整in model .parameters(): param.requires_grad=True extend_epoch =8 #オプティマイザーの微調整中は学習率を小さくする必要があります = torch.optim.Adam(model.parameters(),lr=0.00001) # # #トレーニング プロセス train_loss =[] train_acc =[] test_loss =[] test_acc=[] 範囲(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)