一、基本介绍
(一)卷积神经网络
- 卷积层是卷积神经网络的核心基石。在图像识别里我们提到的卷积是二维卷积,即离散二维滤波器(也称作卷积核)与二维图像做卷积操作,简单的讲是二维滤波器滑动到二维图像上所有位置,并在每个位置上与该像素点及其领域像素点做内积。卷积操作被广泛应用与图像处理领域,不同卷积核可以提取不同的特征,例如边沿、线性、角等特征。在深层卷积神经网络中,通过卷积操作可以提取出图像低级到复杂的特征。
- 一个卷积神经网络由若干卷积层、Pooling层、全连接层组成。
卷积神经网络的主要组成:
卷积层(Convolutional layer),卷积运算的目的是提取输入的不同特征,第一层卷积层可能只能提取一些低级的特征如边缘、线条和角等层级,更多层的网络能从低级特征中迭代提取更复杂的特征。
采样层(Pooling),它实际上一种形式的向下采样。下采样的目的是为了降低网络训练参数及模型的过拟合程度。下采样层的池化方式通常有两种:最大值池化和均值池化。
全连接层(Full connection), 与普通神经网络一样的连接方式,一般都在最后几层。 - 卷积的计算:
这里的蓝色矩阵就是输入的图像,粉色矩阵就是卷积层的神经元,这里表示了有两个神经元(w0,w1)。绿色矩阵就是经过卷积运算后的输出矩阵,这里的步长设置为2。灰色部分为填充部分。蓝色的矩阵(输入图像)对粉色的矩阵(filter)进行矩阵内积计算并将三个内积运算的结果与偏置值b相加,计算后的值就是绿框矩阵的一个元素。
参考文章:
https://blog.csdn.net/happyorg/article/details/78274066
https://cuijiahua.com/blog/2018/01/dl_3.html
(二)LeNet
- LeNet是Yann LeCun在1998年设计的用于手写数字识别的卷积神经网络,当年美国大多数银行就是用它来识别支票上面的手写数字的,它是早期卷积神经网络中最有代表性的实验系统之一。
- LeNet共有7层(输入层不算在网络结构中),每层都包含不同数量的训练参数,如下图所示。
(1) 输入层为3232图像,一般限定字符最大范围为2020
(2)C1:卷积层为6副28×28的特征图。C1层具有如下特点:
拓扑结构:输入层相邻节点卷积后仍然相邻
稀疏连接:每个像素仅与输入层的相邻结点相连
权值共享:同一副特征图共享相同的卷积核
C1层神经元连接数量为28 * 28* (5*5+1) * 6=122304,由于采用了权值共享,
因此待学习参数为(5 * 5+1) * 6=156。如果采用全连接策略,总参数量可达(32 * 32+1) * (28 * 28) * 6,参数数量太多。
减少了参数数量也是卷积神经网络的一个优点,每个神经元不再和上一层的所有神经元相连,而只和一小部分神经元相连,这样就减少了很多参数。
(3)S2:Pooling层将28 * 28的特征图将采样为14 * 14的图像
(4)C3:将6副28 * 28的特征图卷积为16副10 * 10的图像,卷积核为5 * 5
(5)S4:将10 * 10的特征图将采样为16副5 * 5的图像
(6)C5:将16副5 * 5的特征图卷积为长度为120的向量
(7)F6:构建84个神经元,每个神经元与C5的120个神经元全连接
具体可以参考:https://cuijiahua.com/blog/2018/01/dl_3.html
(二)分析与结果
(一)训练
- MNIST 数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST). 训练集 (training set) 由来自 250 个不同人手写的数字构成, 其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员. 测试集(test set) 也是同样比例的手写数字数据。
- 下载地址:http://yann.lecun.com/exdb/mnist/
- 这次使用TensorFlow作为框架,它是Google的深度学习框架,TensorBoard可视化很方便,数据和模型并行化好,速度快。我装的是GPU版本,运行起来几秒就可以,但是GPU版本的安装可能会有问题,安装失败可以改用CPU版本,只是CPU版本运行起来速度会慢许多。
- 代码:
以图片形式训练,我跑起来花了一小时还没跑完,CPU大概会跑更久。
#coding:utf8
import os
import cv2
import numpy as np
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
sess = tf.InteractiveSession()
def getTrain():
train=[[],[]] # 指定训练集的格式,一维为输入数据,一维为其标签
# 读取所有训练图像,作为训练集
train_root="mnist_train"
labels = os.listdir(train_root)
for label in labels:
imgpaths = os.listdir(os.path.join(train_root,label))
for imgname in imgpaths:
img = cv2.imread(os.path.join(train_root,label,imgname),0)
array = np.array(img).flatten() # 将二维图像平铺为一维图像
array=MaxMinNormalization(array)
train[0].append(array)
label_ = [0,0,0,0,0,0,0,