目录
- 经典数据集mnist与手写体识别
- 全连接神经网络的图像输入与问题思考
- 卷积操作的引入与简单卷积核示例
- 基于全连接神经网络的代码实现:
- 卷积神经网络:图像识别实战
- 经典卷积神经网络结构:LeNet-5
- LeNet-5编程代码实现
经典数据集mnist与手写体识别
全连接神经网络的图像输入与问题思考
mnist数据集的图片采用的是28*28的灰度图,灰度图一行有28个像素点,共28行,每个像素点用一个字节的无符号数表示其灰度值,0为最暗,纯黑色,255即为最亮,纯白色,通过每个像素点灰度值的不同来达到图像生成的目的:
为了达到手写体识别的目的,需要整个辨别系统有一定的容错能力,借助神经网络便是很好的选择。为了能将整个图像输入到神经网络中去,我们只需要将其按行展开,“平铺”成一个以为行向量,即可变成输入向量。即一个28×28=784的行向量:
训练集与数据集
在神经网络中,我们将训练时使用的数据成为训练集,用来在训练之后测试拟合效果准确率的样本数据称为测试集。在测试集上的高准确率意味着模型有足够的泛化能力
- 三种不同的表现:
- 欠拟合:在训练集上的准确率较差
- 过拟合:在训练集上的准确李较高,但是在测试集上的准确率明显下降
- 泛化能力较好:在训练集与测试集上准确率都较高
调节过拟合的方式:调节网络结构,L2正则化,节点失活(Dropout)正则化等等
mnist数据集有6w个训练集样本和1w个测试集样本。通过上文注释,我们很容易会发现一个问题:采用这种平铺方式展开后输入神经网络进行训练,很容易导致模型过拟合。一个很容易的例子:如果将一个茶杯的图像按照这样的平铺方式展开为一个一维的行向量像素点图片,没有人能够知道这是一个茶杯。唯一的办法就是“记住它”,这也就是全连接神经网络干的事情。但是我们很容易变会找到漏洞:当我们改变测试集的茶杯图像颜色或者是仅仅改变这个茶杯在图像区域中的位置时,全连接神经网络得到就是完全不同的信息,很容易造成误判。
卷积操作的引入与简单卷积核示例
图像作为一个二维物体,在二维平面相邻像素之间是存在关联的,我们把它强行降到一维,实际上就破坏了这些关联的隐藏信息。人在观察一个图像时,往往会不自觉地提取图像的某些特征,比如曲线、折线、边界等信息。
基于这种思想,我们可以通过对图像进行卷积操作:
卷积核有时也被称为过滤器(filter),通过卷积核的“过滤操作”,我们可以很方便的处理得到图像的边界信息:上图所示的这个卷积核便可以轻易实现这样的功能:只有当卷积核处于不同颜色(黑、白)的分界处时,最终卷积后的到的卷积值才是“非0”的,同种颜色的区域中卷积核左右两侧的权值直接将同种颜色色值进行了抵消。
抵消作用较强 :
抵消作用明显下降:
因此这样的卷积核具备了竖直边界识别能力。同样的,我们也可以利用区分横向边界的卷积核来简单实现“1”和“7”的分辨:
基于全连接神经网络的代码实现:
from keras.datasets import mnist
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import SGD
import matplotlib.pyplot as plt
from keras.utils import to_categorical
m = 100
(X,Y),(X_test,Y_test) = mnist.load_data()
print("X.shape:"+str(X.shape))
print("Y.shape:"+str(Y.shape))
print("X_test.shape:"+str(X_test.shape))
print("Y_test.shape:"+str(Y_test.shape))
print(Y[0])
plt.imshow(X[0],cmap = 'gray')
plt.show()
X= X.reshape(60000,784)/255
X_test = X_test.reshape(10000,784)/255
Y = to_categorical(Y,10)
Y_test = to_categorical(Y_test,10)
model = Sequential()
model.add(Dense(units = 256,activation = 'relu',input_dim = 784))
model.add(Dense(units = 256,activation = 'relu'))
model.add(Dense(units = 256,activation = 'relu'))
model.add(Dense(units = 10,activation = 'softmax'))
model.compile(loss='categorical_crossentropy',optimizer=SGD(lr=0.05),metrics = ['accuracy'])
model.fit(X,Y,epochs = 5000,batch_size = 10)
loss,accuracy = model.evaluate(X_test,Y_test)
print(loss)
print(accuracy)
在Windows操作系统中,Keras数据集会被放置于C:\Users\用户名\.keras\datasets
目录处,可以自行直接添加
卷积神经网络:图像识别实战
前文已经初步介绍了垂直边沿提取与水平边沿提取的两种卷积核,但在实际应用中,我们自然无法事先给定卷积核的各个权值大小,往往要通过训练得到具体的权值。其实,从本质上看,卷积核的卷积操作也是一个类似普通神经元的线性计算部分(注意最后加上偏置项b):
加上偏置项与激活函数后,便更像一个普通的线性神经元模型了
实际的卷积层得到的是一个矩阵模型,在送入全连接层时需要我们手动铺开。同时要注意,这四个神经元的权值参数(包含偏置项b)并不是独立的,这四个神经元共用了一套参数,也即所谓的 参数共享
经典卷积神经网络结构:LeNet-5
如果我们使用多个卷积核对一个二维图像进行卷积操作,那么就会得到一个三维的卷积结果,也即得到一个三维张量,同样的,可以使用一个三维的卷积核对卷积结果进行再次卷积:
被卷积的三维张量的第三个维度值也就是所谓的通道数。即卷积核的通道数应当与被卷积张量的通道数一致:
再来看经典的LeNet-5卷积神经网络结构模型:
可以看到,除了我们熟知的两层卷积层(Convolutions)以外,还多了两层结构Subsampling,我们将其称为池化层。
池化
>池化操作也是选择了一个指定的矩形区域大小,对该区域中的所有卷积结果进行某种数学处理,达到该矩形区域的池化值。如:
- 取区域最大值:Maxpooling —— 最大池化
- 取区域平均值:AveragePooling —— 平均池化
经过池化操作后,原来的通道数不会改变,只是区域“变细”了
池化层不一定是必须的,且因为池化过程是进行一个固定的操作,因此在反向传播的过程中,并没有任何需要学习的参数
LeNet-5编程代码实现
from keras.datasets import mnist
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Conv2D
from keras.layers import AveragePooling2D
from keras.layers import Flatten
from keras.optimizers import SGD
import matplotlib.pyplot as plt
from keras.utils import to_categorical
m = 100
(X,Y),(X_test,Y_test) = mnist.load_data()
print("X.shape:"+str(X.shape))
print("Y.shape:"+str(Y.shape))
print("X_test.shape:"+str(X_test.shape))
print("Y_test.shape:"+str(Y_test.shape))
print(Y[0])
plt.imshow(X[0],cmap = 'gray')
plt.show()
X= X.reshape(60000,28,28,1)/255
X_test = X_test.reshape(10000,28,28,1)/255
Y = to_categorical(Y,10)
Y_test = to_categorical(Y_test,10)
model = Sequential()
model.add(Conv2D(filters = 6,kernel_size = (5,5),strides = (1,1),input_shape = (28,28,1),padding = 'valid',activation = 'relu'))
model.add(AveragePooling2D(pool_size = (2,2)))
model.add(Conv2D(filters = 16,kernel_size = (5,5),strides = (1,1),padding = 'valid',activation = 'relu'))
model.add(AveragePooling2D(pool_size = (2,2)))
model.add(Flatten())
model.add(Dense(units = 120 , activation = 'relu'))
model.add(Dense(units = 84,activation = 'relu'))
model.add(Dense(units = 10,activation = 'softmax'))
model.compile(loss='categorical_crossentropy',optimizer=SGD(lr=0.05),metrics = ['accuracy'])
model.fit(X,Y,epochs = 5000,batch_size = 10)
loss,accuracy = model.evaluate(X_test,Y_test)
print(loss)
print(accuracy)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)