簡單訓練一個分類器——CIFAR10
阿新 • • 發佈:2020-12-14
簡單訓練一個分類器
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
transform = transforms.Compose([transforms.ToTensor( ), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True,
transform=transform)
# root - 資料集的根目錄
# train - 如果為True,則建立資料集training.pt,否則建立資料集test.pt。
# download - 如果為true,則從Internet下載資料集並將其放在根目錄中。
# transform(callable ,optional) - 一個函式/轉換,它接收PIL影象並返回轉換後的版本。例如,transforms.RandomCrop
trainloader = torch.utils.data.DataLoader(trainset, batch_size=10,
shuffle=True, num_workers=0) # 資料集,批次樣本數,遍歷後是否隨機排序, 資料載入的子程序數
testset = torchvision.datasets.CIFAR10(root='./data' , train=False, download=True,
transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=10,
shuffle=False, num_workers=0)
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
def imshow(img):
img = img / 2 + 0.5 # denormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
# 獲取隨機資料
data_iter = iter(trainloader)
images, labels = data_iter.next()
# 展示影象
imshow(torchvision.utils.make_grid(images))
# 顯示影象標籤
print(' '.join('%5s' % classes[labels[j]] for j in range(10)))
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__() # 定義Net的初始化函式,這個函式定義了該神經網路的基本結構
# Conv2d 輸入通道, 輸出通道, 核心大小
self.conv1 = nn.Conv2d(3, 10, 5) # 影象卷積,3通道輸入,10通道輸出
self.pool = nn.MaxPool2d(2, 2) # 池化層,可以降低資料體的空間尺寸 kernel_size:視窗大小, stride=None 視窗移動的步長、預設值是kernel_size
self.conv2 = nn.Conv2d(10, 16, 5) # 影象卷積,10通道輸入,16通道輸出
self.fc1 = nn.Linear(16 * 5 * 5, 120) # 全連線層 線性函式為:y = Wx + b,將conv2輸出的16通道5*5個節點連結到120個節點
self.fc2 = nn.Linear(120, 84) # 影象卷積 線性函式為:y = Wx + b,將fc1輸出120個節點連線至84個節點
self.fc3 = nn.Linear(84, 10) # 影象卷積 線性函式為:y = Wx + b,將fc2輸出84個節點連線至10個節點
def forward(self, x):
x = self.pool(F.relu(self.conv1(x))) # 輸入x,conv1卷積,relu函式啟用,pool池化
x = self.pool(F.relu(self.conv2(x))) # 輸入x,conv2卷積,relu函式啟用,pool池化
x = x.view(-1, 16 * 5 * 5) # 將x轉換為fc1輸入的位數
x = F.relu(self.fc1(x)) # 輸入x,進入第一層網路,relu函式啟用
x = F.relu(self.fc2(x)) # 輸入x,進入第二層網路,relu函式啟用
x = self.fc3(x) # 輸入x,進入第二層網路
return x
net = Net()
criterion = nn.CrossEntropyLoss() # 損失函式,輸入模型、學習樣本,計算誤差
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 優化函式
# momentum動量 若當前的梯度方向與累積的歷史梯度方向一致,則當前的梯度會被加強,從而這一步下降的幅度更大。若當前的梯度方向與累積的梯度方向不一致,則會減弱當前下降的梯度幅度。
for epoch in range(2): # 多批次迴圈
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# 獲取輸入
inputs, labels = data # labels為學習樣本
# 梯度置0
optimizer.zero_grad()
# 正向傳播,反向傳播,優化
outputs = net(inputs) # 模型
loss = criterion(outputs, labels)
loss.backward() # 反向傳播,計算當前梯度;
optimizer.step() # 根據梯度更新網路引數
# 列印狀態資訊
running_loss += loss.item()
if i % 2000 == 1999: # 每2000批次列印一次
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
data_iter = iter(testloader) # 讀取批測試集
images, labels = data_iter.next() # 提取一批測試集
imshow(torchvision.utils.make_grid(images)) # 顯示圖片
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(10)))
outputs = net(images) # 將測試集通過訓練好的網路
_, predicted = torch.max(outputs, 1) # 獲得輸出的判斷中最大的
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(10)))
correct, total = 0, 0
with torch.no_grad(): # 內容不進行計算圖構建
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item() # predicted == labels比較每個元素是否相等,sum()求和,item()將單元素張量轉為元素值
print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs, 1)
c = (predicted == labels).squeeze()
for i in range(10):
label = labels[i]
class_correct[label] += c[i].item()
class_total[label] += 1
for i in range(10):
print('Accuracy of %5s : %2d %%' % (classes[i], 100 * class_correct[i] / class_total[i]))
plt.show()
for i in range(10):
print('Accuracy of %5s : %2d %%' % (classes[i], 100 * class_correct[i] / class_total[i]))
plt.show()