142

自己动手做一个识别手写数字的web应用01

 6 years ago
source link: http://mp.weixin.qq.com/s/Ipyu8uZN_WMXzOAYE162ug
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

自己动手做一个识别手写数字的web应用01

Original shadow 无界社区mixlab 2017-11-02 06:48 Posted on

最近在深入地学习keras,发现网上各种教程都是教你怎么训练模型的,很少有问题提到如何把训练好的模型部署为后端服务,为web及app提供服务。

于是,我决定把学习的过程完整的记录下来,帮大家更快地把深度学习的模型应用到实际场景中。

用到的技术:

keras+tensorflow+flask

这个教程分为4篇。

第一篇

介绍开发环境--训练模型--保存至本地;

第二篇

介绍导入训练好的模型--识别任意的手写数字图片;

第三篇

介绍用Flask整合keras训练好的模型,并开发后端服务;

第四篇

介绍前端web单页应用的开发。

为了方便入门,下面采用docker的方式进行实验。

 01 

采用docker部署开发环境

首先安装好docker,我是mac,window用户请查阅官方安装教程,运行docker,终端输入:

docker pull floydhub/dl-docker:cpu

在本地电脑新建一个目录,我这边是kerasStudy,路径是

/Users/shadow/Documents/02-coding/kerasStudy

大家可以改成自己本机对应的路径。

终端运行:

docker run -it  -p 6006:6006 -p 8888:8888 -v /Users/shadow/Documents/02-coding/kerasStudy:/root/kerasStudy floydhub/dl-docker:cpu bash

-p 6006:6006,表示将Docker主机的6006端口与容器的6006接口绑定;

-v 参数中,冒号":"前面的目录是宿主机目录,后面的目录是容器内目录。

记得,还需要在docker中配置宿主机的与镜像共享的目录地址

Image

将新建一个容器,并在容器中开启一个交互模式的终端,结果如下:

Image

 02 

启动jupyter notebook

终端输入:

mkdir  $HOME/.keras/

cd $HOME/.keras/

vim keras.json

键盘按 i ,按回车及方向键控制光标,把floydhub/dl-docker:cpu镜像默认的使用Theano作为后端,改为如下:

{
    "image_data_format": "channels_last",
    "epsilon": 1e-07,
    "floatx": "float32",
    "backend": "tensorflow"
}

按下esc键;输入:wq,保存修改结果。

终端输入:

jupyter notebook

Image

上图显示jupyter notebook已经运行成功,打开浏览器,在地址栏中输入:

localhost:8888

即可访问jupyter

Image

 03 

Hello Jupyter Notebook

上文提到的jupyter notebook到底是什么东西?

Jupyter Notebook 是一款集编程写作于一体的效率工具,优点:

  • 交互式展现

在浏览器可以访问Jupyter Notebook,也就是说,我可以部署成web应用的形式,用户可以分享,通过域名访问,并且可以利用web的任何交互方式。

继续我们的教程,在浏览器打开Jupyter Notebook后,找到我们与本地共享的项目目录kerasStudy,点击进入,然后点击jupyter右上角的new,选择python2,如下图所示:

Image

新建一个notebook。

先来做个小实验:

import numpy as np

np.random.seed(1337)

np.random.rand(5)

然后在菜单中,选择Cell--Run Cells,运行代码

Image

如下图所示,输出了一些结果。

Image

第一行代码:

import numpy as np

引入 numpy ,一个用python实现的科学计算包。提供了许多高级的数值编程工具,如:矩阵数据类型、矢量处理,以及精密的运算库。专为进行严格的数字处理而产生。numpy的教程可以参看官网http://www.numpy.org/

np.random.seed()

使得随机数据可预测。相当于给随机数赋了个id,下次调用随机数的时候,只要再次取这个id,再调用随机数,即可产生相同的随机数

可以做下这个练习:

3.1

np.random.seed(0)

np.random.rand(5)

#控制台输出结果

 array([ 0.5488135 ,  0.71518937,  0.60276338,  0.54488318,  0.4236548 ])

3.2

np.random.seed(1676)

np.random.rand(5)

#控制台输出结果 

array([ 0.39983389,  0.29426895,  0.89541728,  0.71807369,  0.3531823 ])

3.3

np.random.seed(1676)

np.random.rand(5)

#控制台输出结果

array([ 0.39983389,  0.29426895,  0.89541728,  0.71807369,  0.3531823 ])    

 04 

Keras训练模型

这里结合了keras的官方案例,训练一个多层感知器。

4.1

重新建一个notebook,

from __future__ import print_function
'''
 Python 3.x引入了一些与Python 2不兼容的关键字和特性,在Python 2中,
可以通过内置的__future__模块导入这些新内容。

 如果你希望在Python 2环境下写的代码也可以在Python 3.x中运行,那么建议使用__future__模块。

 import print_function 这里使用3.x的 print方法

 在Python 3中必须用括号将需要输出的对象括起来。
在Python 2中使用额外的括号也是可以的。
但反过来在Python 3中想以Python2的形式不带括号调用print函数时,
会触发SyntaxError。

'''
import numpy as np

4.2

from keras.datasets import mnist
# 导入mnist数据库, mnist是常用的手写数字库
from keras.models import Sequential
#导入序贯模型,Sequential是多个网络层的线性堆叠,也就是“一条路走到黑”。
from keras.layers.core import Dense, Dropout, Activation
#导入全连接层Dense,激活层Activation 以及 Dropout层
from keras.optimizers import SGD, Adam, RMSprop
#导入优化器 SGD, Adam, RMSprop
from keras.utils import np_utils
#导入numpy工具,主要是用to_categorical来转换类别向量

4.3

#变量初始化
batch_size = 128 
#设置batch的大小
nb_classes = 10
#设置类别的个数
nb_epoch = 20
#设置迭代的次数

4.4

#准备数据 
(X_train, y_train), (X_test, y_test) = mnist.load_data()
print(X_test.shape,X_test[0])
#keras中的mnist数据集已经被划分成了60,000个训练集,10,000个测试集的形式,按以上格式调用即可
X_train = X_train.reshape(60000, 784)
#X_train原本是一个60000*28*28的三维向量,将其转换为60000*784的二维向量
X_test = X_test.reshape(10000, 784)
print(X_test.shape)
#X_test原本是一个10000*28*28的三维向量,将其转换为10000*784的二维向量
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
#将X_train, X_test的数据格式转为float32存储
X_train /= 255
X_test /= 255
#归一化
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')

4.5

# 转换类标号 convert class vectors to binary class matrices
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)

4.6

#建立模型 使用Sequential()
'''
模型需要知道输入数据的shape,
因此,Sequential的第一层需要接受一个关于输入数据shape的参数,
后面的各个层则可以自动推导出中间数据的shape,
因此不需要为每个层都指定这个参数
''' 
model = Sequential()
model.add(Dense(512, input_shape=(784,)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
# 输入层有784个神经元
# 第一个隐层有512个神经元,激活函数为ReLu,Dropout比例为0.2
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.2))
# 第二个隐层有512个神经元,激活函数为ReLu,Dropout比例为0.2
model.add(Dense(10))
model.add(Activation('softmax'))
# 输出层有10个神经元,激活函数为SoftMax,得到分类结果
# 输出模型的整体信息
# 总共参数数量为784*512+512 + 512*512+512 + 512*10+10 = 669706
model.summary()

4.7

#打印模型
model.summary()

4.8

#配置模型的学习过程
'''
compile接收三个参数:
1.优化器optimizer:参数可指定为已预定义的优化器名,如rmsprop、adagrad,
或一个Optimizer类对象,如此处的RMSprop()
2.损失函数loss:参数为模型试图最小化的目标函数,可为预定义的损失函数,
如categorical_crossentropy、mse,也可以为一个损失函数
3.指标列表:对于分类问题,一般将该列表设置为metrics=['accuracy']
'''
model.compile(loss='categorical_crossentropy',
              optimizer=RMSprop(),
              metrics=['accuracy'])

4.9

#训练模型
'''
batch_size:指定梯度下降时每个batch包含的样本数
nb_epoch:训练的轮数,nb指number of
verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为epoch输出一行记录
validation_data:指定验证集
fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,
如果有验证集的话,也包含了验证集的这些指标变化情况
'''
history = model.fit(X_train, Y_train,
                    batch_size=batch_size, nb_epoch=nb_epoch,
                    verbose=2, validation_data=(X_test, Y_test))

这个时候,可以Cell--Run All 一下,可以看到训练过程,如下图:

Image

4.10

#模型评估

score = model.evaluate(X_test, Y_test, verbose=0)

print('Test score:', score[0])

print('Test accuracy:', score[1])

4.11

#保存神经网络的结构与训练好的参数

json_string = model.to_json()  

open('my_model_architecture.json','w').write(json_string)    

model.save_weights('my_model_weights.h5')

系列文章第一篇至此结束。

关于第四部分Keras训练模型的源代码文件,可以在后台留言,索取。


码字不易,开启新的打赏方式:

Image

本公众号定期更新关于

设计师、程序员发挥创意

互相融合的指南、作品。

主要技术栈:

nodejs、react native、electron

Elasticsearch

Solidity

Keras

欢迎关注,转发~

欢迎长按二维码

关注本号

Image

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK