深度神经网络之Keras(三)——正则化、超参数调优和学习方向

本文将继续探索Keras框架下的深度神经网络知识,主要介绍了利用Keras构建的深度神经网络正则化及超参数调优问题。

目录

  • 深度神经网络之Keras(三)——正则化、超参数调优和学习方向
  • 一级目录
    • 二级目录
      • 三级目录
    • 一、 过拟合问题
    • 二、正则化
      • 2.1 L1正则化
      • 2.2 L2正则化
      • 2.3 丢弃正则化
    • 三、超参数调优
      • 3.1 深度学习中的超参数
        • 3.1.1 层中的神经元数量
        • 3.1.2 层的数量
        • 3.1.3 历元数
        • 3.1.4 权重初始化
        • 3.1.5 批尺寸
        • 3.1.6 学习率
        • 3.1.7 激活函数
        • 3.1.8 优化
      • 3.2 超参数调优方法
        • 3.2.1 手工搜索
        • 3.2.2 网格搜索
        • 3.2.3 随机搜索
    • 四、模型部署
      • 4.1 定制测试数据
      • 4.2 将模型保存到内存
      • 4.3 用新数据重新训练模型
      • 4.4 在线模型
      • 4.5 以API形式交付模型
      • 4.6 组件集成
    • 五、学习方向
      • 5.1 卷积神经网络(CNN)
      • 5.2 递归神经网络(RNN)

一级目录

二级目录

三级目录

一、 过拟合问题

在开发和训练机器学习与深度学习模型的过程中,经常遇到这样的问题:训练后的模型在训练数据集上表现良好,但在测试数据集上表现不佳。这种现象称为“过拟合”。
模型训练的过程称为“拟合数据”;在该过程中,神经网络学习数据中的潜在模式,并采用数学方法改进模型的权重或结构,以适应其在学习过程中发现的模式。简言之,就是训练模型使其结构权重适应数据模式,从而提高性能。但当模型发现的模式在现实中只是噪音时,这个过程就变得复杂了。然而,数学方程并不具备区分信号和噪声的能力(所谓噪声指的是一个数据点,它无法代表训练样本,而是随机产生的值)。当模型区分不了噪声时,它就将实际噪声当成新信号一并学习,调整其权重以适应噪声。
当深度学习模型学习噪声数据,并通过调整权重来适应噪声时,就会过度拟合数据。当学习噪声导致模型性能显著下降时,这个问题就会变得严重。

二、正则化

什么是正则化?
简单来说,正则化就是一个减少过拟合的过程。它是当模型包含噪音时,向模型学习过程引入警告的一种数学方法。实际上,它是一种在过拟合情况下对模型权重进行惩罚的方法。
在深度学习中,神经元连接的权重会在每次迭代后更新。当模型遇到一个有噪声样本、并假设该样本是有效样本时,它会尝试通过更新与噪声一致的权重来适应模型。在真实的样本数据中,噪声数据点与常规数据大相径庭。因此,权重的更新也将与噪声同步(权重的变化是巨大的)。正则化过程将边的权重加入已定义的损失函数中,整体上表示更高的损失。然后,神经网络通过自我调优以降低损失,使权重朝着正确的方向更新;这是通过在学习过程中忽略噪声、而不是适应噪声来实现的。
正则化的过程可以表示为:损失函数=损失(针对模型定义的)+超参数×[权重]。其中,超参数由λ/2m表示,其中λ的值由用户定义。基于权重加入损失函数的方式,存在两种不同类型的正则化技术:L1正则化和L2正则化。

2.1 L1正则化

对于L1正则化,是将权重的绝对值添加到损失函数中。为使模型更趋一般化,权重值常会被降为0。因此,若精简模型获得更快的运算速度,此方法首选。
L1正则化的方程可表示为:损失函数=损失(针对模型定义的)+超参数×Σ||权重||
在Keras中,通过向kernel regularizer参数提供regularizer对象,可将L1损失添加到一个神经网络层中。以下代码表示如何向Keras的稠密层中添加L1正则化器:

from keras import regularizers
from keras import Sequential
from keras.layers import Dense
from keras import Sequentialmodel = Sequential()
model.add(Dense(256, input_dim=128, kernel_regularizer=regularizers.l1(0.01)))

式中的值0.01是为λ设置的超参数值。

2.2 L2正则化

L2正则化是将权重的平方添加到损失函数中。为使模型较一般化,权重值通常被降低到接近于0(不等于0),因此L2正则化也被称为“权值衰减”方法。大多数情况下,推荐使用L2,与L1相比,L2能更好地减少过拟合。
L2正则化方程可表示为:损失函数=损失(针对模型定义的)+超参数×||权重||×||权重||
向深度学习模型中添加L2正则化器的方式与L1一样,如下所示:

model = Sequential()
model.add(Dense(256, input_dim=128, kernel_regularizer=regularizers.l2(0.01)))

式中的值0.01是为λ设置的超参数值。

2.3 丢弃正则化

除了L1和L2正则化外,深度学习中还有一种减少过拟合的技术,该技术采用的是一种丢弃机制。在这种方法中,每轮迭代期间模型都会任意地丢弃或停用某一层的一些神经元。因此,该模型在每轮迭代中都会面向自身的一个略微不同的结构进行优化(因为一些神经元和连接被停用)。假设有两个连续的层H1和H2,两者分别有15和20个神经元,在这两层之间应用丢弃技术,将导致H1根据预定义的百分比随机丢弃一些神经元,从而减少H1和H2之间的连接。该过程将在每一轮迭代中以随机方式重复,所以如果模型已经学习了一个批次并更新了权重,那么下一批次可能有一组完全不同的权重和连接需要训练。该方法相当高效,不仅降低了计算量,而且直观地减少了过拟合,提高了整体性能。
“丢弃”概念可用下图直观地理解。可以看到,正常网络的所有神经元和两个连续层之间的连接是完整无缺的。在丢弃机制下,每轮迭代都通过任意地停用或丢弃一些神经元及其相关的权重连接,来引入一定程度的随机性。

在keras中,可通过以下代码将丢弃机制应用到某一层:

keras.layers.Dropout(rate, noise_shape=None, seed=None)

下面的代码表示对稠密隐藏层应用丢弃机制,参数值0.25表示丢弃率(丢弃神经元的百分比):

from keras import Sequential
from keras.layers.core import Dropout, Densemodel = Sequential()
model.add(Dense(100, input_dim= 50, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(1,activation="linear"))

三、超参数调优

超参数是定义模型整体结构和学习过程的参数,也可将超参数理解为模型的元参数。超参数不同于模型的实际参数,后者是在训练过程中学习的(如模型的权重),而超参数无法学习——我们需要使用各种方法对他们进行调优,以提高模型性能。
为更好地理解这个问题,下面将以一种更简单的方式来看超参数的定义。在设计一个深度神经网络时,模型的架构是由一些高级元件定义的。这些元件可能是一层中的神经元数量、隐藏层的数量、激活函数、优化器、架构学习率、历元数、批尺寸等。所有这些参数都一并用于设计神经网络,它们对模型的学习过程和最终性能具有巨大影响。这些参数是无法训练的;实际上,它们需要根据经验和判断进行选择。定义模型整体架构的参数统称为超参数。选择正确的超参数是一个密集的迭代过程,但它会随着经验的积累而变得容易起来。用不同的超参数值进行实验以改进整个模型性能的过程,称为模型调优或超参数调优。

3.1 深度学习中的超参数

3.1.1 层中的神经元数量

对于大多数使用表格式横截面数据的分类和回归应用场景来说,深度神经网络可通过调整网络的宽度(即一层中神经元的数量)实现鲁棒性。通常,选定第一层神经元数目的简单经验法则是参考输入维度的数目。如果给定的训练数据集中输入维的最终数量(这里也包括经独热编码过得特征)是x,那么神经元的数量至少应为2的幂中最接近2x的值。假设训练数据集中有100个输入维度,则最好从2×100=200开始,取2的幂中最接近200的值,即256。将神经元的数量设为在2的幂是有效果的,有助于提高网络的计算速度。同样,神经元数量的最佳选择也是8、16、32、64等2的幂数,根据输入维度的数量,取最接近其2倍大小的值。

3.1.2 层的数量

通常仅增加少数几个层就能提高模型性能(至少会有少量提高)。但问题是随着层数的增加,训练时间和计算量也会增加。需要执行更多的历元才能得到理想结果。较深层的网络有时是需要的。
如果采用了一个非常大的网络,例如超过20层,可尝试采用一种缩减架构(即随着深度的增加逐渐减少每一层中神经元的数量)。因此,如果采用了30层的架构,每层有512个神经元,应尝试慢慢减少层中的神经元数量。改进的架构如下:前8层有512个神经元,接下来的8层有256个神经元,再接下来的8层有128个神经元,以此类推。对于最后一个隐藏层(不是输出层),尝试将神经元的数量保持在输入大小的30%-40%左右。
或者,如果要采用较宽的网络(即不减少较低层中神经元的数量),则必须使用L2正则化,或使用丢弃率约为30%的丢弃层。这将使得过拟合出现概率降低。

3.1.3 历元数

有时仅增加模型训练的历元数就可获得更好的结果,尽管这以增加计算和训练时间为代价。

3.1.4 权重初始化

初始化网络的权重也会对整体性能产生巨大影响。好的权重初始化技术不仅可以加速训练过程,而且可以避免模型训练过程中的死锁。默认情况下,Keras框架使用Glorot均匀初始化,也称为Xavier均匀初始化,但可根据需要进行更改。
可使用内核初始化参数来初始化一个层的权重,也可以使用偏差初始化来初始化该层的偏差。其他常用的选项有He Normal(He正态)和He Uniform(He均匀)初始化以及Lecun Normal(Lecun正态) Lecun Uniform(Lecun均匀)初始化。在Keras中还有其他很多选项,但前面提到的这些是最常用的。下面的代码片段展示了一个使用random_uniform参数初始化深度神经网络某一层权重的示例。

from keras import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(64,activation="relu", input_dim = 32, kernel_initializer = "random_uniform",bias_initializer = "zeros"))
model.add(Dense(1,activation="sigmoid"))

3.1.5 批尺寸

采用适当的批尺寸总是有助于获得平滑的模型学习过程。无论数据集大小和样本数量如何,32或64的批尺寸在大多数情况下都可以实现平滑的学习曲线。即使在硬件环境拥有大量RAM内存来容纳更大的批尺寸的情况下,仍然建议使用32或64的批尺寸。

3.1.6 学习率

学习率是在优化算法的背景下定义的。它定义了每一步优化的长度,或者简单地说,定义了在每轮选代中对权重进行更新的大小。本文中忽略了对学习率的设置或更改,因为本书使用了各类优化算法的默认值。以Adam算法为例,其默认值为0.001,这也是大多数场景的最佳选择。然而,某些特殊情况下也可能遇到这样的应用场景,在其中使用较低或者稍高一点的学习率可能效果更好。

3.1.7 激活函数

对于神经元的激活函数,可有很多选择。大多数情况下,ReLU都非常适用。几乎任何情况都可以使用ReLU作为任何用例的激活函数,并获得满意的结果。在ReLU可能不会产生良好结果的情况下,尝试用PReLU进行实验是很不错的选择。

3.1.8 优化

与激活函数类似,神经网络的优化算法也有相当多的选择。虽然最推荐的算法是Adam,但是在Adam可能无法为架构提供最佳结果的场景中,也可以尝试采用Adamax和Nadam优化器。对于那些很少更新参数的架构(如词向量wordembedding,最常用于自然语言处理技术中)来说,Adamax通常是更好的选择。

3.2 超参数调优方法

到目前为止,本文已经讨论了可用于深度学习模型的各种超参数,还研究了一般情况下最推荐的选项。然而,根据数据和问题类型为超参数选择最合适的值,更像是一门艺术。这门艺术也是艰辛而漫长的。深度学习中的超参数调优过程几乎总是缓慢而耗费资源。但是,根据选择超参数值和进一步调优模型性能的方式,可以大致将不同类型的调优方法分为四大类:手工搜索;网格搜索;随机搜索;贝叶斯优化。

3.2.1 手工搜索

顾名思义,手工搜索以完全手动方式为深度学习模型中所需的超参数选择最佳候选值。这种方法要求具有训练网络方面的非凡经验,通过最少的实验次数为所有期望的超参数获得正确的候选值集合。在对其拥有充足使用经验的情况下,这种方法通常是非常有效的。手动搜索的最佳途径,就是简单地利用给定超参数的所有推荐值,然后开始训练网络。这样得到的结果可能不是最好的,但肯定不是最差的。对于使用手工搜索的新手来说,尝试一些风险最低的超参数候选值是一个很好的起点。

3.2.2 网格搜索

在网格搜索方法中,可对超参数的一系列已定义值当中的所有可能组合进行实验。“网格”这个名字正是来源于每个超参数给出的候选值之间所形成的网格状组合。下图是一个逻辑网格如何查找三个超参数的示例视图,其中每个超参数有三个不同的值。

该方法将尝试为前面所示的每个超参数组合开发一个模型。图中的x表示将按照该位置所指定的超参数值来开发模型。例如,对于学习率0.1,其对应垂直列表示学习率取0.1时,分别使用不同的优化器值和批尺寸所开发的不同模型。类似地,如果查看超参数batch-size=32的水平行,则行中所有单元格中的x表示batch-size取32 时,使用不同学习率和优化器值所开发的不同模型。因此,在一个只有3个超参数、每个超参数有3个值的网格中,我们不必考虑开发太多模型。但如果要开发特别大的网络,并使用较大的训练数据样本,这个过程将是痛苦而漫长的。这种方法的优点在于,它给出了其所定义的超参数网格中的最佳模型。然而,其缺点在于,如果网格中本来就没有很好的选择,那么模型也不会是最好的。它只是简单地假定:研究这个模型的科学家很清楚哪些组合可能是给定超参数的最佳候选。
Keras没有直接提供对模型执行网格搜索调优的方法。不过,可以使用一个自定义的for循环对给定的训练值进行选代;或使用Keras提供的sklearn包装器将模型打包到sklearn类型对象中,然后利用sklearn中的网格搜索方法来获取结果。
下面的代码片段展示了通过使用虚拟模型的Keras包装器从sklearn包中调用网格搜索的方法。

from keras import Sequential
from sklearn.model_selection import GridSearchCV
from keras.wrappers.scikit_learn import KerasClassifier
from keras.layers import Dense
import numpy as np# 为3个特征和1000个样本生成虚拟数据
x_train = np.random.random((1000, 3))# 为1000个样本生成虚拟结果:1或0
y_train = np.random.randint(2, size=(1000, 1))# 创建一个返回编译DNN模型的python函数
def create_dnn_model():model = Sequential()model.add(Dense(12, input_dim=3, activation='relu'))model.add(Dense(1, activation='sigmoid'))model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])return model # 使用Keras包装器将模型封装为sklearn对象
model = KerasClassifier(build_fn=create_dnn_model)# 定义网格搜索参数
batch_size = [32,64,128]
epochs = [15, 30, 60]# 创建一个包含参数的列表
param_grid =  {"batch_size":batch_size, "epochs":epochs}
#Invoke the grid search method with the list of hyperparameters
grid_model = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1)
# 训练模型
grid_model.fit(x_train, y_train)# 提取网格搜索的最优模型
best_model = grid_model.best_estimator_

3.2.3 随机搜索

随机搜索是网格搜索的一种改进方案。在随机搜索中,可从分布中为超参数(例如学习率)随机选择一个值,而不是从一个已定义的数值列表中选择一个值。不过,该方法仅适用于数值型超参数。因此,相对于逐个尝试0.1、0.01或0.001、的学习率,随机搜索可以从我们为属性所定义的分布中随机选取学习率的值。这样,学习率参数就有更大的值域可供实验,从而获得更好性能的机会也更大。该方法通过引入随机性,克服了在限定范围内人工猜测超参数最佳值的缺陷,为更好的超参数选择带来了可能。

四、模型部署

4.1 定制测试数据

下面用一个例子来理解该过程。假设你设计并开发了一个深度神经网络,它使用监督分类模型来预测信用卡交易是“真实的”还是“欺诈的”。在开发模型时,你可以访问客户数据、交易数据、销售点属性、时间相关属性、地理属性等。所有这些数据点都存在于不同的数据源中。为了开发模型,你将努力从这些不同的源头获取数据,开将其整合为统一的形式。对于你的实验,该过程实际上是一次性工作。但当模型在现实中运行时,就需要对整个过程进行设计,使其能够重复获得给定客户的数据以及来自不同数据源的所有其他必要属性,整合它们并转换为指定的形式供模型预测,然后进行大规模推断。设想一家大型银行,它的实时应用程序要同时处理全球范围内数以千计的交易。为了利用模型进行推断而获取据需要十分可靠的工程原理,以使模型能够无故障地运行。
要建立能够实时计算查询请求的数据库或集群/节点,其设计原则必须考虑数据工程和需要对训练数据集所做的转换,因为每一次要使用模型进行预测时都要执行这一完全相同的过程。这种动态定制数据以进行推断的过程本身就是一门完全不同的艺术,需要精细的工程构建。通常,数据科学家最不担心的就是这部分问题:“我们不用考虑这个问题,我们认为是软件和数据工程师的工作,不去管它就行了。”这种谬见迟早要被打破,必须建立起一种严肃的协调机制来恰当地解决这一迷局。两个团队,即数据科学家和软件工程师,应当携手合作来完成这项任务。数据科学家在理解软件工程师的需求(反之亦然)时所面临的困难,导致了行业中“机器学习工程师”新角色的出现。机器学习工程师是对这两个领域的交集有深刻理解的候选人。

4.2 将模型保存到内存

当见到到深度学习工程师连续几周在超级计算机上训练模型时,一点也不用感到惊讶。包含图像、音频和非结构化文本数据的现代深度学习模型会消耗大量的训练时间。在这种场景下,一个有用的措施应该是能够暂停并恢复深度模型的训练,并保存中间结果,这样执行到特定时间点的训练进程就不会被浪费。这可以通过一个简单的回调(Keras中的一个过程,可在不同的训练阶段应用于模型)来实现,它可以在一个定义好的节点之后将模型的权重以及模型结构保存到一个文件中。被保存的模型稍后可在任何想要恢复训练时再次导入,训练进程可以如期望的那样继续下去。我们需要做的就是在一个历元之后或当已获得最优模型时,注意保存模型的结构和权重。
下面的代码片段展示了在进行大量历元的训练期间保存模型最优权重的示例。

from keras.callbacks import ModelCheckpointfilepath = "ModelWeights-{epoch:.2f}-{val_acc:.2f}.hdf5"
checkpoint = ModelCheckpoint(filepath, save_best_only=True, monitor="val_acc")model.fit(x_train, y_train, callbacks=[checkpoint],epochs=100, batch_size=64)

可以看到,这段代码中使用想要的参数定义了一个callbacks对象,这里定义了什么时候保存模型,使用什么度量标准以及将模型保存到哪里。根据文件路径使用的命名约定,模型权重将存储到一个文件中,该文件的名称描述了历元数量和相应的精度度量。最后, callbacks对象将作为列表传递给模型的fit方法。
或者,可使用save_model方法在完成训练后保存整个模型,然后(可能是第二天)使用load_model方法将其加载到内存中。下面的代码片段展示了一个示例。

from keras.models import load_model
# 训练一个定义了代数目的模型
model.fit(x_train, y_train, epochs=100, batch_size=64)# 将整个模型保存
model.save('dnn_model.h5')  # 加载经过训练的模型进行预测
model = load_model('dnn_model.h5')

4.3 用新数据重新训练模型

将模型部署到生产环境中时,生态系统将持续生成更多数据,这些数据可用于再次训练模型。例如,对于信用卡欺诈用例,先期已使用100 000个样本训练模型,并获得了93%的准确率。此时若认为其性能已经足够开始实际运行,便可将模型部署到生产环境中。经过一个月的时间,模型从客户所做的新交易中可以获得额外的10000个样本。现在,就可以期望模型将这些新获得的数据利用起来,以进一步改进性能。为实现这一点,并不需要重新训练整个模型,而是可采用暂停然后继续的方法。此时需要做的就是使用已经训练好的模型权重,通过几个历元来传递和迭代新样本以提供额外的数据。模型已经习得的权重不需要处理,可以简单地使用暂停-恢复公式,然后继续处理增量数据。

4.4 在线模型

理解了模型的再训练过程后,可能会直接引起思考的一个问题是:应该以怎样的频率这样做:每天、每周或每月进行再训练是好方法吗?正确的方法是尽可能频繁地进行再训练。每当有新的数据点可用时,只要所需的计算不是瓶颈,增量地训练模型是没有害处的。一个好的方案是一旦有新一批样本可用就选代一个训练实例。因此,如果将batch_size设置为64,就可将模型训练自动化以摄入最新可用的一批数据;还可以通过建立自动化的软件架构,针对每一批新数据样本训练模型,进一步提高未来的预测性能。将模型性能保持在最佳状态的一种非常积极的方法是:增量地对每个新数据点进行训练,并将先前的样本作为批次的其余部分添加进来。这种方法需要大量的计算,而回报却很低。这种对每个新样本(而非一批新样本)进行超实时增量训练的方法通常是不推荐的。
这类模型当有新批次数据可用时总是会学习——称为在线模型。在线模型最常见的例子可以在手机上看到。像文本输入预测和自动纠错这样的功能会随着时间的推移而显著改进。如果你通常以某种特定的风格输入,比如把两种语言结合在一起,或者缩写几个单词,或者使用便语等,你就会发现手机非常积极地倾向于适应你的风格。这纯粹是因为手机后台的操作系统启动了在线模型不断学习和改进的机制。

4.5 以API形式交付模型

目前,要将模型作为服务交付给更大的软件栈,最佳方案是以API形式交付–这是非常有用和有效的,因为它完全摆脱了技术栈的要求。模型可以很容易地在软件生态系统中多样和复杂的组件集合之间实现协作,因而可以不那么操心开发模型的语言或框架。通常在开发机器学习或深度学习模型时,交付模型的选择仅由两个简单的点中的一个来驱动: 用软件工程师能够理解的语言构建模型;使用API。
虽然Python和Keras在当今的现代技术栈中几乎是通用的,但是仍然可以有一些例外,因为某项技术可能并不容易集成。因此,我们总是可以选择API作为深度模型的首选部署模式,并适当地定义API的数据需求和调用风格。要将服务部署为API,有两个非常有用且易于操作的选项:可以使用Flask(一种轻量级的Python Web 框架)或Amazon Sagemaker(在 AWS上可用),还有其他值得去探索的选择项。Keras博客上有一篇非常好的关于如何使用Flask部署深度学习模型的文章。

4.6 组件集成


当然,这只是对生成模型的一种过于简化的解释。当模型的规模、数据量、安全性和可用性等方面需求水涨船高时,很多事情都会发生变化。前面的视图演示了一个适用于小型软件的架构。一旦完成了模型构建过程,就可以将大部分逻辑设置为预测、调整数据、定期测量性能、自动在线学习、日志记录等,并将其放入一个小型的Flask应用程序中,然后在服务器上运行并将其部署为API。软件客户端可以是Web 客户端,也可以是运行在同一服务器上的另一个服务,它能通过以预定义的方式调用API来利用模型。关于深度学习模型的大规模部署、动态定制数据的艺术、在线学习的实现、服务的整体扩展等方面的讨论,需要读者的书籍。

五、学习方向

5.1 卷积神经网络(CNN)

CNN是一类用于计算机视觉应用场景的深度学习算法,如对图像或视频进行分类以及检测图像(甚至图像某个区域)中的对象。CNN算法是计算机视觉领域的一项重大突破,因为与当时的其他流行技术相比,它只需要很少的图像处理,并且表现得也非常出色。CNN在图像分类方面的性能改进是显著的。在Keras中,构建CNN的过程也得到了简化,所有的逻辑组件都被巧妙地抽象出来。Keras提供了CNN层,开发CNN模型的整个过程与前面在开发回归和分类模型时所学的非常相似。
接着将通过一个小示例的实现来简要介绍该过程,以下代码段展示了CNN类似于Hello World 程序的实现。我们将使用MNIST数据(即一个包含手写数字的图像集合),将数据中的图像分类为[0,1,2,3,4,5,6,7,8,9]中的一个数字, Keras的数据集模块已提供了该数据。尽管这个主题是全新的,但下面代码片段中的注释将提供该模型设计的基本思想。

import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.utils import np_utils# 从Keras数据集加载数据
(x_train, y_train), (x_test, y_test) = mnist.load_data()# 定义样本的身高、体重和数量
# 每个图像是一个28 x 28的1通道矩阵
training_samples, height, width = x_train.shape
testing_samples,_,_ = x_test.shapeprint("Training Samples:",training_samples)
print("Testing Samples:",testing_samples)
print("Height: "+str(height)+" x Width:"+ str(width))输出结果:
Training Samples: 60000
Testing Samples: 10000
Height: 28 x Width:28# 让我们看一下训练数据中的示例图像
plt.imshow(x_train[0],cmap='gray', interpolation='none')

# 我们现在必须将图像数据设计成正确的形式
# 对于 CNN,我们需要高度 x 宽度 X 通道窗体中的数据
# 由于图像是灰度的,我们将使用通道 = 1
channel =1
x_train = x_train.reshape(training_samples, height, width,channel).astype('float32')
x_test = x_test.reshape(testing_samples, height, width, channel).astype('float32')# 为了改进训练过程,我们需要标准化或规范化这些值
# 对于所有值,我们可以使用简单除以256来实现这一点。
x_train = x_train/255
x_test =x_test/255# 总位数 = 10
target_classes = 10# 数字0-9,所以十类
n_classes = 10# 将整数标签转换为一个热向量
y_train = np_utils.to_categorical(y_train, n_classes)
y_test = np_utils.to_categorical(y_test, n_classes)# 设计CNN模型
model = Sequential()
model.add(Conv2D(64, (5, 5), input_shape=(height,width ,1), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(n_classes, activation='softmax'))# 编译模型
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])# 拟合模型
model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10, batch_size=200)

输出结果:
Epoch 1/10
300/300 [——————————————————] - 76s 253ms/step - loss: 0.2229 - accuracy: 0.9359 - val_loss: 0.0564 - val_accuracy: 0.9823
Epoch 2/10
300/300 [——————————————————] - 79s 265ms/step - loss: 0.0605 - accuracy: 0.9815 - val_loss: 0.0391 - val_accuracy: 0.9867
Epoch 3/10
300/300 [——————————————————] - 92s 308ms/step - loss: 0.0442 - accuracy: 0.9864 - val_loss: 0.0312 - val_accuracy: 0.9896
Epoch 4/10
300/300 [——————————————————] - 89s 297ms/step - loss: 0.0350 - accuracy: 0.9889 - val_loss: 0.0302 - val_accuracy: 0.9899
Epoch 5/10
300/300 [——————————————————] - 87s 289ms/step - loss: 0.0291 - accuracy: 0.9909 - val_loss: 0.0268 - val_accuracy: 0.9920
Epoch 6/10
300/300 [——————————————————] - 94s 315ms/step - loss: 0.0248 - accuracy: 0.9922 - val_loss: 0.0253 - val_accuracy: 0.9914
Epoch 7/10
300/300 [——————————————————] - 94s 315ms/step - loss: 0.0219 - accuracy: 0.9928 - val_loss: 0.0247 - val_accuracy: 0.9913
Epoch 8/10
300/300 [——————————————————] - 93s 310ms/step - loss: 0.0194 - accuracy: 0.9938 - val_loss: 0.0316 - val_accuracy: 0.9904
Epoch 9/10
300/300 [——————————————————] - 93s 310ms/step - loss: 0.0180 - accuracy: 0.9940 - val_loss: 0.0283 - val_accuracy: 0.9906
Epoch 10/10
300/300 [——————————————————] - 98s 328ms/step - loss: 0.0162 - accuracy: 0.9946 - val_loss: 0.0211 - val_accuracy: 0.9930

# 最后,让我们评估模型性能
metrics = model.evaluate(x_test, y_test, verbose=0)
for i in range(0,len(model.metrics_names)):print(str(model.metrics_names[i])+" = "+str(metrics[i]))

输出结果:
loss = 0.02110256254673004
accuracy = 0.9929999709129333

当图像的大小和要预测的类别数量增加时,就会出现并发问题。要更深入地了解CNN的工作原理,可参考以下几个有趣的博客:
https://adeshpande3.github.io/adeshpande3.github.io/A-Beginner’s-Guide-ToUnderstandingConvolutional-Neural-Networks/
要进行更多实验并研究一些非常酷且易于理解的示例,可以查看一些与CNN用例相关的流行git资源库。
https://github.com/pranoyr/image-classification

5.2 递归神经网络(RNN)

研究完CNN后,下一步将开始研究深度学习中的RNN,即众所周知的“序列模型”。这个名称之所以流行,是因为RNN利用了序列信息。到目前为止,我们已研究过的所有深度神经网络在处理数据时均建立在任意两个训练样本之间没有关系的假设基础上。但对很多问题而言,这是一个可用数据解决的问题。仔细想一下iOS 或Android手机中的文字联想输入功能,下一个单词的预测高度依赖于最新输入的几个单词,这就是序列模型的用武之地。RNN也可以理解为具有记忆的神经网络,它将某一层连接到自身,从而可以同时访问两个或多个连续的输入样本,以得到最终输出结果。这个特性是RNN特有的,随着其研究的兴起,它在自然语言理解领域取得了惊人的成功。所有传统的自然语言处理技术现在都可通过应用RNN得到显著改进。聊天机器人的兴起,短信自动纠错功能的改进,电子邮件客户端和其他应用程序的回复建议,以及机器翻译(例如,从源语言到目标语言的文本翻译,其中谷歌翻译是一个经典的例子)都推动了RNN的运用。还有不同类型的LSTM(长短时记忆)网络,它们克服了现有RNN架构的限制,将自然语言处理相关任务的性能提高了一个档次。最流行的RNN 是LSTM和GRU(门控递归单元)网络。
类似于介绍CNN的方式,下面将介绍RNN/LSTM网络的一个简单示例实现(等同于Hello World)。下面的代码段对Keras中的IMDB电影评论数据集执行二元分类。在本示例中,提供了用户评论(文本日期)和与之相关的Positive(正)或Negative(负)结果。

# 导入必要的软件包
from keras.datasets import imdb
from keras.models import Sequential
from keras.layers import Dense, LSTM
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence# 为不同字数设置最大上限
top_words = 5000
# 从 keras 数据集加载训练和测试数据
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=top_words)# 由于每个文本的长度会有所不同
# 我们将填充序列(即文本)以获得统一的长度
max_text_length = 500
x_train = sequence.pad_sequences(x_train, maxlen=max_text_length)
x_test = sequence.pad_sequences(x_test, maxlen=max_text_length)# 设计网络
embedding_length = 32
model = Sequential()
model.add(Embedding(top_words, embedding_length, input_length=max_text_length))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))# 编译模型
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])# 拟合模型
model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=3, batch_size=64)# 评估测试数据集的准确性
scores = model.evaluate(x_test, y_test, verbose=0)
print("Accuracy:",scores[1])

输出结果:
Train on 25000 samples, validate on 25000 samples
Epoch 1/3
25000/25000 [——————————————————] - 226s 9ms/step - loss: 0.5312 - acc: 0.7176 - val_loss: 0.5133 - val_acc: 0.7521
Epoch 2/3
25000/25000 [——————————————————] - 219s 9ms/step - loss: 0.3137 - acc: 0.8710 - val_loss: 0.3116 - val_acc: 0.8737
Epoch 3/3
25000/25000 [——————————————————] - 223s 9ms/step - loss: 0.2616 - acc: 0.8986 - val_loss: 0.3872 - val_acc: 0.8277

Accuracy: 0.8277

准确率随着训练历元数的增加和架构的改进而提高,为了全面了解RNN的工作原理,可浏览以下几个博客:
https://colah.github.io/posts/2015-08-Understanding-LSTMs/
https://medium.com/mlreview/understanding-Istmand-its-diagrams-37e2f46f1714
https://towardsdatascience.com/illustratedguide-to-Istms-and-gru-s-a-step-by-step-explanation-44e9eb85bf21
若要进行更多实验并对一些非常酷的示例进行研究,可以查看一些与LSTM用例相关的流行git资源库。以下是一些相关链接:
https://github.com/philiparvidsson/LSTM-Text-Generation
https://github.com/danielefranceschi/lstm-climatological-time-series
https://github.com/shashankbhatt/Keras-LSTM-Sentiment-Classifcation

本系列所有内容基于《Keras深度神经网络(Learn keras for deep neural networks)》这本书,供大家交流学习,传送门

深度神经网络之Keras(三)——正则化、超参数调优和学习方向相关推荐

  1. python minimize_简单三步实现Python脚本超参数调优(附代码)

    作者:Jakub Czakon, Neptune.ai 翻译:陈之炎 校对:和中华 本文约1500字,建议阅读5分钟. Python机器学习模型建立起来之后,如何对它的性能进行优化?按照本指南中的三个 ...

  2. 独家 | 简单三步实现Python脚本超参数调优(附代码)

    作者:Jakub Czakon, Neptune.ai 翻译:陈之炎 校对:和中华 本文约1500字,建议阅读5分钟. Python机器学习模型建立起来之后,如何对它的性能进行优化?按照本指南中的三个 ...

  3. DL之模型调参:深度学习算法模型优化参数之对LSTM算法进行超参数调优

    DL之模型调参:深度学习算法模型优化参数之对LSTM算法进行超参数调优 目录 基于keras对LSTM算法进行超参数调优 1.可视化LSTM模型的loss和acc曲线

  4. 深度学习-超参数调优

    在机器学习中有很多调优的方式机器学习--超参数调优,深度学习中也存在同样的方式,接下来,介绍一下深度学习框架里边的自动调参模块. 1. 基于Tensorflow的Keras tuner 官方教程如下: ...

  5. 一文详解超参数调优方法

    ©PaperWeekly 原创 · 作者|王东伟 单位|Cubiz 研究方向|深度学习 本文介绍超参数(hyperparameter)的调优方法. 神经网络模型的参数可以分为两类: 模型参数,在训练中 ...

  6. python代码设置超参数_超参数调优总结,贝叶斯优化Python代码示例

    本文介绍超参数(hyperparameter)的调优方法. 神经网络模型的参数可以分为两类,模型参数,在训练中通过梯度下降算法更新: 超参数,在训练中一般是固定数值或者以预设规则变化,比如批大小(ba ...

  7. tf.saved_model.save模型导出、TensorFlow Serving模型部署、TensorBoard中的HParams 超参数调优

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 4.11 综合案例:模型导出与部署 学习目标 目标 掌握Ten ...

  8. 开源sk-dist,超参数调优仅需3.4秒,sk-learn训练速度提升100倍

    作者 | Evan Harris 译者 | Monanfei 编辑 | Jane  出品 | AI科技大本营(ID:rgznai100) [导语]这篇文章为大家介绍了一个开源项目--sk-dist.在 ...

  9. 机器学习模型评估与超参数调优详解

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:李祖贤  深圳大学,Datawhale高校群成员 机器学习分为两类 ...

最新文章

  1. 青少年编程竞赛交流群周报(第043周)
  2. Silverlight学习之——如何在 Silverlight 中使用 Deep Zoom
  3. Go 语言编程 — encoding/json 库
  4. TCP滑动窗口和拥塞控制机制
  5. binary_sort 二叉树
  6. java静态变量,静态代码块,普通代码块,构造函数加载顺序
  7. 无人承运平台系统流程图
  8. [转] 计算机视觉领域稍微容易中的期刊
  9. makefile:5: *** missing separator. Stop.
  10. 计算机图形学前沿领域的设想,计算机图形学
  11. .NET——NPOI操作excel
  12. Vim配置Java IDE
  13. 官方开源的安卓客户端
  14. 【Java开发】之配置文件的读取
  15. fftshift有什么用?MATLAB做FFT后为什么还要fftshift?
  16. Load Runner:了解软件安装后目录http://www.boobooke.com/bbs/thread-1959-1-1.html
  17. 3种常见的统计学方法
  18. 闲谈mac地址学习以及IVL/SVL
  19. 在Composure去除掉对体积云和雾的捕获
  20. 电子招标采购系统源码之什么是电子招投标系统?

热门文章

  1. python(2048)
  2. Hbuilder 连接夜神模拟器
  3. 微信原生组件|基于小程序实现音视频通话
  4. 写作的意义,从一枚勋章开始
  5. 8086汇编工作环境_[C语言]什么是编辑器和编译器,什么是集成开发环境?编译原理又是什么?
  6. 拉升股价套利为饵狂骗157万 广州邦臣机械气化炉警方:防理财诈骗
  7. Firefox/Chrome渗透测试插件推荐
  8. IMP-00003 ORA-00942 IMP-00023 IMP-00000
  9. css样式 向下补白,div+css[3]:css中边框border与补白padding属性设置
  10. 计算机网络中的OSI模型和TCP/IP模型