神经网络作业三

 

设计一个三层神经网络解决手写数字的识别问题。
要求(1)三层神经网络如图:784-15-10结构
(2)使⽤随机梯度下降算法和MNIST训练数据。
http://yann.lecun.com/exdb/mnist/

import torch
from torch import nn
from torch import optim
import torch.nn.functional as F
import torchvision

def get_dataloader(train=True):
    assert isinstance(train,bool),"train 必须是bool类型"
    #准备数据集,其中0.13070.3081为MNIST数据的均值和标准差,这样操作能够对其进行标准化
    #因为MNIST只有一个通道(黑白图片),所以元组中只有一个值
    dataset = torchvision.datasets.MNIST('/data', train=train, download=False,
                                         transform=torchvision.transforms.Compose([
                                         torchvision.transforms.ToTensor(),
                                         torchvision.transforms.Normalize((0.1307,), (0.3081,)),]))
    #准备数据迭代器
    batch_size = train_batch_size if train else test_batch_size
    dataloader = torch.utils.data.DataLoader(dataset,batch_size=batch_size,shuffle=True)
    return dataloader

class MnistNet(nn.Module):
    def __init__(self):
        super(MnistNet,self).__init__()
        self.fc1 = nn.Linear(28*28*1,15)#nn.Linear(n_featuers,n_hidden)输入为28x28,隐藏层为15个神经元
        self.fc2 = nn.Linear(15,10)#nn.Linear(n_hidden,n_outputs)   10分类

    def forward(self,x):
        x = x.view(-1,28*28*1)#展平数据集,784长度的向量,-1表示自适应
        x = self.fc1(x) #[batch_size,15]
        x = F.relu(x)  #[batch_size,15]
        x = self.fc2(x) #[batch_size,10]

        return F.log_softmax(x,dim=-1)#dim=-1就是对行进行对数计算,与F.nll_loss搭配使用

def train(epoch):
    mode = True
    mnist_net.train(mode=mode)#训练模式
    train_dataloader = get_dataloader(train=mode)
    print(len(train_dataloader.dataset))#数据集个数
    print(len(train_dataloader))#数据集batch个数
    for idx,(data,target) in enumerate(train_dataloader):
        optimizer.zero_grad()#梯度设为0
        output = mnist_net(data)#预测值
        loss = F.nll_loss(output,target) #对数似然损失,F.nll_loss用于处理多分类问题,输入是对数化的概率值。
        loss.backward()#反向传播,计算梯度
        optimizer.step()#利用梯度更新参数
        if idx % 10 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, idx * len(data), len(train_dataloader.dataset),
                       100. * idx / len(train_dataloader), loss.item()))

def test():
    test_loss = 0
    correct = 0
    mnist_net.eval()#评估模式,不会反向传播
    test_dataloader = get_dataloader(train=False)#获取测试数据
    with torch.no_grad():#with torch.no_grad()里面的作用就是不计算梯度
        for data, target in test_dataloader:
            output = mnist_net(data)
            test_loss += F.nll_loss(output, target, reduction='sum').item()# reduction='sum'对N个误差结果求和
            pred = output.data.max(1, keepdim=True)[1] #获取最大值的位置,[batch_size,1]     最大值的位置就是其预测的目标值
            # print('sssss:')
            # print(output.data[0])
            # print(pred[0])
            # print('llllll:')
            # print(target.data[0])
            # print(target.data.view_as(pred)[0])
            correct += pred.eq(target.data.view_as(pred)).sum()#view_as()该函数的作用是将调用函数的变量,转变为同参数tensor同样的形状       ‘正确的个数’
    test_loss /= len(test_dataloader.dataset)#求平均损失误差
    print('\nTest set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format(
        test_loss, correct, len(test_dataloader.dataset),
        100. * correct / len(test_dataloader.dataset)))

train_batch_size = 60
test_batch_size = 1000
mnist_net = MnistNet()
optimizer = optim.SGD(mnist_net.parameters(),lr= 0.001)#学习率为0.001

if __name__ == '__main__':
    test()
    for i in range(5): #模型训练5轮
        train(i)#训练一轮保存一轮模型
        test()

结果:

 

posted @ 2022-10-28 23:04  ziyuliu  阅读(22)  评论(0编辑  收藏  举报