import torch
import torch.nn as nn
import torch.nn.functional as fun
import argparse
from torchvision import datasets, transforms
import torch.optim as optim
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 20, 5, 1)
self.conv2 = nn.Conv2d(20, 50, 5, 1)
self.fc1 = nn.Linear(4 * 4 * 50, 500) # 图像经过卷及池化后的尺寸,再压缩
self.fc2 = nn.Linear(500, 10)
def forward(self, x):
x = fun.relu(self.conv1(x))
x = fun.max_pool2d(x, 2, 2) # kernel_size, stride
x = fun.relu(self.conv2(x))
x = fun.max_pool2d(x, 2, 2)
x = x.view(-1, 4 * 4 * 50)
x = fun.relu(self.fc1(x))
x = self.fc2(x)
result = fun.log_softmax(x, dim=1)
return result
def train(args, model, device, train_loader, optimizer, epoch):
model.train() # Sets the module in training mode.
for batch_idx, (data, target) in enumerate(train_loader):
# to_GPU
data, target = data.to(device), target.to(device)
# 去除积累的梯度
optimizer.zero_grad()
# predicted
predicted = model(data)
# loss+backward
loss = fun.nll_loss(predicted, target) # 负对数似然损失函数
loss.backward()
# 执行一次优化
optimizer.step()
# 打印记录
if batch_idx % args.log_interval == 0: # 记录间隔
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()))
def test(args, 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 += fun.nll_loss(output, target,
reduction='sum').item() # sum up batch loss将整个batch的loss都加起来,再取平均,表示这一次迭代的loss
pred = output.argmax(dim=1, keepdim=True) # 取最大概率所在项作为预测结果
correct += pred.eq(target.view_as(pred)).sum().item() # 整理target与pred的维度相同,与pred对比,累计本次迭代所有正确个数
test_loss /= len(test_loader.dataset) # test_loader装载着一个数据集
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
100. * correct / len(test_loader.dataset)))
def argument_parser():
# training settings
# metavar:为帮助消息中的可选参数提供了不同的名称
parse = argparse.ArgumentParser(description='Pytorch MNIST Example')
parse.add_argument('--batch-size', type=int, default=64, metavar='N',
help='input batch size for training (defaule:64)')
parse.add_argument('--test-batch-size', type=int, default=1000)
parse.add_argument('--epochs', type=int, default=10)
parse.add_argument('--lr', type=int, default=0.01)
parse.add_argument('--momentum', type=float, default=0.5)
parse.add_argument('--no-cuda', action='store_true', default=False)
parse.add_argument('--seed', type=int, default=1)
parse.add_argument('--log-interval', type=int, default=1000, metavar='N',
help='how many batches to wait before logging training status')
parse.add_argument('--save-model', action='store_true', default=True)
args = parse.parse_args()
return args
def run():
# 输入参数
args = argument_parser()
# GPU
use_cuda = not args.no_cuda and torch.cuda.is_available()
# random seed
torch.manual_seed(args.seed) # 生成随机数种子,以使得结果是确定的
# device
device = torch.device('cuda' if use_cuda else 'cpu')
kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}
"""加载数据。组合数据集和采样器,提供数据上的单或多进程迭代器
参数:
dataset:Dataset类型,从其中加载数据
batch_size:int,可选。每个batch加载多少样本
shuffle:bool,可选。为True时表示每个epoch都对数据进行洗牌
sampler:Sampler,可选。从数据集中采样样本的方法。
num_workers:int,可选。加载数据时使用多少子进程。默认值为0,表示在主进程中加载数据。
collate_fn:callable,可选。
pin_memory:bool,可选
drop_last:bool,可选。True表示如果最后剩下不完全的batch,丢弃。False表示不丢弃。
"""
# data_loader
train_set = datasets.MNIST('./data', train=True, download=True, transform=transforms.Compose(
[transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]))
test_set = datasets.MNIST('./data', train=False, transform=transforms.Compose(
[transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]))
train_loader = torch.utils.data.DataLoader(train_set, batch_size=args.batch_size,
shuffle=True, **kwargs)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=args.test_batch_size,
shuffle=True, **kwargs)
# 实例化
model = Net().to(device)
# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum)
# train
for epoch in range(1, args.epochs + 1):
train(args, model, device, train_loader, optimizer, epoch)
test(args, model, device, test_loader)
# model save
if (args.save_model):
torch.save(model.state_dict(), "./mnist_cnn.pt")
if __name__ == '__main__':
run()
转载:https://blog.csdn.net/weixin_41803874/article/details/102593175
查看评论