Pytorch框架構(gòu)建ResNet模型的實(shí)現(xiàn)示例
一、訓(xùn)練模型
1.導(dǎo)入資源包
import torch.optim as optim: 導(dǎo)入PyTorch的優(yōu)化工具包,其中包括了各種優(yōu)化算法,如SGD、Adam等。
import torchvision.transforms as transforms: 導(dǎo)入PyTorch的視覺(jué)變換工具包,用于對(duì)圖像進(jìn)行預(yù)處理和變換,如調(diào)整大小、裁剪、歸一化等。
from torchvision import models: 從torchvision模塊中導(dǎo)入預(yù)訓(xùn)練的模型,如ResNet、AlexNet、VGG等。
from sched import scheduler import torch.optim as optim import torch import torch.nn as nn import torch.utils.data import torchvision.transforms as transforms import torchvision.datasets as datasets from torch.utils.data import DataLoader import torch.optim.lr_scheduler as lr_scheduler import os from torchvision import models
2.定義數(shù)據(jù)預(yù)處理
這些預(yù)處理操作的目的是為了增強(qiáng)模型的泛化能力,并確保模型在訓(xùn)練和驗(yàn)證時(shí)輸入數(shù)據(jù)的格式一致。通過(guò)這些操作,模型能夠接受不同尺寸、角度和方向的圖像,從而提高其在實(shí)際應(yīng)用中的表現(xiàn)。同時(shí),歸一化處理有助于穩(wěn)定訓(xùn)練過(guò)程,加速模型收斂。,這些預(yù)處理操作的目的是為了增強(qiáng)模型的泛化能力,并確保模型在訓(xùn)練和驗(yàn)證時(shí)輸入數(shù)據(jù)的格式一致。通過(guò)這些操作,模型能夠接受不同尺寸、角度和方向的圖像,從而提高其在實(shí)際應(yīng)用中的表現(xiàn)。同時(shí),歸一化處理有助于穩(wěn)定訓(xùn)練過(guò)程,加速模型收斂。
# 定義數(shù)據(jù)預(yù)處理 transform = { 'train': transforms.Compose([ transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)), transforms.RandomRotation(degrees=15), transforms.RandomHorizontalFlip(), transforms.CenterCrop(size=224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]), 'val': transforms.Compose([ transforms.Resize(size=256), transforms.CenterCrop(size=224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) }
3.讀取數(shù)據(jù)
# 讀取數(shù)據(jù) dataset = './dataset' train_directory = os.path.join(dataset, 'train') valid_directory = os.path.join(dataset, 'val') batch_size = 32 num_classes = 2 # 修改為您的分類數(shù) data = { 'train': datasets.ImageFolder(root=train_directory, transform=transform['train']), 'val': datasets.ImageFolder(root=valid_directory, transform=transform['val']) } train_loader = DataLoader(data['train'], batch_size=batch_size, shuffle=True, num_workers=8) test_loader = DataLoader(data['val'], batch_size=batch_size, shuffle=False, num_workers=8)
注:這段代碼的主要目的是讀取和準(zhǔn)備圖像數(shù)據(jù)集,以便用于訓(xùn)練和驗(yàn)證深度學(xué)習(xí)模型,這段代碼設(shè)置了數(shù)據(jù)加載器,它們將在訓(xùn)練和驗(yàn)證過(guò)程中提供經(jīng)過(guò)預(yù)處理的圖像數(shù)據(jù)。這些數(shù)據(jù)加載器是PyTorch中用于批量加載數(shù)據(jù)并使其易于迭代的重要工具。
二、定義卷積神經(jīng)網(wǎng)絡(luò)
1.導(dǎo)入必要的庫(kù)
from torch.autograd import Variable: 從torch.autograd模塊中導(dǎo)入Variable類。Variable是PyTorch中自動(dòng)微分的關(guān)鍵類,它封裝了張量,并提供了自動(dòng)計(jì)算梯度等功能。然而,從PyTorch 0.4版本開(kāi)始,Variable已經(jīng)被整合到torch.Tensor中,因此不再需要顯式地從torch.autograd中導(dǎo)入Variable。在最新的PyTorch版本中,直接使用torch.Tensor即可,它繼承了Variable的所有功能。
# 神經(jīng)網(wǎng)絡(luò) import torch import torch.nn as nn from torch.autograd import Variable
2.定義名為convolutional_block的卷積塊類
這個(gè)convolutional_block類定義了一個(gè)卷積塊,它將輸入張量通過(guò)兩個(gè)并行路徑(step1和step2),然后將它們的結(jié)果相加,并應(yīng)用ReLU激活函數(shù)。這種結(jié)構(gòu)通常用于殘差網(wǎng)絡(luò)(ResNet)中,有助于解決深度網(wǎng)絡(luò)訓(xùn)練過(guò)程中的梯度消失問(wèn)題。
class convolutional_block(nn.Module):#convolutional_block層 def __init__(self,cn_input,cn_middle,cn_output,s=2): super(convolutional_block,self).__init__() self.step1=nn.Sequential(nn.Conv2d(cn_input,cn_middle,(1,1),(s,s),padding=0,bias=False),nn.BatchNorm2d(cn_middle,affine=False),nn.ReLU(inplace=True), nn.Conv2d(cn_middle,cn_middle,(3,3),(1,1),padding=(1,1),bias=False),nn.BatchNorm2d(cn_middle,affine=False),nn.ReLU(inplace=True), nn.Conv2d(cn_middle,cn_output,(1,1),(1,1),padding=0,bias=False),nn.BatchNorm2d(cn_output,affine=False)) self.step2=nn.Sequential(nn.Conv2d(cn_input,cn_output,(1,1),(s,s),padding=0,bias=False),nn.BatchNorm2d(cn_output,affine=False)) self.relu=nn.ReLU(inplace=True) def forward(self,x): x_tmp=x x=self.step1(x) x_tmp=self.step2(x_tmp) x=x+x_tmp x=self.relu(x) return x
3.定義了一個(gè)名為identity_block的恒等塊類
定義了一個(gè)名為identity_block的恒等塊類,它也是nn.Module的子類。這個(gè)類實(shí)現(xiàn)了一個(gè)恒等塊的構(gòu)造和前向傳播過(guò)程,它通常用于深度卷積神經(jīng)網(wǎng)絡(luò)(CNN)中,特別是在殘差網(wǎng)絡(luò)(ResNet)結(jié)構(gòu)中。恒等塊的主要特點(diǎn)是輸入和輸出之間有一個(gè)直接的聯(lián)系(即殘差連接),這有助于解決深度網(wǎng)絡(luò)訓(xùn)練過(guò)程中的梯度消失問(wèn)題。
class identity_block(nn.Module):#identity_block層 def __init__(self,cn,cn_middle): super(identity_block,self).__init__() self.step=nn.Sequential(nn.Conv2d(cn,cn_middle,(1,1),(1,1),padding=0,bias=False),nn.BatchNorm2d(cn_middle,affine=False),nn.ReLU(inplace=True), nn.Conv2d(cn_middle,cn_middle,(3,3),(1,1),padding=1,bias=False),nn.BatchNorm2d(cn_middle,affine=False),nn.ReLU(inplace=True), nn.Conv2d(cn_middle,cn,(1,1),(1,1),padding=0,bias=False),nn.BatchNorm2d(cn,affine=False)) self.relu=nn.ReLU(inplace=True) def forward(self,x): x_tmp=x x=self.step(x) x=x+x_tmp x=self.relu(x) return x
4.定義了一個(gè)名為Resnet的深度卷積神經(jīng)網(wǎng)絡(luò)類
class Resnet(nn.Module):#主層 def __init__(self,c_block,i_block): super(Resnet,self).__init__() self.conv=nn.Sequential(nn.Conv2d(3,64,(7,7),(2,2),padding=(3,3),bias=False),nn.BatchNorm2d(64,affine=False),nn.ReLU(inplace=True),nn.MaxPool2d((3,3),2,1)) self.layer1=c_block(64,64,256,1) self.layer2=i_block(256,64) self.layer3=c_block(256,128,512) self.layer4=i_block(512,128) self.layer5=c_block(512,256,1024) self.layer6=i_block(1024,256) self.layer7=c_block(1024,512,2048) self.layer8=i_block(2048,512) self.out=nn.Linear(2048,2,bias=False) self.avgpool=nn.AvgPool2d(7,7) def forward(self,input): x=self.conv(input) x=self.layer1(x) for i in range(2): x=self.layer2(x) x=self.layer3(x) for i in range(3): x=self.layer4(x) x=self.layer5(x) for i in range(5): x=self.layer6(x) x=self.layer7(x) for i in range(2): x=self.layer8(x) x=self.avgpool(x) x=x.view(x.size(0),-1) output=self.out(x) return output net=Resnet(convolutional_block,identity_block).cuda()
注:這段代碼定義了一個(gè)ResNet結(jié)構(gòu)的深度學(xué)習(xí)模型,它可以用于圖像分類任務(wù)。模型的結(jié)構(gòu)是模塊化的,可以通過(guò)調(diào)整卷積塊和恒等塊的數(shù)量和配置來(lái)適應(yīng)不同的需求和數(shù)據(jù)集。最后,模型被移動(dòng)到GPU上以加速訓(xùn)練和推理過(guò)程。
三、創(chuàng)建模型
1. 檢查GPU設(shè)備
如果 GPU 可用,則定義一個(gè) torch.device 對(duì)象,表示使用 GPU。如果 GPU 不可用,則定義一個(gè) torch.device 對(duì)象,表示使用 CPU。
以下是函數(shù)的詳細(xì)步驟:
1)檢查 GPU 可用性:
if torch.cuda.is_available(): 這行代碼檢查是否有可用的 GPU 設(shè)備。
device = torch.device(‘cuda’): 如果 GPU 可用,則定義一個(gè) torch.device 對(duì)象,表示使用 GPU。
print(“CUDA is available! Using GPU for training.”): 打印一條消息,表示 CUDA
可用,并且使用 GPU 進(jìn)行訓(xùn)練。else: 如果 GPU 不可用,則執(zhí)行以下代碼。
2)使用 CPU 進(jìn)行訓(xùn)練:
- evice = torch.device(‘cpu’): 定義一個(gè) torch.device 對(duì)象,表示使用 CPU。
- print(“CUDA is not available. Using CPU for training.”): 打印一條消息,表示 CUDA 不可用,并且使用 CPU 進(jìn)行訓(xùn)練。
# 首先,檢查是否有可用的 GPU if torch.cuda.is_available(): # 定義 GPU 設(shè)備 device = torch.device('cuda') print("CUDA is available! Using GPU for training.") else: # 如果沒(méi)有可用的 GPU,則使用 CPU device = torch.device('cpu') print("CUDA is not available. Using CPU for training.")
2. 訓(xùn)練過(guò)程
如果 GPU 可用,將模型移動(dòng)到 GPU 上,并使用 GPU 進(jìn)行訓(xùn)練;如果 GPU 不可用,則使用 CPU 進(jìn)行訓(xùn)練。
3)將模型移動(dòng)到 GPU:
- model.to(device): 將模型移動(dòng)到之前定義的 device 對(duì)象所表示的設(shè)備上。如果 device 是 ‘cuda’,則模型將被移動(dòng)到 GPU;如果 device 是 ‘cpu’,則模型將被移動(dòng)到 CPU。
4)定義損失函數(shù):
- criterion = nn.CrossEntropyLoss(): 定義交叉熵?fù)p失函數(shù),這是用于分類問(wèn)題的常見(jiàn)損失函數(shù)。
5)創(chuàng)建優(yōu)化器:
- optimizer = optim.Adam(Alex_model.parameters(), lr=0.001, weight_decay=1e-4): 創(chuàng)建Adam 優(yōu)化器,其中 lr=0.001 表示學(xué)習(xí)率為 0.001,weight_decay=1e-4 表示權(quán)重衰減為 0.0001。
# 將模型移動(dòng)到 GPU model.to(device) # 定義損失函數(shù) criterion = nn.CrossEntropyLoss() # 創(chuàng)建優(yōu)化器 optimizer = optim.Adam(Alex_model.parameters(), lr=0.001, weight_decay=1e-4)
運(yùn)行結(jié)果:
四、訓(xùn)練模型
1. 設(shè)置模型為訓(xùn)練模式
這個(gè)函數(shù)是訓(xùn)練過(guò)程中的核心部分,它執(zhí)行了模型的前向傳播、損失計(jì)算、反向傳播和參數(shù)更新,以及定期輸出訓(xùn)練進(jìn)度和性能指標(biāo)。
def train(model, device, train_loader, optimizer, epoch): model.train() running_loss = 0.0 correct = 0 total = 0 for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = criterion(output, target) loss.backward() optimizer.step() running_loss += loss.item() _, predicted = torch.max(output.data, 1) total += target.size(0) correct += (predicted == target).sum().item() if batch_idx % 10 == 0: # 每10個(gè)批次打印一次 print(f'Epoch {epoch}, Batch {batch_idx}, Loss: {loss.item()}') print(f'Epoch {epoch}, Loss: {running_loss / len(train_loader)}, Accuracy: {100 * correct / total}%')
2.定義實(shí)驗(yàn)過(guò)程
這個(gè)函數(shù)是模型評(píng)估過(guò)程中的核心部分,它計(jì)算了模型在驗(yàn)證集上的損失和準(zhǔn)確率,這些指標(biāo)對(duì)于監(jiān)控模型性能和調(diào)整訓(xùn)練策略非常重要。
# 定義驗(yàn)證過(guò)程 def val(model, device, test_loader, criterion): model.eval() running_loss = 0.0 correct = 0 total = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) loss = criterion(output, target) running_loss += loss.item() _, predicted = torch.max(output.data, 1) total += target.size(0) correct += (predicted == target).sum().item() print(f'Validation, Loss: {running_loss / len(test_loader)}, Accuracy: {100 * correct / total}%')
3.增加學(xué)習(xí)率調(diào)度器
通過(guò)訓(xùn)練和驗(yàn)證過(guò)程來(lái)優(yōu)化模型參數(shù),并使用學(xué)習(xí)率調(diào)度器來(lái)調(diào)整學(xué)習(xí)率,以提高模型的性能。在實(shí)際應(yīng)用中,EPOCHS通常會(huì)設(shè)置為一個(gè)較大的值,以確保模型得到充分的訓(xùn)練。
# 創(chuàng)建優(yōu)化器 optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4) # 創(chuàng)建學(xué)習(xí)率調(diào)度器 scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1) # 訓(xùn)練模型 EPOCHS = 1 for epoch in range(1, EPOCHS + 1): train(model, device, train_loader, optimizer, epoch) val(model, device, test_loader, criterion) scheduler.step() # 調(diào)整學(xué)習(xí)率
運(yùn)行結(jié)果:
六、測(cè)試模型
1.導(dǎo)入資源包
torchvision.transforms:這個(gè)模塊提供了一組圖像轉(zhuǎn)換操作,可以在數(shù)據(jù)加載時(shí)對(duì)圖像進(jìn)行預(yù)處理,例如調(diào)整大小、裁剪、翻轉(zhuǎn)等。
import torch from PIL import Image import torchvision.transforms as transforms from torchvision import models from torch.autograd import Variable
2.定義數(shù)據(jù)預(yù)處理
定義圖像的預(yù)處理步驟,并將使用GPU(如果可用)進(jìn)行模型訓(xùn)練。在實(shí)際應(yīng)用中,您需要根據(jù)自己的數(shù)據(jù)集和任務(wù)需求來(lái)調(diào)整這些參數(shù)。
定義數(shù)據(jù)預(yù)處理
transform = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) # 定義類別 classes = ['cat', 'dog'] # 替換為您的實(shí)際類別名稱 # 檢查是否有可用的 GPU DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
3.自定義Resnet50模型
定義了一個(gè)自定義的ResNet-50模型,這是一個(gè)在圖像識(shí)別任務(wù)中廣泛使用的卷積神經(jīng)網(wǎng)絡(luò)(CNN)架構(gòu)。代碼中使用了一些簡(jiǎn)寫,比如c_block和i_block,這些應(yīng)該是在代碼的其他部分定義的類,分別代表ResNet中的convolution block(卷積塊)和identity block(恒等塊)。
# 定義自定義的 Resnet50 模型 class Resnet(nn.Module):#主層 def __init__(self,c_block,i_block): super(Resnet,self).__init__() self.conv=nn.Sequential(nn.Conv2d(3,64,(7,7),(2,2),padding=(3,3),bias=False),nn.BatchNorm2d(64,affine=False),nn.ReLU(inplace=True),nn.MaxPool2d((3,3),2,1)) self.layer1=c_block(64,64,256,1) self.layer2=i_block(256,64) self.layer3=c_block(256,128,512) self.layer4=i_block(512,128) self.layer5=c_block(512,256,1024) self.layer6=i_block(1024,256) self.layer7=c_block(1024,512,2048) self.layer8=i_block(2048,512) self.out=nn.Linear(2048,2,bias=False) self.avgpool=nn.AvgPool2d(7,7) def forward(self,input): x=self.conv(input) x=self.layer1(x) for i in range(2): x=self.layer2(x) x=self.layer3(x) for i in range(3): x=self.layer4(x) x=self.layer5(x) for i in range(5): x=self.layer6(x) x=self.layer7(x) for i in range(2): x=self.layer8(x) x=self.avgpool(x) x=x.view(x.size(0),-1) output=self.out(x) return output
4.實(shí)例化 Resnet50 類
用于加載預(yù)訓(xùn)練的ResNet-50模型,并使用該模型對(duì)上傳的圖片進(jìn)行預(yù)測(cè),image = Variable(image).to(DEVICE): 這一行將預(yù)處理后的圖像轉(zhuǎn)換為PyTorch變量(如果您的模型需要),并將其移動(dòng)到DEVICE上。
# 實(shí)例化 Resnet50 類 model=Resnet(convolutional_block,identity_block).cuda() # 加載權(quán)重 model.load_state_dict(torch.load("Resnet50.pth")) model.to(DEVICE) model.eval() # 定義預(yù)測(cè)函數(shù) def predict_image(image_path): # 打開(kāi)圖片 image = Image.open(image_path) # 應(yīng)用預(yù)處理 image = transform(image).unsqueeze(0) # 添加batch維度 # 轉(zhuǎn)換為Variable(如果模型需要) image = Variable(image).to(DEVICE) # 獲取模型預(yù)測(cè) output = model(image) _, prediction = torch.max(output.data, 1) return classes[prediction.item()] # 上傳的圖片路徑 uploaded_image_path = '77.jpg' # 進(jìn)行預(yù)測(cè) predicted_class = predict_image(uploaded_image_path) print(f"The uploaded image is predicted as: {predicted_class}")
運(yùn)行結(jié)果:
到此這篇關(guān)于Pytorch框架構(gòu)建ResNet模型的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Pytorch構(gòu)建ResNet模型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python中不同數(shù)據(jù)對(duì)象的空值校驗(yàn)總結(jié)
在Python中,我們可以使用不同的方式來(lái)校驗(yàn)數(shù)值的空值、字符串的空值以及對(duì)象的空值,本文為大家整理了一些常見(jiàn)的方法,希望對(duì)大家有所幫助2024-01-01python中multiprosessing模塊的Pool類中的apply函數(shù)和apply_async函數(shù)的區(qū)別
這篇文章主要介紹了python中multiprosessing模塊的Pool類中的apply函數(shù)和apply_async函數(shù)的區(qū)別、文章圍繞主題的相關(guān)內(nèi)容展開(kāi)詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06Django 添加靜態(tài)文件的兩種實(shí)現(xiàn)方法(必看篇)
下面小編就為大家?guī)?lái)一篇Django 添加靜態(tài)文件的兩種實(shí)現(xiàn)方法(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07Python讀取Excel一列并計(jì)算所有對(duì)象出現(xiàn)次數(shù)的方法
這篇文章主要給大家介紹了關(guān)于Python讀取Excel一列并計(jì)算所有對(duì)象出現(xiàn)次數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Python3利用SMTP協(xié)議發(fā)送E-mail電子郵件的方法
SMTP(Simple Mail Transfer Protocol)即簡(jiǎn)單郵件傳輸協(xié)議,它是一組用于由源地址到目的地址傳送郵件的規(guī)則,由它來(lái)控制信件的中轉(zhuǎn)方式。下面這篇文章主要給大家介紹了關(guān)于Python3如何利用SMTP協(xié)議發(fā)送E-mail電子郵件的方法,需要的朋友可以參考下。2017-09-09python導(dǎo)入導(dǎo)出redis數(shù)據(jù)的實(shí)現(xiàn)
本文主要介紹了python導(dǎo)入導(dǎo)出redis數(shù)據(jù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02python調(diào)用opencv實(shí)現(xiàn)貓臉檢測(cè)功能
這篇文章主要介紹了python調(diào)用opencv實(shí)現(xiàn)貓臉檢測(cè)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Python實(shí)現(xiàn)批量Excel拆分功能
在日常辦公中,我們經(jīng)常需要將包含多個(gè)Sheet頁(yè)的Excel文件拆分成多個(gè)獨(dú)立的Excel文件,下面我們就來(lái)看看如何使用Python實(shí)現(xiàn)批量Excel拆分的功能吧2025-02-02