1. 程式人生 > 實用技巧 >PyTorch學習-總結篇(3)——最實用部分

PyTorch學習-總結篇(3)——最實用部分

PyTorch學習-總結篇(3)——最實用部分

PyTorch學習-總結篇(3)——最實用部分

  一、每個專案程式碼應該有五個部分(大同小異)

  二、以一個專案示例來進行講解(MNIST手寫資料集)

    1.導包及定義超引數(這步往往是最後才能完成的,因為只有寫完了下面,才能知道你要定義什麼及用什麼包)

    2.資料集讀入

    3.模型的搭建

    4.損失函式、優化器、視覺化及繼續訓練

    5.模型的訓練

經過(1)和(2)的學習,相信對基礎知識有一定的瞭解,其實如果想快速進行程式碼書寫與專案除錯及執行,僅看(3)應該可以讓你快速掌握專案的編寫規則。

一、每個專案程式碼應該有五個部分(大同小異)

  • 首先,一個專案的程式碼應該是導包及定義我們的超引數

  • 然後,將本次專案所需資料集讀入,一般包括訓練集和測試集兩個部分

  • 其次,開始搭建我們的網路模型主體框架

  • 再然後,是進行模型的損失函式、優化器及視覺化操作

  • 最後,是進行我們模型的訓練及測試

二、以一個專案示例來進行講解(MNIST手寫資料集)

1.導包及定義超引數(這步往往是最後才能完成的,因為只有寫完了下面,才能知道你要定義什麼及用什麼包)

# -*- coding: utf-8 -*-
# -程式碼界的小菜鳥-

import os
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from tensorboardX import SummaryWriter
from torchvision import datasets,transforms

batch_size = 64
epochs = 10
checkpoints_dir = './checkpoints'
event_dir = './event_file'
model_name = None # 如果需要載入模型繼續訓練,則’/10.pth‘
lr = 1e-4

#檢測GPU是否可以使用
print('GPU是否可用:', torch.cuda.is_available()) # 可用為True
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

2.資料集讀入

# 例項化資料集Dataset
train_dataset = datasets.MNIST(root='./dataset/', train=True, download=True,transform=transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]))
test_dataset = datasets.MNIST(root='./dataset/', train=False, transform=transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]))

# 資料載入器
train_loader = Data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) # shuffle是否隨機打亂順序
test_loader = Data.DataLoader(test_dataset, batch_size=batch_size, shuffle=True)

# 儲存檢查點的地址
if not os.path.exists(checkpoints_dir):
os.makedirs(checkpoints_dir)

3.模型的搭建

# 模型搭建(pytorch框架定義的的神經網路模型都需要繼承nn.Module類)
class Net(nn.Module):

# 初始化函式,定義了該神經網路的基本結構
def __init__(self):
super(Net, self).__init__() # 複製並使用Net的父類的初始化方法,即先執行nn.Module的初始化函式
self.conv1 = nn.Conv2d(in_channels=1, out_channels=20, kernel_size=5, stride=1) # 輸入為影象(1),即灰度圖,輸出為20張特徵圖,卷積和為5*5的正方形
self.conv2 = nn.Conv2d(in_channels=20, out_channels=20, kernel_size=5, stride=1)
self.fc1 = nn.Linear(in_features=4*4*50, out_features=500) # 定義全連線線性函式:y=Wx+b,並將4*4*50個節點連線到500個節點上
self.fc2 = nn.Linear(in_features=500, out_features=10)

# 定義神經網路的前向傳播函式
def forward(self, x):
x = F.relu(self.conv1(x)) # 輸入x經過卷積conv1後,再經過一個啟用函式更新x
x = F.max_pool2d(x, kernel_size=2, stride=2) # 經過啟用函式後,使用2*2的視窗進行最大池化,更新x
x = F.relu(self.conv2(x))
x = F.max_pool2d(x, 2, 2)
x = x.view(-1, 4 * 4 * 50) # 利用view函式將張量x變成一維向量的形式,總特徵個數不變
x = F.relu(self.fc1(x)) # 更新後的x經過全連線函式,再經過啟用函式,更新x
x = self.fc2(x)
return x

# 模型例項化
model = Net().to(device)

4.損失函式、優化器、視覺化及繼續訓練

# 定義損失函式
criterion = nn.CrossEntropyLoss() # 交叉熵損失函式

# 定義優化器
optimzer = optim.SGD(model.parameters(), lr=lr)

# 視覺化處理
writer = SummaryWriter(event_dir)

# 繼續訓練
start_epoch = 0
if model_name:
print('載入模型:',checkpoints_dir + model_name)
checkpoint = torch.load(checkpoints_dir + model_name)
model.load_state_dict(checkpoint['model_state_dict'])
optimzer.load_state_dict(checkpoint['optimizer_state_dict'])
start_epoch = checkpoint['epoch']

5.模型的訓練

# 開始訓練
for epoch in range(start_epoch, epochs):
model.train() # 模型訓練的標誌
for batch_idx, (data, target) in enumerate(train_loader):
data = data.to(device) # 訓練資料,放到GPU上
target = target.to(device) # 訓練標籤,放到GPU上

# 前向傳播
output = model(data)
loss = criterion(output, target) # 計算損失函式

# 反向傳播
optimzer.zero_grad() # 首先進行梯度清零
loss.backward() # 反向傳播
optimzer.step() # 更新引數

print('Train Epoch: {} \tLoss:{{:,6f}}'.format(epoch+1, loss.item()))

# 視覺化
writer.add_scalar(tag='train_loss', scalar_value=loss.item(), global_step=epoch + 1)
writer.flush()


model.eval() # 模型測試的標誌
test_loss = 0
correct = 0

with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)

output = model(data)
pred = output.argmax(dim=1, keepdim=True) # 獲取最大的對數概率的索引
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss += criterion(output, target).item()

test_loss /= len(test_loader.dataset)
print('測試集:損失:{:.4f},精度:{:.2f}%'.format(test_loss, 100. * correct / len(test_loader.dataset)))

# 視覺化
writer.add_scalar(tag='val_loss', scalar_value=test_loss, global_step=epoch + 1)
writer.flush()


# 儲存模型
if (epoch + 1) % 10 ==0:
checkpoint = {'model_state_dict':model.state_dict(), 'optimizer_state_dict': optimzer.state_dict(), 'epoch': epoch + 1}
torch.save(checkpoint, '%s/%d.pth' % (checkpoints_dir, epochs))

#結果顯示
GPU是否可用: True
Train Epoch: 1 Loss:2.264611
測試集:損失:0.0358,精度:20.98%
Train Epoch: 2 Loss:2.253827
測試集:損失:0.0354,精度:28.34%
Train Epoch: 3 Loss:2.217229
測試集:損失:0.0349,精度:39.88%
Train Epoch: 4 Loss:2.233548
測試集:損失:0.0343,精度:50.97%
Train Epoch: 5 Loss:2.144451
測試集:損失:0.0335,精度:58.34%
Train Epoch: 6 Loss:2.111312
測試集:損失:0.0325,精度:64.29%
Train Epoch: 7 Loss:1.988998
測試集:損失:0.0310,精度:68.26%
Train Epoch: 8 Loss:1.837759
測試集:損失:0.0290,精度:71.13%
Train Epoch: 9 Loss:1.635040
測試集:損失:0.0264,精度:72.52%
Train Epoch: 10 Loss:1.344689
測試集:損失:0.0232,精度:75.39%

視覺化步驟:

1.開啟event_file資料夾,在當前資料夾開啟cmd,然後輸入tensorboard --logdir "./",就可以看到:

2.開啟瀏覽器在 瀏覽器中輸入https://localhost:6006/ 即可顯示 :