什么是Keras,为什么要学Keras
在学习深度学习的过程中,有些人用的是MatLab,有些人用的Python。而使用Python的同学必定也用过Tensorflow、PyTorch这些机器学习库。但通过Tensorflow等这些库来实现我们的深度学习模型的时候仍然需要大量的编程,对诸如前向传递、后向传递、优化算法等方法都要自己去通过编程实现。这对于初学者来说简直就是噩梦一样。
相比来说,Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow、Theano以及CNTK后端。Keras 为支持快速实验而生,能够把你的idea迅速转换为结果。
Keras的Sequential模型API可以让我们通过简单地操作将神经网络的层加入到模型中,下面通过一个简单的例子来看我们是怎样通过Sequential的API来实现一个神经网络模型的。
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Flatten()) # input layer
model.add(tf.keras.layers.Dense(128,activation=tf.nn.relu)) # hidden layer
model.add(tf.keras.layers.Dense(128,activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(10,activation=tf.nn.softmax))
在Keras中,通过仅仅5行代码就可以实现一个MLP多层感知机的神经网络模型,而在TensorFlow中相应的代码往往是上百行。Keras的方便性可见一斑。
环境搭建
在学习了这么久的机器学习过后,Windows、Linux下的环境也应该搭建了很多次。由于Keras的后端我们选择使用TensorFlow,因此整个环境的搭建便不需要过多地浪费笔墨。
在进一步进行学习之前,我推荐大家通过VirtualEnv或者Anaconda来创建Python的虚拟环境,这样我们安装的软件包不会相互影响,使得针对机器学习开发与桌面软件或服务器开发的不同虚拟环境相对干净。
这里以Anaconda为例说明环境搭建的要求。
环境要求:
1、Anaconda(要求安装Python3版本)
2、TensorFlow*
3、Keras*
4、Jupyter Notebook*
5、CUDA和CuDNN
上述各个软件的安装这里不再赘述,前面的教程里面有相应的讲解。带有星号的则是可以通过pip指令进行安装的。
在安装完毕之后,我们来到CMD控制台(Windows环境下),输入如下命令来建立虚拟环境。
conda create --name tensorflow python=3.*
python的版本具体由安装的时候的版本来指定,如安装的是Python3.6的Anaconda则指定python=3.6
使用如下指令激活虚拟环境
activate tensorflow
在激活虚拟环境之后,我们的控制台提示前面会加入(tensorflow)D:\dev\pythonwork>
的提示。
使用如下指令退出虚拟环境
deactivate tensorflow
在激活了环境之后通过简单地pip install
指令来安装TensorFlow与Keras。安装完毕之后使用jupyter notebook
来打开Jupyter交互式编译器。
Keras简单入门——实现MLP手写体识别
说到神经网络的入门,有何人想不到MNIST呢?
对于本教程的Keras的简单入门,我们也将编写一个多层感知机的MNIST手写数字识别的神经网络。通过这个教程你将会真正意义上地感受到Keras的好处。
首先导入TensorFlow和Keras的包。
import tensorflow as tf
import keras
上述代码在Jupyter Notebook这个交互式的笔记本中看起来是这样的。
通过选中这一行,并且点击Run按钮,我们可以只运行这一行代码,这使得当我们需要修改代码的时候从修改的地方开始执行,而不是执行全部代码。这也是我们为何选择Jupyter Notebook来进行学习,而不是选择诸如PyCharm等IDE进行学习的原因。
在导入完TensorFlow和Keras两个包之后,我们通过keras自带的方法来加载MNIST的数据集,并通过load_data的方法解包(unpack)到训练集和测试集。
mnist = keras.datasets.mnist # 28x28大小的图像的0-9数字的手写体数据集
(x_train,y_train),(x_test,y_test) = mnist.load_data()
在准备好训练集和测试集之后,让我们先来看看MNIST中的数据到底是怎样的格式的。通过print(x_train[0])
输出训练集的第一个28x28的图像数据。
[...
[ 0 0 0 0 0 0 0 0 0 0 0 0 3 18 18 18 126 136
175 26 166 255 247 127 0 0 0 0]
[ 0 0 0 0 0 0 0 0 30 36 94 154 170 253 253 253 253 253
225 172 253 242 195 64 0 0 0 0]
[ 0 0 0 0 0 0 0 49 238 253 253 253 253 253 253 253 253 251
93 82 82 56 39 0 0 0 0 0]
[ 0 0 0 0 0 0 0 18 219 253 253 253 253 253 198 182 247 241
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 80 156 107 253 253 205 11 0 43 154
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 14 1 154 253 90 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
...]
可以看到这是一个28x28的二维数组,元素的取值从0到255。也就是说,MNIST手写数字数据集中的图片是单通道的灰度图片。单纯地从数值的角度来看这张图片十分烧脑,甚至看不出这是一个数字,那么这时我可以通过matplotlib.pyplot来进行绘图。如果你有相应的经验,那么可以自己继续写下去,然后将上面的数字显示出来,之后再回来看下面的代码。
在继续进行之前,先导入matplotlib.pyplot的包,然后使用plt的imshow来显示图像。
import matplotlib.pyplot as plt
plt.imshow(x_train[0], cmap='gray')
plt.show()
通过pyplot我们可以很明显地看到,x_train[0]是一个数值为5的手写数字。
在继续下去之前,我们还需要对MNIST的数据进行一些简单地处理,将0-255的整数标准化为0-1的范围之间的浮点数。幸运的是,Keras给我们提供了将这些数值标准化的方法。
x_train=keras.utils.normalize(x_train,axis=1)
x_test=keras.utils.normalize(x_test,axis=1)
通过keras.utils.normalize
我们可以轻松地将测试集和数据集标准化。
那么接下来便是重头戏了,也就是我们在开头所说过的,通过Keras的Sequential模型来构建这个多层感知机的模型。如果你对于神经网络不很了解,不知道什么是多层感知机的话,可以看一下我前面写的机器学习相关的文章。
在Keras中,使用Sequential模型十分简单通过
keras.models.Sequential
来创建一个模型对象,然后依次调用add
来添加层,层添加的顺序则是从输入层到输出层的顺序。最后,我们通过compile
来编译这个模型,在编译的时候需要指定模型的优化算法、损失函数和评价指标。
model = keras.models.Sequential()
model.add(keras.layers.Flatten()) # input layer
model.add(keras.layers.Dense(128,activation=tf.nn.relu)) # hidden layer
model.add(keras.layers.Dense(128,activation=tf.nn.relu))
model.add(keras.layers.Dense(10,activation=tf.nn.softmax))
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
上述6行代码则完整地定义了这个MLP的模型。首先是输入层,输入层指定是Flatten(扁平)的,也就是把二维的图像数据一维化,输入多层感知机。然后通过Dense创建2个128个神经元的全连接层,该全连接层使用ReLU作为激活函数。最后再创建一个与上一个隐藏层全连接的具有10个输出的全连接层作为输出层,通过SoftMax函数将输出映射为0~9的10个概率的输出。
最后通过model.fit(x_train,y_train,epochs=3)
开始指定训练集、测试集和epochs来进行训练。训练时的输出如下:
Epoch 1/3
60000/60000 [==============================] - 7s 115us/step - loss: 0.2641 - acc: 0.9229
Epoch 2/3
60000/60000 [==============================] - 5s 84us/step - loss: 0.1073 - acc: 0.9662
Epoch 3/3
60000/60000 [==============================] - 5s 84us/step - loss: 0.0726 - acc: 0.9775
可以看到,通过3个epochs的训练过后,网络的损失达到了0.07,准确率达到了97.75%。但这只是对测试集的训练得到的结果,有时模型会出现过拟合的情况,此时便需要通过对模型没有遇见过的验证集的数据进行测试。
val_loss,val_acc=model.evaluate(x_test,y_test)
print(val_loss,val_acc)
运行评估之后,针对验证集输出如下:
10000/10000 [==============================] - 0s 47us/step
0.0927426937890239 0.9701
由此可见,针对验证集进行评估之后,模型的损失为0.0927、准确率为97.01%。这证明模型并未出现过拟合。
通过predictions = model.predict([x_test])
针对x_test进行预测,使用numpy的argmax方法来得到相应预测的值应该是多少。
将预测的结果使用pyplot可视化显示出来便可以看出预测是否是对的。
predictions = model.predict([x_test])
import numpy as np
print(np.argmax(predictions[0]))
plt.imshow(x_test[0])
plt.show()