使用 Theano 框架进行 MNIST 数字识别

358 阅读7分钟

概要:使用 Theano 机器学习框架,设计一个深度学习神经网络,对 MNIST 数据集进行手写数字识别。\

Theano 是蒙特利尔理工学院开发的机器学习框架,派生出了 Keras 等深度学习 Python 软件包。Theano 是为处理深度学习的大型神经网络算法而专门设计的,它的核心是一个数学表达式的编译器,它知道如何获 取网络结构,能够使相关代码高效地运行。Keras 是一个高级、快速和模块化的 Python 神经网络库,能够在 Theano 或 TensorFlow 平台上运行。

Keras 是一个简洁、高度模块化的神经网络库,可以通过如下命令进行安装。

$> pip install keras

也可以使用如下命令在线安装 Keras 的最新版本。

$> pip install git+git://github.com/fchollet/keras.git

安装过程如下图所示。

MNIST 手写数字识别是一个分类问题,下面介绍怎样使用 Theano 和 Keras 简单地训练和测试一个神经 网络。

首先需要启动 Jupyter notebook 导入一些必要的模块。如果 Keras 是首次导入,输出信息中会显示它选 择的后端模块,毫无疑问,这里选择 Theano 作为后端引擎。

from keras.models import Sequential
from keras.layers import DenseDropoutFlatten
from keras.layers.convolutional import Convolution2DMaxPooling2D
from keras.utils import np_utils
import numpy as np

然后加载 MNIST 数据集,这里将使用 Keras 命令自动下载。

from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

使用 x_train.shape 可以查看数据集的大小及图像尺寸。现在需要对数据集进行预处理,使它转换成Keras 使用的格式。当处理图像数据时,Keras 需要知道图像通道数,为了加快处理速度,将数据转换为 0~1 的 32 位浮点数。

num_pixels = x_train.shape[1] * x_train.shape[2] n_channels = 1
def preprocess(matrix):
return matrix.reshape(matrix.shape[0], \ n_channels, \
matrix.shape[1], \
matrix.shape[2]
).astype('float32') / 255.
x_train, x_test = preprocess(x_train), preprocess(x_test)

现在,还需要对输出结果进行处理。由于它是一个具有 10 个类别的分类问题,因此每一类都应该有自己 的输出列,每一列都对应输出层的一个神经元。

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

现在来创建一个简单的基准模型。我们创建一个 Sequential 模型,模型的每一个层都是按顺序堆叠的。首先将输入图像拉伸为向量,即将 28×28 的单通道图像变换成 784 维的向量,然后输入层采用 784 个神经元, 紧接着的输出层有 10 个神经元。对于第一层,可以选择 ReLU 函数作为激活函数,由于是分类任务,第二层 采用 softmax 函数。最后,用 Keras 编译模型,它使用类的交叉熵作为优化损失函数,采用分类精度作为主要 性能指标。

def baseline_model():
model = Sequential()
model.add(Flatten(input_shape=(12828)))
model.add(Dense(num_pixels, init='normal', activation='relu'))
model.add(Dense(num_classes, init='normal', activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam',
metrics=['accuracy'])
return model

为了展示模型提升的效果,可以构建一个稍微复杂的卷积神经网络,命名为 convolution_small,模型包含步骤如下:

(1) 操作在二维矩阵上的卷积滤波器 (Convolutional Filter):使用窗口为 5×5 的滤波器,对二维图像进行 卷积滤波操作,产生 32 维的输出向量。
(2) 最大池化层 (max-pooler):对 2×2 窗口进行最大化选择,以非线性的方式对图像进行采样。 
(3) dropout 层:随机将神经元的 20% 重置为 0,这样能够防止模型过拟合。
(4) 其他步骤和基准模型一样。

def convolution_small():
model = Sequential()
model.add(Convolution2D(3255, border_mode='valid',input_shape=(12828), activation='relu'))
model.add(MaxPooling2D(pool_size=(22)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(num_classes, activation='softmax')) model.compile(loss='categorical_crossentropy',optimizer='adam', metrics=['accuracy'])
return model 

为了展现神经网络的威力,还可以创建一个更复杂的神经网络,它和前面的模型类似,但是Convolution2D 和 MaxPooling2D 的层数是原来的 2 倍。

def convolution_large():
model = Sequential()
model.add(Convolution2D(3055, border_mode='valid', input_shape=(12828), activation='relu')) model.add(MaxPooling2D(pool_size=(22))) model.add(Convolution2D(1533, activation='relu')) model.add(MaxPooling2D(pool_size=(22)))

     model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(50, activation='relu'))
model.add(Dense(num_classes, activation='softmax')) model.compile(loss='categorical_crossentropy',optimizer='adam', metrics=['accuracy'])
return model 

最后,来测试一下这些模型,注意观察模型的性能和产生结果的时间。在相同的验证集上测试这些算法。训练阶段的轮数设置为 10。

np.random.seed(101)
models = [('baseline', baseline_model()),
('small', convolution_small()),
('large', convolution_large())]
for name, model in models:
print("With model:", name)
# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), nb_epoch=10, batch_size=100, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0) print("Baseline Error: %.2f%%" % (100-scores[1]*100))
print()
Out: With model: baseline
Train on 60000 samples, validate on 10000 samples
Epoch 1/10
3s - loss: 0.2332 - acc: 0.9313 - val_loss: 0.1113 - val_acc: 0.9670 Epoch 2/10
3s - loss: 0.0897 - acc: 0.9735 - val_loss: 0.0864 - val_acc: 0.9737 [...]
Epoch 10/10
2s - loss: 0.0102 - acc: 0.9970 - val_loss: 0.0724 - val_acc: 0.9796 Baseline Error2.04%
With model: small
Train on 60000 samples, validate on 10000 samples
Epoch 1/10
17s - loss: 0.1878 - acc: 0.9449 - val_loss: 0.0600 - val_acc: 0.9806 Epoch 2/10
16s - loss: 0.0631 - acc: 0.9808 - val_loss: 0.0424 - val_acc: 0.9850 [...]
Epoch 10/10
16s - loss: 0.0110 - acc: 0.9965 - val_loss: 0.0410 - val_acc: 0.9894 Baseline Error1.06%
With model: large
Train on 60000 samples, validate on 10000 samples
Epoch 1/10

   26s - loss: 0.2920 - acc: 0.9087 - val_loss: 0.0738 - val_acc: 0.9749 Epoch 2/10
25s - loss: 0.0816 - acc: 0.9747 - val_loss: 0.0454 - val_acc: 0.9857 [...]
Epoch 10/10
27s - loss: 0.0253 - acc: 0.9921 - val_loss: 0.0253 - val_acc: 0.9919
Baseline Error0.81%

从上面结果可以看出,深度越深(convolution_large 越大)神经网络模型误差越小,同时花费的训练时间也越长。相反,基准模型速度很快,但最终的精确性却最低。

留言回复你在机器学习方面做过哪些有趣的应用,我们会在留言中随机抽取一位读者免费送出北京大学出版社出版的《Python 3 数据分析与机器学习实战》图书一本。活动截止时间:5月8日 周三 晚上22:00。

热 门 推 荐
用Python查看微信共同好友
用Python获取摄像头并实时控制人脸

用 Python 验证股神巴菲特的投资经验

开源项目 | 如何免费创建云端爬虫集群

用Python分析《都挺好》中的人物关系

推荐Python中文社区旗下的几个服务类公众号\

640?wx_fmt=jpeg

文章节选自北京大学出版社出版的《Python 3 数据分析与机器学习实战》,5.5-5.7 京东品类日,本书现在京东参加满100减50的活动,点击阅读原文购书有优惠~