日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PyTorch系列 | 快速入门迁移学习

發布時間:2023/12/10 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PyTorch系列 | 快速入门迁移学习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方“算法猿的成長”,選擇“加為星標”

第一時間關注 AI 和 Python 知識

圖片來源:Pexels,作者:Arthur Ogleznev

2019 年第 68 篇文章,總第 92 篇文章

本文大約?6800?字,建議收藏閱讀

原題?| TRANSFER LEARNING TUTORIAL

作者?| Sasank Chilamkurthy

原文?| https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html#transfer-learning-tutorial

譯者?| kbsc13("算法猿的成長"公眾號作者)

聲明?| 翻譯是出于交流學習的目的,歡迎轉載,但請保留本文出于,請勿用作商業或者非法用途

簡介

本次教程主要介紹如何用深度學習實現遷移學習。更多更詳細的遷移學習知識可以查看 cs231n 課程--https://cs231n.github.io/transfer-learning/

實際應用中,很少人會從頭開始,通過隨機初始化來訓練一個卷積神經網絡,因為擁有足夠數量的數據集太少了。通常,大家都會選擇一個在比較大的數據集(比如 ImageNet 數據集,1000個類別總共120萬張圖片)上訓練好的預訓練模型,然后對卷積神經網絡進行初始化,或者用于提取特征。

遷移學習的兩大主要應用場景:

  • 微調網絡:采用預訓練模型對網絡進行初始化,而不是隨機初始化,這種做法可以更快收斂,同時也能取得更好的效果。

  • 作為一個特征提取器:這種應用會將除了最后的全連接層外的網絡層都固定權重參數,然后最后的全連接層會根據數據集類別數量進行修改輸出,并隨機初始化其權值,然后訓練該層。

本文的教程,代碼中需要導入的模型如下所示:

#?License:?BSD #?Author:?Sasank?Chilamkurthyfrom?__future__?import?print_function,?divisionimport?torch import?torch.nn?as?nn import?torch.optim?as?optim from?torch.optim?import?lr_scheduler import?numpy?as?np import?torchvision from?torchvision?import?datasets,?models,?transforms import?matplotlib.pyplot?as?plt import?time import?os import?copyplt.ion()???#?interactive?mode

加載數據

加載數據這部分將采用?torchvision?和?torch.utils.data?兩個模塊。

本次教程的目標是訓練一個二分類模型,類別是螞蟻和蜜蜂,因此數據集中分別包含了 120 張螞蟻和蜜蜂的訓練圖片,然后每個類別還包含 75 張圖片作為驗證集。也就是說這個數據集總管只有 390 張圖片,不到一千張圖片,是一個非常小的數據集,如果從頭訓練模型,很難獲得很好的泛化能力。因此,本文將對這個數據集采用遷移學習的方法來得到更好的泛化能力。

獲取本文數據集和代碼,可以在公眾號后臺回復“pytorch遷移學習”獲取。

加載數據的代碼如下所示:

#?數據增強方法,訓練集會實現隨機裁剪和水平翻轉,然后進行歸一化 #?驗證集僅僅是裁剪和歸一化,并不會做數據增強 data_transforms?=?{'train':?transforms.Compose([transforms.RandomResizedCrop(224),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize([0.485,?0.456,?0.406],?[0.229,?0.224,?0.225])]),'val':?transforms.Compose([transforms.Resize(256),transforms.CenterCrop(224),transforms.ToTensor(),transforms.Normalize([0.485,?0.456,?0.406],?[0.229,?0.224,?0.225])]), } #?數據集所在文件夾 data_dir?=?'data/hymenoptera_data' image_datasets?=?{x:?datasets.ImageFolder(os.path.join(data_dir,?x),data_transforms[x])for?x?in?['train',?'val']} dataloaders?=?{x:?torch.utils.data.DataLoader(image_datasets[x],?batch_size=4,shuffle=True,?num_workers=4)for?x?in?['train',?'val']} dataset_sizes?=?{x:?len(image_datasets[x])?for?x?in?['train',?'val']} class_names?=?image_datasets['train'].classesdevice?=?torch.device("cuda:0"?if?torch.cuda.is_available()?else?"cpu")

可視化圖片

首先可視化一些訓練圖片,以便于更好理解數據增強。代碼如下所示:

#?圖片展示的函數 def?imshow(inp,?title=None):"""Imshow?for?Tensor."""#?逆轉操作,從?tensor?變回?numpy?數組需要轉換通道位置inp?=?inp.numpy().transpose((1,?2,?0))mean?=?np.array([0.485,?0.456,?0.406])std?=?np.array([0.229,?0.224,?0.225])#?從歸一化后變回原始圖片inp?=?std?*?inp?+?meaninp?=?np.clip(inp,?0,?1)plt.imshow(inp)if?title?is?not?None:plt.title(title)plt.pause(0.001)??#?pause?a?bit?so?that?plots?are?updated#?獲取一個?batch?的訓練數據 inputs,?classes?=?next(iter(dataloaders['train']))#?Make?a?grid?from?batch out?=?torchvision.utils.make_grid(inputs)imshow(out,?title=[class_names[x]?for?x?in?classes])

展示的圖片如下所示:

訓練模型

加載數據后,就是開始進行訓練模型,這里會介紹以下兩個內容:

  • 制定學習率的策略

  • 保存最佳模型

在下面的代碼中,參數?scheduler?是采用?torch.optim.lr_scheduler?初始化的 LR 策略對象:

#?訓練模型的函數 def?train_model(model,?criterion,?optimizer,?scheduler,?num_epochs=25):since?=?time.time()best_model_wts?=?copy.deepcopy(model.state_dict())best_acc?=?0.0for?epoch?in?range(num_epochs):print('Epoch?{}/{}'.format(epoch,?num_epochs?-?1))print('-'?*?10)#?每個?epoch?都分為訓練階段和驗證階段for?phase?in?['train',?'val']:#?注意訓練和驗證階段,需要分別對?model?的設置if?phase?==?'train':scheduler.step()model.train()??#?Set?model?to?training?modeelse:model.eval()???#?Set?model?to?evaluate?moderunning_loss?=?0.0running_corrects?=?0#?Iterate?over?data.for?inputs,?labels?in?dataloaders[phase]:inputs?=?inputs.to(device)labels?=?labels.to(device)#?清空參數的梯度optimizer.zero_grad()#?只有訓練階段才追蹤歷史with?torch.set_grad_enabled(phase?==?'train'):outputs?=?model(inputs)_,?preds?=?torch.max(outputs,?1)loss?=?criterion(outputs,?labels)#?訓練階段才進行反向傳播和參數的更新if?phase?==?'train':loss.backward()optimizer.step()#?記錄?loss?和?準確率running_loss?+=?loss.item()?*?inputs.size(0)running_corrects?+=?torch.sum(preds?==?labels.data)epoch_loss?=?running_loss?/?dataset_sizes[phase]epoch_acc?=?running_corrects.double()?/?dataset_sizes[phase]print('{}?Loss:?{:.4f}?Acc:?{:.4f}'.format(phase,?epoch_loss,?epoch_acc))#?deep?copy?the?modelif?phase?==?'val'?and?epoch_acc?>?best_acc:best_acc?=?epoch_accbest_model_wts?=?copy.deepcopy(model.state_dict())print()time_elapsed?=?time.time()?-?sinceprint('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

上述函數實現了模型的訓練,在一個 epoch 中分為訓練和驗證階段,訓練階段自然需要前向計算加反向傳播,并更新網絡層的參數,但驗證階段只需要前向計算,然后記錄 loss 和驗證集上的準確率即可。

此外就是需要設置保存模型的條件,這里是當每次驗證集的準確率都高于之前最好的準確率時,保存模型。

可視化模型的預測結果

下面定義了一個可視化模型預測結果的函數,用于展示圖片和模型對該圖片的預測類別信息:

#?可視化模型預測結果,即展示圖片和模型對該圖片的預測類別信息,默認展示?6?張圖片 def?visualize_model(model,?num_images=6):was_training?=?model.trainingmodel.eval()images_so_far?=?0fig?=?plt.figure()with?torch.no_grad():for?i,?(inputs,?labels)?in?enumerate(dataloaders['val']):inputs?=?inputs.to(device)labels?=?labels.to(device)outputs?=?model(inputs)_,?preds?=?torch.max(outputs,?1)for?j?in?range(inputs.size()[0]):images_so_far?+=?1ax?=?plt.subplot(num_images//2,?2,?images_so_far)ax.axis('off')ax.set_title('predicted:?{}'.format(class_names[preds[j]]))imshow(inputs.cpu().data[j])if?images_so_far?==?num_images:model.train(mode=was_training)returnmodel.train(mode=was_training)

微調網絡

這部分就是本次遷移學習的核心內容,前面都是正常的加載數據、定義訓練過程的代碼,這里介紹的就是如何進行微調網絡,代碼如下所示:

#?加載?resnet18?網絡模型,并且設置加載預訓練模型 model_ft?=?models.resnet18(pretrained=True) num_ftrs?=?model_ft.fc.in_features #?修改輸出層的輸出數量,本次采用的數據集類別為?2 model_ft.fc?=?nn.Linear(num_ftrs,?2)model_ft?=?model_ft.to(device)criterion?=?nn.CrossEntropyLoss()#?對所有網絡層參數進行更新 optimizer_ft?=?optim.SGD(model_ft.parameters(),?lr=0.001,?momentum=0.9)#?學習率策略,每?7?個?epochs?乘以?0.1 exp_lr_scheduler?=?lr_scheduler.StepLR(optimizer_ft,?step_size=7,?gamma=0.1)

這一步因為是設置加載預訓練模型,所以運行后會下載預訓練的?resnet18?網絡模型文件

訓練和驗證

接下來開始正式訓練網絡模型了,代碼如下所示,如果采用 cpu,大約需要 15-25 分鐘的過程,而如果采用 gpu,那么速度就很快了,基本一分鐘左右就訓練完成了。

model_ft?=?train_model(model_ft,?criterion,?optimizer_ft,?exp_lr_scheduler,num_epochs=25)

訓練結果:

可視化模型預測結果:

visualize_model(model_ft)

可視化結果如下:

用于特征提取器

剛剛是用于微調網絡,即將預訓練模型用于初始化網絡層的參數,接下來介紹遷移學習的第二種用法,作為特征提取器,也就是固定預訓練模型部分的網絡層的權值參數,這部分的實現代碼,如下所示,其中需要將卷積層部分的參數固定,即設置?requires_grad==False?,這樣在反向傳播過程就不會計算它們的梯度,更多內存可以查看 https://pytorch.org/docs/notes/autograd.html#excluding-subgraphs-from-backward

model_conv?=?torchvision.models.resnet18(pretrained=True) #?固定卷積層的權重參數 for?param?in?model_conv.parameters():param.requires_grad?=?False#?新的網絡層的參數默認?requires_grad=True num_ftrs?=?model_conv.fc.in_features model_conv.fc?=?nn.Linear(num_ftrs,?2)model_conv?=?model_conv.to(device)criterion?=?nn.CrossEntropyLoss()#?只對輸出層的參數進行更新 optimizer_conv?=?optim.SGD(model_conv.fc.parameters(),?lr=0.001,?momentum=0.9)#?學習率策略,每?7?個?epochs?乘以?0.1 exp_lr_scheduler?=?lr_scheduler.StepLR(optimizer_conv,?step_size=7,?gamma=0.1)

再次進行訓練:

model_conv?=?train_model(model_conv,?criterion,?optimizer_conv,exp_lr_scheduler,?num_epochs=25)

訓練結果:

可視化網絡的預測結果

visualize_model(model_conv)plt.ioff() plt.show()

輸出結果:

小結

本文教程簡單介紹了遷移學習的內容,通過訓練一個二分類模型,簡單介紹遷移學習的兩個用法,微調網絡和用于固定的特征提取器。

本文代碼地址:

https://github.com/ccc013/DeepLearning_Notes/blob/master/Pytorch/pytorch_transfer_learning_example.ipynb

獲取本文的代碼和數據集方法:

  • 關注公眾號“算法猿的成長

  • 公眾號會話界面回復“pytorch遷移學習"

  • 歡迎關注我的微信公眾號--算法猿的成長,或者掃描下方的二維碼,大家一起交流,學習和進步!

    如果覺得不錯,在看、轉發就是對小編的一個支持!

    總結

    以上是生活随笔為你收集整理的PyTorch系列 | 快速入门迁移学习的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。