keras实现手写数字识别(数据集:MNIST)

准备工作

  • keras
  • tensorflow
  • numpy
  • PIL

下载MNIST数据集

from keras.dataset import mnist

mnist.load_data(path)

path是保存的路径

模型结构

keras实现手写数字识别(数据集:MNIST)_第1张图片
model1.png

这个模型用了两个Convolution2D层,两个MaxPooling2D层,一个Flatten层,两个全连接Dense层,使用的激活函数是relu,优化器是adam

训练代码

from keras.model import Sequential
from keras.layers import Convolution2D, Dense, Flatten, Activation, MaxPooling2D
from keras.utils import to_catagorical
from keras.optimizers import Adam
import numpy as np

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 28, 28, 1)
x_test = x_test.reshape(10000, 28, 28, 1)
y_test = to_categorical(y_test, 10)
y_train = to_categorical(y_train, 10)

# design model
model = Sequential()
model.add(Convolution2D(25, (5, 5), input_shape=(28, 28, 1)))
model.add(MaxPooling2D(2, 2))
model.add(Activation('relu'))
model.add(Convolution2D(50, (5, 5)))
model.add(MaxPooling2D(2, 2))
model.add(Activation('relu'))
model.add(Flatten())

model.add(Dense(50))
model.add(Activation('relu'))
model.add(Dense(10))
model.add(Activation('softmax'))
adam = Adam(lr=0.001)
# compile model
model.compile(optimizer=adam,loss='categorical_crossentropy',metrics=['accuracy'])
# training model
model.fit(x_train, y_train, batch_size=100, epochs=5)
# test model
print model.evaluate(x_test, y_test, batch_size=100)
# save model
model.save('/Users/zhang/Desktop/my_model2.h5')
训练效果
Using TensorFlow backend.
Epoch 1/5
2017-09-12 14:49:32.779373: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
2017-09-12 14:49:32.779389: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2017-09-12 14:49:32.779393: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
2017-09-12 14:49:32.779398: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
2017-09-12 14:49:32.779401: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
60000/60000 [==============================] - 33s - loss: 2.5862 - acc: 0.8057    
Epoch 2/5
60000/60000 [==============================] - 32s - loss: 0.0603 - acc: 0.9820    
Epoch 3/5
60000/60000 [==============================] - 32s - loss: 0.0409 - acc: 0.9873    
Epoch 4/5
60000/60000 [==============================] - 32s - loss: 0.0338 - acc: 0.9895    
Epoch 5/5
60000/60000 [==============================] - 33s - loss: 0.0259 - acc: 0.9922    
 9900/10000 [============================>.] - ETA: 0s[0.054905540546023986, 0.98440000832080843]
  • 可以看到在测试集上识别准确率达到了98.44%。
  • 其实在训练过程中存在运气问题,对于batch_size=100来说,如果从一开始没有跑出最优值,可能就进入了死胡同,导致训练的准确率一直只有9%。
  • 经过一轮训练就能达到80%的准确率,这样的训练效果很有可能导致过拟合,虽然在测试集上有98%的准确率。

测试

我用ps画出了几个手写数字的图片进行测试
这些都是28*28的图片
测试代码如下
from keras.models import load_model
import numpy as np
from PIL import Image


def ImageToMatrix(filename):
    im = Image.open(filename)
    #change to greyimage
    im=im.convert("L")
    data = im.getdata()
    data = np.matrix(data,dtype='int')
    return data

model = load_model('/Users/zhang/Desktop/my_model.h5')


while 1:
    i = input('number:')
    j = input('type:')
    data = ImageToMatrix('/Users/zhang/Desktop/picture/'+str(i)+'_'+str(j)+'.png')
    data = np.array(data)
    data = data.reshape(1, 28, 28, 1)
    print 'test['+str(i)+'_'+str(j)+'], num='+str(i)+':'
    print model.predict_classes(
        data, batch_size=1, verbose=0
    )
选取了几个结果
number:7
type:1
test[7_1], num=7:
[7]

number:7
type:2
test[7_2], num=7:
[7]

number:7
type:3
test[7_3], num=7:
[7]

number:2
type:1
test[2_1], num=2:
[2]

number:1
type:1
test[1_1], num=1:
[4]

number:1
type:2
test[1_2], num=1:
[1]

number:1
type:3
test[1_3], num=1:
[1]

number:6
type:1
test[6_1], num=6:
[5]

总结:

  • 该模型对于小字体没法正常识别(和训练集字体大小有关)
  • 对于类似 '1' 等数字,如果放在图片边缘,如:1_1,没法准确识别
  • 当然,对于颠倒方向,横放竖放的数字也没法准确识别
  • 在mnist的测试集中,可以说是10000张图片只有大约200张识别错误

改进方案

  • 对读取进来的图片进行先行处理(颠倒,居中,缩放等等),使得识别更加容易
  • 对训练集进行处理,使用不同方向的数字训练集(训练量加大)
  • 对神经层进行改进(由于没有深入了解,其实这次的神经网络也是瞎编的,只不过使用了卷积层和全连接层的结合)
推荐李宏毅的机器学习的视频(youtube:李宏毅)

你可能感兴趣的:(keras实现手写数字识别(数据集:MNIST))