keras入门实战:手写数字识别

近些年由于理论知识的硬件的快速发展,使得深度学习达到了空前的火热。深度学习已经在很多方面都成功得到了应用,尤其是在图像识别和分类领域,机器识别图像的能力甚至超过了人类。

本文用深度学习Python库Keras实现深度学习入门教程mnist手写数字识别。mnist手写数字识别是机器学习和深度学习领域的“hello world”,MNIST数据集是手写数字的数据集合,训练集规模为60000,测试集为10000。

本文的内容包括:

  • 如何用Keras加载MNIST数据集
  • 对于MNIST问题如何实现一个baseline的神经网络
  • 基于MNIST问题如何实现并评价一个卷积神经网络(CNN)
  • 基于MNIST问题如何实现一个接近最高准确率的深度学习模型

MNIST手写数字识别问题

MNIST问题是由Yann LeCun, Corinna Cortes 和Christopher Burges为了评估机器学习模型而设立的。问题的数据集是从一些National Institute of Standards and Technology (NIST)的文档中得来,是计算机视觉入门级的数据集,它包含各种手写数字图片:

它也包含每一张图片对应的标签,告诉我们这个是数字几。比如,上面这四张图片的标签分别是5,0,4,1。

每张图片是28*28像素(共784个像素)。对于一般的图片像素通道通常是3维,即rgb,代表red、green、blue三个颜色通道,而MNIST数据集的像素通道只有一位即为灰度值,每一个像素值在0到1之间表示这个像素的灰度,0表示白色,1表示黑色。图片的类别标签是这个图片的数字,取值范围为0-9.因此MNIST问题是一个多分类的问题,类别为10。

现在好的分类结果可是使错误率降到1%以下。接近最好效果的错误率大约为0.2%,可用大规模的CNN实现。

加载MNIST数据集

Keras提供了实现深度学习所需要的绝大部分函数库,可实现多种神经网络模型,并可加载多种数据集来评价模型的效果。下面的代码会自动加载数据,如果是第一次调用,数据会保存在你的hone目录下~/.keras/datasets/mnist.pkl.gz,大约15MB。

# Plot ad hoc mnist instances
from keras.datasets import mnist
import matplotlib.pyplot as plt
# load (downloaded if needed) the MNIST dataset
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# plot 4 images as gray scale
plt.subplot(221)
plt.imshow(X_train[0], cmap=plt.get_cmap(‘gray‘))
plt.subplot(222)
plt.imshow(X_train[1], cmap=plt.get_cmap(‘gray‘))
plt.subplot(223)
plt.imshow(X_train[2], cmap=plt.get_cmap(‘gray‘))
plt.subplot(224)
plt.imshow(X_train[3], cmap=plt.get_cmap(‘gray‘))
# show the plot
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

上面的代码加载了数据集并画出了前4个图片:

多层感知机的baseline模型

在实现卷积神经网络这种复杂的模型之前,先实现一个简单但效果也不错的模型:多层感知机。这种模型也叫含隐层的神经网络。模型的效果可以使错误率达到1.87%。

第一步是加载所需要的库

import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.utils import np_utils
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

设定随机数种子,保证结果的可重现性

seed = 7
numpy.random.seed(seed)
  • 1
  • 2
  • 1
  • 2

加载数据

(X_train, y_train), (X_test, y_test) = mnist.load_data()
  • 1
  • 1

数据集是3维的向量(instance length,width,height).对于多层感知机,模型的输入是二维的向量,因此这里需要将数据集reshape,即将28*28的向量转成784长度的数组。可以用numpy的reshape函数轻松实现这个过程。

num_pixels = X_train.shape[1] * X_train.shape[2]
X_train = X_train.reshape(X_train.shape[0], num_pixels).astype(‘float32‘)
X_test = X_test.reshape(X_test.shape[0], num_pixels).astype(‘float32‘)
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

给定的像素的灰度值在0-255,为了使模型的训练效果更好,通常将数值归一化映射到0-1。

X_train = X_train / 255
X_test = X_test / 255
  • 1
  • 2
  • 1
  • 2

最后,模型的输出是对每个类别的打分预测,对于分类结果从0-9的每个类别都有一个预测分值,表示将模型输入预测为该类的概率大小,概率越大可信度越高。由于原始的数据标签是0-9的整数值,通常将其表示成0ne-hot向量。如第一个训练数据的标签为5,one-hot表示为[0,0,0,0,0,1,0,0,0,0]。

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

现在需要做得就是搭建神经网络模型了,创建一个函数,建立含有一个隐层的神经网络。

# define baseline model
def baseline_model():
    # create model
    model = Sequential()
    model.add(Dense(num_pixels, input_dim=num_pixels, kernel_initializer=‘normal‘, activation=‘relu‘))
    model.add(Dense(num_classes, kernel_initializer=‘normal‘, activation=‘softmax‘))
    # Compile model
    model.compile(loss=‘categorical_crossentropy‘, optimizer=‘adam‘, metrics=[‘accuracy‘])
    return model
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

模型的隐含层含有784个节点,接受的输入长度也是784(28*28),最后用softmax函数将预测结果转换为标签的概率值。

将训练数据fit到模型,设置了迭代轮数,每轮200个训练样本,将测试集作为验证集,并查看训练的效果。

# build the model
model = baseline_model()
# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

训练和测试结果如下:

Train on 60000 samples, validate on 10000 samples

Epoch 1/10

6s - loss: 0.2789 - acc: 0.9210 - val_loss: 0.1416 - val_acc: 0.9578

Epoch 2/10

5s - loss: 0.1117 - acc: 0.9677 - val_loss: 0.0917 - val_acc: 0.9707

Epoch 3/10

5s - loss: 0.0717 - acc: 0.9796 - val_loss: 0.0787 - val_acc: 0.9767

Epoch 4/10

6s - loss: 0.0502 - acc: 0.9859 - val_loss: 0.0741 - val_acc: 0.9767

Epoch 5/10

5s - loss: 0.0372 - acc: 0.9890 - val_loss: 0.0681 - val_acc: 0.9788

Epoch 6/10

5s - loss: 0.0269 - acc: 0.9925 - val_loss: 0.0625 - val_acc: 0.9808

Epoch 7/10

5s - loss: 0.0208 - acc: 0.9948 - val_loss: 0.0619 - val_acc: 0.9814

Epoch 8/10

6s - loss: 0.0140 - acc: 0.9970 - val_loss: 0.0639 - val_acc: 0.9799

Epoch 9/10

5s - loss: 0.0108 - acc: 0.9978 - val_loss: 0.0597 - val_acc: 0.9812

Epoch 10/10

5s - loss: 0.0080 - acc: 0.9985 - val_loss: 0.0591 - val_acc: 0.9813

Baseline Error: 1.87%

简单的卷积神经网络

前面介绍了如何加载训练数据并实现一个简单的单隐层神经网络,并在测试集上取得了不错的效果。现在要实现一个卷积神经网络,想要在MNIST问题上取得更好的效果。

卷积神经网络(CNN)是一种深度神经网络,与单隐层的神经网络不同的是它还包含卷积层、池化层、Dropout层等,这使得它在图像分类的问题上有更优的效果。详细的CNN教程可以参见斯坦福大学的cs231n课程讲义,中文版链接

第一步依然是导入需要的函数库

import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
K.set_image_dim_ordering(‘th‘)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

设定随机数种子

seed = 7
numpy.random.seed(seed)
  • 1
  • 2
  • 1
  • 2

将数据集reshape,CNN的输入是4维的张量(可看做多维的向量),第一维是样本规模,第二维是像素通道,第三维和第四维是长度和宽度。并将数值归一化和类别标签向量化。

# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# reshape to be [samples][pixels][width][height]
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype(‘float32‘)
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype(‘float32‘)

X_train = X_train / 255
X_test = X_test / 255
# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

接下来构造CNN。

  1. 第一层是卷积层。该层有32个feature map,或者叫滤波器,作为模型的输入层,接受[pixels][width][height]大小的输入数据。feature map的大小是5*5,其输出接一个‘relu’激活函数。
  2. 下一层是pooling层,使用了MaxPooling,大小为2*2。
  3. 下一层是Dropout层,该层的作用相当于对参数进行正则化来防止模型过拟合。
  4. 接下来是全连接层,有128个神经元,激活函数采用‘relu’。
  5. 最后一层是输出层,有10个神经元,每个神经元对应一个类别,输出值表示样本属于该类别的概率大小。
def baseline_model():
    # create model
    model = Sequential()
    model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28), activation=‘relu‘))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(128, activation=‘relu‘))
    model.add(Dense(num_classes, activation=‘softmax‘))
    # Compile model
    model.compile(loss=‘categorical_crossentropy‘, optimizer=‘adam‘, metrics=[‘accuracy‘])
    return model
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

接着开始训练模型

# build the model
model = baseline_model()
# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

训练和测试结果如下:

Train on 60000 samples, validate on 10000 samples

Epoch 1/10

137s - loss: 0.2329 - acc: 0.9340 - val_loss: 0.0820 - val_acc: 0.9742

Epoch 2/10

140s - loss: 0.0736 - acc: 0.9781 - val_loss: 0.0466 - val_acc: 0.9842

Epoch 3/10

138s - loss: 0.0531 - acc: 0.9839 - val_loss: 0.0432 - val_acc: 0.9860

Epoch 4/10

145s - loss: 0.0404 - acc: 0.9876 - val_loss: 0.0389 - val_acc: 0.9872

Epoch 5/10

135s - loss: 0.0335 - acc: 0.9893 - val_loss: 0.0341 - val_acc: 0.9886

Epoch 6/10

133s - loss: 0.0275 - acc: 0.9915 - val_loss: 0.0308 - val_acc: 0.9893

Epoch 7/10

133s - loss: 0.0233 - acc: 0.9926 - val_loss: 0.0363 - val_acc: 0.9880

Epoch 8/10

137s - loss: 0.0204 - acc: 0.9937 - val_loss: 0.0320 - val_acc: 0.9889

Epoch 9/10

139s - loss: 0.0167 - acc: 0.9945 - val_loss: 0.0294 - val_acc: 0.9893

Epoch 10/10

139s - loss: 0.0143 - acc: 0.9957 - val_loss: 0.0310 - val_acc: 0.9907

Baseline Error: 0.93%

可以看出相对于单隐层神经网络,CNN的效果有很大提升,error rate 从1.87%降到了0.93%。

上面实现了一个只含有一层卷积层和pooling层的CNN,为了实现更好的分类效果,可以添加多层的Convolution2D和MaxPooling2D,CNN会自动提取特征,学习到更好的分类效果。

时间: 2024-10-28 16:04:57

keras入门实战:手写数字识别的相关文章

Tensorflow实战 手写数字识别(Tensorboard可视化)

一.前言 为了更好的理解Neural Network,本文使用Tensorflow实现一个最简单的神经网络,然后使用MNIST数据集进行测试.同时使用Tensorboard对训练过程进行可视化,算是打响学习Tensorflow的第一枪啦. 看本文之前,希望你已经具备机器学习和深度学习基础. 机器学习基础可以看我的系列博文: https://cuijiahua.com/blog/ml/ 深度学习基础可以看吴恩达老师的公开课: http://mooc.study.163.com/smartSpec/

Pytorch入门实战一:LeNet神经网络实现 MNIST手写数字识别

记得第一次接触手写数字识别数据集还在学习TensorFlow,各种sess.run(),头都绕晕了.自从接触pytorch以来,一直想写点什么.曾经在2017年5月,Andrej Karpathy发表的一片Twitter,调侃道:l've been using PyTorch a few months now, l've never felt better, l've more energy.My skin is clearer. My eye sight has improved.确实,使用p

Kaggle竞赛丨入门手写数字识别之KNN、CNN、降维

引言 这段时间来,看了西瓜书.蓝皮书,各种机器学习算法都有所了解,但在实践方面却缺乏相应的锻炼.于是我决定通过Kaggle这个平台来提升一下自己的应用能力,培养自己的数据分析能力. 我个人的计划是先从简单的数据集入手如手写数字识别.泰坦尼克号.房价预测,这些目前已经有丰富且成熟的方案可以参考,之后关注未来就业的方向如计算广告.点击率预测,有合适的时机,再与小伙伴一同参加线上比赛. 数据集 介绍 MNIST ("Modified National Institute of Standards an

手写数字识别——利用keras高层API快速搭建并优化网络模型

在<手写数字识别——手动搭建全连接层>一文中,我们通过机器学习的基本公式构建出了一个网络模型,其实现过程毫无疑问是过于复杂了——不得不考虑诸如数据类型匹配.梯度计算.准确度的统计等问题,但是这样的实践对机器学习的理解是大有裨益的.在大多数情况下,我们还是希望能多简单就多简单地去搭建网络模型,这同时也算对得起TensorFlow这个强大的工具了.本节,还是以手写数据集MNIST为例,利用TensorFlow2.0的keras高层API重现之前的网络. 一.数据的导入与预处理 关于这个过程,与上节

机器学习(二)-kNN手写数字识别

一.kNN算法 1.kNN算法是机器学习的入门算法,其中不涉及训练,主要思想是计算待测点和参照点的距离,选取距离较近的参照点的类别作为待测点的的类别. 2,距离可以是欧式距离,夹角余弦距离等等. 3,k值不能选择太大或太小,k值含义,是最后选取距离最近的前k个参照点的类标,统计次数最多的记为待测点类标. 4,欧式距离公式: 二.关于kNN实现手写数字识别 1,手写数字训练集测试集的数据格式,本篇文章说明的是<机器学习实战>书提供的文件,将所有数字已经转化成32*32灰度矩阵. 三.代码结构构成

深度学习面试题12:LeNet(手写数字识别)

目录 神经网络的卷积.池化.拉伸 LeNet网络结构 LeNet在MNIST数据集上应用 参考资料 LeNet是卷积神经网络的祖师爷LeCun在1998年提出,用于解决手写数字识别的视觉任务.自那时起,CNN的最基本的架构就定下来了:卷积层.池化层.全连接层.如今各大深度学习框架中所使用的LeNet都是简化改进过的LeNet-5(-5表示具有5个层),和原始的LeNet有些许不同,比如把激活函数改为了现在很常用的ReLu. 神经网络的卷积.池化.拉伸 前面讲了卷积和池化,卷积层可以从图像中提取特

使用AI算法进行手写数字识别

人工智能 ??人工智能(Artificial Intelligence,简称AI)一词最初是在1956年Dartmouth学会上提出的,从那以后,研究者们发展了众多理论和原理,人工智能的概念也随之扩展.由于人工智能的研究是高度技术性和专业的,各分支领域都是深入且各不相通的,因而涉及范围极广 . 人工智能的核心问题包括建构能够跟人类似甚至超越人类的推理.知识.学习.交流.感知.使用工具和操控机械的能力等,当前人工智能已经有了初步成果,甚至在一些影像识别.语言分析.棋类游戏等等单方面的能力达到了超越

Tensorflow快速入门2--实现手写数字识别

Tensorflow快速入门2–实现手写数字识别 环境: 虚拟机ubuntun16.0.4 Tensorflow(仅使用cpu版) Tensorflow安装见: http://blog.csdn.net/yhhyhhyhhyhh/article/details/54429034 或者: http://www.tensorfly.cn/tfdoc/get_started/os_setup.html 本文将利用Tensorflow以softmax回归和卷积神经网络两种模型简单测试MNIST数据集,快

手把手教你搭建caffe及手写数字识别(全程命令提示、纯小白教程)

手把手教你搭建caffe及手写数字识别 作者:七月在线课程助教团队,骁哲.小蔡.李伟.July时间:二零一六年十一月九日交流:深度学习实战交流Q群 472899334,有问题可以加此群共同交流.另探究实验背后原理,请参看此课程:11月深度学习班. 一.前言 在前面的教程中,我们搭建了tensorflow.torch,教程发布后,大家的问题少了非常多.但另一大框架caffe的问题则也不少,加之caffe也是11月深度学习班要讲的三大框架之一,因此,我们再把caffe的搭建完整走一遍,手把手且全程命