一、Keras中的不同优化器测试
梯度下降(Gradient Descent,GD),含有单一变量w的一般成本函数C(w):
梯度下降可以看作是一名要从山上到山谷的背包客,山上表示成函数C,山谷表示成最小值Cmin,背包客的起点为w0。 背包客慢慢移动,对每一步r,梯度就是最大增量的方向。从数学上讲,该方向就是在步r到达的点wr上求得的偏导数。 因此,通过走相反的方向
,背包客可以向山谷移动。每一步,背包客都能在下一步之前判别步长,这就是梯度下降中讲的学习率
。注意,如果步长太小,背包客就会移动得很慢;如果过大,背包客又很可能会错过山谷。现在你应该记住,sigmoid是一个连续函数,并且可以计算导数。 可以证明sigmoid函数如下所示:
它的导数如下:
ReLU函数在点0处不可微,然而,我们可以将点0处的一阶导数扩展到整个定义域,使其为0或1。这种和点相关的ReLU函数y=max(0,x)的导数如下:
一旦我们有了导数,就可以用梯度下降技术优化网络。Keras基于后端TensorFlow或Theano计算导数。
Keras实现了梯度下降的一个快速变体,称随机梯度下降(Stochasticn Gradient Descent,SGD),以及RMSprop和Adam这两种更先进的优化技术。除SGD具有加速度分量之外,RMSprop和Adam还包括了动量的概念(速度分量)。这样就可以通过更多的计算代价实现更快的收敛。
实验证明,RMSprop比SGD快,20次迭代后,训练集准确率达97.97%,验证集准确率达97.59%,测试集准确率达97.84%:
进一步地,Adam更好一些,20次迭代后,训练集准确率达98.28%,验证集准确率达98.03%,测试集准确率达97.93%:
二、采用正则化避免过拟合
为捕捉训练数据内在表达的所有关系,模型可能会变得过渡复杂。而复杂性的增加可能产生两种负面后果:
1)复杂的模型可能需要大量时间来执行;
2)在训练数据上,因其所有内在关系全被记忆下来,可取得优秀性能。但在验证集上以及全新的数据上,模型不能进行很好的泛化。
学习更多的是注重泛化而非记忆!
1)模型复杂度
为解决过拟合问题,需捕捉模型复杂度:模型不过是权重向量,因此,模型复杂度可以方便地表示为非零权重的数量。
min:{loss(训练数据|模型)} + λ*complexity(模型) (λ>=0)
机器学习中用到3种不同类型的正则化方法:
1)L1正则化(lasso):模型复杂度表示为权重的绝对值之和;
2)L2正则化(ridge):模型复杂度表示为权重的平方和;
3)弹性网络正则化:模型复杂度通过联合前述两种技术捕捉。
注意,相同的正则化方案可以独立应用于权重、模型和激活函数。
Keras中,全连接和卷积模块常用的正则化参数配置:
-
kernel_regularizer
:施加在权重上的正则项,为keras.regularizer.Regularizer
对象 -
bias_regularizer
:施加在偏置向量上的正则项,为keras.regularizer.Regularizer
对象 -
activity_regularizer
:施加在输出上的正则项,为keras.regularizer.Regularizer
对象
例,在内核(权重W)上使用L2正则化方法:
from keras import regularizers model.add(Dense(64, input_dim=64, kernel_regularizer=regularizers.l2(0.01)))
2)Dropout
Dropout层也可以用作正则化层,这通常是一个有效的方法:
三、分批(Batches),增加批处理的大小
四、批归一化,分批标准化(Batch Normalization)
分批标准化就像是人们在河流中用以监测水位的监察站一样。这是为了保证下一层网络得到的数据拥有合适的分布。在训练神经网络的过程中,每一次梯度下降后权重因子都会得到改变,从而会改变相应的数据结构。
但是下一层网络希望能够得到与之前分布相似的数据,因此在每一次数据传递前都需要对数据进行一次正则化处理。
五、激活函数
(a) Sigmoid函数
sigmoid函数为值域在0到1之间的光滑函数,当需要观察输入信号数值上微小的变化时,与阶梯函数相比,平滑函数(比如Sigmoid函数)的表现更好。
(b) 线性整流函数(ReLU-Rectified Linear Units)
近来的神经网络倾向于使用ReLU替代掉sigmoid函数作为隐层的激活函数,它的定义为 f(x) = max(x,0)。当x大于0时,函数输出x,其余的情况输出为0。使用ReLU函数的好处是,对于所有大于0的输入,导数是恒定的,这能够加快训练网络的速度。
(c) softmax函数
softmax激活函数通常应用在分类问题的输出层上。它与Sigmoid函数相似,唯一的不同是softmax函数输出结果是归一化的。sigmoid函数能够在双输出的时候奏效,但当面对多种类分类问题的时候,softmax函数可以方便地直接将各个分类出现的概率算出。
六、损失函数
1)准确率/Accuracy:对于分类问题,其取值有多种
-
binary_accuracy:二分类问题预测准确率
- categorical_accuracy:多分类问题预测准确率
- sparse_categorical_accuracy:针对稀疏目标值预测时使用
- top_k_categorical_accuracy:当预测值的前k个值中存在目标类别即认为预测正确时使用
2)误差损失/Error Loss:用于度量预测值与实际值之间的差异,有多种取值
-
mean_squared_error或mse:均方误差
- root_mean_squared_error或rmse:均方根误差
-
mean_absolute_error或mae:平均绝对误差
-
mean_absolute_percentage_error或mape:平均绝对百分比误差
-
mean_squared_logarithmic_error或msle:均方对数误差
3) Hinge Loss:常用于训练分类器,有两种取值
-
hinge:max(1-yture*ypred,0)
- squared_hinge:hinge损失的平方值
4)Class Loss:用于计算分类问题中的交叉熵,存在多个取值
-
binary_crossentropy:二分交叉熵
-
categorical_crossentropy:分类交叉熵
七、保存/加载模型
使用model.save(filepath)将Keras模型和权重保存在一个HDF5文件,包含
- 模型的结构,以便重构该模型
- 模型的权重
- 训练配置(损失函数,优化器等)
- 优化器的状态,以便于从上次训练中断的地方开始
from keras.models import load_model model.save('my_model.h5') # 创建HDF5文件'my_model.h5' del model # 删除模型 # 返回编译好的模型 # 和前面模型相同 model = load_model('my_model.h5')
只希望保存模型的结构,而不包含其权重或配置信息:
# 把模型序列化为JSON或YAML文件,其可以手动打开并进行编辑
# 保存为JSON字串 json_string = model.to_json() # 保存为YAML字串
yaml_string = model.to_yaml()
# 从JSON字串重构模型 from keras.models import model_from_json model = model_from_json(json_string) # 从YAML字串重构模型 model reconstruction from YAML model = model_from_yaml(yaml_string)
八、自定义训练过程的回调函数
当评估函数已经不能继续优化时,可通过调用合适的回调函数来停止训练过程:
keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=0, verbose=0, mode='auto')
损失函数历史信息可以定义一个回调函数来保存:
class LossHistory(keras.callbacks.Callback): def on_train_begin(self, logs={}): self.losses = [] def on_batch_end(self, batch, logs={}): self.losses.append(logs.get('loss')) model = Sequential() model.add(Dense(10, input_dim=784, kernel_initializer='uniform')) model.add(Activation('softmax')) model.compile(loss='categorical_crossentropy', optimizer='rmsprop') history = LossHistory() model.fit(X_train, Y_train, batch_size=128, epochs=20, verbose=0, callbacks=[history]) print history.losses
九、检查点设置
设置检查点就是在一个规则的时间间隔里保存应用程序状态的快照的过程,以便在出现失败的情况下可以把应用程序恢复到最后一次保存时的状态。这对极其耗时的深度学习任务的训练过程非常有用。深度学习模型在任何时间点的状态就是模型在那个时间点的权重。Keras用HDF5格式保存这些权重,并通过回调函数API来提供检查点设置。
3种应用场景:
1)在AWS Spot实例后或谷歌可抢占虚机意外终止时恢复到上一个检查点;
2)停止训练过程:为了用测试数据测试模型,然后从上一个检查点继续训练过程;
3)在多轮训练过程中保存最佳版本(通过校验损失的评估函数)。
前两种场景可以通过每一轮训练后保存一个检查点来处理,设置检查点通过ModelCheckpoint回调函数的默认使用就可以完成。
例,用Keras在深度学习模型训练过程中添加检查点:
from keras.callbacks import ModelCheckpoint model = Sequential() model.add(Dense(10, input_dim=784, kernel_initializer='uniform')) model.add(Activation('softmax')) model.compile(loss='categorical_crossentropy', optimizer='rmsprop') ''' 保存最佳模型 saves the model weights after each epoch if the validation loss decreased ''' # checkpointer = ModelCheckpoint(filepath="/tmp/weights.hdf5", verbose=1, save_best_only=True) checkpointer = ModelCheckpoint(filepath=os.path.join("/tmp", "model-{epoch:02d}.h5"), verbose=1, save_best_only=True) model.fit(X_train, Y_train, batch_size=128, epochs=20, verbose=0, validation_data=(X_test, Y_test), callbacks=[checkpointer])
第三种场景涉及对评估函数的监督,如准确率或损失的校验,其只在当前评估比之前的更好的情况下才保存一个检查点。
Keras提供了一个额外的参数——save_best_only,在初始化检查点对象的时候需要把该参数值设为true才支持此功能。
十、使用TensorBoard
keras提供了模型中不同层的激活的柱状图——可视化的展示器:
keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=0, write_graph=True, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None)
保存好的数据可通过命令运行TensorBoard来查看其图形化结果:
tensorboard --logdir=/full_path_to_your_logs
十一、使用Quiver
它是一个卷积特征可视化的交互式工具。
安装:
pip install quiver_engine
使用:
# 在本机5000端口运行可视化工具,可视化查看模型
from quiver_engine import server server.launch(model)
十二、数据增强(Data Augmentation)
数据增强(Data Augmentation)指的是从已有数据中创造出新的数据,通过增加训练量以期望能够提高预测的准确率。
例,手写数字识别中,其可能是倾斜或旋转的,因此如果将训练的图片进行适度的旋转,增大训练量,那么模型的准确性就可能会得到提高。通过“旋转”的操作,训练数据的品质得到了提升,这种过程被称作数据增强。
十三、梯度传递
(1) 梯度消失问题
当激活函数的梯度很小时就会发生梯度消失问题。在反向传播的过程中,权重因子会被多次乘以这些小的梯度,因此会越变越小,随着递归的深入趋于“消失”, 使得神经网络失去了长程可靠性。这在递归神经网络中是一个较普遍的问题。
(2) 梯度爆炸问题
当激活函数的梯度较大时,就会发生梯度爆炸问题。在反向传播的过程中,部分节点的大梯度使得他们的权重变得非常大,从而削弱了其他节点对于结果的影响,这个问题可以通过截断(即设置一个梯度允许的最大值)的方式来有效避免。