PyTorch_简单神经网络搭建_MNIST数据集

今天用PyTorch参考《Python深度学习基于PyTorch》搭建了一个简单的神经网络,在这里做一下笔记。

首先附上PyTorch中文文档链接,下面的各接口函数在这里面基本都能查到,宝藏文档,对于像我一样的新手菜鸟特别友好,强推!!!
PyTorch中文文档链接

正文开始:
这是本次搭建神经网络的结构图

此网络包含两个隐藏层,激活函数都为relu函数,最后用torch.max(out,1)找出张量out最大值索引作为预测值。

下面不废话了,直接代码实现

1. 先导入必要的模块

import numpy as np
import torch

#导入PyTorch内置的mnist数据
from torchvision.datasets import mnist

#导入预处理模块
from torchvision import transforms
from torch.utils.data import DataLoader

#导入神经网络工具
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

from torch.utils.data import DataLoader:
该接口主要用来将自定义的数据读取接口的输出或者PyTorch已有的数据读取接口的输入按照batch size封装成Tensor。

2. 定义超参数

#定义后面要用到的超参数
train_batch_size = 64
test_batch_size = 128

#学习率与训练次数
learning_rate = 0.01
nums_epoches = 20

#优化器的时候使用的参数
lr = 0.1
momentum = 0.5

batch_size:相当于每次导入训练的样本量大小(相比较于一次导入完,一次导入一张,需要设置一个合适的量)一般高级算法要注意设置量,简单神经网络不用太过在意。

3.下载数据并对数据进行预处理

#用compose来定意预处理函数
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.5],[0.5])])

#下载数据,在工程文件夹里新建一个data文件夹储存下载的数据
train_dataset = mnist.MNIST('./data', train=True, transform=transform, target_transform=None, download=True)
test_dataset = mnist.MNIST('./data', train=False, transform=transform, target_transform=None, download=False)

#数据加载器,组合数据集和采样器,并在数据集上提供单进程或多进程迭代器
train_loader = DataLoader(train_dataset, batch_size=train_batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=test_batch_size, shuffle=False)

把预处理需要用到的东西组合在Compose里面。
transforms.ToTensor()是把一个取值范围是[0,255]的PIL.Image或者shape为(H,W,C)的numpy.ndarray,转换成形状为[C,H,W],取值范围是[0,1.0]的torch.FloadTensor。(这句话我的理解是把数据格式转换成网络里可以使用的数据格式)
transforms.Normalize则是将灰度图像正则化。

4.可视化数据

import matplotlib.pyplot as plt
%matplotlib inline
examples = enumerate(test_loader)
batch_idx,(example_data,example_targets) = next(examples)
fig = plt.figure()
for i in range(6):
    plt.subplot(2,3,i+1)
    plt.tight_layout()
    plt.imshow(example_data[i][0],cmap='gray',interpolation='none')
    plt.title("Ground Truth:{}".format(example_targets[i]))
    plt.xticks([])
    plt.yticks([])

数据可视化这部分我没有仔细看,直接把代码列出,以后如果之后再用到的时候我再单独写一个笔记。
下面是可视化后的结果:
这是可视化后的mnist数据

5.构建模型

class CNN(nn.Module):
    def __init__(self,in_dim,hidden_1,hidden_2,out_dim):
        super(CNN,self).__init__()
        self.layer1 = nn.Sequential(nn.Linear(in_dim, hidden_1, bias=True),nn.BatchNorm1d(hidden_1))
        self.layer2 = nn.Sequential(nn.Linear(hidden_1,hidden_2,bias=True),nn.BatchNorm1d(hidden_2))
        self.layer3 = nn.Sequential(nn.Linear(hidden_2,out_dim))
        
    def forward(self,x):
    	#注意 F 与 nn 下的激活函数使用起来不一样的
        x = F.relu(self.layer1(x))
        x = F.relu(self.layer2(x))
        x = self.layer3(x)
        return x

class torch.nn.Sequential(* args):一个时序容器,Modules 会以他们传入的顺序被添加到容器中,当然,也可以传入一个。

**注:**我敲的时候还不知道CNN 跟简单神经网络的区别,所以把这个类名定义为CNN了,大家在实现的时候可以定义为Net。

6.实例化网络

#实例化网络,只考虑使用CPU
model = CNN(28*28,300,100,10)
#定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
#momentum:动量因子有什么用处?
optimizer = optim.SGD(model.parameters(),lr=lr,momentum=momentum)

class torch.nn.CrossEntropyLoss(weight=None, size_average=True):此标准将LogSoftMax和NLLLoss集成到一个类中。当训练一个多类分类器的时候,这个方法是十分有用的。
动量因子的作用后面会了我再来修改!

7.训练模型

#开始训练 先定义存储损失函数和准确率的数组
losses = []
acces = []
#测试用
eval_losses = []
eval_acces = []

for epoch in range(nums_epoches):
    #每次训练先清零
    train_loss = 0
    train_acc = 0
    #将模型设置为训练模式
    model.train()
    #动态学习率
    if epoch%5 == 0:
        optimizer.param_groups[0]['lr'] *= 0.1
    for img,label in train_loader:
        #例如 img=[64,1,28,28] 做完view()后变为[64,1*28*28]
        #把图片数据格式转换成与网络匹配的格式
        img = img.view(img.size(0),-1)
        #前向传播,将图片数据传入模型中
        out = model(img)
        loss = criterion(out,label)
        #反向传播
        #optimizer.zero_grad()意思是把梯度置零,也就是把loss关于weight的导数变成0
        optimizer.zero_grad()
        loss.backward()
        #这个方法会更新所有的参数,一旦梯度被如backward()之类的函数计算好后,我们就可以调用这个函数
        optimizer.step()
        
        #记录误差 
        train_loss += loss.item()
        
        #计算分类的准确率,找到概率最大的下标
        _,pred = out.max(1)
        num_correct = (pred == label).sum().item()#记录标签正确的个数
        acc = num_correct/img.shape[0]
        train_acc += acc
    losses.append(train_loss/len(train_loader))
    acces.append(train_acc/len(train_loader))
    
    eval_loss = 0
    eval_acc = 0
    model.eval()
    for img,label in test_loader:
        img = img.view(img.size(0),-1)
        
        out = model(img)
        loss = criterion(out,label)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        eval_loss += loss.item()
        
        _,pred = out.max(1)
        num_correct = (pred == label).sum().item()
        acc = num_correct/img.shape[0]
        eval_acc += acc
    eval_losses.append(eval_loss/len(test_loader))
    eval_acces.append(eval_acc/len(test_loader))
    

    print('epoch:{},Train Loss:{:.4f},Train Acc:{:.4f},Test Loss:{:.4f},Test Acc:{:.4f}'
             .format(epoch,train_loss/len(train_loader),train_acc/len(train_loader),
                    eval_loss/len(test_loader),eval_acc/len(test_loader)))

这是训练后的输出:
epoch:0,Train Loss:0.3494,Train Acc:0.9190,Test Loss:0.1510,Test Acc:0.9550
epoch:1,Train Loss:0.1290,Train Acc:0.9644,Test Loss:0.1037,Test Acc:0.9687
epoch:2,Train Loss:0.0882,Train Acc:0.9756,Test Loss:0.0848,Test Acc:0.9744
epoch:3,Train Loss:0.0676,Train Acc:0.9818,Test Loss:0.0686,Test Acc:0.9778
epoch:4,Train Loss:0.0535,Train Acc:0.9853,Test Loss:0.0569,Test Acc:0.9824
epoch:5,Train Loss:0.0385,Train Acc:0.9906,Test Loss:0.0308,Test Acc:0.9906
epoch:6,Train Loss:0.0345,Train Acc:0.9920,Test Loss:0.0306,Test Acc:0.9911
epoch:7,Train Loss:0.0321,Train Acc:0.9930,Test Loss:0.0301,Test Acc:0.9916
epoch:8,Train Loss:0.0324,Train Acc:0.9931,Test Loss:0.0293,Test Acc:0.9919
epoch:9,Train Loss:0.0304,Train Acc:0.9937,Test Loss:0.0288,Test Acc:0.9921
epoch:10,Train Loss:0.0302,Train Acc:0.9935,Test Loss:0.0282,Test Acc:0.9925
epoch:11,Train Loss:0.0294,Train Acc:0.9937,Test Loss:0.0274,Test Acc:0.9929
epoch:12,Train Loss:0.0289,Train Acc:0.9938,Test Loss:0.0274,Test Acc:0.9931
epoch:13,Train Loss:0.0294,Train Acc:0.9941,Test Loss:0.0274,Test Acc:0.9930
epoch:14,Train Loss:0.0286,Train Acc:0.9944,Test Loss:0.0280,Test Acc:0.9925
epoch:15,Train Loss:0.0289,Train Acc:0.9939,Test Loss:0.0279,Test Acc:0.9924
epoch:16,Train Loss:0.0287,Train Acc:0.9939,Test Loss:0.0277,Test Acc:0.9925
epoch:17,Train Loss:0.0290,Train Acc:0.9937,Test Loss:0.0272,Test Acc:0.9929
epoch:18,Train Loss:0.0295,Train Acc:0.9938,Test Loss:0.0277,Test Acc:0.9924
epoch:19,Train Loss:0.0285,Train Acc:0.9942,Test Loss:0.0275,Test Acc:0.9932

8.可视化训练及测试损失值

plt.title('trainloss')
plt.plot(np.arange(len(losses)),losses)
plt.legend(['Train Loss'],loc='upper right')

可视化训练次数于损失函数值的关系:
在这里插入图片描述
end
第一次在CSDN上写笔记,希望可以坚持,慢慢成长。

猜你喜欢

转载自blog.csdn.net/weixin_40585997/article/details/109249760