pytorch学习笔记-高阶篇(卷积神经网络实战1)
本篇主要是卷积神经网络的实战,数据集用的是CIFAR-10
一、CIFAR-10介绍
CIFAR-10有10大类图片,分别是:airplane,automobile,bird,cat,deer,dog,frog,horse,ship,truck。CIFAR-100是把这10大类细分为100类。每张图片的尺寸是32x32,每一类有6000张图片,一共60000张,按照5:1分为训练和测试数据集。
二、Lenet类
import torch
from torch import nn
from torch.nn import functional as F
class Lenet5(nn.Module):
"""
for cifar10 dataset
"""
def __init__(self):
super(Lenet5, self).__init__()
self.conv_unit = nn.Sequential(
# x:[b, 3, 32, 32] => [b, 6, ]
nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5, stride=1, padding=0),
nn.AvgPool2d(kernel_size=2, stride=2, padding=0),
#
nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5, stride=1, padding=0),
nn.AvgPool2d(kernel_size=2, stride=2, padding=0),
#
)
# flatten
# full_connected unit
self.fc_unit = nn.Sequential(
nn.Linear(16 * 5 * 5, 120),
nn.ReLU(),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84, 10)
)
'''
# [b, 3, 32, 32]
# 全连接层的输入维度不知道,这里测试一下
tmp = torch.randn(2, 3, 32, 32)
out = self.conv_unit(tmp)
print('conv out:', out.shape)
# conv out: torch.Size([2, 16, 5, 5])
'''
# use Cross Entropy Loss
# 分类问题用交叉熵更合适
# self.criteon = nn.CrossEntropyLoss()
def forward(self, x):
"""
Args:
x: [b, 3, 32, 32]
Returns:
"""
batchsz = x.size(0)
# [b, 3, 32, 23] => [b, 16, 5, 5]
x = self.conv_unit(x)
# [b, 16, 5, 5] => [b, 16*5*5]
x = x.view(batchsz, 16 * 5 * 5)
# [b, 16*5*5] => [b, 10]
# softmax/sigmoid前面的变量一般称为logits
logits = self.fc_unit(x)
# [b, 10]
# 做Cross Entropy Loss里面包括了sofmax操作,不需要重复写
# pred = F.softmax(logits, dim=1)
# loss = self.criteon(logits, y)
return logits
def main():
net = Lenet5()
tmp = torch.randn(2, 3, 32, 32)
out = net(tmp)
print('lenet out:', out.shape)
if __name__ == '__main__':
main()
三、main
import torch
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision import transforms
from lenet5 import Lenet5
def main():
batchsz = 8
# 训练数据集加载
# 一次加载一张
cifar_train = datasets.CIFAR10("./dataset", train=True, transform=transforms.Compose([
transforms.Resize([32, 32]),
transforms.ToTensor()
]), download=True)
# 一次加载多张
cifar_train = DataLoader(dataset=cifar_train, batch_size=batchsz, shuffle=True)
# 测试数据集加载
# 一次加载一张
cifar_test = datasets.CIFAR10("./dataset", train=False, transform=transforms.Compose([
transforms.Resize([32, 32]),
transforms.ToTensor()
]), download=True)
# 一次加载多张
cifar_test = DataLoader(dataset=cifar_test, batch_size=batchsz, shuffle=True)
# 迭代器
x, label = iter(cifar_train).next()
print('x:', x.shape, 'label:', label.shape)
device = torch.device('cuda')
model =Lenet5().to(device)
criteon = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-3)
print(model)
for epoch in range(1000):
model.train()
for batchidx, (x, label) in enumerate(cifar_train):
# [b, 3, 32, 32]
# [b]
x, label = x.to(device), label.to(device)
logits = model(x)
# logits: [b, 10]
# label: [b]
# loss: tensor scalar
loss = criteon(logits, label)
# backprop
optimizer.zero_grad()
loss.backward()
optimizer.step()
#
print(epoch, loss.item())
model.eval()
with torch.no_grad():
# test
total_correct = 0
total_num = 0
for x, label in cifar_test:
# [b, 3, 32, 32]
# [b]
x, label = x.to(device), label.to(device)
# [b, 10]
logits = model(x)
# [b]
pred = logits.argmax(dim=1)
# [b] vs [b] => scalar tensor
total_correct = total_correct + torch.eq(pred, label).float().sum().item()
total_num = total_num + x.size(0)
acc = total_correct / total_num
print(epoch, acc)
if __name__ == '__main__':
main()
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 不听话的兔子君!