Keras是一个高层神经网络API,Keras由纯Python编写而成并基 Tensorflow、 Theano以及 CNTK后端。Keras 为支持快速实验而生,能够把你的idea迅速转换为结果,如果你有如下需求,请选择Keras:
- 简易和快速的原型设计(keras具有高度模块化,极简,和可扩充特性)
- 支持CNN和RNN,或二者的结合
- 无缝CPU和GPU切换
Keras适用的Python版本是:Python 2.7-3.6
本文面向的对象是对深度学习有一些了解的同学快速入门kears 实现代码开发,能够实现部分神经网络。其中涉及的到的概念如下:
- 卷积层、池化层、全连接层
- 各种优化方法
- 各种损失函数
- …
了解一个简单的 keras 实例
这个应用实现的是图像数字识别,使用的数据是keras中自带的mnist数据集。实例的全部代码如下,简单了解之后我们将分步骤、详细讲解具体涉及到的函数及其参数。
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD
from keras.datasets import mnist
import numpy
# 第一步:选择模型
model = Sequential()
# 第二步:构建网络层
model.add(Dense(500,input_shape=(784,))) # 输入层,28*28=784
model.add(Activation('tanh')) # 激活函数是tanh
model.add(Dropout(0.5)) # 采用50%的dropout
model.add(Dense(500)) # 隐藏层节点500个
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(10)) # 输出结果是10个类别,所以维度是10
model.add(Activation('softmax')) # 最后一层用softmax作为激活函数
# 第三步:编译
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) # 优化函数,设定学习率(lr)等参数
model.compile(loss='categorical_crossentropy', optimizer=sgd) # 使用交叉熵作为loss函数
'''
第四步:训练
.fit的一些参数
batch_size:对总的样本数进行分组,每组包含的样本数量
epochs :训练次数
shuffle:是否把数据随机打乱之后再进行训练
validation_split:拿出百分之多少用来做交叉验证
verbose:屏显模式 0:不输出 1:输出进度 2:输出每次的训练结果
'''
(X_train, y_train), (X_test, y_test) = mnist.load_data() # 使用Keras自带的mnist工具读取数据(第一次需要联网)
# 由于mist的输入数据维度是(num, 28, 28),这里需要把后面的维度直接拼起来变成784维
X_train = X_train.reshape(X_train.shape[0], X_train.shape[1] * X_train.shape[2])
X_test = X_test.reshape(X_test.shape[0], X_test.shape[1] * X_test.shape[2])
Y_train = (numpy.arange(10) == y_train[:, None]).astype(int)
Y_test = (numpy.arange(10) == y_test[:, None]).astype(int)
model.fit(
X_train,
Y_train,
batch_size=200,
epochs=50,
shuffle=True,
verbose=1,
validation_split=0.3)
model.evaluate(X_test, Y_test, batch_size=200, verbose=0)
'''
第五步:输出
'''
print("test set")
scores = model.evaluate(X_test,Y_test,batch_size=200,verbose=0)
print("")
print("The test loss is %f" % scores)
result = model.predict(X_test,batch_size=200,verbose=0)
result_max = numpy.argmax(result, axis = 1)
test_max = numpy.argmax(Y_test, axis = 1)
result_bool = numpy.equal(result_max, test_max)
true_num = numpy.sum(result_bool)
print("")
print("The accuracy of the model is %f" % (true_num/len(result_bool)))
查看数据集
查看图片数据
每张图片的信息都以numpy.ndarray
保存,每张图片都是28*28
大小的数字矩阵。
plt.imshow(X_train[23])
print(X_train.shape)
print(type(X_train[0]))
输出
(60000, 28, 28)![]()
<class 'numpy.ndarray'>
查看训练集、测试集相关数据
print("训练集数据大小:", X_train.shape)
print("测试集数据大小:", X_test.shape)
print("训练集标签", Y_train.shape)
print("测试集标签", Y_test.shape)
输出
训练集数据大小: (60000, 28, 28)
测试集数据大小: (10000, 28, 28)
训练集标签 (60000, 10)
测试集标签 (10000, 10)
keras编程开始
正如文章最开始的案例中表示,keras编程能够划分为五个步骤:
- 选择模型
- 构建神经网络结构
- 编译
- 训练
- 预测
选择模型
Keras有两种类型的模型,顺序模型(Sequential)和泛型模型(Model),本文选择的是简单的顺序模型。直接实例化对象即可:
model = Sequential()
相对于泛型模型而言,顺序模型简单容易上手,但是缺点也很明显,模型的灵活性不够。相关的泛型模型本文不过多介绍,参考文档keras 泛型模型
构建网络
神经网络中的数据层包括全连接层(Dense)、激活层(Activation)、随机失活层(Dropout)、Flatten层、Reshape层、Permute层、RepeatVector层、Lambda层、ActivityRegularizer层、Masking层。每一层的功能如下:
层名称 | 功能 |
---|---|
Dense层 | Dense就是常用的全连接层,所实现的运算是output = activation(dot(input, kernel)+bias) 。其中activation 是逐元素计算的激活函数,kernel 是本层的权值矩阵,bias 为偏置向量,只有当use_bias=True 才会添加。 |
Activation层 | 激活层对一个层的输出施加激活函数 |
Dropout层 | 为输入数据施加Dropout。Dropout将在训练过程中每次更新参数时按一定概率(rate)随机断开输入神经元,Dropout层用于防止过拟合。 |
Flatten层 | Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。 |
Reshape层 | Reshape层用来将输入shape转换为特定的shape |
Permute层 | Permute层将输入的维度按照给定模式进行重排,例如,当需要将RNN和CNN网络连接时,可能会用到该层。 |
RepeatVector层 | RepeatVector层将输入重复n次 |
Lambda层 | 本函数用以对上一层的输出施以任何Theano/TensorFlow表达式 |
ActivityRegularizer层 | 经过本层的数据不会有任何变化,但会基于其激活值更新损失函数值 |
Masking层 | 使用给定的值对输入的序列信号进行“屏蔽”,用以定位需要跳过的时间步 |
不同层之间的实例化参数不全相同,具体参考文档keras 常用层 。这里对本文出现的Dense层进行详细说明:
keras.layers.core.Dense(
units,
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None)
重要参数如下:
- units:大于0的整数,代表该层的输出维度。
- activation:激活函数,为预定义的激活函数名(参考激活函数),或逐元素(element-wise)的Theano函数。如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)
- use_bias: 布尔值,是否使用偏置项
本文的神经网络结构:
model.add(Dense(500,input_shape=(784,))) # 输入层,28*28=784
model.add(Activation('tanh')) # 激活函数是tanh
model.add(Dropout(0.5)) # 采用50%的dropout
model.add(Dense(500)) # 隐藏层节点500个
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(10)) # 输出结果是10个类别,所以维度是10
model.add(Activation('softmax')) # 最后一层用softmax作为激活函数
编译
compile(self,
optimizer,
loss,
metrics=[],
loss_weights=**None**,
sample_weight_mode=**None**)
- optimizer:优化器,为预定义优化器名或优化器对象,参考优化器
- loss:目标函数,为预定义损失函数名或一个目标函数,参考目标函数
- metrics:列表,包含评估模型在训练和测试时的性能的指标,典型用法是
metrics=['accuracy']
如果要在多输出模型中为不同的输出指定不同的指标,可像该参数传递一个字典,例如metrics={'ouput_a': 'accuracy'}
- sample_weight_mode:如果你需要按时间步为样本赋权(2D权矩阵),将该值设为“temporal”。默认为“None”,代表按样本赋权(1D权)。如果模型有多个输出,可以向该参数传入指定sample_weight_mode的字典或列表。在下面
fit
函数的解释中有相关的参考内容。 - kwargs:使用TensorFlow作为后端请忽略该参数,若使用Theano作为后端,kwargs的值将会传递给 K.function
# 第三步:编译
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) # 优化函数,设定学习率(lr)等参数
model.compile(loss='categorical_crossentropy', optimizer=sgd) # 使用交叉熵作为loss函数
训练
fit(self, x, y,
batch_size=32,
nb_epoch=10,
verbose=1,
callbacks=[],
validation_split=0.0,
validation_data=None,
shuffle=True,
class_weight=None,
sample_weight=None)
本函数将模型训练nb_epoch
轮,其参数有:
- x:输入数据。如果模型只有一个输入,那么x的类型是numpy array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array
- y:标签,numpy array
- batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
- nb_epoch:整数,训练的轮数,训练数据将会被遍历nb_epoch次。Keras中nb开头的变量均为"number of"的意思
- verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
- callbacks:list,其中的元素是
keras.callbacks.Callback
的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数 - validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。
- validation_data:形式为(X,y)的tuple,是指定的验证集。此参数将覆盖validation_spilt。
- shuffle:布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱。
- class_weight:字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)
- sample_weight:权值的numpy array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了
sample_weight_mode='temporal'
。
fit
函数返回一个History
的对象,其History.history
属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况
(X_train, y_train), (X_test, y_test) = mnist.load_data() # 使用Keras自带的mnist工具读取数据(第一次需要联网)
# 由于mist的输入数据维度是(num, 28, 28),这里需要把后面的维度直接拼起来变成784维
X_train = X_train.reshape(X_train.shape[0], X_train.shape[1] * X_train.shape[2])
X_test = X_test.reshape(X_test.shape[0], X_test.shape[1] * X_test.shape[2])
Y_train = (numpy.arange(10) == y_train[:, None]).astype(int)
Y_test = (numpy.arange(10) == y_test[:, None]).astype(int)
model.fit( X_train, Y_train,batch_size=200,
epochs=50,shuffle=True, verbose=1, validation_split=0.3)
model.evaluate(X_test, Y_test, batch_size=200, verbose=0)
预测
evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
本函数按batch计算在某些输入数据上模型的误差,其参数有:
- x:输入数据,与
fit
一样,是numpy array或numpy array的list - y:标签,numpy array
- batch_size:整数,含义同
fit
的同名参数 - verbose:含义同
fit
的同名参数,但只能取0或1 - sample_weight:numpy array,含义同
fit
的同名参数
predict(self, x, batch_size=32, verbose=0)
-
本函数按batch获得输入数据对应的输出,其参数有:
-
函数的返回值是预测值的numpy array
'''
第五步:输出
'''
print("test set")
scores = model.evaluate(X_test,Y_test,batch_size=200,verbose=0)
print("The test loss is %f" % scores)
result = model.predict(X_test,batch_size=200,verbose=0)
result_max = numpy.argmax(result, axis = 1)
test_max = numpy.argmax(Y_test, axis = 1)
result_bool = numpy.equal(result_max, test_max)
true_num = numpy.sum(result_bool)
print("The accuracy of the model is %f" % (true_num/len(result_bool)))
总结
经过上面五步之后就能够实现了一个简单是神经网络,顺序模型的实现简单,能够依据提供的模型快速的进行设计以及神经网络的迭代。处理全连接层(Dense)外还有卷积层、池化层等其他的相关层能够进行设计,相关文档参考关于Keras的“层”(Layer),以及相关的层对象及其参数。