本系列将作为个人的paddle学习笔记,关于paddle的安装记录后期会补充在这里。本文要介绍深度学习中的“hello world”,手写数字识别。主要是对官方文档和其他文章进行学习,并做一个小小的记录,如有描述不准确的地方期待大家指正。
背景介绍
手写数字识别作为机器学习(或深度学习)的入门教程,一般使用的都是MINIST数据库。这一数据库作为一个简单的计算机视觉数据集,包含了一系列手写数字和对应的标签,并且每张图片都进行了很好的归一化和居中处理。作为新手,我们不必关注复杂的数据处理过程,只需试着理解分类过程跑通代码即可。
模型训练步骤
paddle训练模型的过程可以分为以下几个部分:
加载包--加载数据--搭建网络结构--训练模型--测试结果
官方文档为了对比效果,搭建了三种不同的网络结构进行训练:softmax、多层感知机和CNN网络结构。
模型概览
softmax回归
最简单的softmax回归模型是先将输入层经过一个全连接层得到的特征,然后直接通过softmax 函数进行多分类。
输入层的数据X传到输出层,在激活操作之前,会乘以相应的权重 W ,并加上偏置变量 b ,具体如下:
$ y_i = \text{softmax}(\sum_j W_{i,j}x_j + b_i) $
softmax回归的网络图如下:
[图片上传失败...(image-6f564-1517234805981)]
softmax模型搭建非常简单,在一些小数据集上可以得到不太差的结果。
softmax函数
softmax函数在机器学习中有着广泛的应用,新入门的同学大概更熟悉sigmoid或relu,但softmax无疑也是一种十分好用的函数。从它的名字就可以看出这个函数的意义:max意味着每次都只取概率最大的情况,但完美主义未必能得到最好的结果,伟大的发现总是来自于偶然!因此我们希望可以在一群最大的值中偶尔得到一个小概率事件,这就不是max函数了,我们称之为sofemax。
那么具体每一个取值的概率是多少呢:
假设我们有一个数组,V,Vi表示V中的第i个元素,那么这个元素的softmax值就是[图片上传失败...(image-27a936-1517234805981)]
多层感知器
softmax回归模型只有输入与输出两层网络,尽管它能得到不错的结果,但在追求更加精准的识别效果时,就需要增加在输入输出层之间添加更多的隐含层。
[图片上传失败...(image-17af98-1517234805981)]
其中,每个隐含层中都包含着激活函数,常见的激活函数有sigmoid、tanh、relu等等。
卷积神经网络
卷积神经网络(CNN),是一种专门用来处理具有类似网格结构的数据的神经网络,例如图像数据(可以看作二位的像素网格)。它与FC不同的地方在于,CNN的上下层神经元并不都能直接连接,而是通过“卷积核”作为中介,通过“核”的共享大大减少了隐含层的参数。简单的CNN是一系列层,并且每个层都通过一个可微函数将一个量转化为另一个量,通常用三个主要类型的层去构建CNN结构,包括卷积层(Convolutional Layer)、池化层(Pooling Layer)和全连接层(FC)。卷积网络在诸多应用领域有很好的应用效果,特别是在大型图像处理的场景表现格外出色。
本次手写数字识别使用的是卷积神经网络是LeNet-5,下图展示了它的结构:输入二维图像,经过两次卷积,再经过全连接,最后使用softmax分类作为输出层。
[图片上传失败...(image-387dd7-1517234805981)]
卷积与池化层的内容下次补充
paddle实现
加载包
import paddle.v2 as paddle
分别定义三个分类器:
softmax
def softmax_regression(img):
predict = paddle.layer.fc(input=img,
size=10,
act=paddle.activation.Softmax())
return predict
多层感知器
def multilayer_perceptron(img):
# 第一个全连接层,激活函数为ReLU
hidden1 = paddle.layer.fc(input=img, size=128, act=paddle.activation.Relu())
# 第二个全连接层,激活函数为ReLU
hidden2 = paddle.layer.fc(input=hidden1,
size=64,
act=paddle.activation.Relu())
# 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10
predict = paddle.layer.fc(input=hidden2,
size=10,
act=paddle.activation.Softmax())
return predict
CNN
def convolutional_neural_network(img):
# 第一个卷积-池化层
conv_pool_1 = paddle.networks.simple_img_conv_pool(
input=img,
filter_size=5,
num_filters=20,
num_channel=1,
pool_size=2,
pool_stride=2,
act=paddle.activation.Relu())
# 第二个卷积-池化层
conv_pool_2 = paddle.networks.simple_img_conv_pool(
input=conv_pool_1,
filter_size=5,
num_filters=50,
num_channel=20,
pool_size=2,
pool_stride=2,
act=paddle.activation.Relu())
# 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10
predict = paddle.layer.fc(input=conv_pool_2,
size=10,
act=paddle.activation.Softmax())
return predict
通过layer.data调用来获取数据,然后调用分类器得到结果,计算其损失函数(分类问题常使用交叉熵函数)
# 该模型运行在单个CPU上
paddle.init(use_gpu=False, trainer_count=1)
images = paddle.layer.data(
name='pixel', type=paddle.data_type.dense_vector(784))
label = paddle.layer.data(
name='label', type=paddle.data_type.integer_value(10))
# predict = softmax_regression(images) # Softmax回归
# predict = multilayer_perceptron(images) #多层感知器
predict = convolutional_neural_network(images) #LeNet5卷积神经网络
cost = paddle.layer.classification_cost(input=predict, label=label)
parameters = paddle.parameters.create(cost)
optimizer = paddle.optimizer.Momentum(
learning_rate=0.1 / 128.0,
momentum=0.9,
regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128))
trainer = paddle.trainer.SGD(cost=cost,
parameters=parameters,
update_equation=optimizer)
输出训练结果
from paddle.v2.plot import Ploter
train_title = "Train cost"
test_title = "Test cost"
cost_ploter = Ploter(train_title, test_title)
step = 0
# event_handler to plot a figure
def event_handler_plot(event):
global step
if isinstance(event, paddle.event.EndIteration):
if step % 100 == 0:
cost_ploter.append(train_title, step, event.cost)
cost_ploter.plot()
step += 1
if isinstance(event, paddle.event.EndPass):
# save parameters
with open('params_pass_%d.tar' % event.pass_id, 'w') as f:
trainer.save_parameter_to_tar(f)
result = trainer.test(reader=paddle.batch(
paddle.dataset.mnist.test(), batch_size=128))
cost_ploter.append(test_title, step, result.cost)
lists = []
def event_handler(event):
if isinstance(event, paddle.event.EndIteration):
if event.batch_id % 100 == 0:
print "Pass %d, Batch %d, Cost %f, %s" % (
event.pass_id, event.batch_id, event.cost, event.metrics)
if isinstance(event, paddle.event.EndPass):
# save parameters
with open('params_pass_%d.tar' % event.pass_id, 'w') as f:
trainer.save_parameter_to_tar(f)
result = trainer.test(reader=paddle.batch(
paddle.dataset.mnist.test(), batch_size=128))
print "Test with Pass %d, Cost %f, %s\n" % (
event.pass_id, result.cost, result.metrics)
lists.append((event.pass_id, result.cost,
result.metrics['classification_error_evaluator']))
trainer.train(
reader=paddle.batch(
paddle.reader.shuffle(
paddle.dataset.mnist.train(), buf_size=8192),
batch_size=128),
event_handler=event_handler_plot,
num_passes=5)
打印日志如下:
# Pass 0, Batch 0, Cost 2.780790, {'classification_error_evaluator': 0.9453125}
# Pass 0, Batch 100, Cost 0.635356, {'classification_error_evaluator': 0.2109375}
# Pass 0, Batch 200, Cost 0.326094, {'classification_error_evaluator': 0.1328125}
# Pass 0, Batch 300, Cost 0.361920, {'classification_error_evaluator': 0.1015625}
# Pass 0, Batch 400, Cost 0.410101, {'classification_error_evaluator': 0.125}
# Test with Pass 0, Cost 0.326659, {'classification_error_evaluator': 0.09470000118017197}
训练之后,检查模型预测准确度,一般 softmax回归模型的分类准确率为约为 92.34%,多层感知器为97.66%,卷积神经网络可以达到 99.20%
网友评论