Keras手写识别入门深度学习

 

MNIST数据集是机器学习领域的一个经典数据集,包括了28*28像素的0-9的手写数字灰度图片(如下图),共60000张训练图片以及10000张测试图片,我们可以将解决MNIST数据集的手写识别看作是深度学习领域的Hello World。此次使用Python的Keras库来构建神经网络解决这个问题。


在此之前首先需要了解一些概念。

  1. 张量:在某些情况下我们会讨论坐标超过两维的数组,一般的一个数组中的元素分布在若干维坐标的规则网络中我们称之为张量。像矩阵就是二维张量,因此张量是矩阵向任意维度的推广。目前所有的机器学习系统都是用张量作为基本的数据结构。我们经常使用的包含一个数字的张量叫做标量,也成为0维的张量。而向量(数组)则是1维张量,矩阵则是二维张量。多个矩阵可以合成更高维的张量。在python中可以nump库中的array方法创建张量。

            import numpy as np
            #0维张量
            x=np.array(1)
            #1维张量
            x=np.array([1,2,3,4])
            #2维张量,一个上三角矩阵
            x=np.array([
                        [1,1,1],
                        [0,1,1],
                        [0,0,1]
                      ])
            #四维张量
            x=np.array([
                        [[1,1,1],[0,1,1],[0,0,1]],
                        [[1,1,1],[0,1,1],[0,0,1]]
                      ])

       张量在现实生活中也有很多实例,例如一张黑白图像是2维张量,彩色的图片因为有RGB三个通道所有是三维张量,而彩色图片数据集又包含了多张图片所有是四维张量,形状为(samples,heigth,weight,channels)。而视频是由一帧一帧的图片组成,视频集的形状为(samples,frames,height,weight,channels),所以视频集是个5维张量,相比彩色图片集多了时间这个维度。如图为MNIST数据集中的一张图片。

2.损失函数:给定数据(x,y),输入想得到预期预测输入y',损失函数即为衡量误差的函数。损失函数越小,模型的鲁棒性就越好。

3.梯度:梯度的本意是一个向量,表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。

4.优化器:基于训练数据得到的预测值和损失函数来不断调整网络进行学习的机制。常用的方法有梯度下降法。为使损失值降到最低,需要寻找出此函数的极值点,但实际情况中损失函数往往是一个包含n个变量的多项式方程,所以通过解析法往往是无法求解的。这是就需要寻找梯度的方向,沿着梯度的反方向即下降最快的方向去尝试改变权值。

 

5.神经网络:是一种运算模型,由大量的节点(或称神经元)之间相互联接构成。每个节点代表一种特定的输出函数,称为激励函数(activation function)。每两个节点间的连接都代表一个对于通过该连接信号的加权值,称之为权重。

  • 神经元按照来布局。最左边的层叫做输入层,负责接收输入数据;最右边的层叫输出层,我们可以从这层获取神经网络输出数据。输入层和输出层之间的层叫做隐藏层,因为它们对于外部来说是不可见的。
  • 同一层的神经元之间没有连接。
  • 第N层的每个神经元和第N-1层的所有神经元相连构成全连接层,第N-1层神经元的输出就是第N层神经元的输入。
  • 每个连接都有一个权值

简单来说输入的数据依靠神经网络的层中的权值进行数据变换最终得到输出即预测值。

6.卷积神经网络:包含卷积层和池化层,卷积层主要通过卷积核对图片进行卷积运算来提取特征。例如对5*5的图片用3*3的卷积运算,即卷积核与对应区域进行点积运算。

 

根据卷积核的权值可以提取图片中的特征。如下图,左边为卷积核,右边为可识别的特征。

而在卷积神经网络中存在多个卷积核,其中权值根据预测值与损失函数进行不断调整,从而在不依靠显式设置的情况下网络能调整为相应的权值。这个过程即为学习的过程。

而池化层主要作用是下采样,通过类似卷积核来进一步减少参数量。常见池化方法有max pooling和average pooling。下图中4*4的图片使用2*2的区域进行最大值池化。

卷积神经网络一般结构为输入->[卷积层,池化层 ]*n->全连接层->输出。


了解上述概念后利用keras进行MNIST数据集进行识别。

from keras.datasets import mnist
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Conv2D,MaxPool2D,Dense,Flatten
from keras.optimizers import RMSprop
import matplotlib

#若为linux平台需要加上该语句
matplotlib.use('Agg')

import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

import numpy as np
# 导入数据,train_x.shape=[6000]
(train_x,train_y),(test_x,test_y)=mnist.load_data()

#建立矩阵,并归一化值哦0~1范围内,每个像素强度最大值为255
train_x=np.array(train_x,dtype=float)/255.0
train_x=train_x.reshape((60000,28,28,1))


test_x=np.array(test_x,dtype=float)/255.0
test_x=test_x.reshape((10000,28,28,1))


#将标注转化为one-hot向量,1对应[0,1,0,0,0,0,0,0,0,0]
train_y=to_categorical(train_y)
test_y=to_categorical(test_y)
#分割出验证集
X_train, X_val, Y_train, Y_val = train_test_split(train_x, train_y,test_size=0.40)
#建立卷积神经网络模型
model=Sequential()
#卷积层
model.add(Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', 
                 activation ='relu', input_shape = (28,28,1)))
#池化层
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', 
                 activation ='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', 
                 activation ='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
#将四维张量转化为向量,以此进入全连接层
model.add(Flatten())
model.add(Dense(256))
#输出,softmax函数输出每个种类的概率。
model.add(Dense(10,activation='softmax'))

#编译模型,设定优化器,损失函数以及需要检测的值,这里优化器采用RMSprop学习率0.001,损失函数为多分类损失函数,检测准确率
model.compile(optimizer=RMSprop(lr=0.001),loss="categorical_crossentropy",metrics=['accuracy'])
#开始训练
H=model.fit(train_x,train_y,epochs=10,batch_size=128,validation_data=(X_val,Y_val))

# 绘制loss图像
plt.style.use("ggplot")
plt.figure()
N = 10
plt.plot(np.arange(0, N), H.history["loss"],linestyle='--', color='r',label="train_loss")
plt.plot(np.arange(0, N), H.history["val_loss"],color='b',label="val_loss")
plt.title("Loss ")
plt.xlabel("Epoch #")
plt.ylabel("Accuracy")
plt.legend()
plt.savefig("Loss.png")

# 绘制acc
plt.figure()
N = 10
plt.plot(np.arange(0, N), H.history["acc"], linestyle='--',color='r',label="train_acc")
plt.plot(np.arange(0, N), H.history["val_acc"], color='b',label="val_acc")
plt.title("Training Loss and Accuracy")
plt.xlabel("Epoch #")
plt.ylabel("Accuracy")
plt.legend()
plt.savefig("Accuracy.png")

#评估模型
test_loss,test_acc=model.evaluate(test_x,test_y)
print("test_loss:",test_loss)
print("test_acc:",test_acc)

输出结果为

可见在训练10轮的情况下测试集的准确率已达到99.22%。 

参考

  1. Ian Goodfellow ,"Deep Learing"
  2. Francois CHollet,"Deep Learing with Python"
  3. https://www.zybuluo.com/hanbingtao/note/476663
  4. Andrew Ng, "Machine Learning on coursera"
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值