Pytorch框架構建ResNet模型的實現示例
一、訓練模型
1.導入資源包
import torch.optim as optim: 導入PyTorch的優(yōu)化工具包,其中包括了各種優(yōu)化算法,如SGD、Adam等。
import torchvision.transforms as transforms: 導入PyTorch的視覺變換工具包,用于對圖像進行預處理和變換,如調整大小、裁剪、歸一化等。
from torchvision import models: 從torchvision模塊中導入預訓練的模型,如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.定義數據預處理
這些預處理操作的目的是為了增強模型的泛化能力,并確保模型在訓練和驗證時輸入數據的格式一致。通過這些操作,模型能夠接受不同尺寸、角度和方向的圖像,從而提高其在實際應用中的表現。同時,歸一化處理有助于穩(wěn)定訓練過程,加速模型收斂。,這些預處理操作的目的是為了增強模型的泛化能力,并確保模型在訓練和驗證時輸入數據的格式一致。通過這些操作,模型能夠接受不同尺寸、角度和方向的圖像,從而提高其在實際應用中的表現。同時,歸一化處理有助于穩(wěn)定訓練過程,加速模型收斂。
# 定義數據預處理 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.讀取數據
# 讀取數據 dataset = './dataset' train_directory = os.path.join(dataset, 'train') valid_directory = os.path.join(dataset, 'val') batch_size = 32 num_classes = 2 # 修改為您的分類數 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)
注:這段代碼的主要目的是讀取和準備圖像數據集,以便用于訓練和驗證深度學習模型,這段代碼設置了數據加載器,它們將在訓練和驗證過程中提供經過預處理的圖像數據。這些數據加載器是PyTorch中用于批量加載數據并使其易于迭代的重要工具。
二、定義卷積神經網絡
1.導入必要的庫
from torch.autograd import Variable: 從torch.autograd模塊中導入Variable類。Variable是PyTorch中自動微分的關鍵類,它封裝了張量,并提供了自動計算梯度等功能。然而,從PyTorch 0.4版本開始,Variable已經被整合到torch.Tensor中,因此不再需要顯式地從torch.autograd中導入Variable。在最新的PyTorch版本中,直接使用torch.Tensor即可,它繼承了Variable的所有功能。
# 神經網絡 import torch import torch.nn as nn from torch.autograd import Variable
2.定義名為convolutional_block的卷積塊類
這個convolutional_block類定義了一個卷積塊,它將輸入張量通過兩個并行路徑(step1和step2),然后將它們的結果相加,并應用ReLU激活函數。這種結構通常用于殘差網絡(ResNet)中,有助于解決深度網絡訓練過程中的梯度消失問題。
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.定義了一個名為identity_block的恒等塊類
定義了一個名為identity_block的恒等塊類,它也是nn.Module的子類。這個類實現了一個恒等塊的構造和前向傳播過程,它通常用于深度卷積神經網絡(CNN)中,特別是在殘差網絡(ResNet)結構中。恒等塊的主要特點是輸入和輸出之間有一個直接的聯(liá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.定義了一個名為Resnet的深度卷積神經網絡類
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()
注:這段代碼定義了一個ResNet結構的深度學習模型,它可以用于圖像分類任務。模型的結構是模塊化的,可以通過調整卷積塊和恒等塊的數量和配置來適應不同的需求和數據集。最后,模型被移動到GPU上以加速訓練和推理過程。
三、創(chuàng)建模型
1. 檢查GPU設備
如果 GPU 可用,則定義一個 torch.device 對象,表示使用 GPU。如果 GPU 不可用,則定義一個 torch.device 對象,表示使用 CPU。
以下是函數的詳細步驟:
1)檢查 GPU 可用性:
if torch.cuda.is_available(): 這行代碼檢查是否有可用的 GPU 設備。
device = torch.device(‘cuda’): 如果 GPU 可用,則定義一個 torch.device 對象,表示使用 GPU。
print(“CUDA is available! Using GPU for training.”): 打印一條消息,表示 CUDA
可用,并且使用 GPU 進行訓練。else: 如果 GPU 不可用,則執(zhí)行以下代碼。
2)使用 CPU 進行訓練:
- evice = torch.device(‘cpu’): 定義一個 torch.device 對象,表示使用 CPU。
- print(“CUDA is not available. Using CPU for training.”): 打印一條消息,表示 CUDA 不可用,并且使用 CPU 進行訓練。
# 首先,檢查是否有可用的 GPU if torch.cuda.is_available(): # 定義 GPU 設備 device = torch.device('cuda') print("CUDA is available! Using GPU for training.") else: # 如果沒有可用的 GPU,則使用 CPU device = torch.device('cpu') print("CUDA is not available. Using CPU for training.")
2. 訓練過程
如果 GPU 可用,將模型移動到 GPU 上,并使用 GPU 進行訓練;如果 GPU 不可用,則使用 CPU 進行訓練。
3)將模型移動到 GPU:
- model.to(device): 將模型移動到之前定義的 device 對象所表示的設備上。如果 device 是 ‘cuda’,則模型將被移動到 GPU;如果 device 是 ‘cpu’,則模型將被移動到 CPU。
4)定義損失函數:
- criterion = nn.CrossEntropyLoss(): 定義交叉熵損失函數,這是用于分類問題的常見損失函數。
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 表示學習率為 0.001,weight_decay=1e-4 表示權重衰減為 0.0001。
# 將模型移動到 GPU model.to(device) # 定義損失函數 criterion = nn.CrossEntropyLoss() # 創(chuàng)建優(yōu)化器 optimizer = optim.Adam(Alex_model.parameters(), lr=0.001, weight_decay=1e-4)
運行結果:
四、訓練模型
1. 設置模型為訓練模式
這個函數是訓練過程中的核心部分,它執(zhí)行了模型的前向傳播、損失計算、反向傳播和參數更新,以及定期輸出訓練進度和性能指標。
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個批次打印一次 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.定義實驗過程
這個函數是模型評估過程中的核心部分,它計算了模型在驗證集上的損失和準確率,這些指標對于監(jiān)控模型性能和調整訓練策略非常重要。
# 定義驗證過程 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.增加學習率調度器
通過訓練和驗證過程來優(yōu)化模型參數,并使用學習率調度器來調整學習率,以提高模型的性能。在實際應用中,EPOCHS通常會設置為一個較大的值,以確保模型得到充分的訓練。
# 創(chuàng)建優(yōu)化器 optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4) # 創(chuàng)建學習率調度器 scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1) # 訓練模型 EPOCHS = 1 for epoch in range(1, EPOCHS + 1): train(model, device, train_loader, optimizer, epoch) val(model, device, test_loader, criterion) scheduler.step() # 調整學習率
運行結果:
六、測試模型
1.導入資源包
torchvision.transforms:這個模塊提供了一組圖像轉換操作,可以在數據加載時對圖像進行預處理,例如調整大小、裁剪、翻轉等。
import torch from PIL import Image import torchvision.transforms as transforms from torchvision import models from torch.autograd import Variable
2.定義數據預處理
定義圖像的預處理步驟,并將使用GPU(如果可用)進行模型訓練。在實際應用中,您需要根據自己的數據集和任務需求來調整這些參數。
定義數據預處理
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'] # 替換為您的實際類別名稱 # 檢查是否有可用的 GPU DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
3.自定義Resnet50模型
定義了一個自定義的ResNet-50模型,這是一個在圖像識別任務中廣泛使用的卷積神經網絡(CNN)架構。代碼中使用了一些簡寫,比如c_block和i_block,這些應該是在代碼的其他部分定義的類,分別代表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.實例化 Resnet50 類
用于加載預訓練的ResNet-50模型,并使用該模型對上傳的圖片進行預測,image = Variable(image).to(DEVICE): 這一行將預處理后的圖像轉換為PyTorch變量(如果您的模型需要),并將其移動到DEVICE上。
# 實例化 Resnet50 類 model=Resnet(convolutional_block,identity_block).cuda() # 加載權重 model.load_state_dict(torch.load("Resnet50.pth")) model.to(DEVICE) model.eval() # 定義預測函數 def predict_image(image_path): # 打開圖片 image = Image.open(image_path) # 應用預處理 image = transform(image).unsqueeze(0) # 添加batch維度 # 轉換為Variable(如果模型需要) image = Variable(image).to(DEVICE) # 獲取模型預測 output = model(image) _, prediction = torch.max(output.data, 1) return classes[prediction.item()] # 上傳的圖片路徑 uploaded_image_path = '77.jpg' # 進行預測 predicted_class = predict_image(uploaded_image_path) print(f"The uploaded image is predicted as: {predicted_class}")
運行結果:
到此這篇關于Pytorch框架構建ResNet模型的實現示例的文章就介紹到這了,更多相關Pytorch構建ResNet模型內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python中multiprosessing模塊的Pool類中的apply函數和apply_async函數的區(qū)別
這篇文章主要介紹了python中multiprosessing模塊的Pool類中的apply函數和apply_async函數的區(qū)別、文章圍繞主題的相關內容展開詳細介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-06-06Django 添加靜態(tài)文件的兩種實現方法(必看篇)
下面小編就為大家?guī)硪黄狣jango 添加靜態(tài)文件的兩種實現方法(必看篇)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07Python3利用SMTP協(xié)議發(fā)送E-mail電子郵件的方法
SMTP(Simple Mail Transfer Protocol)即簡單郵件傳輸協(xié)議,它是一組用于由源地址到目的地址傳送郵件的規(guī)則,由它來控制信件的中轉方式。下面這篇文章主要給大家介紹了關于Python3如何利用SMTP協(xié)議發(fā)送E-mail電子郵件的方法,需要的朋友可以參考下。2017-09-09