Pytorch进阶(1)------手写数字识别之全连接神经网络实现

        经过几天的研究,参考了许多文章之后,终于用pytorch搭建了两个完整的神经网络,并且基本上每句代码都弄清楚了,一个是只有全连接层的网络,另一个则是加入卷积层和池化层的CNN,实现的步骤总结如下:

首先对上一篇博客中定义的类进行扩充:

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer=nn.Sequential(
          nn.Linear(in_dim,hidden1_dim),
          nn.ReLU(),
          nn.Linear(hidden1_dim,hidden2_dim),
          nn.ReLU(),
          nn.Linear(hidden2_dim,out_dim))
    def forward(self,x):
        x=self.layer(x)
        return x

在这里引入Sequential的用法,这可以理解为一个容器,可以把一系列神经网络的操作按顺序排列在其中,把输入数据传送到网络中时,网络就会按这个容器里设置的操作顺序进行计算,省去了一层一层计算的步骤。该网络的结构为:Affine-ReLU-Affine-ReLU-Affine,输出层用的是恒等函数。

接下来就是下载MNIST数据集、接着载入数据集进行训练了,完整的程序及注释如下:

import torch
import torch.nn as nn
import time#用于计时
from torch import optim #用于获取梯度下降的方法
from torch.autograd import variable#用于数据类型转换
from torch.utils.data.dataloader import DataLoader#用于载入数据
from torchvision import datasets,transforms#用于下载并转换数据集
#各层神经元数目
in_dim=784
hidden1_dim=200
hidden2_dim=100
out_dim=10

epoch=10#神经网络学完样本集中所有的样本为一个epoch,例如mnist有60000张训练样本,则训练到60000张时为一个epoch
batch_num=60#采用mini-batch的方式训练
lr_rate=0.01#学习率
sum_loss=0.0

class Net(nn.Module):#定义网络
    def __init__(self):
        super().__init__()
        self.layer=nn.Sequential(
          nn.Linear(in_dim,hidden1_dim),
          nn.ReLU(),
          nn.Linear(hidden1_dim,hidden2_dim),
          nn.ReLU(),
          nn.Linear(hidden2_dim,out_dim))
    def forward(self,x):
        x=self.layer(x)
        return x
    
data_tf=transforms.ToTensor()#数据转换为tensor类型,也就是pytorch能处理的类型
train_set=datasets.MNIST(root='data',train=True,transform=data_tf,download=True)#下载mnist训练数据集并转换
test_set=datasets.MNIST(root='data',train=False,transform=data_tf,download=True)#载mnist测试数据集并转换
train_loader=DataLoader(train_set,batch_size=batch_num,shuffle=True)#载入mnist训练数据集
test_loader=DataLoader(test_set,batch_size=batch_num,shuffle=False)#载入mnist测试数据集

since = time.time()#开始计时

net=Net()

if torch.cuda.is_available():#用gpu计算,没有可用gpu可以把这段删掉
   net = net.cuda()
   
criterion = nn.CrossEntropyLoss()#交叉熵损失函数
optimizer = optim.SGD(net.parameters(), lr=lr_rate)#SGD梯度下降法,也可以选择其他方法
for e in range(epoch):#设置循环开始训练
    for data in train_loader:
        img,label=data
        img = img.view(img.size(0), -1)
        '''这句话很关键,意思是将img矩阵重新排列成(img.size(0), -1)的形状,因为采用mini-batch
        训练方式,上面参数中的batch-size意思就是将所有样本分成若干份,每份的数量为
        batch—size张,每次训练时将这一份中的所有图片一起训练,所以img.size(0)就应该等于batch—size
        -1表示自动获取,因为img.size(0)已经是一个确定的数了,所以第二个维数可以通过计算获取,
        因此就不想要我们手动填了'''
        if torch.cuda.is_available():#用gpu计算,没有可用gpu可以把这段删掉
           img = img.cuda()
           label = label.cuda()
      
        img=variable(img)#还是转换数据类型
        label=variable(label)
        output=net(img)#将处理好的图像矩阵输入到神经网络
        
        loss=criterion(output,label)#通过损失函数计算损失值
        optimizer.zero_grad()#将梯度置零
        loss.backward()#反向传播
        optimizer.step()#可以理解为更新模型的参数
        sum_loss+=loss.item()#计算每个batch损失的和
    print('loss is :{:.16f}'.format(sum_loss/len(train_set)))#求损失的平均
    sum_loss=0.0
    sum_true=0
    #if epoch % 10 == 0:
    for data in test_loader:# 每个epoch完后都测试一下识别准确率
        img,label=data
        img = img.view(img.size(0), -1)
        
        if torch.cuda.is_available():
           img = img.cuda()
           label = label.cuda()

        out=net(img)
        _,predict=torch.max(out,1)
        num_true=(predict==label).sum()#求每个batch中识别正确的样本总数
        sum_true+=num_true.item()#求全部识别正确的样本和
    print('accuracy rate is :{:.4f}'.format(sum_true/len(test_set)))
time_elapsed = time.time() - since#计时结束并打印时间
print('Training complete in {:.0f}s'.format(time_elapsed) )     

另外需注明的是数据下载有可能会不成功,多运行几次就可以了,下载时会在该python程序所在文件夹中生成一个名叫data的文件,mnist数据就在其中,下载完之后再运行程序就不会重复下载过程了。以下为epoch设置为10轮的运行结果:

下一期将用卷积神经网络进行手写数字识别,并和这个结果简单的对比

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值