keras实现mnist数据集手写数字识别

经过几天的爬坑,“东搞西搞”终于把深度学习的“HELLO,WORLD”做出来了,以下是自己的实战过程:

关于keras识别手写数字的入门准备:

1.Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow、Theano以及CNTK后端。所以在安装keras的前面,要先搭建tensorflow环境和安装https://www.tensorflow.org/install/install_windows(这里是官方的安装过程)

2.Mnist数据集的准备

3.导入数据集测试

4.实现baseline模型:

5.实现简单的卷积神经网络

 

一. Tensorflow环境的安装

这里我们只讲CPU版本,使用 Anaconda 进行安装

a.首先我们要安装 Anaconda

链接:https://pan.baidu.com/s/1AxdGi93oN9kXCLdyxOMnRA 密码:79ig

过程如下:

第一步:点击next

第二步:I Agree

第三步:Just ME

第四步:自己选择一个恰当位置放它就好

第五步:建议只选择第二个

 

第六步:就直接install啦啦啦啦,然后你就可以上手万能库了

 

b.找到Anaconda prompt,然后

 

以管理员的身份打开终端

c.按照以下步骤在 Anaconda 环境中安装 TensorFlow:

  1. 通过调用以下命令创建名为 tensorflow 的 conda 环境:

C:> conda create -n tensorflow pip python=3.5

  1. 通过发出以下命令激活 conda 环境:

C:> activate tensorflow (tensorflow)C:> # Your prompt should change

  1. 发出相应命令以在 conda 环境中安装 TensorFlow。要安装仅支持 CPU 的 TensorFlow 版本,请输入以下命令:

(tensorflow)C:> pip install --ignore-installed --upgrade tensorflow

 

d.测试tensorflow的安装

启动Anaconda prompt(同样是以管理员身份打开)终端。

如果您是通过 Anaconda 进行安装,请激活您的 Anaconda 环境。

终端输入 activate tensorflow即可

然后再输入python

如:

 

在 Python 交互式 shell 中输入以下几行简短的程序代码:

>>> import tensorflow as tf

>>> hello = tf.constant('Hello, TensorFlow!')

>>> sess = tf.Session()

>>> print(sess.run(hello))

如果系统输出以下内容,说明您可以开始编写 TensorFlow 程序了:

Hello, TensorFlow!

 

 

完成以上步骤,你就把tensorflow搭建好了......

 

二.安装keras

a.首先,担心我们anaconda里面各个包未更新到最新,所以我们以管理员的身份打开Anaconda终端,输入 conda update conda,执行完后,再输入:conda update --all

b.然后我们激活我们的tensorflow环境:activate tensorflow

c.然后我们就可以输入:pip install keras

 

三.完成上述步骤,我们就可以来试下加载keras里面的mnist数据集了

# 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()

 

上面的代码加载了数据集并画出了前4个图片: 
keras实现mnist数据集手写数字识别_第1张图片

好了接下来我们对上述代码进行进一步的解释:

from keras.datasets import mnist 这里是从keras的datasets中导入mnist数据集
import matplotlib.pyplot as plt  这里是将matplotlib.pyplot重名为plt
(X_train, y_train), (X_test, y_test) = mnist.load_data()#
所以这里返回的是手写图片的两个tuple,第一个tuple存储的是我们已经人工分类好的图片,也就是每一张图片都有自己对应的标签,然后可以拿来训练,第二个tuple存储的是我们还没分类的图片,在第一个tuple训练完后,我们可以把第二个tuple利用神经网络进行分类,根据实验结果的真实值与我们的预测值进行对比得到相应的损失值,再利用反向传播进行参数更新,再进行分类,然后重复前述步骤直至损失值最小
# plot 4 images as gray scale
plt.subplot(331)
这个subplot函数的作用是确定图像的位置以及图像的个数,前两个3的意思是可以放9张图片,如果变成221的话,就是可以放4张图片,然后后面的1,是确定图像的位置,处于第一个,以下的subplot同理
plt.imshow(X_test[0], cmap=plt.get_cmap('gray'))
这里个把图片显示出来
X_train存储的是图像的像素点组成的list数据类型,这里面又由一个二维的list(28 x 28的像素点值)和一个对应的标签list组成,y_train存储的是对应图像的标签,也就是该图像代表什么数字
plt.subplot(332)
plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))
plt.subplot(333)
plt.imshow(X_train[2], cmap=plt.get_cmap('gray'))
plt.subplot(334)
plt.imshow(X_train[3], cmap=plt.get_cmap('gray'))
plt.subplot(335)
plt.imshow(X_train[4], cmap=plt.get_cmap('gray'))
plt.subplot(336)
plt.imshow(X_train[5], cmap=plt.get_cmap('gray'))
plt.subplot(337)
plt.imshow(X_train[6], cmap=plt.get_cmap('gray'))
plt.subplot(338)
plt.imshow(X_train[7], cmap=plt.get_cmap('gray'))
plt.subplot(339)
plt.imshow(X_train[8], cmap=plt.get_cmap('gray'))
在这里imshow函数的官方文档:https://matplotlib.org/api/_as_gen/matplotlib.pyplot.imshow.html#matplotlib.pyplot.imshow
我们这里第一个参数是图片的像素点值组成的数组(列表),第二个参数是指明图片的色彩
# show the plot
plt.show()最后这里官方文档是这样说的:Display a figure. When running in ipython with its pylab mode, display all figures and return to the ipython prompt.,所以我们可以知道show函数是把所有图片都展示出来。

上述代码展示的结果是:

keras实现mnist数据集手写数字识别_第2张图片

 

多层感知机的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

seed = 7   #设置随机种子
numpy.random.seed(seed)

(X_train, y_train), (X_test, y_test) = mnist.load_data() #加载数据

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

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

#最后,模型的输出是对每个类别的打分预测,对于分类结果从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]

#现在需要做得就是搭建神经网络模型了,创建一个函数,建立含有一个隐层的神经网络。
# 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

#型的隐含层含有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))

训练和测试结果如下:

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')

设定随机数种子

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

将数据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]
  •  

接下来构造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

接着开始训练模型

# 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))

训练和测试结果如下:

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会自动提取特征,学习到更好的分类效果。

 

 

你可能感兴趣的:(学习总结,python,s,n',深度学习)