欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

pytorch模型的定義、修改、讀取、斷點(diǎn)續(xù)訓(xùn)深入解析

 更新時間:2024年03月09日 09:28:00   作者:nuocheng  
模型定義是深度學(xué)習(xí)中重要的一環(huán),PyTorch提供了強(qiáng)大而靈活的工具和函數(shù),使我們能夠輕松定義各種類型的深度學(xué)習(xí)模型,通過深入理解模型定義的原理和應(yīng)用,我們能夠更好地理解和設(shè)計自己的模型,從而提升深度學(xué)習(xí)任務(wù)的性能和效果

在機(jī)器學(xué)習(xí)和深度學(xué)習(xí)領(lǐng)域,PyTorch是一種廣泛使用的開源深度學(xué)習(xí)框架。它提供了豐富的工具和函數(shù),方便用戶定義、訓(xùn)練和部署各種深度學(xué)習(xí)模型。本篇博客將詳細(xì)介紹PyTorch中模型定義的方式,并結(jié)合原理和代碼示例進(jìn)行講解,旨在幫助讀者深入理解PyTorch的模型定義過程。

前言

模型定義的基本原理

在PyTorch中,模型定義是通過定義一個繼承自torch.nn.Module類的Python類來實(shí)現(xiàn)的。torch.nn.Module是PyTorch中模型定義的基礎(chǔ),它提供了一組豐富的工具和函數(shù),用于定義和操作神經(jīng)網(wǎng)絡(luò)模型。

模型定義的基本原理如下:

創(chuàng)建一個繼承自torch.nn.Module的子類,這個子類將成為我們定義的模型。
在子類的構(gòu)造函數(shù)中,首先調(diào)用super().__init__()來初始化父類torch.nn.Module,然后在構(gòu)造函數(shù)中定義模型的各個層和模塊。
在子類中實(shí)現(xiàn)forward方法,該方法定義了模型的前向傳播過程,即定義了輸入數(shù)據(jù)如何經(jīng)過各個層進(jìn)行計算得到輸出。
可選地,在子類中實(shí)現(xiàn)__str__方法,用于打印模型的結(jié)構(gòu)信息。
接下來,我們將通過一個簡單的神經(jīng)網(wǎng)絡(luò)模型的定義和代碼示例來進(jìn)一步解釋以上原理。

模型參數(shù)和層的概念

在深入了解模型定義之前,讓我們先來了解一些基本概念:模型參數(shù)和層。

模型參數(shù)

模型參數(shù)是模型內(nèi)部可學(xué)習(xí)的參數(shù),它們會在訓(xùn)練過程中自動更新以優(yōu)化模型的性能。常見的模型參數(shù)包括權(quán)重(weights)和偏置(biases)。權(quán)重是連接不同神經(jīng)元的連接強(qiáng)度,而偏置是每個神經(jīng)元的激活閾值。

在PyTorch中,層是模型中的構(gòu)建塊,它們接受輸入數(shù)據(jù)并將其轉(zhuǎn)換為輸出數(shù)據(jù)。層通常包含一些可學(xué)習(xí)的參數(shù),例如全連接層中的權(quán)重和偏置。常見的層類型包括全連接層、卷積層、池化層等。

pytorch的模型定義

pytorch有3種模型定義方式,三種方式都是基于nn.Module建立的,Module是所有網(wǎng)絡(luò)的基礎(chǔ)。

  • Sequential
  • ModuleList
  • ModuleDict

1) Sequential

該方法與tf2很相似,使用也很簡單

以數(shù)字作為層的名稱

import torch
import torch.nn as nn
model = nn.Sequential(
	nn.Linear(56,512),
    nn.ReLU(),
    nn.Linear(512,8)
)
print(model)

對層的名稱進(jìn)行自定義

import collections
import torch
import torch.nn as nn

model = nn.Sequential(collections.OrderedDict([
    ('layer_1',nn.Linear(56,512)),
    ('layer_2',nn.ReLU()),
    ('layer_3',nn.Linear(512,8)),
]))

2) ModuleList

ModuleList接收一個子模塊的列表作為輸入(一個列表中不同的module,并把參數(shù)注冊到網(wǎng)絡(luò)中),可以使用append,extend進(jìn)行操作。

class ModuleListExample(nn.module):
    def __init__(self):
        super().__init__()
        self.model = nn.ModuleList([nn.Linear(56,512),nn.ReLU(),nn.Linear(512,8)])
    def forward(self,x):
        for layers in self.model:
            x=f(x)
        return x
  1. nn.Sequential內(nèi)部實(shí)現(xiàn)了forward函數(shù),因此可以不用寫forward函數(shù),而nn.ModuleList則沒有實(shí)現(xiàn)內(nèi)部forward函數(shù),需要人工實(shí)現(xiàn)。
  2. nn.Sequential初始調(diào)用時就決定了里面Module的調(diào)用順序,因此需要保證上一個Module的輸出大小能符合下一個Module輸入大小的要求。nn.ModuleList只是簡單的將Module打包并注冊到網(wǎng)絡(luò)中,需要在人工實(shí)現(xiàn)的forward里面去決定調(diào)用順序。

3)ModuleDict

該方法與ModuleList類似,只是能加入網(wǎng)絡(luò)層的名稱

class ModuleDictExample(nn.module):
    def __init__(self):
        super().__init__()
        self.choices = nn.ModuleDict([
            'conv': nn.Conv2d(10,10,3),
            'pool': nn.MaxPool2d(3)
        ])
        self.activations = nn.ModuleDict([
            ['lrelu',nn.LeakyReLU()],
            ['prelu',nn.PReLU()]
        ])
    def forward(self,x,choice,act):
        x = self.choices[choice](x)
        x = self.activations[act](x)
        return x

模型的修改

1)修改模型

這里以resnet50作為修改模型,修改全連接層的輸出大小

import torch.nn as nn
import torchvision.models as models
from collections import OrderedDict

resnet = models.resnet50()

classifier_ten = nn.Sequential(OrderedDict([
      ('layer_1',nn.Linear(56,512)),
      ('layer_2',nn.ReLU()),
      ('layer_3',nn.Linear(512,8)),
]))
net.fc = classifier_ten

2)添加額外輸入

將原模型添加輸入位置前的部分作為一個整體,同時在forward中定義好原模型不變的部分,添加輸入和后續(xù)層之間的鏈接關(guān)系;

class myModel(nn.Module):
    def __init__(self,net):
        super().__init__()
        self.net = net
        self.relu = nn.Relu()
        self.dropout = nn.Dropout(0.5)
    def forward(self,x,add_variable):
        x = self.net(x)
        x = torch.cat((self.drop(self.relu(x)),add_variable.unsqueeze(1)))
        x = self.fc_add(x)
        x = self.output(x)
        return x

net = models.resnet50()
print('添加額外輸入之前:\n', net)
model = Model(net)
print('添加額外輸入之后:\n', model)

3)額外輸出

import torch.nn as nn
import  torch
import torchvision.models as models
from collections import OrderedDict

# 添加額外輸出
class Model(nn.Module):
    def __init__(self, net):
        super(Model, self).__init__()
        self.net = net
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(0.5)
        self.fc1 = nn.Linear(1000, 10, bias=True)
        self.output = nn.Softmax(dim=1)

    def forward(self, x):
        x1000 = self.net(x)
        x10 = self.dropout(self.relu(x1000))
        x10 = self.fc1(x10)
        x10 = self.output(x10)
        # 輸出倒數(shù)第二層x1000,和最后一層x10
        return x10, x1000

net = models.resnet50()
print('添加額外輸出之前:\n', net)
model = Model(net)
print('添加額外輸出之后:\n', model)

模型的保存與讀取

保存的格式:pkl,pt,pth

多卡模型存儲:torch.nn.DataParallel(model).cuda()

1)模型結(jié)構(gòu)與模型參數(shù)的保存

保存

save_dir = './models/resnet50.pkl'
model = models.resnet50(pretrained=True)
torch.save(model, save_dir)

加載

loaded_model = toch.load(save_dir)
loaded_model.eval()

2)只保存權(quán)重

保存

save_dir = './models/resnet50_state_dict.pkl'
torch.save(model.state_dict(),save_dir)

model.state_dict()返回的事一個orderdict,存儲了網(wǎng)絡(luò)結(jié)構(gòu)的名字和對應(yīng)的參數(shù)

加載

loaded_dict = torch.load(save_dir) #加載參數(shù)
loaded_model = models.resnet50()   #加載模型
loaded_model.state_dict = loaded_dict #還原模型中的變量值
loaded_model.eval()

loaded_model.state_dict = loaded_dict

可以使用下面的代碼進(jìn)行替換

loaded_model.load_statie_dict(loaded_dict,strict=True)

load_state_dict() 中還有一個關(guān)鍵的參數(shù) strict, 當(dāng)strict=True,要求預(yù)訓(xùn)練權(quán)重層數(shù)的鍵值與新構(gòu)建的模型中的權(quán)重層數(shù)名稱完全吻合;如果新構(gòu)建的模型在層數(shù)上進(jìn)行了部分微調(diào),則上述代碼就會報錯:key對應(yīng)不上, 此時,采用strict=False 就能夠解決這個問題

斷點(diǎn)續(xù)訓(xùn)

模型訓(xùn)練過程中的保存

checkpoint ={
    'net':model.state_dict(),
    'optimzer':optimizer.state_dict(),
    'epoch':epoch
}
torch.save(checkpoint, './models/checkpoint/ckpt_weight_12.pth')

斷點(diǎn)回復(fù)

1)首先加載最近的權(quán)重信息到模型中

2)配置epoch

3)讓模型開始訓(xùn)練

path_checkpoint = "./models/checkpoint/ckpt_weight_12.pth"
checkpoint = torch.load(path_checkpoint)
model.load_state_dict(checkpoint['net'])
optimizer.load_state_dict(checkpoint['optimizer'])
start_epoch = checkpoint['epoch']

for epoch in range(start_epoch+1,100):
    for step,(b_img,b_label) in enumerate(train_loader):
        train_output = model(b_img)
        loss = loss_func(train_output,b_label)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

學(xué)習(xí)率自動下降

TensorFlow提供了一種更加靈活的學(xué)習(xí)率設(shè)置方法-指數(shù)衰減法,使用tf.train.exponential_decay實(shí)現(xiàn)。指數(shù)衰減法的核心思想是,先使用較大的學(xué)習(xí)率來快速得到一個比較優(yōu)的解,然后隨著迭代的繼續(xù)逐步減小學(xué)習(xí)率,使得模型更加穩(wěn)定。tf.train.exponential_decay函數(shù)可以用以下代碼實(shí)現(xiàn)的功能來展示:

decayed_learning_rate = learning_rate*decay_rate^(global_step/decay_steps)
#decayed_learning_rate為每一輪優(yōu)化時使用的學(xué)習(xí)率,learning_rate為事先設(shè)定的初始學(xué)習(xí)率,decay_rate為衰減系數(shù),global_step為迭代次數(shù),decay_steps為衰減速度(即迭代多少次進(jìn)行衰減)

可見使用此函數(shù),隨著迭代次數(shù)的增加,學(xué)習(xí)率逐步降低。

tf.train.exponential_decay可以通過設(shè)置參數(shù)staircase選擇不同的衰減方式,其默認(rèn)值為False,既每一次迭代都進(jìn)行學(xué)習(xí)率的優(yōu)化,

global_step = tf.Variable(0)
learning_rate = tf.train.exponential_decay(0.1,global_step,100,0.96,staircase=True)
#0.1表示初始學(xué)習(xí)率,global_step表示迭代次數(shù),100表示衰減速度,0.96表示衰減率
#使用指數(shù)衰減的學(xué)習(xí)率,在minimize函數(shù)中傳入global_step,它將自動更新,learning_rate也隨即被更新
learning_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
#神經(jīng)網(wǎng)絡(luò)反向傳播算法,使用梯度下降算法GradientDescentOptimizer來優(yōu)化權(quán)重值,learning_rate為學(xué)習(xí)率,minimize中參數(shù)loss是損失函數(shù),global_step表明了當(dāng)前迭代次數(shù)(會被自動更新)

pytorch中進(jìn)行使用

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import StepLR
import itertools
initial_lr = 0.1

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()
optimizer_1 = torch.optim.Adam(net_1.parameters(),lr=initial_lr)
#對優(yōu)化方法進(jìn)行優(yōu)化
scheduler_1 = StepLR(optimizer_1, step_sie=3, gamma=0.1)
for epoch in range(1, 11):

    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d個epoch的學(xué)習(xí)率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()
import torch
import torch.nn as nn
from torch.optim.lr_scheduler import LambdaLR
class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()

optimizer_1 = torch.optim.Adam(net_1.parameters(), lr = initial_lr)
scheduler_1 = LambdaLR(optimizer_1, lr_lambda=lambda epoch: 1/(epoch+1))

print("初始化的學(xué)習(xí)率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train

    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d個epoch的學(xué)習(xí)率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

多步長SGD繼續(xù)訓(xùn)練

在簡單的任務(wù)中,我們使用固定步長(也就是學(xué)習(xí)率LR)進(jìn)行訓(xùn)練,但是如果學(xué)習(xí)率lr設(shè)置的過小的話,則會導(dǎo)致很難收斂,如果學(xué)習(xí)率很大的時候,就會導(dǎo)致在最小值附近,總會錯過最小值,loss產(chǎn)生震蕩,無法收斂。所以這要求我們要對于不同的訓(xùn)練階段使用不同的學(xué)習(xí)率,一方面可以加快訓(xùn)練的過程,另一方面可以加快網(wǎng)絡(luò)收斂。

所以我們在保存網(wǎng)絡(luò)中的訓(xùn)練的參數(shù)的過程中,還需要保存lr_scheduler的state_dict,然后斷點(diǎn)繼續(xù)訓(xùn)練的時候恢復(fù)

optimizer = torch.optim.SGD(model.parameters(),lr=0.1)
#這里我設(shè)置了不同的epoch對應(yīng)不同的學(xué)習(xí)率衰減,在10->20->30,學(xué)習(xí)率依次衰減為原來的0.1,即一個數(shù)量級
lr_schedule = torch.optim.lr_scheduler.MultiStepLR(optimizer,milestones=[10,20,30,40,50],gamma=0.1)


for epoch in range(start_epoch+1,80):
    optimizer.zero_grad()
    optimizer.step()
    lr_schedule.step()

    if epoch %10 ==0:
        print('epoch:',epoch)
        print('learning rate:',optimizer.state_dict()['param_groups'][0]['lr'])

我們在保存的時候,也需要對lr_scheduler的state_dict進(jìn)行保存,斷點(diǎn)繼續(xù)訓(xùn)練的時候也需要恢復(fù)lr_scheduler

if RESUME:
    path_checkpoint = "./model_parameter/test/ckpt_best_50.pth"  # 斷點(diǎn)路徑
    checkpoint = torch.load(path_checkpoint)  # 加載斷點(diǎn)

    model.load_state_dict(checkpoint['net'])  # 加載模型可學(xué)習(xí)參數(shù)

    optimizer.load_state_dict(checkpoint['optimizer'])  # 加載優(yōu)化器參數(shù)
    start_epoch = checkpoint['epoch']  # 設(shè)置開始的epoch
    lr_schedule.load_state_dict(checkpoint['lr_schedule'])#加載lr_scheduler
for epoch in range(start_epoch+1,80):

    optimizer.zero_grad()

    optimizer.step()
    lr_schedule.step()


    if epoch %10 ==0:
        print('epoch:',epoch)
        print('learning rate:',optimizer.state_dict()['param_groups'][0]['lr'])
        checkpoint = {
            "net": model.state_dict(),
            'optimizer': optimizer.state_dict(),
            "epoch": epoch,
            'lr_schedule': lr_schedule.state_dict()
        }
        if not os.path.isdir("./model_parameter/test"):
            os.mkdir("./model_parameter/test")
        torch.save(checkpoint, './model_parameter/test/ckpt_best_%s.pth' % (str(epoch)))
optimizer = torch.optim.SGD(model.parameters(),lr=0.1)
lr_schedule = torch.optim.lr_scheduler.MultiStepLR(optimizer,milestones=[10,20,30,40,50],gamma=0.1)
start_epoch = 9
# print(schedule)


if RESUME:
    path_checkpoint = "./model_parameter/test/ckpt_best_50.pth"  # 斷點(diǎn)路徑
    checkpoint = torch.load(path_checkpoint)  # 加載斷點(diǎn)

    model.load_state_dict(checkpoint['net'])  # 加載模型可學(xué)習(xí)參數(shù)

    optimizer.load_state_dict(checkpoint['optimizer'])  # 加載優(yōu)化器參數(shù)
    start_epoch = checkpoint['epoch']  # 設(shè)置開始的epoch
    lr_schedule.load_state_dict(checkpoint['lr_schedule'])

for epoch in range(start_epoch+1,80):

    optimizer.zero_grad()

    optimizer.step()
    lr_schedule.step()


    if epoch %10 ==0:
        print('epoch:',epoch)
        print('learning rate:',optimizer.state_dict()['param_groups'][0]['lr'])
        checkpoint = {
            "net": model.state_dict(),
            'optimizer': optimizer.state_dict(),
            "epoch": epoch,
            'lr_schedule': lr_schedule.state_dict()
        }
        if not os.path.isdir("./model_parameter/test"):
            os.mkdir("./model_parameter/test")
        torch.save(checkpoint, './model_parameter/test/ckpt_best_%s.pth' % (str(epoch)))

 總結(jié)

模型定義是深度學(xué)習(xí)中重要的一環(huán),PyTorch提供了強(qiáng)大而靈活的工具和函數(shù),使我們能夠輕松定義各種類型的深度學(xué)習(xí)模型。通過深入理解模型定義的原理和應(yīng)用,我們能夠更好地理解和設(shè)計自己的模型,從而提升深度學(xué)習(xí)任務(wù)的性能和效果。

到此這篇關(guān)于pytorch模型的定義、修改、讀取、斷點(diǎn)續(xù)訓(xùn)深入解析的文章就介紹到這了,更多相關(guān)pytorch模型的定義、修改、讀取、斷點(diǎn)續(xù)訓(xùn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python利用正則表達(dá)式搜索單詞示例代碼

    python利用正則表達(dá)式搜索單詞示例代碼

    正則表達(dá)式本身是一種小型的、高度專業(yè)化的編程語言,下面這篇文章主要給大家介紹了關(guān)于python利用正則表達(dá)式實(shí)現(xiàn)搜索單詞的相關(guān)資料,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • Python中反射和描述器總結(jié)

    Python中反射和描述器總結(jié)

    這篇文章主要介紹了Python中的反射和描述器一些知識的匯總,非常的詳細(xì),有需要的小伙伴可以參考下
    2018-09-09
  • pycharm 2019 最新激活方式(pycharm破解、激活)

    pycharm 2019 最新激活方式(pycharm破解、激活)

    這篇文章主要介紹了最新2019pycharm激活方式(pycharm破解、激活),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • python遍歷 truple list dictionary的幾種方法總結(jié)

    python遍歷 truple list dictionary的幾種方法總結(jié)

    下面小編就為大家?guī)硪黄猵ython遍歷 truple list dictionary的幾種方法總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • python 默認(rèn)參數(shù)問題的陷阱

    python 默認(rèn)參數(shù)問題的陷阱

    本文給大家講述的是python 默認(rèn)參數(shù)問題的陷阱,有需要的小伙伴可以參考下
    2016-02-02
  • PyTorch中Tensor的維度變換實(shí)現(xiàn)

    PyTorch中Tensor的維度變換實(shí)現(xiàn)

    這篇文章主要介紹了PyTorch中Tensor的維度變換實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Python入門(六)Python數(shù)據(jù)類型

    Python入門(六)Python數(shù)據(jù)類型

    這篇文章主要介紹了Python入門(六)Python數(shù)據(jù)類型,Python是一門非常強(qiáng)大好用的語言,也有著易上手的特性,本文為入門教程,需要的朋友可以參考下
    2023-04-04
  • ruff check文件目錄檢測--exclude參數(shù)設(shè)置路徑詳解

    ruff check文件目錄檢測--exclude參數(shù)設(shè)置路徑詳解

    這篇文章主要為大家介紹了ruff check文件目錄檢測exclude參數(shù)如何設(shè)置多少路徑詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 使用python構(gòu)建一個自己的聊天室

    使用python構(gòu)建一個自己的聊天室

    這篇文章主要介紹了使用python構(gòu)建一個自己的聊天室,有助于幫助小伙伴們理解掌握Python的socket編程,需要的朋友可以參考下
    2023-04-04
  • 教你利用Python破解ZIP或RAR文件密碼

    教你利用Python破解ZIP或RAR文件密碼

    常常會從網(wǎng)絡(luò)上下載一些帶密碼的壓縮包,想要獲取里面的內(nèi)容,往往就要給提供商支付一些費(fèi)用.想要白嫖其中的內(nèi)容,常見的做法是百度搜索一些壓縮包密碼破解軟件,但后果相信體驗(yàn)過的人都知道.本文詳細(xì)介紹了怎么破解壓縮包,需要的朋友可以參考下
    2021-05-05

最新評論