用paddle实现一个CNN神经网络

标签: paddle cnn 神经网络 | 发表时间:2018-06-15 11:19 | 作者:mxdxm
出处:http://www.iteye.com

 

问题:实现在MNIST数据集上,对数字的识别。

 

分析:

(1)输入:MNIST手写的数字图片,它是一个28*28的二维图片,为了计算,我们将其转为784维的一个向量。

(2)输出:分类器的输出是0-9的数字的概率。

(3)分类器的设计:5层的卷积神经网络。即:conv->pool->conv->pool->FC->softmax



 

 

代码如下:

"""
    定义卷积神经网络分类器:
        输入的二维图像,经过两个卷积-池化层,使用以softmax为激活函数的全连接层作为输出层
    Args:
        img -- 输入的原始图像数据
    Return:
        predict -- 分类的结果
    """
    # Your Code Begin:
    # 第一个卷积-池化层
    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()
    )
    # 全连接层
    predict = paddle.layer.fc(
        input=conv_pool_2,
        size=10,
        act=paddle.activation.Softmax()
    )
    # Your Code End:
    return predict

 

下面是完整代码:

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
    Authors: xiake([email protected])
    Date:    2017/11/29

    使用paddle框架实现逻辑数字识别案例,关键步骤如下:
    1.定义分类器网络结构
    2.初始化
    3.配置网络结构
    4.定义成本函数cost
    5.定义优化器optimizer
    6.定义事件处理函数
    7.进行训练
    8.利用训练好的模型进行预测
"""

import os
import numpy as np
from PIL import Image

import matplotlib
matplotlib.use('Agg')

import paddle.v2 as paddle
from paddle.v2.plot import Ploter

LEARNING_STEP = 0

# 绘图相关标注
TRAIN_TITLE_COST = "Train cost"
TEST_TITLE_COST = "Test cost"

TRAIN_TITLE_ERROR = "Train error rate"
TEST_TITLE_ERROR = "Test error rate"


def softmax_regression(img):
    """
    定义softmax分类器:
        只通过一层简单的以softmax为激活函数的全连接层,可以得到分类的结果
    Args:
        img -- 输入的原始图像数据
    Return:
        predict -- 分类的结果
    """

    # Your Code Begin:
    predict = paddle.layer.fc(
        input=img,
        size=10,
        act=paddle.activation.Softmax()
    )
    # Your Code End:
    return predict


def multilayer_perceptron(img):
    """
    定义多层感知机分类器:
        含有两个隐藏层(即全连接层)的多层感知器
        其中两个隐藏层的激活函数均采用ReLU,输出层的激活函数用Softmax
    Args:
        img -- 输入的原始图像数据
    Return:
        predict -- 分类的结果
    """

    # Your Code Begin:
    # 第一个全连接层
    hidden1= paddle.layer.fc(
        input=img, size=128, act=paddle.activation.Relu()
    )
    # 第二个全连接层
    hidden2 = paddle.layer.fc(
        input=hidden1, size=64, act=paddle.activation.Relu()
    )
    # 第三个全连接层,需要注意输出尺寸为10,,对应0-9这10个数字
    predict = paddle.layer.fc(
        input=hidden2, size=10, act=paddle.activation.Softmax()
    )
    # Your Code End:
    return predict


def convolutional_neural_network(img):
    """
    定义卷积神经网络分类器:
        输入的二维图像,经过两个卷积-池化层,使用以softmax为激活函数的全连接层作为输出层
    Args:
        img -- 输入的原始图像数据
    Return:
        predict -- 分类的结果
    """
    # Your Code Begin:
    # 第一个卷积-池化层
    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()
    )
    # 全连接层
    predict = paddle.layer.fc(
        input=conv_pool_2,
        size=10,
        act=paddle.activation.Softmax()
    )
    # Your Code End:
    return predict


def network_config():
    """
    配置网络结构
    Args:
    Return:
        images -- 输入层
        label -- 标签数据
        predict -- 输出层
        cost -- 损失函数
        parameters -- 模型参数
        optimizer -- 优化器
    """

    """
        输入层:
        paddle.layer.data表示数据层,
        name=’pixel’:名称为pixel,对应输入图片特征
        type=paddle.data_type.dense_vector(784):数据类型为784维(输入图片的尺寸为28*28)稠密向量
    """

    images = paddle.layer.data(
        name='pixel', type=paddle.data_type.dense_vector(784))

    """
        数据层:
        paddle.layer.data表示数据层,
        name=’label’:名称为label,对应输入图片的类别标签
        type=paddle.data_type.dense_vector(10):数据类型为10维(对应0-9这10个数字)稠密向量
    """

    label = paddle.layer.data(
        name='label', type=paddle.data_type.integer_value(10))

    """
        选择分类器:
        在此之前已经定义了3种不同的分类器,在下面的代码中,
        我们可以通过保留某种方法的调用语句、注释掉其余两种,以选择特定的分类器
    """
    # predict = softmax_regression(images)
    # predict = multilayer_perceptron(images)
    predict = convolutional_neural_network(images)

    # 定义成本函数,paddle.layer.classification_cost()函数内部采用的是交叉熵损失函数
    cost = paddle.layer.classification_cost(input=predict, label=label)

    # 利用cost创建参数parameters
    parameters = paddle.parameters.create(cost)

    # 创建优化器optimizer,下面列举了2种常用的优化器,不同类型优化器选一即可
    # 创建Momentum优化器,并设置学习率(learning_rate)、动量(momentum)和正则化项(regularization)
    optimizer = paddle.optimizer.Momentum(
        learning_rate=0.01 / 128.0,
        momentum=0.9,
        regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128))

    # 创建Adam优化器,并设置参数beta1、beta2、epsilon
    # optimizer = paddle.optimizer.Adam(beta1=0.9, beta2=0.99, epsilon=1e-06)

    config_data = [images, label, predict, cost, parameters, optimizer]

    return config_data


def plot_init():
    """
    绘图初始化函数:
        初始化绘图相关变量
    Args:
    Return:
        cost_ploter -- 用于绘制cost曲线的变量
        error_ploter -- 用于绘制error_rate曲线的变量
    """
    # 绘制cost曲线所做的初始化设置
    cost_ploter = Ploter(TRAIN_TITLE_COST, TEST_TITLE_COST)

    # 绘制error_rate曲线所做的初始化设置
    error_ploter = Ploter(TRAIN_TITLE_ERROR, TEST_TITLE_ERROR)

    ploter = [cost_ploter, error_ploter]

    return ploter


def load_image(file_path):
    """
    定义读取输入图片的函数:
        读取指定路径下的图片,将其处理成分类网络输入数据对应形式的数据,如数据维度等
    Args:
        file_path -- 输入图片的文件路径
    Return:
        im -- 分类网络输入数据对应形式的数据
    """
    image = Image.open(file_path).convert('L')
    image = image.resize((28, 28), Image.ANTIALIAS)
    image = np.array(image).astype(np.float32).flatten()
    image = image / 255.0
    return image


def infer(predict, parameters, file_path):
    """
    定义判断输入图片类别的函数:
        读取并处理指定路径下的图片,然后调用训练得到的模型进行类别预测
    Args:
        predict -- 输出层
        parameters -- 模型参数
        file_path -- 输入图片的文件路径
    Return:
    """
    # 读取并预处理要预测的图片
    test_data = []
    cur_dir = os.path.dirname(os.path.realpath(__file__))
    test_data.append((load_image(cur_dir + file_path),))

    # 利用训练好的分类模型,对输入的图片类别进行预测
    probs = paddle.infer(
        output_layer=predict, parameters=parameters, input=test_data)
    lab = np.argsort(-probs)
    print "Label of image/infer_3.png is: %d" % lab[0][0]


def main():
    """
    主函数:定义神经网络结构,训练模型并打印学习曲线、预测测试数据类别
    """

    # 初始化,设置是否使用gpu,trainer数量
    paddle.init(use_gpu=False, trainer_count=1)

    # 定义神经网络结构
    images, label, predict, cost, parameters, optimizer = network_config()

    # 构造trainer,配置三个参数cost、parameters、update_equation,它们分别表示成本函数、参数和更新公式
    trainer = paddle.trainer.SGD(
        cost=cost, parameters=parameters, update_equation=optimizer)

    # 初始化绘图变量 (only with python-tk installed)
    cost_ploter, error_ploter = plot_init()

    # lists用于存储训练的中间结果,包括cost和error_rate信息,初始化为空
    lists = []

    def event_handler_plot(event):
        """
        定义event_handler_plot事件处理函数:
            事件处理器,可以根据训练过程的信息做相应操作:包括绘图和输出训练结果信息
        Args:
            event -- 事件对象,包含event.pass_id, event.batch_id, event.cost等信息
        Return:
        """
        global LEARNING_STEP
        if isinstance(event, paddle.event.EndIteration):
            # 每训练100次(即100个batch),添加一个绘图点
            if LEARNING_STEP % 100 == 0:
                cost_ploter.append(TRAIN_TITLE_COST, LEARNING_STEP, event.cost)
                # 绘制cost图像,保存图像为‘train_test_cost.png’
                cost_ploter.plot('./train_test_cost')
                error_ploter.append(TRAIN_TITLE_ERROR, LEARNING_STEP,
                                    event.metrics['classification_error_evaluator'])
                # 绘制error_rate图像,保存图像为‘train_test_error_rate.png’
                error_ploter.plot('./train_test_error_rate')
            LEARNING_STEP += 1
            # 每训练100个batch,输出一次训练结果信息
            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):
            # 保存参数至文件
            with open('params_pass_%d.tar' % event.pass_id, 'w') as parameter_file:
                trainer.save_parameter_to_tar(parameter_file)
            # 利用测试数据进行测试
            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)
            # 添加测试数据的cost和error_rate绘图数据
            cost_ploter.append(TEST_TITLE_COST, LEARNING_STEP, result.cost)
            error_ploter.append(
                TEST_TITLE_ERROR, LEARNING_STEP, result.metrics['classification_error_evaluator'])
            # 存储测试数据的cost和error_rate数据
            lists.append((
                event.pass_id, result.cost, result.metrics['classification_error_evaluator']))

    """
    训练模型:
        paddle.reader.shuffle(paddle.dataset.mnist.train(), buf_size=8192):
            表示trainer从paddle.dataset.mnist.train()这个reader中读取了buf_size=8192大小的数据并打乱顺序
        paddle.batch(reader(), batch_size=128):
            表示从打乱的数据中再取出batch_size=128大小的数据进行一次迭代训练
        event_handler:事件处理函数,可以自定义event_handler,根据事件信息做相应的操作,
            下方代码中选择的是event_handler_plot函数
        num_passes:定义训练的迭代次数
    """

    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=10)

    # 在多次迭代中,找到在测试数据上表现最好的一组参数,并输出相应信息
    best = sorted(lists, key=lambda list: float(list[1]))[0]
    print 'Best pass is %s, testing Avgcost is %s' % (best[0], best[1])
    print 'The classification accuracy is %.2f%%' % (100 - float(best[2]) * 100)

    # 预测输入图片的类型
    infer(predict, parameters, '/image/infer_3.png')


if __name__ == '__main__':
    main()

 

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [paddle cnn 神经网络] 推荐:

用paddle实现一个CNN神经网络

- - 非技术 - ITeye博客
问题:实现在MNIST数据集上,对数字的识别. (1)输入:MNIST手写的数字图片,它是一个28*28的二维图片,为了计算,我们将其转为784维的一个向量. (2)输出:分类器的输出是0-9的数字的概率. (3)分类器的设计:5层的卷积神经网络. 即:conv->pool->conv->pool->FC->softmax.

直白介绍卷积神经网络(CNN) - 文章 - 伯乐在线

- -
什么是卷积神经网络,它为何重要. 神经网络的一种,它在图像识别和分类等领域已被证明非常有效. 卷积神经网络除了为机器人和自动驾驶汽车的视觉助力之外,还可以成功识别人脸,物体和交通标志. 图1所示,卷积神经网络能够识别图片的场景并且提供相关标题(“足球运动员正在踢足球”),. 图2则是利用卷积神经网络识别日常物品、人类和动物的例子.

轻量的神经网络

- - Just for Life.
很久之前我觉得移动端应用几百兆的模型不切实际,在不考虑蒸馏、量化等压缩方法下,发现了 MobileNet 设计的很神奇,大小只有几 MB,可以说是一股清流了. 就整理发布了一下,然后今天发现找不到了,神奇. (于是顺手和 ShuffleNet 一并整理到轻量化的神经网络中). 基本上可以说这个版本是后面几个版本的出发点.

Zite 正和 CNN 谈判收购事宜?

- Leo - 爱范儿 · Beats of Bits
根据 Venturebeat 的最新消息,Zite 正在和 CNN 谈判收购事宜. CNN 可能出价 2000 万或 2500 万元. 关于 Zite 我们曾经做过介绍. 简单的说,Zite 是 iPad 平台的个性化电子杂志,可免费下载. 相比 Flipboard 的“定制化”,Zite 试图提供更加“个性化”的阅读体验.

[转]Tensorflow实现的CNN文本分类

- - Soul Joy Hub
在这篇文章中,我们将实现一个类似于Kim Yoon的卷积神经网络语句分类的模型. 本文提出的模型在一系列文本分类任务(如情感分析)中实现了良好的分类性能,并已成为新的文本分类架构的标准基准. 本文假设你已经熟悉了应用于NLP的卷积神经网络的基础知识. 如果没有,建议先阅读Understanding Convolutional Neural Networks for NLP 以获得必要的背景.

BP神经网络的Java实现

- - ITeye博客
课程作业要求实现一个BPNN. 此前只用Matlab实现过,这次尝试使用Java实现了一个. 关于BPNN的原理,就不赘述了.  为了验证正确性,我写了一个测试用例,目的是对于任意的整数(int型),BPNN在经过训练之后,能够准确地判断出它是奇数还是偶数,正数还是负数. System.out.println("训练完毕,下面请输入一个任意数字,神经网络将自动判断它是正数还是复数,奇数还是偶数.

神经网络与用户行为

- - 博客园_新闻
英文原文: Neurology & User Behavior: What We Know. 流量和转化率是我们衡量一个网站是否成功的两个重要指标. 网站转化率就是指用户进行了相应目标行动的访问次数(成交人数)与总访问次数的比率. 这里所指的相应的行动可以是用户登录、用户注册、用户订阅、用户下载、用户购买等一些列用户行为,因此网站转化率是一个广义的概念.

[译] 调试神经网络的清单

- - IT瘾-dev
训练深度学习模型是非常耗时的工作,没有什么比花费了好几天训练而最终结果效果不佳更让人沮丧的了. 因此翻译了这篇文章: Checklist for debugging neural networks,希望能给你一点启发,尽早发现模型中的问题. 原文地址:https://towardsdatascience.com/checklist-for-debugging-neural-networks-d8b2a9434f21 ,略有删减.

CNN评选皮蛋“最恶心”引哗然

- 秀峰 - 联合早报网 zaobao.com - 中国新闻
美国有线电视新闻网(CNN)评选中国的皮蛋为“全球最恶心食物”而引起华人世界哗然后,有关记者写信澄清并道歉.

CNN专访宫崎骏:最伟大的动画大师

- 姜小白 - 东西
(CNN)宫崎骏,被许多人看做是世界上最伟大的动漫家之一以及日本流行文化的代表人物. 2002年,他的作品《千与千寻》以突然之势进入国际观众的视野,这部电影打破了日本电影票房纪录,并为他赢得了奥斯卡最佳动画长片奖. 吉卜力动漫工作室于1985年成立至今,这位70岁高龄的老人一共制作了18部动画长片.