PyTorch用最简单的多层感知机(深度神经网络)实现手写数字识别

版权声明:转载注明出处 https://blog.csdn.net/york1996/article/details/81805740

首先,你需要安装torch和torchvision(现在支持Windows了)

接下来就是准备好mnist数据集,你可以把代码中 DOWNLOAD_MNIST 赋值为 True 下载数据集,如果下载很慢或者不成功,可以参考我的另一篇博客:使用torchvision下载外网数据集mnist没有进度的解决方案

以下代码注释还算详细,在windows下使用cpu和gpu均可正常运行。

import torch.nn as nn
import torch
import torchvision
from torch.utils.data import DataLoader
import time

print("start")
EPOCH=50#总的训练次数
BATCH_SIZE=20#批次的大小
LR=0.03#学习率#交叉熵损失函数不需要太大的学习率
DOWNLOAD_MNIST=False#运行代码的时候是否下载数据集

cuda_available=torch.cuda.is_available()#获取GPU是否可用,可用的话就用GPU进行训练和测试
# #对于这样的网络,可能cpu更快一些
cuda_available=False#即使gpu可用,也可以执行这一句,测试训练在cpu上的训练速度
#设置一个转换的集合,先把数据转换到tensor,再归一化为均值.5,标准差.5的正态分布
trans=torchvision.transforms.Compose(
    [
        torchvision.transforms.ToTensor(),#ToTensor方法把[0,255]变成[0,1]
        torchvision.transforms.Normalize([0.5],[0.5])#变成mean(均值)=.5,std(标准差standard deviation)=.5的分布
    ]
)

print("load data")
train_data=torchvision.datasets.MNIST(
    root="./mnist",#设置数据集的根目录
    train=True,#是否是训练集
    transform=trans,#对数据进行转换
    download=DOWNLOAD_MNIST
)
#第二个参数是数据分块之后每一个块的大小,第三个参数是是否大乱数据
train_loader=DataLoader(train_data,batch_size=BATCH_SIZE,shuffle=True)

test_data=torchvision.datasets.MNIST(
    root="./mnist",
    train=False,#测试集,所以false
    transform=trans,
    download=DOWNLOAD_MNIST
)
test_loader=DataLoader(test_data,batch_size=len(test_data),shuffle=False)
print("net creating")

#用最简单的方式搭建一个dnn
net=torch.nn.Sequential(
    nn.Linear(28*28,30),#输入28*28个,输出30个
    nn.Tanh(),#激活函数
    nn.Linear(30,10)#输入30个,输出10个,对应10个类别
)

if cuda_available:
    net.cuda()#使用GPU

#定义损失函数和优化方法
loss_function=nn.CrossEntropyLoss()#交叉熵损失函数
optimizer=torch.optim.SGD(net.parameters(),lr=LR)#优化方法

print("start training")
for ep in range(EPOCH):
    #记录把所有数据集训练+测试一遍需要多长时间
    startTick = time.clock()
    for data in train_loader:#对于训练集的每一个batch
        img,label=data
        img = img.view(img.size(0), -1)#拉平图片成一维向量

        if cuda_available:
            img=img.cuda()
            label=label.cuda()

        out=net(img)#送进网络进行输出
        loss=loss_function(out,label)#获得损失

        optimizer.zero_grad()#梯度归零
        loss.backward()#反向传播获得梯度,但是参数还没有更新
        optimizer.step()#更新梯度

    num_correct=0#正确分类的个数,在测试集中测试准确率
    #由于测试集的batchsize是测试集的长度,所以下面的循环只有一遍
    for data in test_loader:
        img,label=data
        img = img.view(img.size(0), -1)

        if cuda_available:
            img=img.cuda()
            label=label.cuda()

        out=net(img)#获得输出

        _,prediction=torch.max(out,1)
        print(prediction)
        #torch.max()返回两个结果,
        # 第一个是最大值,第二个是对应的索引值;
        # 第二个参数 0 代表按列取最大值并返回对应的行索引值,1 代表按行取最大值并返回对应的列索引值。
        num_correct+=(prediction==label).sum()#找出预测和真实值相同的数量,也就是以预测正确的数量

    accuracy=num_correct.cpu().numpy()/len(test_data)#计算正确率,num_correct是gpu上的变量,先转换成cpu变量
    timeSpan=time.clock()-startTick
    print("第%d迭代期,准确率为%f,耗时%dS"%(ep+1,accuracy,timeSpan))

下面是运行结果:

start
load data
net creating
start training
第1迭代期,准确率为0.923500,耗时7S
第2迭代期,准确率为0.935600,耗时7S

...

猜你喜欢

转载自blog.csdn.net/york1996/article/details/81805740