====================================================================
PyTorch是一个开源的深度学习框架,由Facebook开发并维护,广泛应用于学术研究和工业界。它提供了灵活的张量计算功能(类似于NumPy),并支持GPU加速,同时采用动态计算图(DynamicComputationalGraph)机制,使得模型构建和调试更加直观高效。本文利用PyTorch简单实现MNIST手写数字识别。
====================================================================
GitHub地址:
https://github.com/gao7025/fcc_nn_mnist.git
主要步骤如下:
1.加载已有或下载mnist数据集
定义Dataset与DateLoader,加载已有或下载mnist数据集。
- 1.1 dataset类对数据进行统一封装,本质是一个表示数据集的抽象类,里面有三个函数:init,getitem,len三个函数。
- 1.2 dataloader则是加载dataset,并设置其batch_size(单次训练时送入的样本数目),以及shuffle(是否打乱样本顺序,训练集一定要设置shuffle为True,测试集则无强制性规定)
- 1.3 Compose把多种数据处理的方法集合在一起。将需要被处理的数据转为Tensor类型,数据被转化为Tensor类型后,对其进行减均值(0.1307)和除标准差(0.3081),以实现数据的正则化。
"""
method 1: load existing dataset
"""
# 定义转换操作
transform = transforms.Compose([
transforms.ToTensor(), # 将图片转换为Tensor
transforms.Normalize((0.1307,), (0.3081,)) # 归一化
])
# 加载训练数据集
train_dataset = datasets.MNIST(root='mnist_data', train=True, download=False, transform=transform)
# 加载测试数据集
test_dataset = datasets.MNIST(root='mnist_data', train=False, download=False, transform=transform)
# 创建数据加载器
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)
print(train_dataset, train_loader)
"""
method 2: load online dataset
"""
batch_size = 512
train_loader = torch.utils.data.DataLoader(
torchvision.datasets.MNIST('mnist_data', train=True, download=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
(0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
torchvision.datasets.MNIST('mnist_data/', train=False, download=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
(0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=False)
print(train_dataset, train_loader)
2.创建神经网络架构
创建一个全连接神经网络(FullyConnectedNetwork),由三层线性变换的全连接层构成,主要用于解决分类任务(如MNIST手写数字识别)。模型通过nn.Module类继承实现,这是PyTorch中构建神经网络的标准方式。
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(28*28, 256)
self.fc2 = nn.Linear(256, 64)
self.fc3 = nn.Linear(64, 10)
# 定义数据如何通过网络流动
def forward(self, x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
3.训练网络
设置一个优化器(optimizer)和一个损失准则(losscriterion)。创建一个随机梯度下降(stochasticgradientdescent)优化器,其中,第一个参数包括权重w,和偏置b等是神经网络中的参数;第二个参数lr是学习率;第三个参数momentum是冲量,每次学习中更新量的加减速的系数;第四个参数weight_decay是权重衰减,即L2正则化前面的那个λ参数。
# 创建这个网络架构的实例
net = Net()
# [w1, b1, w2, b2, w3, b3]
# 训练网络
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
# # 创建一个损失函数
# criterion = nn.NLLLoss()
train_loss = []
for epoch in range(3):
for batch_idx, (x, y) in enumerate(train_loader):
x = x.view(x.size(0), 28*28)
out = net(x)
y_onehot = one_hot(y)
loss = F.mse_loss(out, y_onehot)
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss.append(loss.item())
log_interval = 100
if batch_idx % log_interval == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(x), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()))
4.评价与调优
查看训练集与测试集的loss函数曲线和acc曲线,并进行调优。
plot_curve(train_loss)
print('test acc:', acc)
5.保存模型与预测
plot_image(x, pred, 'test')
预测结果