Keras
Keras是一个高层神经网络库。Keras是由Python编写而成的,后端实现是基于Tensorflow,CNTK或Theano(Keras是一个库,可以理解为一个基于多种不同机器学习库提供相同api的库)。
Keras发展的要义是:将想法快速转换实验成果,(类似Python的理念:人生苦短,我用Python),正因为这样,Keras很适合做研究使用。
如果你对深度学习库有以下要求:
- 能够快速的、简便的实现idea
- 支持CNN和RNN
- 在CPU和GPU上快速切换
那么Keras会是一个非常好的选择~
安装Keras
Keras依赖
在安装Keras之前,需要安装一个Keras需要的任意一个后端引擎
(backend engines,后端是指Keras需要依赖的底层张量运算所需要的机器学习库):
- TensorFlow
- CNTK
- Theano
建议选用TensorFlow。参考我的安装方法–>Ubuntu16.04+1080下配置Tensorflow
还有一些可选的依赖:
- cuDNN (使用GPU加速Keras运行)
- HDF5 and h5py (用于保存Keras模型)
- graphviz and pydot (绘制模型图)
我个人觉得安装Anaconda+TensorFlow+Keras这一套,省心省力~
安装Keras库本身
安装Keras有两种方法:
-
使用PyPI安装(推荐)
sudo pip install keras
-
也可以使用源码安装
-
First: 从github上将Keras源码clone下来
git clone https://github.com/fchollet/keras.git
-
Then: 进入Keras目录,并执行安装程序
cd keras sudo python setup.py install
-
查看是否安装和Keras的后端设置
打开终端
>>>python # 进入python环境
>>>import keras # 导入keras
Using TensorFlow backend.
>>>keras.__version__ # 查看当前Keras版本
'2.0.8'
如何切换后端为CNTK或Theano
Keras默认使用TensorFlow作为后端实现张量计算,如果你想切换Keras的后端为CNTK或Theano,参考Keras backends。
(现在Theano已经停止更新了,建议还是用TensorFlow吧)
一些基本概念
在学习Keras之前,需要有一些关于Keras、深度学习的基本概念。
张量
通常,在机器学习系统中使用张量
(tensors)作为数据的基本结构,张量是这个领域的基础概念,那么tensor是啥?
张量是包含数据的容器,可以看做数字、向量、矩阵的扩展,它们都是张量的特殊表现。
-
0维的张量就是数字,即
标量
(0D tensors:Scale
)>>> import numpy as np >>> x = np.array(12) >>> x array(12) >>> x.ndim 0
只包含一个数字的张量称之为标量,在numpy中可通过
ndim
属性访问张量的维度 -
1维的张量就是一组数据,即
向量
(1D tensors:Vectors
)>>> x = np.array([12, 3, 6, 14]) >>> x array([12, 3, 6, 14]) >>> x.ndim 1
-
2维的张量就是一组向量,即
矩阵
(2D tensors:Matrices
)>>> x = np.array([[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]]) >>> x.ndim 2
-
3维(例如一张彩色图片)及更多维度的张量
>>> x = np.array([[[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]], [[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]], [[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]]]) >>> x.ndim 3
在张量的表述上,一般把维度(dimension)称为轴
(axis)。在深度学习中,一般使用的是从0D到4D的张量,在处理video data时可能会用到5D的张量
下图是4D张量的表示:
多张图片组成的4D张量,分别为长、宽、通道数、样本数。一般的我们在训练CNN模型时,定义的输入张量就是这样的形式。
张量的属性
一个张量有3个关键属性:
- 张量的
axes
(阶数)。 张量的
shape
。shape描述的张量每个axis的维度。例如上面举例的3D张量的shape为(3,3,5);2D的张量shape为(2,5);1D的张量shape为(4,);0D的张量shape为()。张量的数据类型(
data type
)。在numpy中dtype表示。
函数式模型
在原本的Keras版本中,模型其实有两种:
一种叫Sequential,称为序贯模型,也就是单输入单输出,一条路通到底,层与层之间只有相邻关系,跨层连接统统没有。这种模型编译速度快,操作上也比较简单。
第二种模型称为Graph,即图模型(大部分机器学习库都是基于这个模型),这个模型支持多输入多输出,层与层之间想怎么连怎么连,但是编译速度慢。
可以看到,Sequential其实是Graph的一个特殊情况。新版Keras中,图模型被移除,而增加了functional model API
,这更加强调了Sequential是特殊情况。一般的模型就称为Model,如果你要用简单的Sequential,还有一个快捷方式Sequential。
functional model API
将其译为泛型模型,即只要是接收一个或一些张量作为输入,然后输出的也是一个或一些张量,统统都称作“model”。
Pyhon和深度学习基础
- Keras使用的是Python语言,所以应该对Python有一定得了解。
- Keras是一个深度学习库,所以基本的深度学习基础是要有的。
- 模型:监督学习、无监督学习、分类、回归等
- 损失函数、激活函数、过拟合、欠拟合等
- BP算法、梯度下降法、SGD、batch、epoch等
- 训练集、校验集、测试集等
开发环境
我的开发环境:
- Ubuntu16.04(强烈建议在linux上开发)
- TensorFlow 1.3-GPU(我的后端是tensorflow)
- i7-7700k+GTX1080(没有显卡也能搞,就是速度慢点)
在MNIST上构建一个简单的神经网络
源代码:我的github。
MNIST数据集
Keras内置操作MNIST数据集的函数MNIST数据集介绍。可通过下面格式载入:
>>>from keras.datasets import mnist
>>>(train_images, train_labels), (test_images, test_labels) = mnist.load_data() # 下载完MNIST数据集并载入
# ... 下载
>>>train_images.shape # 看一下训练集
(60000, 28, 28)
>>>len(train_labels)
60000
>>>test_images.shape # 看一下测试集
(10000, 28, 28)
>>>len(test_labels)
10000
在使用之前,我们对数据做reshape
以便于后面直接塞给model,同时对数据做归一化处理。原本我们的训练图片shape为(60000, 28, 28);dtype为uint8;值为[0, 255]之间。我们将其转化为dtype为float32; shape为(60000, 28 * 28);值为[0, 1].
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
同样的,我们也需要对labels做编码,用如下代码:
from keras.utils import to_categorical
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
这样我们算是准备好了数据集了~
构建网络模型
神经网络的核心组成模型是层
,层
就是数据处理模块,也称之为过滤器
(filter)。一般的有输入层、隐藏层、输出层。
from keras import models
from keras import layers
network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))
这里我们构建的模型由两个Dense
层组成,Dense
层就是densely-connected (也称之为”fully-connected”,即FC)层。(我就在琢磨17年的整出来了DenseNet,Keras该怎么起名字)。第二层是softmax层,输出是一个10维向量,对应的就是数字0-9的可能性。(总和为1)。
为了能够训练模型,我们还需要做以下三步:
- 添加
损失函数
(loss function):评估模型在训练集上训练的好坏程度,为模型修正提供了正确方向。 -
优化器
(optimizer):模型优化自身参数的方法 - 训练和测试之间的度量标准。
network.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
训练模型并评估
在构建好的模型上,开始训练:
>>>network.fit(train_images, train_labels, epochs=5, batch_size=128) Epoch 1/5 60000/60000 [==============================] - 2s - loss: 0.2577 - acc: 0.9245 Epoch 2/5 60000/60000 [==============================] - 1s - loss: 0.1042 - acc: 0.9690 Epoch 3/5 60000/60000 [==============================] - 1s - loss: 0.0687 - acc: 0.9793 Epoch 4/5 60000/60000 [==============================] - 1s - loss: 0.0508 - acc: 0.9848 Epoch 5/5 60000/60000 [==============================] - 1s - loss: 0.0382 - acc: 0.9890
可以看到,这里打印的log里主要有2个指标,’loss’表示network和训练集之间的loss,’acc’即表示network和训练集之间accuracy。可以看到,在训练集上acc很快达到了98.9%, 下面看看模型在测试集上的表现:
>>>test_loss, test_acc = network.evaluate(test_images, test_labels)
9536/10000 [===========================>..] - ETA: 0s
>>>print('test_acc:', test_acc)
test_acc: 0.9777
可以看到在测试集上达到了97.7%,也还算不错。到此为止,我们搭建了一个简易的神经网络模型用于手写数字的识别,后面还将详细的讲解本小节用到的函数。
参考资料
Keras中文文档 SCP-173
《Deep Learning with Python》 Francois Chollet