基于Pytorch的MLP实现基于Pytorch的MLP实现

基于Pytorch的MLP实现

目标

  • 使用pytorch构建MLP网络
  • 训练集使用MNIST数据集
  • 使用GPU加速运算
  • 要求准确率能达到92%以上
  • 保存模型

实现

数据集:MNIST数据集的载入

MNIST数据集是一种常用的数据集,为28*28的手写数字训练集,label使用独热码,在pytorch中,可以使用torchvision.datasets.MNIST()torch.utils.data.DataLoader()来导入数据集,其中

  • torchvision.datasets.MNIST():用于下载,导入数据集
  • torch.utils.data.DataLoader():用于将数据集整理成batch的形式并转换为可迭代对象
import torch as pt
import torchvision as ptv
import numpy as np
train_set = ptv.datasets.MNIST("../../pytorch_database/mnist/train",train=True,transform=ptv.transforms.ToTensor(),download=True)
test_set = ptv.datasets.MNIST("../../pytorch_database/mnist/test",train=False,transform=ptv.transforms.ToTensor(),download=True)
train_dataset = pt.utils.data.DataLoader(train_set,batch_size=100)
test_dataset = pt.utils.data.DataLoader(test_set,batch_size=100)

网络结构构建

网络使用最简单的MLP模型,使用最简单的线性层即可构建,本次网络一共有3层全连接层,分别为28*28->512,512->128,128->10,除了输出层的激活函数使用softmax以外,其他均采用relu

class MLP(pt.nn.Module):
    def __init__(self):
        super(MLP,self).__init__()
        self.fc1 = pt.nn.Linear(784,512)
        self.fc2 = pt.nn.Linear(512,128)
        self.fc3 = pt.nn.Linear(128,10)
        
    def forward(self,din):
        din = din.view(-1,28*28)
        dout = pt.nn.functional.relu(self.fc1(din))
        dout = pt.nn.functional.relu(self.fc2(dout))
        return pt.nn.functional.softmax(self.fc3(dout))
model = MLP().cuda()
print(model)
MLP (
  (fc1): Linear (784 -> 512)
  (fc2): Linear (512 -> 128)
  (fc3): Linear (128 -> 10)
)

代价函数,优化器和准确率检测

代价函数使用交叉熵函数,使用numpy计算准确率(pytorch中也有相关函数),优化器使用最简单的SGD

# loss func and optim
optimizer = pt.optim.SGD(model.parameters(),lr=0.01,momentum=0.9)
lossfunc = pt.nn.CrossEntropyLoss().cuda()

# accuarcy
def AccuarcyCompute(pred,label):
    pred = pred.cpu().data.numpy()
    label = label.cpu().data.numpy()
#     print(pred.shape(),label.shape())
    test_np = (np.argmax(pred,1) == label)
    test_np = np.float32(test_np)
    return np.mean(test_np)

# test accuarcy
# print(AccuarcyCompute(
#     np.array([[1,10,6],[0,2,5]],dtype=np.float32),
#     np.array([[1,2,8],[1,2,5]],dtype=np.float32)))

训练网络

训练网络的步骤分为以下几步:

  1. 初始化,清空网络内上一次训练得到的梯度
  2. 载入数据为Variable,送入网络进行前向传播
  3. 计算代价函数,并进行反向传播计算梯度
  4. 调用优化器进行优化
for x in range(4):
    for i,data in enumerate(train_dataset):
    
        optimizer.zero_grad()
    
        (inputs,labels) = data
        inputs = pt.autograd.Variable(inputs).cuda()
        labels = pt.autograd.Variable(labels).cuda()
    
        outputs = model(inputs)
    
        loss = lossfunc(outputs,labels)
        loss.backward()
    
        optimizer.step()
    
        if i % 100 == 0:
            print(i,":",AccuarcyCompute(outputs,labels))
0 : 0.9
100 : 0.84
200 : 0.82
300 : 0.88
400 : 0.9
500 : 0.92
0 : 0.93
100 : 0.91
200 : 0.9
300 : 0.91
400 : 0.9
500 : 0.91
0 : 0.93
100 : 0.91
200 : 0.94
300 : 0.91
400 : 0.93
500 : 0.92
0 : 0.96
100 : 0.94
200 : 0.95
300 : 0.91
400 : 0.93
500 : 0.94

测试网络

使用使用测试集训练网络,直接计算结果并将计算准确率即可

accuarcy_list = []
for i,(inputs,labels) in enumerate(test_dataset):
    inputs = pt.autograd.Variable(inputs).cuda()
    labels = pt.autograd.Variable(labels).cuda()
    outputs = model(inputs)
    accuarcy_list.append(AccuarcyCompute(outputs,labels))
print(sum(accuarcy_list) / len(accuarcy_list))
0.936700002551

保存网络

pytorch提供了两种保存网络的方法,分别是保存参数和保存模型

  • 保存参数:仅仅保存网络中的参数,不保存模型,在load的时候要预先定义模型
  • 保存模型:保存全部参数与模型,load后直接使用
# only save paramters
pt.save(model.state_dict(),"../../pytorch_model/mlp/params/mlp_params.pt")

# save model
pt.save(model,"../../pytorch_model/mlp/model/mlp_model.pt")
/home/sky/virtualpython/pytorch0p2/lib/python3.5/site-packages/torch/serialization.py:147: UserWarning: Couldn't retrieve source code for container of type MLP. It won't be checked for correctness upon loading.
  "type " + obj.__name__ + ". It won't be checked "
test_save_net = MLP().cuda()
test_save_net.load_state_dict(pt.load("../../pytorch_model/mlp/params/mlp_params.pt"))
accuarcy_list = []
for i,(inputs,labels) in enumerate(test_dataset):
    inputs = pt.autograd.Variable(inputs).cuda()
    labels = pt.autograd.Variable(labels).cuda()
    outputs = model(inputs)
    accuarcy_list.append(AccuarcyCompute(outputs,labels))
print(sum(accuarcy_list) / len(accuarcy_list))
0.936700002551
test_save_model = pt.load("../../pytorch_model/mlp/model/mlp_model.pt")
accuarcy_list = []
for i,(inputs,labels) in enumerate(test_dataset):
    inputs = pt.autograd.Variable(inputs).cuda()
    labels = pt.autograd.Variable(labels).cuda()
    outputs = model(inputs)
    accuarcy_list.append(AccuarcyCompute(outputs,labels))
print(sum(accuarcy_list) / len(accuarcy_list))
0.936700002551

问题记录

Variable转numpy的问题

Variable目前没查到转为numpy的方法,考虑Variable中的数据保存在一个torch.Tensor中,该Tensor为Variable.data,直接将其转为numpy即可

GPU产生的转换问题

GPU上的Tensor不能直接转换为numpy,需要一个在CPU上的副本,因此可以先使用Variable.cpu()创建CPU副本,再使用Variable.data.numpy()方法

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Ldpe2G的个人博客

仿射变换实现组合操作 抠图+缩放+旋转

1973
来自专栏小小挖掘机

听说GAN很高大上,其实就这么简单

本文使用的tensorflow版本:1.4 tensorflow安装:pip install tensorflow 1、先来目睹一下效果吧 这篇文章讲解了如何使...

5894
来自专栏AI科技评论

开发 | 用 Kaggle 经典案例教你用 CNN 做图像分类!

前言 在上一篇专栏中,我们利用卷积自编码器对 MNIST 数据进行了实验,这周我们来看一个 Kaggle 上比较经典的一个图像分类的比赛 CIFAR( CIFA...

4046
来自专栏Python中文社区

机器学习算法KNN简介及实现

KNN(K近邻算法)是一种不需要学习任何参数同时也非常简单的机器学习算法,既可以用来解决分类问题也可以用来解决回归问题。直观解释这个算法就是'近朱者赤,近墨者黑...

1282
来自专栏青青天空树

趣味问题:画图(c++实现)

描述:在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。下图给出了一...

1114
来自专栏Petrichor的专栏

深度学习: 参数初始化

好的开始是成功的一半。 为了让你的模型跑赢在起跑线 ε=ε=ε=(~ ̄▽ ̄)~ ,请慎重对待参数初始化。

3773
来自专栏决胜机器学习

机器学习(十一) ——神经网络基础

机器学习(十一)——神经网络基础 (原创内容,转载请注明来源,谢谢) 一、概述 神经网络,可以理解为输入的内容,经过一系列的内部的处理,得到输出的假设函数。简...

3786
来自专栏大数据挖掘DT机器学习

机器学习-R-特征选择

特征选择是实用机器学习的重要一步,一般数据集都带有太多的特征用于模型构建,如何找出有用特征是值得关注的内容。 1. Feature selection: Al...

5388
来自专栏IT派

机器学习算法KNN简介及实现

KNN(K近邻算法)是一种不需要学习任何参数同时也非常简单的机器学习算法,既可以用来解决分类问题也可以用来解决回归问题。直观解释这个算法就是'近朱者赤,近墨者黑...

1250
来自专栏Ldpe2G的个人博客

仿射变换实现组合操作 抠图+缩放+旋转

之前在工作中需要用仿射变换的方式来实现,用给定的bounding box(标注框)从一张

1484

扫码关注云+社区

领取腾讯云代金券