东方耀AI技术分享
标题:
06、使用PyTorch在Mnist数据集上训练与验证的所有流程实现
[打印本页]
作者:
东方耀
时间:
2020-4-13 18:40
标题:
06、使用PyTorch在Mnist数据集上训练与验证的所有流程实现
06、使用PyTorch在Mnist数据集上训练与验证的所有流程实现
# -*- coding: utf-8 -*-
__author__ = u'东方耀 微信:dfy_88888'
__date__ = '2020/4/13 下午5:11'
__product__ = 'PyCharm'
__filename__ = 'dfy03_mnist'
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
print(torch.__version__)
BATCH_SIZE = 512 # 大概需要2G的显存
EPOCHS = 10 # 总共训练批次
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 让torch判断是否使用GPU,建议使用GPU环境,因为会快很多
# 对图片数据进行预处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=(0.1307,), std=(0.3081,))
])
trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
testset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
print(type(trainset))
# pytorch中的数据加载器DataLoader
train_loader = torch.utils.data.DataLoader(trainset, batch_size=BATCH_SIZE, shuffle=True)
test_loader = torch.utils.data.DataLoader(testset, batch_size=BATCH_SIZE, shuffle=True)
print(type(train_loader))
minist01 = iter(train_loader) # 迭代器 方便按批次取数据
imgs, labels = minist01.next()
print(type(imgs), imgs.numpy().shape, imgs.size())
print(type(labels), labels.size())
class ConvNet(nn.Module):
def __init__(self):
super().__init__()
# 1,28x28
self.conv1 = nn.Conv2d(1, 10, 5) # 10, 24x24
self.conv2 = nn.Conv2d(10, 20, 3) # 20, 10x10
self.fc1 = nn.Linear(20 * 10 * 10, 500)
self.fc2 = nn.Linear(500, 10)
def forward(self, x):
in_size = x.size(0)
# in_size = batch_size
out = self.conv1(x) # 24
out = F.relu(out)
out = F.max_pool2d(out, 2, 2) # 12
out = self.conv2(out) # 10
out = F.relu(out)
# reshape flatten
out = out.view(in_size, -1) # [None, 2000]
out = self.fc1(out)
out = F.relu(out)
out = self.fc2(out)
out = F.log_softmax(out, dim=1)
return out
model = ConvNet().to(DEVICE)
for i, (name, param) in enumerate(model.named_parameters()):
print('名字是:%s, 第%d个的权重参数的size=' % (name, i), param.size())
optimizer = optim.Adam(model.parameters(), lr=1e-3)
# 下面定义一下训练的函数,我们将训练的所有操作都封装到这个函数中
def train(model, device, train_loader, optimizer, epoch):
# 设置模型的训练模式
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
# 梯度归0
optimizer.zero_grad()
# 模型前向计算
output = model(data)
# 这是什么loss? The negative log likelihood loss
# loss = F.nll_loss(output, target)
loss = F.cross_entropy(output, target)
loss.backward() # 反向传播算梯度
optimizer.step() # 更新权重参数
if (batch_idx + 1) % 30 == 0:
print('第{}轮Train [{}/共{}个训练样本 ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()))
# 测试的操作也一样封装成一个函数
def test(model, device, test_loader):
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)
# test_loss += F.nll_loss(output, target, reduction='sum').item() # 将一批的损失相加
test_loss += F.cross_entropy(output, target, reduction='sum').item()
pred = output.max(1, keepdim=True)[1] # 找到概率最大的下标
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/共{}个验证样本 ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
100. * correct / len(test_loader.dataset)))
# 下面开始训练,这里就体现出封装起来的好处了,只要写两行就可以了
for epoch in range(1, EPOCHS + 1):
train(model, DEVICE, train_loader, optimizer, epoch)
test(model, DEVICE, test_loader)
# MNIST是一个很简单的数据集,由于它的局限性只能作为研究用途,对实际应用带来的价值非常有限。
# 但是通过这个例子,我们可以完全了解一个实际项目的工作流程
#
# 我们找到数据集,对数据做预处理,定义我们的模型,调整超参数,测试训练,
# 再通过训练结果对超参数进行调整或者对模型进行调整。
#
# 并且通过这个实战我们已经有了一个很好的模板,以后的项目都可以以这个模板为样例
复制代码
欢迎光临 东方耀AI技术分享 (http://www.ai111.vip/)
Powered by Discuz! X3.4