吴恩达机器学习课程 笔记6 神经网络的训练方法
神经网络的编译和训练
- 编译compile():输入参数有“损失函数loss”、“优化器optimizer”、“评估指标metrics”。主要考虑前两项。
compile()函数所有的可选选项及其示例
model.compile(loss=tf.keras.losses.BinaryCrossentropy(),
optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
metrics='accuracy'
)
-
“损失函数loss”:决定了神经网络的代价函数。在“训练”的某次迭代结束后,利用输出层的输出结果与真实目标值之间的差异计算神经网络的代价。进而可以通过反向传播更新参数。
-
“优化器optimizer”:则是“梯度下降法”的升级版,可以选择性能更强大、收敛速度更快的迭代算法。
-
“评估指标metrics”:和“训练”本身没有关系,和损失函数没有关系。只是在“训练”的单次迭代结束后,衡量一下所有训练集的推理结果与真实值之间的差异。loss也有此作用,但是不直观;metrics可以选择更加直观的指标,比如metrics='accuracy'可以计算“推理正确的训练样本”的百分比。
神经网络的编译和训练是深度学习中两个非常重要的步骤。在开始之前,我们需要定义一个模型,它包括了神经网络的架构(如层数、每层的节点数、激活函数等)。一旦模型定义好了,就可以进行编译和训练了。
- 训练fit()
# fit()函数所有的可选选项及其示例(ChatGPT)
model.fit(
x=None, # 输入数据
y=None, # 标签
epochs=1, # 训练轮数
batch_size=None, # 指定进行梯度下降时每个批次包含的样本数
verbose=1, # 控制训练过程中的日志输出,0:不输出日志,1:输出进度条记录,2:每个epoch输出一行记录
callbacks=None, # 在训练过程中调用的回调函数列表
validation_split=0.0, # 用于验证的训练数据的比例
validation_data=None, # 用于验证的数据,可以是输入数据和标签的元组
shuffle=True, # 是否在每个epoch之前随机打乱输入数据
class_weight=None, # 类别权重
sample_weight=None, # 样本权重
initial_epoch=0, # 开始训练的epoch值
steps_per_epoch=None, # 每个epoch包含的步数,当为None时,将自动计算
validation_steps=None, # 在每个epoch结束时执行验证的步数,当为None时,将自动计算
validation_batch_size=None, # 用于验证的批次大小
validation_freq=1, # 仅在`validation_data` 的某些训练轮上进行验证
max_queue_size=10, # 生成器队列的最大尺寸
workers=1, # 使用的生成器工作进程数
use_multiprocessing=False, # 是否使用多进程生成器
**kwargs
)
# 运行fit()函数后,会自动打印输出训练过程,下面为单次迭代的输出示例
Epoch 1/40
157/157 [==============================] - 1s 1ms/step - loss: 1.5179 - accuracy: 0.5406
编译
编译阶段主要是配置学习过程。这通常包括以下几个方面:
- 优化器 (Optimizer):选择一个优化算法来更新权重以最小化损失函数。常见的优化器有梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam、RMSprop等。
- 损失函数 (Loss Function):损失函数用于衡量模型预测值与实际值之间的差距。不同的任务类型(如分类或回归)会使用不同的损失函数。
- 评估指标 (Metrics):除了损失函数外,我们还可以指定一些额外的指标来监控模型的训练情况,例如准确率(accuracy)、召回率(recall)等。
在Python的Keras库中,可以使用如下方式编译模型:
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
训练
训练阶段是指用数据集对模型进行训练的过程。在这个过程中,模型通过前向传播计算预测值,并通过反向传播调整权重以减少损失。训练通常涉及以下参数:
- 训练数据 (Training Data) 和 标签 (Labels):提供给模型的数据集及其相应的正确答案。
- 批量大小 (Batch Size):每次更新权重时使用的样本数量。
- 周期数 (Epochs):完整遍历一次训练集并返回的过程称为一个周期。训练通常设置为多个周期。
- 验证数据 (Validation Data):这部分数据用于评估模型在未见过的数据上的表现,而不参与模型权重的更新。
训练模型可以使用如下代码:
model.fit(x_train, y_train, batch_size=32, epochs=10, validation_data=(x_val, y_val))
注意事项
- 过拟合与欠拟合:确保模型既不过拟合也不欠拟合,可以通过调整模型复杂度、使用正则化技术、增加更多的数据等方式来解决。
- 早停法 (Early Stopping):这是一种防止过拟合的技术,在验证集上性能不再提高时提前停止训练。
- 数据预处理:在训练前,通常需要对输入数据进行归一化、标准化或其他形式的预处理。
以上就是神经网络编译和训练的基本概念和流程。实际操作时,可能还需要根据具体应用场景进行更细致的调整。
损失函数和代价函数的数学公式
激活函数
激活函数在神经网络中起着至关重要的作用。它们引入了非线性因素到模型中,使得神经网络能够学习和表示复杂的模式。没有激活函数,每一层神经网络输出都是前一层的线性组合,这样整个网络就相当于一个大的线性模型,无法解决非线性问题。
以下是一些常用的激活函数及其特点:
常见的激活函数
-
Sigmoid 函数
- 函数定义:
- 特点: 输出范围在 (0, 1) 之间,常用于二分类问题的最后一层。但是,由于其梯度在两端接近于零,容易导致梯度消失的问题。
-
tanh 函数
- 函数定义:
- 特点: 输出范围在 (-1, 1) 之间,解决了 Sigmoid 函数偏向一边的问题。同样存在梯度消失的风险。
-
ReLU (Rectified Linear Unit) 函数
- 函数定义:
- 特点: 在正区间内导数恒为 1,有助于加速收敛。但在负区间内导数为 0,可能会导致“死亡”的 ReLU 单元,即当输入为负时,该单元永远输出 0,不再参与训练。
-
Leaky ReLU 或者 PReLU (Parametric ReLU)
- 函数定义:,其中 (\alpha) 是一个小的正数。
- 特点: 解决了标准 ReLU 的“死亡”问题,允许负输入有一个非零的梯度。
-
ELU (Exponential Linear Units)
- 函数定义: ,其中 (\alpha) 是一个参数。
- 特点: 保持了 ReLU 的优点,同时在负半轴上有一个平滑的指数曲线,有助于保持均值接近零,减少内部协变量偏移。
-
Softmax 函数
- 函数定义:,应用于多分类问题的最后一层。
- 特点: 将向量转换成概率分布,所有输出之和为 1,适用于多分类任务。
激活函数的选择
首先我们从输出层开始。输出层的激活函数通常取决于“目标值”,比如二元分类问题就使用Sigmoid函数、如果预测股票涨跌的回归问题就使用线性激活函数(因为有正有负)、如果是“预测房价”这样的回归问题就使用ReLU函数(因为房价非负)。而对于隐藏层来说,若无特殊原因,所有隐藏层的神经元都应选择ReLU函数。最早人们都默认使用Sigmoid函数,但是现在逐渐演变成默认使用ReLU函数,主要有以下几个原因:
ReLU函数形式更简单、计算更快。
ReLU仅在负数域平坦,而Sigmoid函数在正负两侧都平坦。而平坦的区域越大,会导致代价函数平坦的区域越大,“梯度下降”等算法训练模型的速度就越慢。