3. 使用Keras实现全连接神经网络完成手写数字识别

//李宏毅视频官网:http://speech.ee.ntu.edu.tw/~tlkagk/courses.html                                                    点击此处返回总目录

//邱锡鹏《神经网络与深度学习》官网:https://nndl.github.io
//Keras中文文档:https://keras-cn.readthedocs.io/en/latest/

//Keras官方中文文档:https://keras.io/zh/

 

 

 

神经网络如果要实做的话,怎么做呢?

--------------------------------------------------------------------------------------------------------------------------------------

今天要用到Keras,你可能会说怎么不用tensorflow呢?

其实tensorflow没有那么好用。tensorflow跟另外一个相近的工具theano,它们非常flexible。它完全可以做deep learning以外的事情。学起来是有一些难度的。而Keras是可以在数十分钟内就精通,就可以非常熟悉它,就可以用来实现一个自己的DNN了。

 

Keras其实是TensorFlow和theano的interface,所有就有的人说其实TensorFlow也没有那么好用,他搭的interface就是Keras。你用Keras就等于在用TensorFlow了,只是有人帮你把操纵TensorFlow那些事情帮你写好了。

Keras比较好学,而且也有足够的弹性,多数你想做的事情,都有线程的function可以调用。因为背后就是TensorFlow和theano,所以有一天你想精进自己能力的话,就可以改TensorFlow背后的调用,做更厉害的事情。

 

                                    3. 使用Keras实现全连接神经网络完成手写数字识别_第1张图片

 

还有一个小道消息,Keras的作者在Google工作,所以据说Keras要变成TensorFlow的官方的API。所以选择Keras是对的。

 

这里八卦一下,Keras是在希腊文中是牛角的意思。传说,梦精灵在来到人世间的时候,他会通过两种门,一种是象牙做的门,一种是牛角做的门。如果是通过象牙门的梦精灵,那个梦的内容就不会被实现。如果是来自牛角的门的梦精灵,那个梦就会被实现。

                                 3. 使用Keras实现全连接神经网络完成手写数字识别_第2张图片

 

以下是某位同学使用Keras的心得,做成了6格的图,放在了Facebook上面:

                            3. 使用Keras实现全连接神经网络完成手写数字识别_第3张图片

当使用Keras的时候,它是非常的容易的。就是把线程的function叠来叠去而已。所以用Keras就好像是在叠积木一样。

 

--------------------------------------------------------------------------------------------------------------------------------------

现在用手写体识别的例子,来示范Keras怎么用。如果你这辈子还没有写过deep learning的程序的话,那今天这个就是deep learning 的hello world。

                              3. 使用Keras实现全连接神经网络完成手写数字识别_第4张图片

用的Data就是MNIST的数据集。输入图像的大小为28*28。Keras也有自动下载Mnist数据集的函数。

 

--------------------------------------------------------------------------------------------------------------------------------------

如果用Keras,你要怎么做呢?

我们之前讲过,deep learning就是三步。第一步就是决定你的function set,即决定你的神经网络长什么样子。

                                    3. 使用Keras实现全连接神经网络完成手写数字识别_第5张图片

 

在Keras里就是先宣告一个model :model = Sequential() 。

                                              

接下来你就自己决定你的model长什么样子,举例来说我们想要叠一个network,它有两个隐藏层,每一个隐藏层都有500个神经元。要做这件事情,怎么做呢?

做法是在model里面用add()函数加一个全连接网络,全连接网络就是用Dense()来表示。imput_dim = 28*28,表示输入的是一个28*28的image,我们把它拉直为28*28维的向量。units=500就是说输出是500个神经元。activation是说你的激活函数是什么。这里用的relu,当然也可以选别的。

                3. 使用Keras实现全连接神经网络完成手写数字识别_第6张图片

 

如果,再加一个Layer,怎么办呢?同样是add()函数加一个Dense()。这里就不需要给它参数input_dim,因为下一层的输入就等于前一层的输出,Keras自己知道。

                3. 使用Keras实现全连接神经网络完成手写数字识别_第7张图片

最后,要做10分类。所以units就设10。激活函数通常选softmax.

                3. 使用Keras实现全连接神经网络完成手写数字识别_第8张图片

 

--------------------------------------------------------------------------------------------------------------------------------------

接下来,第二步,我们要评价一个function的好坏。

                        3. 使用Keras实现全连接神经网络完成手写数字识别_第9张图片

那怎么做呢?要用model.compile()函数。然后定义你的loss是什么。比如要用交叉熵损失,就写loss = 'categorical crossentropy'。

也支持其他的损失函数,在不同的场合可能用到不同的损失函数,可以去查文档。

                     3. 使用Keras实现全连接神经网络完成手写数字识别_第10张图片

 

--------------------------------------------------------------------------------------------------------------------------------------

接下来是第三步,是training的部分:

                         3. 使用Keras实现全连接神经网络完成手写数字识别_第11张图片

在训练之前,你要下一些configuration,告诉它你训练的时候你打算要怎么做。

要下的第一个东西是optimizer,也就是你要找最好的function的时候,你要用什么样的方式来找最好的function。可以支持各种不同的方法。其实所有的optimizer都是基于gradient descent,不同的方法会帮你决定不同的learning rate。

                   3. 使用Keras实现全连接神经网络完成手写数字识别_第12张图片

 

决定好之后,就是做了。使用model.fit(),需要给四个参数。后面两个参数一会再解释。当调用这一行的时候,Keras就会train你的network。

第一个参数是Training data,Training data就是一张一张的image

第二个参数是label,就是0-9的哪一个数字。

                     3. 使用Keras实现全连接神经网络完成手写数字识别_第13张图片

 

我们来看一下,实际上x_train,y_train应该长什么样子。

x_train是一个numpy array。在这个task里面,要把image 存到numpy array里面。存法是这样的:numpy array是2维的,第一个维度代表有多少张图片,有几个training examples,第二个维度要看有多少个像素(这里有28*28 = 784个像素,所以第二维有784个元素)。因此第一个数组是training examples * 784的二维数组。

y_train也是一个numpy array。同样,第一个维度表示有几个training examples.第二个维度就是10。举例来说,第一张图片是5,所以在他的y_train里面,对应到5的哪一维是1,其他的是0。因此,第二个数组是training examples * 10的数组。

              3. 使用Keras实现全连接神经网络完成手写数字识别_第14张图片

batch_size为100,表示随机挑选100张图片作为一个batch。每个batch更新一次参数。假设有1万ge training examples,则有10000/100 = 100个batch。

epochs = 20表示一共有20个epoch。一个epoch表示把所有的training examples看完一遍。

所用总共要更新20*100次参数。(每个epoch中更新100次,20个epoch)

 

--------------------------------------------------------------------------------------------------------------------------------------

 

Keras可以保存和加载模型。可以把train好的model存起来,以后再用另外一个程序读出来。

            3. 使用Keras实现全连接神经网络完成手写数字识别_第15张图片

 

最后,你要拿来做实际应用。有两种不同的情景。第一种情况是评估,即有一组测试数据,测试数据的答案也知道,Keras可以算正确率。evaluate()有两个输入,分别是testing的image 和testing的label。第二种情况是预测,是指你没有任何的label data,你只有image。也就是你的系统真正上线了,使用者真正给你一张图片,你要告诉他结果是多少。predit()的输入是图片,输出是分类的结果。

 

        3. 使用Keras实现全连接神经网络完成手写数字识别_第16张图片

 

--------------------------------------------------------------------------------------------------------------------------------------

 

我们来实际写一下代码:

import numpy as np

from keras.models import Sequential
from keras.layers.core import Dense,Activation

from keras.layers import Conv2D, MaxPooling2D, Flatten
from keras.optimizers import Adam,SGD
from keras.datasets import mnist
from keras.utils import np_utils
 

def load_data()

       (x_train, y_train),(x_test, y_test) = mnist.load_data()             #从Keras自带的数据集里面下载mnist手写数字数据集

       number  = 10000

       x_train = x_train[0:number]

       y_train = y_train[0:number]
       x_train = x_train.reshape(number,28*28)
       x_test = x_test.reshape(x_test.shape[0],28*28)

       x_train = x_train.astype('float32')

       x_test = x_test.astype('float32')


       y_train = np_utils.to_categorical(y_train, 10)   #把y转换为长为10的向量,手写数字是什么第几个就为1,其他元素为0
       y_test = np_utils.to_categorical(y_test, 10)
       x_train = x_train / 255   #降低图片数据的灰度值,便于训练
       x_test = x_test /255
       

       return (x_train,y_train),(x_test,y_test)


(x_train,y_train),(x_test,y_test) = load_data()

 

//定义结构

model = Seuqential()

model.add(Dense(input_dim = 28*28,units = 633,activation = 'sigmoid'))

model.add(Dense(units = 633,activation = 'sigmoid'))

 

for i in range(10):                                                                               //用for再加十层~~~

        model.add(Dense(units = 633,activation = 'sigmoid'))

model.add(Dense(units = 10,activation = 'softmax'))

 

//下配置

model.compile(loss = 'mse', optimizer = SGD(lr=0.1),metrics = ['accuracy'])  //均方误差。学习率0.1。

 

//训练

model.fit(x_train,y_train,batch_size = 100,epochs = 20)

 

//评估、预测

result = model.evaluate(x_test,y_test)

print("Test ACC: "+result[1])

 

运行结果:暂略。回来再补。

 

 

【分析】

今天的代码其实效率很差的。什么原因呢?怎么办呢?等讲完神经网络的优化部分,再回来改进。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(17,深度学习)