日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Pytorch 微调(Fine-tuning)

發(fā)布時間:2023/12/18 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Pytorch 微调(Fine-tuning) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Pytorch 微調(diào)(Fine-tuning)

0. 環(huán)境介紹

環(huán)境使用 Kaggle 里免費建立的 Notebook

教程使用李沐老師的 動手學深度學習 網(wǎng)站和 視頻講解

小技巧:當遇到函數(shù)看不懂的時候可以按 Shift+Tab 查看函數(shù)詳解。

1. 微調(diào)

1.1 遷移學習(Transfer Learning)

假如我們想識別圖片中不同類型的椅子,然后向用戶推薦購買鏈接。 一種可能的方法是首先識別 100 把普通椅子,為每把椅子拍攝 1000 張不同角度的圖像,然后在收集的圖像數(shù)據(jù)集上訓(xùn)練一個分類模型。 共 100×1000=105100 \times 1000 = 10^5100×1000=105 張圖片,數(shù)量不到 ImageNet 的十分之一。適合 ImageNet 的復(fù)雜模型可能會在這個椅子圖片上過擬合。此外,由于訓(xùn)練樣本數(shù)量有限,訓(xùn)練模型的準確性可能無法滿足實際要求。

一個解決方案就是收集更多數(shù)據(jù)標記數(shù)據(jù)需要更多的時間和金錢成本。
另外一個解決策略就是遷移學習,遷移學習可以從源數(shù)據(jù)集學到的知識遷移到目標數(shù)據(jù)集。例如,盡管ImageNet數(shù)據(jù)集中的大多數(shù)圖像與椅子無關(guān),但在此數(shù)據(jù)集上訓(xùn)練的模型可能會提取更通用的圖像特征,這有助于識別邊緣、紋理、形狀和對象組合。 這些類似的特征也可能有效地識別椅子。

1.2 微調(diào)

一個神經(jīng)網(wǎng)絡(luò)一般可以分為兩塊:

  • 特征提取將原始像素變成容易線性分割的特征(一般是卷積層)
  • 線性分類器來做分類(一般是MLP 和 Softmax)

遷移學習中的常見技巧:微調(diào)。
微調(diào)通過使用在大數(shù)據(jù)上得到的預(yù)訓(xùn)練好的模型來初始化模型權(quán)重,從而提升精度。這就要求預(yù)訓(xùn)練模型質(zhì)量要有保證。微調(diào)通常速度更快、精度更高。

微調(diào)步驟:

  • 在源數(shù)據(jù)集(例如 ImageNet 數(shù)據(jù)集)上預(yù)訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型,即源模型。
  • 創(chuàng)建一個新的神經(jīng)網(wǎng)絡(luò)模型,即目標模型。這將復(fù)制源模型上的所有模型設(shè)計及其參數(shù)(輸出層除外)。我們假定這些模型參數(shù)包含從源數(shù)據(jù)集中學到的知識,這些知識也將適用于目標數(shù)據(jù)集。我們還假設(shè)源模型的輸出層與源數(shù)據(jù)集的標簽密切相關(guān);因此不在目標模型中使用該層。
  • 向目標模型添加輸出層,其輸出數(shù)是目標數(shù)據(jù)集中的類別數(shù)。然后隨機初始化該層的模型參數(shù)。
  • 在目標數(shù)據(jù)集(如椅子數(shù)據(jù)集)上訓(xùn)練目標模型。輸出層將從頭開始進行訓(xùn)練,而所有其他層的參數(shù)將根據(jù)源模型的參數(shù)進行微調(diào)。
  • 1.3 加入微調(diào)訓(xùn)練

    是一個目標數(shù)據(jù)集上的正常訓(xùn)練任務(wù),但是要使用更強的正則化:

    • 使用更小的學習率
    • 是用更少的數(shù)據(jù)迭代

    源數(shù)據(jù)集遠復(fù)雜于目標數(shù)據(jù),通常微調(diào)的效果更好。

    1.4 重用分類器權(quán)重

    • 源數(shù)據(jù)集可能也有目標數(shù)據(jù)中的部分標號
    • 可以使用預(yù)訓(xùn)練好模型分類器中對應(yīng)標號對應(yīng)的向量來做初始化

    1.5 固定一些層

    神經(jīng)網(wǎng)絡(luò)通常學習有層次的特征表示

    • 低層次的特征更加通用
    • 高層次的特征則更跟數(shù)據(jù)集相關(guān)

    所以可以固定底部的一些層的參數(shù),使其不參與更新(更強的正則)

    2. 代碼

    2.1 導(dǎo)入數(shù)據(jù)

    使用的熱狗數(shù)據(jù)集來源于網(wǎng)絡(luò)。 該數(shù)據(jù)集包含 1400 張熱狗的 “正類” 圖像,以及包含盡可能多的其他食物的 “負類” 圖像。 含著兩個類別的 1000 張圖片用于訓(xùn)練,其余的則用于測試。

    解壓下載的數(shù)據(jù)集,我們獲得了兩個文件夾hotdog/train和hotdog/test。 這兩個文件夾都有hotdog(有熱狗)和not-hotdog(無熱狗)兩個子文件夾, 子文件夾內(nèi)都包含相應(yīng)類的圖像。

    !pip install -U d2l %matplotlib inline import os import torch import torchvision from torch import nn from d2l import torch as d2ld2l.DATA_HUB['hotdog'] = (d2l.DATA_URL + 'hotdog.zip','fba480ffa8aa7e0febbb511d181409f899b9baa5')data_dir = d2l.download_extract('hotdog')

    創(chuàng)建兩個實例來分別讀取訓(xùn)練和測試數(shù)據(jù)集中的所有圖像文件:

    train_imgs = torchvision.datasets.ImageFolder(os.path.join(data_dir, 'train')) test_imgs = torchvision.datasets.ImageFolder(os.path.join(data_dir, 'test'))

    顯示前 8 個正類樣本圖片和最后 8 張負類樣本圖片:

    hotdogs = [train_imgs[i][0] for i in range(8)] not_hotdogs = [train_imgs[-i - 1][0] for i in range(8)] d2l.show_images(hotdogs + not_hotdogs, 2, 8, scale=1.4);


    對于 RGB(紅、綠和藍)顏色通道,我們分別標準化每個通道(這個是在 ImageNet 上做的操作,直接 Copy 過來),訓(xùn)練集隨機裁剪后 resize 到 224×224224 \times 224224×224,然后進行隨機的水平翻轉(zhuǎn);測試集 resize 到 256×256256 \times 256256×256 后 取中間的 224×224224 \times 224224×224 像素的圖像:

    # 使用RGB通道的均值和標準差,以標準化每個通道 normalize = torchvision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])train_augs = torchvision.transforms.Compose([torchvision.transforms.RandomResizedCrop(224),torchvision.transforms.RandomHorizontalFlip(),torchvision.transforms.ToTensor(),normalize])test_augs = torchvision.transforms.Compose([torchvision.transforms.Resize(256),torchvision.transforms.CenterCrop(224),torchvision.transforms.ToTensor(),normalize])

    Normalize 第一個參數(shù)為三個通道的均值,第二個參數(shù)為標準差。

    2.2 定義和初始化模型

    使用在 ImageNet 數(shù)據(jù)集上預(yù)訓(xùn)練的 ResNet-18 作為源模型,其中 pretrained=True 表示自動下載預(yù)訓(xùn)練的模型參數(shù):

    pretrained_net = torchvision.models.resnet18(pretrained=True)

    預(yù)訓(xùn)練的源模型實例包含許多特征層和一個輸出層 fc。 此劃分的主要目的是促進對除輸出層以外所有層的模型參數(shù)進行微調(diào)。 下面給出了源模型的成員變量 fc:

    pretrained_net.fc


    可以看到源模型是針對 ImageNet 數(shù)據(jù)集的千分類任務(wù)的,所以針對目標數(shù)據(jù)要進行修改,以下代碼將千分類變成 2 分類:

    finetune_net = torchvision.models.resnet18(pretrained=True) finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 2) # 只對最后一層進行初始化 nn.init.xavier_uniform_(finetune_net.fc.weight)

    2.3 微調(diào)模型

    如果為預(yù)訓(xùn)練模型,輸出層學習率調(diào)整為十倍:

    # 如果param_group=True,輸出層中的模型參數(shù)將使用十倍的學習率 def train_fine_tuning(net, learning_rate, batch_size=128, num_epochs=5,param_group=True):train_iter = torch.utils.data.DataLoader(torchvision.datasets.ImageFolder(os.path.join(data_dir, 'train'), transform=train_augs),batch_size=batch_size, shuffle=True)test_iter = torch.utils.data.DataLoader(torchvision.datasets.ImageFolder(os.path.join(data_dir, 'test'), transform=test_augs),batch_size=batch_size)devices = d2l.try_all_gpus()loss = nn.CrossEntropyLoss(reduction="none")if param_group:# 非最后一層全拿出來params_1x = [param for name, param in net.named_parameters()if name not in ["fc.weight", "fc.bias"]]trainer = torch.optim.SGD([{'params': params_1x},## 最后一層用 10 倍的學習率{'params': net.fc.parameters(),'lr': learning_rate * 10}],lr=learning_rate, weight_decay=0.001)else:trainer = torch.optim.SGD(net.parameters(), lr=learning_rate,weight_decay=0.001)d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,devices)

    2.4 訓(xùn)練

    使用預(yù)訓(xùn)練模型:

    train_fine_tuning(finetune_net, 5e-5)


    可以發(fā)現(xiàn)剛開始精度就很高了,測試精度比訓(xùn)練精度還高。

    為了進行比較,所有模型參數(shù)都進行初始化:

    scratch_net = torchvision.models.resnet18() scratch_net.fc = nn.Linear(scratch_net.fc.in_features, 2) train_fine_tuning(scratch_net, 5e-4, param_group=False)


    可以看到效果沒有微調(diào)模型好。

    2.5 凍結(jié)全連接層之前參數(shù)

    finetune_net2 = torchvision.models.resnet18(pretrained=True) finetune_net2.fc = nn.Linear(finetune_net2.fc.in_features, 2) nn.init.xavier_uniform_(finetune_net2.fc.weight)for name, param in finetune_net2.named_parameters():if 'fc' not in name:param.requires_grad = Falsetrain_fine_tuning(finetune_net2, 5e-5)

    2.6 使用 ImageNet 中自帶與目標數(shù)據(jù)相關(guān)的權(quán)重進行初始化

    微調(diào)模型,輸出層兩個神經(jīng)元,把第一個神經(jīng)元(下標為 0)權(quán)重初始化為 ImageNet 中相關(guān)數(shù)據(jù)權(quán)重(如果想問為什么是第一個而不是第二個?因為熱狗訓(xùn)練數(shù)據(jù)集中正例的標簽值為 0,所以初始化第一個(下標為 0)神經(jīng)元的權(quán)重參數(shù)):

    finetune_net3 = torchvision.models.resnet18(pretrained=True) finetune_net3.fc = nn.Linear(finetune_net3.fc.in_features, 2) nn.init.xavier_uniform_(finetune_net3.fc.weight)# 因為我們是熱狗分類任務(wù), ImageNet 里面第 934 個類別也是熱狗, 可以直接拿出來作為目標模型的初始化 weight = finetune_net3.fc.weight hotdog_w = torch.split(weight.data, 1, dim=0)[934] print(hotdog_w.shape)# 輸出層兩個神經(jīng)元, 把第一個神經(jīng)元(下標為 0)權(quán)重初始化為 ImageNet 中相關(guān)數(shù)據(jù)權(quán)重 finetune_net3.fc.weight[0].data = hotdog_wtrain_fine_tuning(finetune_net3, 5e-5)


    總結(jié)

    以上是生活随笔為你收集整理的Pytorch 微调(Fine-tuning)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。