写点什么

深度学习 keras 像搭积木般构建神经网络模型

用户头像
AI_robot
关注
发布于: 2021 年 03 月 31 日

用 Keras 搭建神经网络的步骤:

搭建 Keras 模型

深度学习框架 Keras——像搭积木般构建神经网络,主要分为 7 个部分,每个部分只需要几个 keras API 函数就能实现,用户即可像搭积木般一层层构建神经网络模型。

1. 创建模型 Create model

2. 添加层级 Add Layer

3. 模型编译 Compile

4. 数据填充 Fit

5. 模型评估 Evaluate

6. 模型预测 Predict

7. 模型保存 Save model

下面章节会对每一部分具体来介绍。。。

1 创建模型

Keras 中主要有三类模型:Sequential model, Functional model, Subclass model

模型分类

  • Sequenctial API: 顺序模型是从头到尾的线性不分叉的结构使用单个输入、输出构建简单模型。

  • Function API: 是构建 Keras 模型最流行的方法。它允许多个输入、多个输出、分支和层共享。

  • 模型子类化:是为需要完全控制模型、层和训练过程的高级开发人员设计的。你需要创建一个定义模型的自定义类,而且你可能不需要它来执行日常任务。但是,如果你是一个有实验需求的研究人员,那么模型子类化可能是最好的选择,因为它会给你所有你需要的灵活性。

2 添加网络层

Layers 是神经网络基本构建块。一个 Layer 包含了 tensor-in/tensor-out 的计算方法和一些状态,并保存在 TensorFlow 变量中(即 layers 的权重 weights)。Layers 主要分为 6 个类别,基础层,核心层,卷基层,池化层,循环层,融合层。

2.2 核心网络层

核心层是最常用的层,涉及到数据的转换和处理的时候都会用到这些层。

2.2.1 Dense

Dense 层就是所谓的全连接神经网络层,简称全连接层。全连接层中的每个神经元与其前一层的所有神经元进行全连接。

2.2.2 Activation

将激活函数应用于输出。输入信号进入神经元后进行的运算处理。

sigmoid、tanh、ReLU、softplus 的对比曲线如下图所示:

激活函数:


2.2.3 Dropout

Dropout 在训练中每次更新时,将输入单元的按比率随机设置为 0,这有助于防止过拟合。未设置为 0 的输入将按 1 /(1-rate)放大,以使所有输入的总和不变。

2.2.4 Flatten

将输入展平。不影响批量大小。注意:如果输入的形状是(batch,)没有特征轴,则展平会增加通道尺寸,而输出的形状是(batch, 1)。

2.2.5 Reshape

将输入重新调整为特定的尺寸

2.2.6 Lambda

将任意表达式封装为 Layer 对象。在 Lambda 层,以便在构造模型时可以使用任意 TensorFlow 函数。 Lambda 层最适合简单操作或快速实验。 Lambda 层是通过序列化 Python 字节码来保存的。

2.2.7 Masking

使用覆盖值覆盖序列,以跳过时间步。

对于输入张量的每一个时间步(张量的第一个维度),如果所有时间步中输入张量的值与 mask_value 相等,则将在所有下游层中屏蔽(跳过)该时间步。如果任何下游层不支持覆盖但仍然收到此类输入覆盖信息,会引发异常。

2.2.8 Embedding

Embedding 是一个将离散变量转为连续向量表示的一个方式。该层只能用作模型中的第一层。

Embedding 有以下 3 个主要目的: 在 embedding 空间中查找最近邻,这可以很好的用于根据用户的兴趣来进行推荐。 作为监督性学习任务的输入。 用于可视化不同离散变量之间的关系.

2.3 卷积层 Convolution layers

由维基百科的介绍我们可以得知,卷积是一种定义在两个函数(𝑓跟𝑔)上的数学操作,旨在产生一个新的函数。那么𝑓和𝑔的卷积就可以写成𝑓∗𝑔,数学定义如下:

卷积定义

对应到不同方面,卷积可以有不同的解释:𝑔 既可以看作我们在深度学习里常说的核(Kernel),也可以对应到信号处理中的滤波器(Filter)。而 𝑓 可以是我们所说的机器学习中的特征(Feature),也可以是信号处理中的信号(Signal)。f 和 g 的卷积 (𝑓∗𝑔)就可以看作是对𝑓的加权求和。

一维时域卷积操作:

时域卷积

二维图像卷积操作:

图像卷积

卷积运算的目的是提取输入的不同特征,第一层卷积层可能只能提取一些低级的特征如边缘、线条和角等层级,更多层的网路能从低级特征中迭代提取更复杂的特征。

2.3.1 Conv1D

一维卷积层(即时域卷积),用以在一维输入信号上进行邻域滤波。

2.3.2 Conv2D

2D 卷积层 (例如对图像的空间卷积)。

2.3.3 Conv3D

3D 卷积层(例如体积上的空间卷积)

2.3.4 SeparableConv1D

深度可分离 1D 卷积。该层执行分别作用在通道上的深度卷积,然后是混合通道的逐点卷积。 如果 use_bias 为 True 并提供了一个偏差初始值设定项,则它将偏差向量添加到输出中。 然后,它可选地应用激活函数以产生最终输出。

2.3.5 SeparableConv2D

深度可分离的 2D 卷积。可分离的卷积包括首先执行深度空间卷积(它分别作用于每个输入通道),然后是点向卷积,它将混合所得的输出通道。 depth_multiplier 参数控制在深度步骤中每个输入通道生成多少个输出通道。

直观上,可分离的卷积可以理解为将卷积内核分解为两个较小内核的一种方式,或者是 Inception 块的一种极端版本。

2.3.6 Conv2DTranspose

转置卷积层 (有时被成为反卷积)。对转置卷积的需求一般来自希望使用 与正常卷积相反方向的变换,将具有卷积输出尺寸的东西 转换为具有卷积输入尺寸的东西, 同时保持与所述卷积相容的连通性模式。

2.4 池化层 Pooling layers

池化层是模仿人的视觉系统对数据进行降维,用更高层次的特征表示图像。实施池化的目的:降低信息冗余;提升模型的尺度不变性、旋转不变性。 防止过拟合。

通常有最大池化层,平均池化层。

  • 最大池化层对每一个小区域选最最大值作为池化结果

  • 平均池化层选取平均值作为池化结果。


池化层有三种形态:1D 用于一维数据,2D 一般用于二维图像数据,3D 带时间序列数据的图像数据

2.5 循环层 Recurrent layers

循环神经网络(Recurrent Neural Network, 简称 RNN),循环神经网络的提出便是基于记忆模型的想法,期望网络能够记住前面出现的特征,并依据特征推断后面的结果,而且整体的网络结构不断循环,因此得名为循环神经网络。

2.5.1 LSTM

长短期记忆网络(Long-Short Term Memory,LSTM)论文首次发表于 1997 年。由于独特的设计结构,LSTM 适合于处理和预测时间序列中间隔和延迟非常长的重要事件。

2.5.2 BRU

GRU门控循环单元- Cho et al. 2014.

在 LSTM 中引入了三个门函数:输入门、遗忘门和输出门来控制输入值、记忆值和输出值。而在 GRU 模型中只有两个门:分别是更新门和重置门。与 LSTM 相比,GRU 内部少了一个”门控“,参数比 LSTM 少,但是却也能够达到与 LSTM 相当的功能。考虑到硬件的计算能力和时间成本,因而很多时候我们也就会选择更加”实用“的 GRU。

3 Compile 编译

在训练模型之前,我们需要配置学习过程,这是通过 compile 方法完成的。

他接收三个参数:优化器 optimizer, 损失函数 loss, 评估标准 metrics


#Compile函数定义:
compile(
optimizer='', loss=None, metrics=None, loss_weights=None,
weighted_metrics=None, run_eagerly=None, **kwargs
)
复制代码
  • 优化器 optimizer:它可以是现有优化器的字符串标识符,如 rmsprop 或 adagrad,也可以是 Optimizer 类的实例。

  • 损失函数 loss:模型试图最小化的目标函数。它可以是现有损失函数的字符串标识符,如 categorical_crossentropy 或 mse,也可以是一个目标函数。

  • 评估标准 metrics:对于任何分类问题,你都希望将其设置为 metrics = ['accuracy']。评估标准可以是现有的标准的字符串标识符,也可以是自定义的评估标准函数。

3.1 优化器 optimizer

优化器 会将计算出的梯度应用于模型的变量,以使 loss 函数最小化。您可以将损失函数想象为一个曲面(见图 3),我们希望通过到处走动找到该曲面的最低点。梯度指向最高速上升的方向,因此我们将沿相反的方向向下移动。我们以迭代方式计算每个批次的损失和梯度,以在训练过程中调整模型。模型会逐渐找到权重和偏差的最佳组合,从而将损失降至最低。损失越低,模型的预测效果就越好。

优化算法在三维空间中随时间推移而变化的可视化效果。

(来源: 斯坦福大学 CS231n 课程,MIT 许可证,Image credit: Alec Radford)

optimizer.gif

Adadelta

一种随机梯度下降方法,它基于每个维度的自适应学习率来解决两个缺点:整个培训期间学习率的持续下降需要手动选择的整体学习率

Adagrad

Adagrad 是一种优化器,具有特定于参数的学习率,相对于训练期间更新参数的频率进行调整。 参数接收的更新越多,更新越小。

Adam

Adam优化是一种基于随机估计的一阶和二阶矩的随机梯度下降方法。

根据 Kingma 等人的说法(2014 年),该方法“计算效率高,内存需求少,不影响梯度的对角线重缩放,并且非常适合数据/参数较大的问题”。

Adamax

Adamax 优化是基于无穷范数的 Adam 的变体。 默认参数遵循本文提供的参数。 Adammax 有时优于 Adam,特别是在带有嵌入 Embedding 的模型中

FTRL

实现FTRL算法的优化程序。请参阅本文的算法。此版本同时支持在线 L2(上面的论文中给出了 L2 损失)和收缩类型 L2(这是对损失函数增加 L2 损失)的支持。

RMSprop

该优化器通常是面对递归神经网络时的一个良好选择。

RMSprop 的要旨是:

  • 保持梯度平方的移动(折后)平均值

  • 将梯度除以该平均值的根

  • RMSprop 的此实现使用简单动量,而不使用 Nesterov 动量。

  • 居中版本还保留了梯度的移动平均值,并使用该平均值来估计方差。

  • momentum 即动量,它模拟的是物体运动时的惯性,即更新的时候在一定程度上保留之前更新的方向,同时利用当前 batch 的梯度微调最终的更新方向。这样一来,可以在一定程度上增加稳定性,从而学习地更快,并且还有一定摆脱局部最优的能力

Nesterov

Nesterov 版本 Adam 优化器。 正像 Adam 本质上是 RMSProp 与动量 momentum 的结合, Nadam 是采用 Nesterov momentum 版本的 Adam 优化器。

SGD

随机梯度下降法,支持动量参数,支持学习衰减率,支持 Nesterov 动量。


3.2 损失函数 losses

损失函数的目的是计算模型在训练过程中寻求最小化。损失函数是模型优化的目标,所以又叫目标函数、优化评分函数。

损失函数分为三大类:概率损失,回归损失,合页损失。

BinaryCrossentropy

计算真实标签和预测标签之间的交叉熵损失。当只有两个标签类别(假定为 0 和 1)时,请使用此交叉熵损失。

CategoricalCrossentropy

计算标签和预测之间的交叉熵损失。有两个或多个标签类别时,请使用此交叉熵损失函数。

CategoricalHinge

计算 y_true 和 y_pred 之间的分类合页损失。

CosineSimilarity

计算标签和预测之间的余弦相似度。

请注意,它是介于-1 和 0 之间的负数,其中 0 表示正交性,而值接近-1 则表示更大的相似性。 这使得它在尝试使预测值与目标值之间的接近度最大化的情况下可用作损失函数。

MeanAbsoluteError

计算标签和预测之间的绝对差的平均值。loss = abs(y_true - y_pred)

MeanAbsolutePercentageError

计算 y_true 和 y_pred 之间的平均绝对百分比误差。loss = 100 * abs(y_true - y_pred) / y_true

MeanSquaredError

计算标签和预测之间的误差平方的平均值。loss = square(y_true - y_pred)


3.3 评估标准 metrics

评价函数用于评估当前训练模型的性能。性能评估模块提供了一系列用于模型性能评估的函数,这些函数在模型编译时由 metrics 关键字设置 性能评估函数类似与目标函数, 只不过该性能的评估结果讲不会用于训练。

可以通过字符串来使用域定义的性能评估函数:

model.compile(loss='mean_squared_error',
optimizer='sgd',
metrics=['mae', 'acc'])
复制代码


Accuracy

计算预测等于标签的频率。

该度量创建两个局部变量,总计和计数,用于计算 y_pred 与 y_true 匹配的频率。 该频率最终以二进制精度返回:幂运算,将总数除以计数。

BinaryAccuracy

计算预测与二进制标签匹配的频率。该度量创建两个局部变量,总计和计数,用于计算 y_pred 与 y_true 匹配的频率。该频率最终以二进制精度返回:幂运算,将总数除以计数。

CategoricalAccuracy

计算预测与 one-hot 标签匹配的频率。该度量创建两个局部变量,总计和计数,用于计算 y_pred 与 y_true 匹配的频率。该频率最终以绝对精度返回:幂等运算,简单地将总数除以计数。

FalseNegatives

计算假阴性的数量。

FalsePositives

计算误报的数量。

Mean

计算给定值的(加权)平均值。

MeanAbsoluteError

计算标签和预测之间的平均绝对误差。

MeanSquaredError

计算 y_true 和 y_pred 之间的均方误差

4 训练模型 fit

为模型训练固定的 epochs(数据集上的迭代)。


# fit定义
fit(
x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None,
validation_split=0.0, validation_data=None, shuffle=True, class_weight=None,
sample_weight=None, initial_epoch=0, steps_per_epoch=None,
validation_steps=None, validation_batch_size=None, validation_freq=1,
max_queue_size=10, workers=1, use_multiprocessing=False
)
复制代码


  • x:输入数据。如果模型只有一个输入,那么 x 的类型是 numpy array,如果模型有多个输入,那么 x 的类型应当为 list,list 的元素是对应于各个输入的 numpy array

  • y:标签,numpy array

  • batch_size:整数,指定进行梯度下降时每个 batch 包含的样本数。训练时一个 batch 的样本会被计算一次梯度下降,使目标函数优化一步。

  • epochs:整数,训练终止时的 epoch 值,训练将在达到该 epoch 值时停止,当没有设置 initial_epoch 时,它就是训练的总轮数,否则训练的总轮数为 epochs - inital_epoch

  • verbose:日志显示,0 为不在标准输出流输出日志信息,1 为输出进度条记录,2 为每个 epoch 输出一行记录

  • callbacks:list,其中的元素是 keras.callbacks.Callback 的对象。这个 list 中的回调函数将会在训练过程中的适当时机被调用,参考回调函数

  • validation_split:0~1 之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个 epoch 结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split 的划分在 shuffle 之前,因此如果你的数据本身是有序的,需要先手工打乱再指定 validation_split,否则可能会出现验证集样本不均匀。

  • 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'。

  • initial_epoch: 从该参数指定的 epoch 开始训练,在继续之前的训练时有用。

  • fit 函数返回一个 History 的对象,其 History.history 属性记录了损失函数和其他指标的数值随 epoch 变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况。

5 评估模型 evaluate

在测试模式下返回模型的误差值和评估标准值。计算逐批次进行。


# evaluate定义
evaluate(
x=None, y=None, batch_size=None, verbose=1, sample_weight=None, steps=None,
callbacks=None, max_queue_size=10, workers=1, use_multiprocessing=False,
return_dict=False)
复制代码
  • x:输入数据。它可能是:Numpy 数组(或类似数组的数组)或数组列表(如果模型具有多个输入)。TensorFlow 张量或张量列表(如果模型具有多个输入)。

  • y:目标数据。像输入数据 x 一样,它可以是 Numpy 数组或 TensorFlow 张量。它应该与 x 一致

  • batch_size:整数或无。 每批计算的样本数。 如果未指定,batch_size 将默认为 32。如果数据是以数据集,生成器或 keras.utils.Sequence 实例的形式(因为它们生成批次),则不要指定 batch_size。

  • sample_weight:测试样本的可选 Numpy 权重数组,用于加权损失函数。

  • steps:整数或无。宣布评估阶段结束之前的步骤总数(样本批次)。

  • callbacks:评估期间要应用的回调列表。

  • max_queue_size:整数。仅用于 generator 或 keras.utils.Sequence 输入。生成器队列的最大大小。如果未指定,max_queue_size 将默认为 10。

  • workers:整数。仅用于 generator 或 keras.utils.Sequence 输入。使用基于进程的线程时,要启动的最大进程数。 如果未指定,worker 将默认为 1。如果为 0,将在主线程上执行生成器。

  • use_multiprocessing:布尔值。仅用于 generator 或 keras.utils.Sequence 输入。如果为 True,则使用基于进程的线程。 如果未指定,则 use_multiprocessing 将默认为 False。 请注意,由于此实现依赖于多处理,因此不应将不可拾取的参数传递给生成器,因为它们无法轻易传递给子进程

  • return_dict:如果为 True,则将损失和指标结果作为 dict 返回,每个键都是指标的名称。 如果为 False,则将它们作为列表返回。


6 预测模型 predict

生成输入样本的输出预测。


# predict定义
predict(
x, batch_size=None, verbose=0, steps=None,
callbacks=None, max_queue_size=10,
workers=1, use_multiprocessing=False
)
复制代码
  • x:输入样本。它可能是:Numpy 数组(或类似数组的数组)或数组列表(如果模型具有多个输入)。TensorFlow 张量或张量列表(如果模型具有多个输入)。

  • batch_size:整数或无。 每批样品数。 如果未指定,batch_size 将默认为 32

  • verbose:详细模式,0 或 1。

  • steps:宣布预测回合完成之前的步骤总数(样本批次)。

  • callbacks:预测期间要应用的回调列表。

  • max_queue_size:整数。 仅用于 generator 或 keras.utils.Sequence 输入。 生成器队列的最大值。如果未指定,max_queue_size 将默认为 10。

  • workers: 仅用于 generator 或 keras.utils.Sequence 输入。 使用基于进程的线程时,要启动的最大进程数。 如果未指定,worker 将默认为 1。如果为 0,将在主线程上执行生成器。

  • use_multiprocessing:布尔值。 仅用于 generator 或 keras.utils.Sequence 输入。 如果为 True,则使用基于进程的线程。 如果未指定,则 use_multiprocessing 将默认为 False。 请注意,由于此实现依赖于多处理,因此不应将不可拾取的参数传递给生成器,因为它们无法轻易传递给子进程。


7 模型保存

模型保存可以在训练期间和训练之后。这意味着模型可以从中断的地方继续进行,避免了长时间的训练。 保存还意味着您可以共享模型,其他人可以重新创建您的作品。

保存整个模型

您可以调用 save_model 函数 将整个模型保存到单个工件中。它将包括:

  • 模型的架构/配置

  • 模型的权重值(在训练过程中学习)

  • 模型的编译信息(如果调用了 compile())

  • 优化器及其状态(如果有的话,使您可以从上次中断的位置重新开始训练)


import tensorflow as tf
model = tf.keras.Sequential([tf.keras.layers.Dense(5, input_shape=(3,)),tf.keras.layers.Softmax()])
model.save('/tmp/model')
model.save("my_h5_model.h5")
复制代码
保存架构

调用 to_json()函数保存指定模型包含的层,以及这些层的连接方式。


from tensorflow import keras
model = keras.Sequential([keras.Input((32,)), keras.layers.Dense(1)])
json_config = model.to_json()
new_model = keras.models.model_from_json(json_config)
复制代码
保存权重值

save_weights()函数可以选择仅保存和加载模型的权重。


# Runnable example
from tensorflow import keras
sequential_model = keras.Sequential(
[
keras.Input(shape=(784,), name="digits"),
keras.layers.Dense(64, activation="relu", name="dense_1"),
keras.layers.Dense(64, activation="relu", name="dense_2"),
keras.layers.Dense(10, name="predictions"),
]
)
sequential_model.save_weights("weights.h5")
sequential_model.load_weights("weights.h5")
复制代码


用户头像

AI_robot

关注

还未添加个人签名 2021.03.31 加入

Deep Learning从业者

评论

发布
暂无评论
深度学习keras像搭积木般构建神经网络模型