典型的卷积神经网络。

数据的预处理

  • Keras傻瓜式读取数据:自动下载,自动解压,自动加载。
  • # X_train:
array([[[[ 0.,  0.,  0., ...,  0.,  0.,  0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
...,
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.]]], ..., [[[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
...,
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.]]]], dtype=float32)
  • # y_train:
array([5, 0, 4, ..., 5, 6, 8], dtype=uint8)

但需要二值化作为output:np_utils.to_categorical(y_train, nb_classes)

  • # Y_train:
Y_train[0]
Out[56]: array([ 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.]) Y_train[1]
Out[57]: array([ 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) Y_train[2]
Out[58]: array([ 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.])

Code: 图片--> Matrix 

#coding:utf-8

import os
from PIL import Image
import numpy as np #读取文件夹mnist下的42000张图片,图片为灰度图,所以为1通道,
#如果是将彩色图作为输入,则将1替换为3,并且data[i,:,:,:] = arr改为data[i,:,:,:] = [arr[:,:,0],arr[:,:,1],arr[:,:,2]]
def load_data():
data = np.empty((42000,1,28,28),dtype="float32")
label = np.empty((42000,),dtype="uint8") imgs = os.listdir("./mnist")
num = len(imgs)
for i in range(num):
img = Image.open("./mnist/"+imgs[i])
arr = np.asarray(img,dtype="float32")
data[i,:,:,:] = arr
label[i] = int(imgs[i].split('.')[0])
return data,label

原始图片二维数组化

如何建模

Figure, LeNet-5的网络结构

Model结构说明:http://blog.csdn.net/strint/article/details/44163869

LeNet-5中主要的有:卷积层、下抽样层、全连接层3中连接方式。

  • 卷积层

采用的都是5x5大小的卷积核,且卷积核每次滑动一个像素,一个特征图谱使用同一个卷积核(即特征图谱内卷积核共享参数)。

每个上层节点的值乘以连接上的参数,把这些乘积及一个偏置参数相加得到一个和,把该和输入激活函数,激活函数的输出即是下一层节点的值。

卷积核有5x5个连接参数加上1个偏置共26个训练参数。

【32*32 卷积(5*5)后得到28*28,如下Figure 6】

Figure 6 卷积神经网络连接与矩阵卷积的对应关系

  • 下抽样层

采用的是2x2的输入域,即上一层的4个节点作为下一层1个节点的输入,且输入域不重叠,即每次滑动2个像素,下抽样节点的结构见Figure 7。

每个下抽样节点的4个输入节点求和后取平均,均值乘以一个参数加上一个偏置参数作为激活函数的输入,激活函数的输出即是下一层节点的值。

一个下抽样节点只有2个训练参数。

Figure 7 一个下抽样节点的连接方式

  • 全连接层

(略)

纪要:

输入层是32x32像素的图片,比数据集中最大的的字符(最大体积是20x20像素的字符位于28x28像素区域的中心)大很多。这样做的原因是能使潜在的特征比如边缘的端点、拐角能够出现在最高层次的特征解码器的接收域的中心。

LeNet-5的最后一个卷积层(C3,见后面)的接收域的中心与输入的32x32的图像的中心的20x20的区域相连。

输入的像素值被标准化为背景色(白色)值为 -0.1、前景色(黑色)值为1.175:这样使得输入的均值大致为0、方差大致为1,从而有利于加快训练的速度,类似矩阵的归一化。

在后面的描述中,卷积层用Cx标记,子抽样层用Sx标记,全连接层用Fx标记,其中x表示该层的是LeNet的第x层。

C1层是卷积层,形成6个特征图谱。

特征图谱中的每个单元与输入层的一个5x5的相邻区域相连,即卷积的输入区域大小是5x5,每个特征图谱内参数共享,即每个特征图谱内只使用一个共同卷积核,卷积核有5x5个连接参数加上1个偏置共26个参数。

卷积区域每次滑动一个像素,这样卷积层形成的特征图谱每个的大小是28x28。

C1层共有(5x5+1)x=个训练参数,有x28x28=122304个连接。

Figure 8 C1层的结构

S2层是一个下抽样层。

C1层的6个28x28的特征图谱分别进行以2x2为单位的下抽样得到6个14x14的图。

每个特征图谱使用一个下抽样核,每个下抽象核有两个训练参数,所以:

共有2x=12个训练参数,但是有(2x2+1)x14x14x=5880个连接。

Figure 9 S2层的网络结构

C3层是一个卷积层,卷积和和C1相同,不同的是C3的每个节点与S2中的多个图相连。

C3层有16个10x10的图,每个图与S2层的连接的方式如Table 1 所示。

C3与S2中前3个图相连的卷积结构见Figure 10。这种不对称的组合连接的方式有利于提取多种组合特征。

改成有:

(5x5x+1)x  C3的与S2的0,1,2连接; C3的1与S2的1,2,3连接; ...

+ (5x5x+1)x  

+ (5x5x+1)x  

+ (5x5x+1)x  

= 个训练参数,

共有x10x10=151600个连接。

Table 1 C3与S2的连接关系

Figure 10 C3与S2中前3个图相连的卷积结构

S4是一个下采样层。

C3层的16个10x10的图分别进行以2x2为单位的下抽样得到16个5x5的图。连接的方式与S2层类似。

共有2x16=32个训练参数,5x5x5x16=2000个连接。

C5层是一个卷积层。

由于S4层的16个图的大小为5x5,与卷积核的大小相同,所以卷积后形成的图的大小为1x1。

这里形成120个卷积结果。每个都与上一层的16个图相连。

共有(5x5x16+1)x120 = 48120个参数,同样有48120个连接。

卷积核种类:120?

Figure 11 C5层的连接方式

F6层是全连接层。

F6层有84个节点,对应于一个7x12的比特图:-1表示白色,1表示黑色,这样每个符号的比特图的黑白色就对应于一个编码。

该层的训练参数和连接数是(120+1)x84=10164。

Figure 12 编码的比特图

Figure 13 F6层的连接方式

Output层也是全连接层

共有10个节点,分别代表数字0到9,且如果节点i的值为0,则网络识别的结果是数字i

采用的是径向基函数(RBF)的网络连接方式。假设x是上一层的输入,y是RBF的输出,则RBF输出的计算方式是:

的值由i的比特图编码确定。越接近于0,则越接近于,即越接近于i的比特图编码,表示当前网络输入的识别结果是字符i。

该层有84x10=840个设定的参数和连接。

Figure 14 Output层的网络连接方式

理解难点:http://blog.csdn.net/u010555688/article/details/24848367

Output层由欧式径向基函数(Euclidean Radial Basis Function)单元组成,每类一个单元,每个有84个输入。换句话说,每个输出RBF单元计算输入向量和参数向量之间的欧式距离。输入离参数向量越远,RBF输出的越大。一个RBF输出可以被理解为衡量输入模式和与RBF相关联类的一个模型的匹配程度的惩罚项。用概率术语来说,RBF输出可以被理解为F6层配置空间的高斯分布的负log-likelihood。给定一个输入模式,损失函数应能使得F6的配置与RBF参数向量(即模式的期望分类)足够接近。这些单元的参数是人工选取并保持固定的(至少初始时候如此)。这些参数向量的成分被设为-1或1。虽然这些参数可以以-1和1等概率的方式任选,或者构成一个纠错码,但是被设计成一个相应字符类的7*12大小(即84)的格式化图片。这种表示对识别单独的数字不是很有用,但是对识别可打印ASCII集中的字符串很有用。

用这种分布编码而非更常用的“1 of N”编码用于产生输出的另一个原因是,当类别比较大的时候,非分布编码的效果比较差。原因是大多数时间非分布编码的输出必须为0。这使得用sigmoid单元很难实现。另一个原因是分类器不仅用于识别字母,也用于拒绝非字母。使用分布编码的RBF更适合该目标。因为与sigmoid不同,他们在输入空间的较好限制的区域内兴奋,而非典型模式更容易落到外边。

RBF参数向量起着F6层目标向量的角色。需要指出这些向量的成分是+1或-1,这正好在F6 sigmoid的范围内,因此可以防止sigmoid函数饱和。实际上,+1和-1是sigmoid函数的最大弯曲的点处。这使得F6单元运行在最大非线性范围内。必须避免sigmoid函数的饱和,因为这将会导致损失函数较慢的收敛和病态问题。

以上是LeNet-5的卷积神经网络的完整结构,共约有60,840个训练参数,340,908个连接。一个数字识别的效果如Figure 15所示。

Figure 15 LeNet-5识别数字3的过程

通过对LeNet-5的网络结构的分析,可以直观地了解一个卷积神经网络的构建方法,为分析、构建更复杂、更多层的卷积神经网络做准备。

a Convolutional Neural Network - 精简版的LeNet-5

一个示例:Code

#Evaluate how the model does on the test set
score = model.evaluate(X_test, Y_test, verbose=0) print('Test score:', score[0])
print('Test accuracy:', score[1]) 

Result:

另一个示例:

#coding:utf-8

'''
GPU run command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python cnn.py
CPU run command:
python cnn.py
'''
#导入各种用到的模块组件
from __future__ import absolute_import
from __future__ import print_function
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.advanced_activations import PReLU
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.optimizers import SGD, Adadelta, Adagrad
from keras.utils import np_utils, generic_utils
from six.moves import range
from data import load_data
import random
import numpy as np np.random.seed(1024) # for reproducibility #加载数据
data, label = load_data()
#打乱数据
index = [i for i in range(len(data))]
random.shuffle(index)
data = data[index]
label = label[index]
print(data.shape[0], ' samples') #label为0~9共10个类别,keras要求格式为binary class matrices,转化一下,直接调用keras提供的这个函数
label = np_utils.to_categorical(label, 10) ###############
#开始建立CNN模型
############### #生成一个model
model = Sequential() #【第一个卷积层】,4个卷积核,每个卷积核大小5*5。1表示输入的图片的通道,灰度图为1通道。
#border_mode可以是valid或者full,参见这里:http://blog.csdn.net/niuwei22007/article/details/49366745
#激活函数用tanh
#你还可以在model.add(Activation('tanh'))后加上dropout的技巧: model.add(Dropout(0.5))
model.add(Convolution2D(4, 5, 5, border_mode='valid',input_shape=(,28,28)))
model.add(Activation('tanh')) #【第二个卷积层】,8个卷积核,每个卷积核大小3*3。4表示输入的特征图个数,等于上一层的卷积核个数
#激活函数用tanh
#采用maxpooling,poolsize为(2,2)
model.add(Convolution2D(8, 3, 3, border_mode='valid'))
model.add(Activation('tanh'))
model.add(MaxPooling2D(pool_size=(2, 2))) #【第三个卷积层】,16个卷积核,每个卷积核大小3*3
#激活函数用tanh
#采用maxpooling,poolsize为(2,2)
model.add(Convolution2D(16, 3, 3, border_mode='valid'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
#【全连接层】,先将前一层输出的二维特征图flatten为一维的。
#Dense就是隐藏层。16就是上一层输出的特征图个数。4是根据每个卷积层计算出来的:(28-5+1)得到24,(24-3+1)/2得到11,(11-3+1)/2得到4
#全连接有128个神经元节点,初始化方式为normal
model.add(Flatten())
model.add(Dense(128, init='normal'))
model.add(Activation('tanh')) #【Softmax分类】,输出是10类别
model.add(Dense(10, init='normal'))
model.add(Activation('softmax')) #############
#开始训练模型
##############
#使用SGD + momentum
#model.compile里的参数loss就是损失函数(目标函数)
sgd = SGD(lr=0.05, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd,metrics=["accuracy"]) #调用fit方法,就是一个训练过程. 训练的epoch数设为10,batch_size为100.
#数据经过随机打乱shuffle=True。verbose=1,训练过程中输出的信息,0、1、2三种方式都可以,无关紧要。show_accuracy=True,训练时每一个epoch都输出accuracy。
#validation_split=0.2,将20%的数据作为验证集。
model.fit(data, label, batch_size=100, nb_epoch=10,shuffle=True,verbose=1,validation_split=0.2)

[Keras] mnist with cnn的更多相关文章

  1. keras框架的CNN手写数字识别MNIST

    参考:林大贵.TensorFlow+Keras深度学习人工智能实践应用[M].北京:清华大学出版社,2018. 首先在命令行中写入 activate tensorflow和jupyter notebo ...

  2. keras实现简单CNN人脸关键点检测

    用keras实现人脸关键点检测 改良版:http://www.cnblogs.com/ansang/p/8583122.html 第一步:准备好需要的库 tensorflow  1.4.0 h5py ...

  3. (三) Keras Mnist分类程序以及改用交叉熵对比

    视频学习来源 https://www.bilibili.com/video/av40787141?from=search&seid=17003307842787199553 笔记 Mnist分 ...

  4. 为何Keras中的CNN是有问题的,如何修复它们?

    在训练了 50 个 epoch 之后,本文作者惊讶地发现模型什么都没学到,于是开始深挖背后的问题,并最终从恺明大神论文中得到的知识解决了问题. 上个星期我做了一些实验,用了在 CIFAR10 数据集上 ...

  5. [GAN] Generative networks

    中文版:https://zhuanlan.zhihu.com/p/27440393 原文版:https://www.oreilly.com/learning/generative-adversaria ...

  6. 数据挖掘入门系列教程(十二)之使用keras构建CNN网络识别CIFAR10

    简介 在上一篇博客:数据挖掘入门系列教程(十一点五)之CNN网络介绍中,介绍了CNN的工作原理和工作流程,在这一篇博客,将具体的使用代码来说明如何使用keras构建一个CNN网络来对CIFAR-10数 ...

  7. Keras入门(四)之利用CNN模型轻松破解网站验证码

    项目简介   在之前的文章keras入门(三)搭建CNN模型破解网站验证码中,笔者介绍介绍了如何用Keras来搭建CNN模型来破解网站的验证码,其中验证码含有字母和数字.   让我们一起回顾一下那篇文 ...

  8. 【keras】用tensorboard监视CNN每一层的输出

    from keras.models import Sequential from keras.layers import Dense, Dropout from keras.layers import ...

  9. TensorFlow——CNN卷积神经网络处理Mnist数据集

    CNN卷积神经网络处理Mnist数据集 CNN模型结构: 输入层:Mnist数据集(28*28) 第一层卷积:感受视野5*5,步长为1,卷积核:32个 第一层池化:池化视野2*2,步长为2 第二层卷积 ...

随机推荐

  1. 在linux下Ant的环境配置

    Ant(英文全称为another neat tool,另一个简洁的工具)是一个基于Java的生成工具,Ant将会被应用到Java项目中. 同样的,现在要来安装Ant(最近要安装的东西还蛮多的=m=), ...

  2. [IOS]使用了cocoapods 抱错Pods was rejected as an implicit dependency for ‘libPods.a’ because its architectures ......

    Pods was rejected as an implicit dependency for ‘libPods.a’ because its architectures ‘i386’ didn’t ...

  3. 设计模式(十三) 职责链(chain of responsibility)

    软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径.设计模式中运用了面向对象编程语言的重要特性:封装.继承.多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累.最 ...

  4. Python3.5+selenium操作Chrome浏览器

    1.安装selenium 命令提示符下输入: pip install selenium 2.下载chromedriver 点击下载 3.将解压后的chromedriver.exe放到chrome浏览器 ...

  5. Myeclipse中web project各种常见错误及解决方法(持续更新)

    创建web project时的问题 error:Install Dynamic web Module Facet卡住 solution:把网络关掉再创建就可以 Servlet error:The se ...

  6. 读取XML直接转换为类对象

    <?xml version="1.0" encoding="utf-8"?> <ArrayOfMenuItems xmlns:xsi=&quo ...

  7. Python黑帽编程2.5 函数

    Python黑帽编程2.5 函数 写了几节的基础知识,真心感觉有点力不从心.这块的内容说实话,看文档是最好的方式,本人的写作水平,真的是找不出更好的写法,头疼.简单带过和没写一样,写详细了和本系列教程 ...

  8. Senparc.Weixin.MP SDK 微信公众平台开发教程(十七):个性化菜单接口说明

    前不久微信上线了个性化菜单接口,Senparc.Weixin SDK也已经同步更新. 本次更新升级Senparc.Weixin.MP版本到v13.5.2,依赖Senparc.Weixin版本4.5.4 ...

  9. SSH实战 · JAVA发送邮件相关

    发送激活邮件 电子邮箱:邮件服务器上的一块空间: 邮件服务器:类比于web服务器(tomcat),有相应的服务器软件: 邮件协议:大公司发送和接收服务器分开,也可以都用一个服务器.           ...

  10. How.To.Process.Image.Infomation.Of.Rotate.And.Flip.From.Server

    需求说明 客户端接收到服务器传送过来的图像数据,客户端通过对图像进行旋转和反转操作. 然后把这个旋转和反转的数据上传到服务器. 客户端在接收图像的时候, 也会下载以前的旋转和反转参数, 然后客户端根据 ...