MNIST集的分类的实现
import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
#定义训练集
train_dataset = datasets.MNIST(root='./', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='./', train=False, transform=transforms.ToTensor(), download=True)
#定义一个批次的大小
batch_size = 64
#装载训练集(dataset是指要读取的数据位置, batch_size是指每个批次读入的数据大小, shuffle是指是否在读取前进行顺序的打乱)
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
#装载测试集
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True)
#数据加载
for i, data in enumerate(train_loader):
inputs, labels = data
print(inputs.shape)
print(labels.shape)
break
#定义分类模型
class Net(torch.nn.Module):
def __init__(self):
#继承父类
super(Net, self).__init__()
#定义神经网络的结构
#定义全连接层(输入的每个样本的大小为28 * 28 == 784, 所以输入神经元个数为784, 输出为0 - 9的10个类别的概率, 所以输出神经元个数为10)
self.fcl = torch.nn.Linear(784, 10)
#定义激活函数为softmax函数, dim=1是因为要按每一行的每一列求取概率来判断每一行属于什么类
self.softmax = torch.nn.Softmax(dim=1)
def forward(self, x):
#由于x的形状为[64, 1, 28, 28], 而神经网络的计算取决于矩阵计算, 所以应该先将x转换为二维的[64, 784]的形状再进行计算
x = x.view(x.size(0), -1)
x = self.fcl(x)
x = self.softmax(x)
return x
#定义模型
model = Net()
#定义代价函数
mse_loss = torch.nn.MSELoss(reduction='mean')
#定义优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.5)
#定义模型的训练
def train():
for i, data in enumerate(train_loader):
inputs, labels = data
#获得数据的输入值并将其放入模型中进行计算
out = model(inputs)
#将labels转换为独热编码, 先将labels数据从一维变成两维
labels = labels.view(-1, 1)
#使用scatter函数得到one_hot_labels
#Tensor.scatter(dim, index, src), 沿着第dim维将Tensor中的第index(索引)位替换为src
one_hot_labels = torch.zeros(labels.size(0), 10).scatter(1, labels, 1)
#通过独热编码和经过softmax计算的概率值(都是从0 - 1的, 可以计算损失, 这也是将标签绘制为独热编码的意义之一)计算损失值
loss = mse_loss(out, one_hot_labels)
#每100个批次输出一次损失值
if (i + 1) % 100 == 0:
print("第", i + 1, "批次的损失值为:", loss.item())
#在反向传播计算梯度之前, 先进行梯度清零
optimizer.zero_grad()
#进行反向传播求解梯度
loss.backward()
#通过优化器更新参数
optimizer.step()
#定义模型的测试
def test():
#定义一个变量correct, 用来统计测试集中正确的次数
correct = 0
for i, data in enumerate(test_loader):
#获得一个批次的输入和标签
inputs, labels = data
#将测试集的inputs放入模型中计算得到测试集的预测结果
test_pred = model(inputs)
#通过max(test_pred, 1)函数得到test_pred中按照每一行取最大值的次序, _,是指无关变量, 因为max函数返回最大的值和最大的值对应的位序, 所以需要两个返回值
_, predict = torch.max(test_pred, 1)
#通过predict和标签进行对比(predict是第几位是最大的概率, 标签是0 - 9的数字, 所以当predict和labels相等时就相当于预测值是正确的)来得到判断正确的数量并赋给correct
correct += (predict == labels).sum()
#计算一整次测试的准确率
print("第", epoch + 1, "次训练后测试的预测准确率为:", correct.item() / len(test_dataset))
#模型进行epoch次训练并且每次训练完都进行一次测试
for epoch in range(10):
print("第", epoch + 1, "次:")
train()
test()