卷积神经网络CNN 手写数字识别
1. 知识点准备
在了解 CNN 网络神经之前有两个概念要理解,第一是二维图像上卷积的概念,第二是 pooling 的概念。
a. 卷积
关于卷积的概念和细节可以参考这里,卷积运算有两个非常重要特性,以下面这个一维的卷积为例子:
第一个特性是稀疏连接。可以看到, layer m 上的每一个节点都只与 layer m-1 对应区域的三个节点相连接。这个局部范围也叫感受野。第二个特性是相同颜色的线条代表了相同的权重,即权重共享。这样做有什么好处呢?一方面权重共享可以极大减小参数的数目,学习起来更加有效,另一方面,相同的权重可以让过滤器不受图像位置的影响来检测图像的特性,从而使 CNN 具有更强的泛化能力。
b. 池化
理论上,我们将图像利用不同的过滤器通过卷积之后得到了多个卷积之后的图像,然后直接利用这些图像进行分类,但是这样计算量太大了。利用池化操作可以将数据量减小,同时在一定程度上保留原有的图像特征。关于 pooling, 概念更加简单了,详情可以参考这里。池化又可以分为平均池化和最大池化,这里我们将采用最大池化。注意到,池化的区域是不重叠的,卷积的感受野是重叠的。
2. 卷积神经网络的搭建
下图是手写数字识别中采用的 lenet-5 简单的卷积神经网络模型:
原图是 28 × 28 的手写数字图片,通过第一次 20 个 5 × 5 的卷积核之后,得到 20 张卷积图片。卷积核的权重是取一定范围内的随机值,这样,一张 28 × 28 的图片就变为 20 张 (28-5+1)× (28-5+1)=24×24 的图片了。
将 24×24 的图片进行 2 × 2 的最大池化,得到 20 张 12 × 12 的图片。该图片的像素还需要进行 tanh 函数的变换才能作为下一个卷积层的输入。
将 tanh 变化之后的 12 × 12 大小的图片同样进行 20 × 50 个 5 × 5 的卷积操作之后得到 50 张 (12-5+1)× (12-5+1) = 8 × 8 的图片。
将 8×8 的图片进行 2×2 的最大池化,得到 50 张 4×4 的图片,再经过 tanh 函数进行归一化处理,就可以作为 MLP 的 800 个输入了。
余下来就是 MLP 的训练工作了。
3. LR, MLP,CNN 识别代码
已经训练好的模型系数的下载地址。
三种方法识别手写数字的代码:

1 import cPickle
2
3 import numpy
4
5 import theano
6 import theano.tensor as T
7 from theano.tensor.signal import downsample
8 from theano.tensor.nnet import conv
9
10 ########################################
11 # define the classifer constructs
12 ########################################
13
14 class LogisticRegression(object):
15 def __init__(self, input, W=None, b=None):
16
17 if W is None:
18 fle = open("../model_param/lr_sgd_best.pkl")
19 W, b = cPickle.load(fle)
20 fle.close()
21
22 self.W = W
23 self.b = b
24
25 self.outputs = T.nnet.softmax(T.dot(input, self.W) + b)
26
27 self.pred = T.argmax(self.outputs, axis=1)
28
29 class MLP(object):
30 def __init__(self, input, params=None):
31 if params is None:
32 fle = open("../model_param/mlp_best.pkl")
33 params = cPickle.load(fle)
34 fle.close()
35
36 self.hidden_W, self.hidden_b, self.lr_W, self.lr_b = params
37
38 self.hiddenlayer = T.tanh(T.dot(input, self.hidden_W) + self.hidden_b)
39
40 self.outputs = T.nnet.softmax(T.dot(self.hiddenlayer, self.lr_W) \
41 + self.lr_b)
42
43 self.pred = T.argmax(self.outputs, axis=1)
44
45 class CNN(object):
46 def __init__(self, input, params=None):
47 if params is None:
48 fle = open("../model_param/cnn_best.pkl")
49 params = cPickle.load(fle)
50 fle.close()
51
52 ################
53 self.layer3_W, self.layer3_b, self.layer2_W, self.layer2_b, \
54 self.layer1_W, self.layer1_b, self.layer0_W, self.layer0_b = params
55
56 # compute layer0
57 self.conv_out0 = conv.conv2d(input=input, filters=self.layer0_W)
58 # filter_shape=(20, 1, 5, 5), image_shape=(1, 1, \
59 # 28, 28))
60 self.pooled_out0 = downsample.max_pool_2d(input=self.conv_out0, \
61 ds=(2, 2), ignore_border=True)
62 self.layer0_output = T.tanh(self.pooled_out0 + \
63 self.layer0_b.dimshuffle('x', 0, 'x', 'x'))
64
65 # compute layer1
66 self.conv_out1 = conv.conv2d(input=self.layer0_output, filters=self.layer1_W)
67 # filter_shape=(50, 20, 5, 5), image_shape=(1, 20, \
68 # 12, 12))
69 self.pooled_out1 = downsample.max_pool_2d(input=self.conv_out1, \
70 ds=(2, 2), ignore_border=True)
71 self.layer1_output = T.tanh(self.pooled_out1 + \
72 self.layer1_b.dimshuffle('x', 0, 'x', 'x'))
73
74 # compute layer2
75 self.layer2_input = self.layer1_output.flatten(2)
76
77 self.layer2_output = T.tanh(T.dot(self.layer2_input, self.layer2_W) + \
78 self.layer2_b)
79
80 # compute layer3
81 self.outputs = T.nnet.softmax(T.dot(self.layer2_output, self.layer3_W)\
82 + self.layer3_b)
83
84 self.pred = T.argmax(self.outputs, axis=1)
85
86 ########################################
87 # build classifier
88 ########################################
89
90 def lr(input):
91 input.shape = 1, -1
92
93 x = T.fmatrix('x')
94 classifer = LogisticRegression(input=x)
95
96 get_p_y = theano.function(inputs=[x], outputs=classifer.outputs)
97 pred_y = theano.function(inputs=[x], outputs=classifer.pred)
98 return (get_p_y(input), pred_y(input))
99
100 def mlp(input):
101 input.shape = 1, -1
102
103 x = T.fmatrix('x')
104 classifer = MLP(input=x)
105
106 get_p_y = theano.function(inputs=[x], outputs=classifer.outputs)
107 pred_y = theano.function(inputs=[x], outputs=classifer.pred)
108 return (get_p_y(input), pred_y(input))
109
110 def cnn(input):
111 input.shape = (1, 1, 28, 28)
112 x = T.dtensor4('x')
113 classifer = CNN(input=x)
114 get_p_y = theano.function(inputs=[x], outputs=classifer.outputs)
115 pred_y = theano.function(inputs=[x], outputs=classifer.pred)
116 return (get_p_y(input), pred_y(input))

卷积神经网络CNN 手写数字识别的更多相关文章
- TensorFlow卷积神经网络实现手写数字识别以及可视化
边学习边笔记 https://www.cnblogs.com/felixwang2/p/9190602.html # https://www.cnblogs.com/felixwang2/p/9190 ...
- 莫烦pytorch学习笔记(八)——卷积神经网络(手写数字识别实现)
莫烦视频网址 这个代码实现了预测和可视化 import os # third-party library import torch import torch.nn as nn import torch ...
- 基于卷积神经网络的手写数字识别分类(Tensorflow)
import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_dat ...
- TensorFlow(十):卷积神经网络实现手写数字识别以及可视化
上代码: import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = inpu ...
- BP神经网络的手写数字识别
BP神经网络的手写数字识别 ANN 人工神经网络算法在实践中往往给人难以琢磨的印象,有句老话叫“出来混总是要还的”,大概是由于具有很强的非线性模拟和处理能力,因此作为代价上帝让它“黑盒”化了.作为一种 ...
- 利用c++编写bp神经网络实现手写数字识别详解
利用c++编写bp神经网络实现手写数字识别 写在前面 从大一入学开始,本菜菜就一直想学习一下神经网络算法,但由于时间和资源所限,一直未展开比较透彻的学习.大二下人工智能课的修习,给了我一个学习的契机. ...
- CNN 手写数字识别
1. 知识点准备 在了解 CNN 网络神经之前有两个概念要理解,第一是二维图像上卷积的概念,第二是 pooling 的概念. a. 卷积 关于卷积的概念和细节可以参考这里,卷积运算有两个非常重要特性, ...
- Keras cnn 手写数字识别示例
#基于mnist数据集的手写数字识别 #构造了cnn网络拟合识别函数,前两层为卷积层,第三层为池化层,第四层为Flatten层,最后两层为全连接层 #基于Keras 2.1.1 Tensorflow ...
- 第二节,TensorFlow 使用前馈神经网络实现手写数字识别
一 感知器 感知器学习笔记:https://blog.csdn.net/liyuanbhu/article/details/51622695 感知器(Perceptron)是二分类的线性分类模型,其输 ...
随机推荐
- 向SD卡写入树莓派的操作系统
这是 meelo 原创的 玩转树莓派 系列文章 用到的工具: Win32 Disk Imager: sd卡读卡器 Raspbian操作系统镜像:下载地址 步骤1:下载操作系统的镜像 树莓派基金会的网 ...
- ZOJ 3955 Saddle Point
排序. 枚举每一个格子,计算这个格子在多少矩阵中是鞍点,只要计算这一行有多少数字比他大,这一列有多少数字比他小,方案数乘一下就是这个格子对答案做出的贡献. #include<bits/stdc+ ...
- 选项卡栏控制器(UITabBarController)
选项卡栏控制器管理的每个场景都包含一个UITabBarItem,它包含标题.图像和徽章. 在场景里可以通过tabBarItem属性来获得UITabBarItem的引用.例如:[self.tabBarI ...
- hp
命令组成hpacucli [parameter=value] 查看: 查看所有控制器状态 hpacucli ctrl all show 查看slot 0阵列信息详细状态 (可以查看物理磁盘和逻辑磁盘的 ...
- Ubuntu下查看软件版本及安装位置
查看软件版本: XXX --version 或 aptitude show xxx 也可用apt-show-versions (要先安装sudo apt-get install apt-show-ve ...
- android 启动流程
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha adb shell 后 用 ps 命令 回车 可以看到 运行的进程. 如下结果: ct ...
- 51nod 1412 AVL树的种类
非常简单的一道题,一眼题 枚举左儿子大小,再枚举深度即可 复杂度$O(n^2 log n)$ #include <cstdio> #include <cstring> #inc ...
- BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 就算是全局变量,也不要忘记,初始化(吐血). 长得一副lca样,没想到是个树形dp(小丫头还有 ...
- 【递推】hdu5927 Auxiliary Set
题意:给你一棵树.q次询问,每次给你一些非关键点,其他的点都是关键点,让你输出树中既不是关键点,也不是关键点的lca的点的数量. 对每次询问的非关键点按照深度从深到浅排序,依次处理,最开始每个点受到的 ...
- 如何使用Eclipse插件—Easy Explorer
Easy Explorer是一个Eclipse插件,主要用于快速浏览项目文件的目录,实用性比较强. 使用方法如下: 1.下载Easy Explorer,从此处下载EasyExplorer:http:/ ...