MXNet网络模型(二)—— 多层感知器

MXNet网络模型(二)—— 多层感知器

上一节展示了MXNet框架使用多层感知器来学习线性回归的代码(传送门),这一节进一步将多层感知器用于图像分类。

MNIST数据集

MNIST是机器学习中的经典数据集,他的主页是:http://yann.lecun.com/exdb/mnist/

MNIST数据集中有70,000个手写数字(从0到9)图像。其中60,000个属于训练集,10,000个属于测试集。每个图像只有1个数字,是28x28的灰度图。

在这里插入图片描述

MNIST数据集是图片分类中最基础的数据集,它比较简单,很容易达到一个很高的准确率。MNIST数据集中也有少量的数字很潦草,模棱两可,肉眼也很难区分,因此也很难达到100%的准确率。

网络模型

感知器对应神经网络中的全连接层,MNIST的数据都是图片,图片不能直接输入到全连接层,所以要先将28x28的图片转变为普通的数据。

把28x28的图片理解为28x28的二维矩阵,将二维矩阵摊平就可以得到长度为784的一维矩阵。接着把一维矩阵输入到神经网络,看图。

在这里插入图片描述

神经网络有2个中间层,中间层一般叫做隐藏层,还有一个输出层。输出层使用了独热(One-Hot)编码。

bit9bit8bit7bit6bit5bit4bit3bit2bit1bit0类别
00000000010
00000000101
00000001002
00000010003
00000100004
00001000005
00010000006
00100000007
01000000008
10000000009

使用mx.viz.print_summary()函数可以查看网络的参数和规模:

网络层网络类型输出数据类型训练参数前一层
data1x28x280
flatten摊平图像7840data
layer1_fc全连接128100,480flatten
layer1_act激活层1280layer1_fc
layer2_fc全连接648,256layer1_act
layer2_act激活层640layer2_fc
layer3_fc全连接10650layer2_act
softmaxSoftmax输出100layer3_fc
统计109,386

其中,训练参数 = (前一层输出数据个数 + 1) x 本层输出数据个数

( 784 + 1 ) x 128 = 100,480
( 128 + 1 ) x 64 = 8,256
( 64 + 1 ) x 10 = 650

Show me the code!

# -*- coding: utf-8 -*-

import logging
import struct
import gzip
import numpy as np
import mxnet as mx

logging.getLogger().setLevel(logging.DEBUG)

# 批大小
batch_size = 32
# 学习轮数
train_epoch = 20

'''
************************************************************
*                          数据准备
************************************************************
'''
# 定义读取数据的函数
def read_data( label_url, image_url ):
    with gzip.open( label_url ) as flbl:
        magic, num = struct.unpack(">II", flbl.read(8))                  # 读入标签文件头
        label = np.fromstring( flbl.read(), dtype = np.int8 )            # 读入标签内容
    with gzip.open( image_url, 'rb' ) as fimg:
        magic, num, rows, cols = struct.unpack( ">IIII", fimg.read(16) ) # 读入图像文件头,rows和cols都是28
        image = np.fromstring( fimg.read(), dtype = np.uint8 )           # 读入图像内容
        image = image.reshape( len(label), 1, rows, cols )               # 设置为正确的数组格式
        image = image.astype( np.float32 ) / 255.0                       # 归一化到 0~1
    return (label, image)

# 读入数据
# 注意路径的问题
( train_lbl, train_img ) = read_data( 'train-labels-idx1-ubyte.gz', 'train-images-idx3-ubyte.gz' )
( eval_lbl , eval_img  ) = read_data( 't10k-labels-idx1-ubyte.gz' , 't10k-images-idx3-ubyte.gz'  )

# 迭代器
train_iter = mx.io.NDArrayIter( train_img, train_lbl, batch_size, shuffle=True )
eval_iter  = mx.io.NDArrayIter( eval_img , eval_lbl , batch_size )   # 验证集可以省略shuffle

'''
************************************************************
*                      定义神经网络模型
************************************************************
'''
# 输入层
net = mx.sym.var( 'data' )
# 第1层隐藏层
net = mx.sym.Flatten       ( data=net, name='flatten' )   # 将图像摊平
net = mx.sym.FullyConnected( data=net, name='layer1_fc' , num_hidden=128 )
net = mx.sym.Activation    ( data=net, name='layer1_act', act_type='relu' )
# 第2层隐藏层
net = mx.sym.FullyConnected( data=net, name='layer2_fc' , num_hidden=64 )
net = mx.sym.Activation    ( data=net, name='layer2_act', act_type='relu' )
# 输出层
net = mx.sym.FullyConnected( data=net, name='layer3_fc' , num_hidden=10 )
net = mx.sym.SoftmaxOutput ( data=net, name='softmax' )  # Softmax也是激活层

# 网络模型
module = mx.mod.Module( symbol=net )

# 网络模型可视化
# shape = {'data':(batch_size, 1, 28, 28)}
# mx.viz.plot_network(symbol=net, shape=shape).view()   # 图片显示
# mx.viz.print_summary(symbol=net, shape=shape)         # 表格显示

'''
************************************************************
*                        训练神经网络
************************************************************
'''
# 定义评价标准(Evaluation Metric)
eval_metrics = mx.metric.CompositeEvalMetric()
eval_metrics.add( mx.metric.Accuracy() );        # 添加准确率作为标准
eval_metrics.add( mx.metric.CrossEntropy() );    # 添加交叉熵作为标准

# 开始训练
module.fit(
    train_iter,                                  # 前面定义的数据集
    eval_data = eval_iter,                       # 前面定义的测试集
    eval_metric = eval_metrics,                  # 前面定义的评价标准
    initializer = mx.initializer.Xavier(),       # Xavier初始化策略
    num_epoch = train_epoch,                     # 训练轮数
    optimizer = 'sgd',                           # “随机梯度下降”求解器
    optimizer_params = {
            'learning_rate':0.01,                # 学习速率
            'momentum': 0.9}                     # 惯性动量
)

# end

运行后,我们可以得到类似这样的输出:

INFO:root:Epoch[0] Train-accuracy=0.915450
INFO:root:Epoch[0] Train-cross-entropy=0.286579
INFO:root:Epoch[0] Time cost=2.580
INFO:root:Epoch[0] Validation-accuracy=0.946486
INFO:root:Epoch[0] Validation-cross-entropy=0.167986
INFO:root:Epoch[1] Train-accuracy=0.963650
INFO:root:Epoch[1] Train-cross-entropy=0.120830
INFO:root:Epoch[1] Time cost=2.750
INFO:root:Epoch[1] Validation-accuracy=0.952476
INFO:root:Epoch[1] Validation-cross-entropy=0.144074
 ...
INFO:root:Epoch[19] Train-accuracy=0.999983
INFO:root:Epoch[19] Train-cross-entropy=0.000889
INFO:root:Epoch[19] Time cost=2.714
INFO:root:Epoch[19] Validation-accuracy=0.981030
INFO:root:Epoch[19] Validation-cross-entropy=0.086616

和上一节相比,图片分类问题中,我们还可以用准确率评价神经网络。

经过20轮的训练,得到一个训练集准确率为99.998%,验证集98.103%的神经网络模型。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值