土堆Pytorch学习笔记(三)
2023.04.02
(一)優化器
同樣是在pytorch官網找到優化器(optim),查看官方文檔。下面以
optim = torch.optim.SGD(nerualnetwork.parameters(), lr=0.01) 為例 optim = torch.optim.SGD(nerualnetwork.parameters(), lr=0.01)for epoch in range(20):running_loss = 0.0for data in dataloader:imgs, targets = dataoutput = nerualnetwork(imgs)# 計算交叉熵損失函數 網絡的輸出和真實的target之間的差距result_loss = loss(output, targets)# 梯度下降(反向傳播optim.zero_grad()result_loss.backward()optim.step()running_loss = running_loss + result_lossprint(running_loss)使用優化器時要先調用 optim.zero_grad() 將原來的梯度置零,然后再進行反向傳播。
一般網絡會進行成百上千甚至上萬次學習(這里設置的是20次),理論上來說誤差函數要越來越小。
(二)Pytorch提供的網絡模型及修改使用
以vgg16為例:
vgg16能夠將圖片分成1000個類別,我們只需要10個類別就足夠了,所以修改的辦法是:
1. 加入一個線性層(將1000映射到10)
2.直接將最后一個線性層的參數修改(1000修改成10)
1.?加入一個線性層
vgg16_true.add_module('add_linear', nn.Linear(1000, 10))這么做的結果是在網絡最后多了一個名為(add_linear)的 model
?那么要是希望將此線性層加在上一個(或任一個)model 中:
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))?2. 直接將最后一個線性層的參數修改
vgg16_false.classifier[6] = nn.Linear(4096, 10)?(三)網絡模型的保存與讀取
1.保存方式1:模型結構+模型參數
torch.save(vgg16, 'vgg16_method1.pth')加載模型:
model = torch.load('vgg16_method1.pth')2.保存方式2:模型參數(官方推薦)
torch.save(vgg16.state_dict(), 'vgg16_method2.pth') # 將vgg16保存成字典形式加載模型:
model = torch.load('vgg16_method2.pth')結果是由參數組成的字典,沒有網絡結構的相關信息
要顯示網絡相關結構的話,需要下面代碼:
# model = torch.load('vgg16_method2.pth') vgg16 = torchvision.models.vgg16(weights=None) vgg16.load_state_dict(torch.load('vgg16_method2.pth'))print(vgg16)(四)完整的模型訓練套路
4.1 首先測試網絡的正確性
? ? ? ? 一般網絡模型是單獨放在一個.py文件里的,并在里面測試網絡的正確性
比如有這樣一個網絡(CIFAR 10):
# 搭建神經網絡 class CIFAR10(nn.Module):def __init__(self):super(CIFAR10, self).__init__()self.model = nn.Sequential(nn.Conv2d(3, 32, 5, 1, 2),nn.MaxPool2d(2,),nn.Conv2d(32, 32, 4, 1 ,2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, 1, 2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024, 64),nn.Linear(64, 10))def forward(self, x):x = self.model(x)return x測試輸出結果的正確性:
if __name__ =='__main__'cifar10 = CIFAR10()# 創建輸入尺寸input = torch.ones((64, 3, 32, 32))output = cifar10(input)print(output)4.2 進行訓練前的一些初始化
# 初始化網絡 cifar10 = CIFAR10() # 創建損失函數 (因為網絡處理的是分類問題,所以可以使用交叉熵損失函數 loss_fn = nn.CrossEntropyLoss() # 定義優化器 learning_rate = 0.01 optim = torch.optim.SGD(cifar10.parameters(), lr=learning_rate) # 設置訓練網絡的參數 # 1. total_train_step:記錄訓練次數 total_train_step = 0 # 2. total_test_step: 記錄測試的次數 total_test_step = 0 # 3. epoch:記錄訓練的輪數 epoch = 104.3 訓練網絡
for i in range(epoch):print('----------第{}輪訓練開始----------'.format(i+1))# 訓練步驟開始for data in train_dataloader:imgs, targets = dataoutputs= cifar10(imgs)loss = loss_fn(outputs, targets)# 調用優化器通過計算出的損失進行優化optim.zero_grad()loss.backward()optim.step()total_train_step += 1print('訓練次數是:{},loss:{}'.format(total_train_step, loss.item))4.4檢驗模型是否訓練好或者是否達到需求?
首先在訓練集上要去除梯度,定義整體的測試loss和準確性,通過調用output的 argmax(1) 屬性來檢驗正確性,代碼如下:
# 為了檢驗模型是否訓練達標,需要每訓練一次都驗證一下,驗證時不需要調優 # 測試步驟開始total_test_loss = 0total_accuracy = 0with torch.no_grad(): # 表示沒有梯度(因為梯度是用來調優的,這里不需要for data in test_dataloader:imgs, targets = dataoutputs = cifar10(imgs)loss = loss_fn(outputs, targets)# 需要的是整個數據集的Losstotal_test_loss = total_test_loss + loss.item()accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint('整體測試集上的loss:{}'.format(total_test_loss))print('整體測試集上的正確率:{}'.format(total_accuracy/test_data_size))writer.add_scalar('test_accuracy', total_accuracy/test_data_size, total_test_step)writer.add_scalar("test_loss", total_test_loss, total_test_step)total_test_loss += 1# 保存每一輪訓練的模型torch.save(cifar10, 'cifar10_{}.pth'.format(i))print('模型已保存')4.5?添加tensorboard來實時查看loss
writer = SummaryWriter('logs_train') writer.add_scalar("train_loss", loss.item(), total_train_step)...
整體的訓練代碼:
import torch.optim from torch import nn from torch.utils.data import DataLoader import torchvision.datasetsfrom torch.utils.tensorboard import SummaryWriter # 準備數據集 train_data = torchvision.datasets.CIFAR10(root='./new_dataset', train=True, transform=torchvision.transforms.ToTensor(), download=True) # 準備測試集 test_data = torchvision.datasets.CIFAR10(root='./new_dataset', train=False, transform=torchvision.transforms.ToTensor(), download=True) # 查看訓練/測試數據集的大小(有多少張圖片 train_data_size = len(train_data) test_data_size = len(test_data)# 利用dataloader加載數據集 train_dataloader = DataLoader(train_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64)# 搭建神經網絡 class CIFAR10(nn.Module):def __init__(self):super(CIFAR10, self).__init__()self.model = nn.Sequential(nn.Conv2d(3, 32, 5, 1, 2),nn.MaxPool2d(2,),nn.Conv2d(32, 32, 4, 1 ,2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, 1, 2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024, 64),nn.Linear(64, 10))def forward(self, x):x = self.model(x)return x # 以上為整個網絡模型,一般是單獨放在一個.py文件里的,并在里面測試網絡的正確性# 初始化網絡 cifar10 = CIFAR10() # 創建損失函數 (因為網絡處理的是分類問題,所以可以使用交叉熵損失函數 loss_fn = nn.CrossEntropyLoss() # 定義優化器 learning_rate = 0.01 optim = torch.optim.SGD(cifar10.parameters(), lr=learning_rate) # 設置訓練網絡的參數 # 1. total_train_step:記錄訓練次數 total_train_step = 0 # 2. total_test_step: 記錄測試的次數 total_test_step = 0 # 3. epoch:記錄訓練的輪數 epoch = 10# 添加tensorboard writer = SummaryWriter('logs_train')for i in range(epoch):print('----------第{}輪訓練開始----------'.format(i+1))# 訓練步驟開始for data in train_dataloader:imgs, targets = dataoutputs= cifar10(imgs)loss = loss_fn(outputs, targets)# 調用優化器通過計算出的損失進行優化optim.zero_grad()loss.backward()optim.step()total_train_step += 1# 由于數據太多了,所以只打印逢100的損失if total_train_step % 100 == 0:print('訓練次數是:{},loss:{}'.format(total_train_step, loss.item()))writer.add_scalar("train_loss", loss.item(), total_train_step)# 為了檢驗模型是否訓練達標,需要每訓練一次都驗證一下,驗證時不需要調優 # 測試步驟開始total_test_loss = 0total_accuracy = 0with torch.no_grad(): # 表示沒有梯度(因為梯度是用來調優的,這里不需要for data in test_dataloader:imgs, targets = dataoutputs = cifar10(imgs)loss = loss_fn(outputs, targets)# 需要的是整個數據集的Losstotal_test_loss = total_test_loss + loss.item()accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint('整體測試集上的loss:{}'.format(total_test_loss))print('整體測試集上的正確率:{}'.format(total_accuracy/test_data_size))writer.add_scalar('test_accuracy', total_accuracy/test_data_size, total_test_step)writer.add_scalar("test_loss", total_test_loss, total_test_step)total_test_loss += 1# 保存每一輪訓練的模型torch.save(cifar10, 'cifar10_{}.pth'.format(i))print('模型已保存')writer.close()(五)使用GPU訓練
方法一:對網絡模型、數據(輸入和標定)和損失函數進行 ' .cuda '操作,具體看自己電腦上的P30_train_GPU1
方法二:device = torch.device('cuda')
? ? ? ? ? ? ? ? 然后同樣的進行‘. to(device)’ 操作
(六)完整的模型驗證(測試、demo)套路
利用已經訓練好的模型,然后給他提供輸入。
1.首先網絡模型中的圖片是32 * 32 大小的,所以要先將圖片進行reshape。
2.另外,如果圖片是png格式的(png格式是4通道的,RGB和一個透明度通道),要調用下行代碼保留其顏色通道,除去透明度通道。
image = image.convert('RGB')3.搭建神經網絡模型,并加載模型
4.這里測試的是胰臟圖片,所以batch_size = 1?
image = torch.reshape(image, (1, 3, 32, 32))5.最后有兩行很重要的代碼,model.eval()表示是用來測試的;with torch.no_grad():目的是將梯度置零(因為我們是測試模型,并不進行調優),這樣做還可以節省空間
6.最后就將圖片放入網絡,再打印其輸出就能查看其準確性了
output = model(image)整體代碼:
import torch import torchvision.transforms from PIL import Image from torch import nnimg_path = 'dog.png' image = Image.open(img_path) # 將圖片讀取成PIL類型# 因為網絡模型中的圖片大小是32 * 32 ,所以要將圖片大小進行調整 image = image.convert('RGB') # 由于圖片是png形式的,有四個通道,需要調用此行代碼進行保留顏色通道除去透明度通道 transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),torchvision.transforms.ToTensor()]) image = transform(image) # 搭建神經網絡 class CIFAR10(nn.Module):def __init__(self):super(CIFAR10, self).__init__()self.model = nn.Sequential(nn.Conv2d(3, 32, 5, 1, 2),nn.MaxPool2d(2,),nn.Conv2d(32, 32, 4, 1 ,2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, 1, 2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024, 64),nn.Linear(64, 10))def forward(self, x):x = self.model(x)return x # 加載網絡模型 model = torch.load('cifar10_0.pth') print(model) image = torch.reshape(image, (1, 3, 32, 32)) model.eval() with torch.no_grad():output = model(image) print(output)print(output.argmax(1)) # 打印輸出對應的類別(通過調試可以看到類別對應的target)總結
以上是生活随笔為你收集整理的土堆Pytorch学习笔记(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 用Steam教育启发学生多元化思维
- 下一篇: 深入浅出kafka原理-2-Kafka为
