【ML】基础概念

Practical Machine Learning
ML、DL 地图

参数和超参数

参数

在深度学习中,参数通常是指神经网络中的权重和偏差。
这些参数是通过反向传播算法,根据训练数据中的梯度信息自动调整的,以最小化损失函数
参数的学习是模型训练的过程,目标是找到最佳的参数配置。

网络参数初始化的方法:全0初始化、随机初始化

超参数

超参数是在训练开始前设置的参数,与模型的参数(权重和偏置)不同,参数是通过训练数据学习得到的。以下是一些常见的深度学习超参数:

深度学习模型的性能很大程度上依赖于其超参数的选择。超参数是在训练过程开始前设置的参数,与模型的参数(权重和偏置)不同,后者是通过训练数据学习得到的。以下是一些常见的深度学习超参数:

1. 学习率 (Learning Rate)

  • 决定模型参数在每次更新时调整的幅度。学习率过高可能导致训练不稳定,过低则训练速度缓慢。
    可以动态调整学习率,如使用cos函数学习率

2. 批大小 (Batch Size)

  • 每次传递给网络以进行一次参数更新的样本数量。批大小影响模型的内存需求和训练稳定性。

Batch size 是指在训练神经网络时,每次迭代(每次前向传播和后向传播过程)中用于计算和更新网络参数的样本数量。Batch size 是深度学习中的一个重要超参数,对模型的训练过程和性能有着重要的影响。

Batch Size 的影响:(参考梯度下降)

  1. 内存使用:较大的 batch size 会增加在每次迭代中处理的数据量,这会导致更高的内存(RAM或GPU内存)使用。如果内存不足,可能无法使用大的 batch size。

  2. 训练速度:理论上,较大的 batch size 可以提高计算效率,因为并行处理的数据量更多。然而,每次迭代处理更多的数据也意味着每次参数更新需要更长的时间。实际的训练速度还会受到硬件能力和数据加载速度的影响。

  3. 收敛性和性能

    • 较小的 batch size 可能导致训练过程中的更多噪声(每次更新的方向变化更大),这有时可以帮助模型跳出局部最小值,可能导致更好的泛化能力。但同时,训练过程可能更不稳定,收敛速度可能较慢。
    • 较大的 batch size 提供了更准确的梯度估计,可能导致更快的收敛。但是,这也可能使模型更容易陷入局部最小值或鞍点,尤其是在损失曲面复杂的情况下。
  4. 泛化能力:一些研究表明,使用较小的 batch size 训练的模型可能具有更好的泛化能力,尽管这并不是绝对的,且可能取决于具体的任务和数据集。

如何选择 Batch Size:

选择合适的 batch size 通常需要考虑多个因素,包括可用的内存资源、训练的稳定性和速度、以及模型的最终性能。实践中,通常会通过实验来确定特定任务和模型结构下的最佳 batch size,有时也会使用一些启发式方法来进行选择。此外,也有一些技术,如梯度累积,可以在内存限制的情况下间接实现较大的有效 batch size,以提高训练的稳定性和效率。

3. 迭代次数 (Epochs)

  • 整个训练数据集被遍历和学习的总次数。

4. 优化器 (Optimizer)

  • 用于更新网络权重的算法,如SGD (随机梯度下降)、Adam、RMSprop等。

5. 权重初始化 (Weight Initialization)

  • 网络参数的初始赋值策略,如随机初始化、Xavier/Glorot初始化、He初始化等。

6. 正则化参数 (Regularization Parameters)

  • 如L1和L2正则化,用于控制模型复杂度和防止过拟合的参数。

7. 激活函数 (Activation Function)

  • 神经网络中使用的非线性函数,如 ReLU、Sigmoid、Tanh 等。

8. 网络架构 (Network Architecture)

  • 涉及模型的层数、每层的神经元数目、卷积核大小等结构性参数。

9. Dropout率 (Dropout Rate)

  • 训练过程中随机丢弃神经元的比率,用于防止过拟合。

10. 学习率衰减 (Learning Rate Decay)

  • 随着训练的进行,逐渐减小学习率的策略。

11. 梯度裁剪 (Gradient Clipping)

  • 限制梯度值的范围,防止梯度爆炸。

辨析
快速搞定 epoch, batch, iteration
进行一次参数更新和完成一个epoch是两个不同的概念,在深度学习的训练过程中它们扮演着不同的角色。

参数更新

  • 在深度学习中,一次参数更新通常指的是基于一批数据(一个batch)计算损失函数的梯度,然后使用这个梯度来更新网络的权重和偏置。这个过程是学习的基本步骤,通过反向传播算法实现。
  • 参数更新的频率取决于批大小(batch size)。例如,如果批大小设置为32,则每处理32个样本后模型的参数就会更新一次。

一个Epoch

  • 一个epoch指的是整个训练数据集被完整地遍历一次的过程。这意味着每个训练样本都已被用于训练模型,参与了一次或多次的参数更新(取决于批大小和数据集大小)。
  • 完成一个epoch通常包括多次参数更新。例如,如果有1000个训练样本,批大小为100,则一个epoch包含10次参数更新。

简而言之,一次参数更新是基于一批数据调整模型参数的单个步骤,而一个epoch是整个训练数据集被完整遍历一次的过程,通常包含多次参数更新。Epoch的概念用于控制训练的总体进度,而参数更新是训练过程中的基本操作。

损失函数

损失函数(Loss Function)
也可称为代价函数(Cost Function)
计算预测值f(x)与真实值Y的差异程度
不同问题常用的损失函数
分类:交叉熵、Hinge Loss(铰链损失函数,常用于 SVM)
回归:MSE(L2 Loss)、MAE(L1 Loss)、RMSE、Huber Loss

交叉熵:衡量模型输出与实际标签之间的差异
hinge loss:使模型能正确分类,且使分类距离越大越好。如果分类确信度不够高,会给予大损失

MAE:记忆:里面是 A,所以是 L1,MSE 因为有平方,所以是2,L2。
L1 Loss 零点不平滑,用的较少
L2 Loss 因为有平方,所以对离群点敏感

正则化(规范化)
一篇文章完全搞懂正则化(Regularization)
在损失函数中添加一个正则项,限制其较高次的参数大小不能过大,使模型学习到更加稀疏的权重分布,防止过拟合。常见的有L1正则化和L2正则化。

L2正则化对于绝对值较大的权重予以很重的惩罚,对于绝对值很小的权重予以非常非常小的惩罚,当权重绝对值趋近于0时,基本不惩罚。

L1正则化对于所有权重(不论参数大小)予以同样的惩罚
L1要在稀疏条件下使用

dropout、早停

向前传播和反向传播

了解反向传播,先了解梯度下降:【ML】以梯度下降(Gradient Descent)展开的优化器总结

向前传播:数据在神经网络中从输入层流向输出层的过程。在这个过程中,每一层的神经元会根据前一层的输入、自身的权重(weights)和偏置(biases),通过激活函数计算出自己的输出。这个输出会作为下一层的输入继续传递。这个过程一直持续到达输出层,最终产生模型的预测结果。

反向传播:从输出层流向输入层的过程。根据模型输出和实际值之间的误差来调整模型参数(即权重和偏置)。这个过程是通过链式法则计算损失函数的梯度并使用这些梯度来更新模型参数来实现的。一旦计算出梯度,就使用优化算法(如SGD、Adam等)来更新网络中的权重和偏置,目的是减小损失函数的值。

5分钟深度学习-反向传播算法
【深度学习篇】:前向传播(forward)和反向传播(backward)

激活函数

增加神经网络的非线性表达能力,使之能更好的拟合非线性模型,常见的有 Sigmoid、Tanh、ReLU
5分钟深度学习-激活函数
深度学习笔记:如何理解激活函数?(附常用激活函数)

特点

  1. 连续可导(梯度下降);
  2. 取值范围是全体实数,将全体实数映射到特定的范围;
  3. 只需增加非线性的因素,而不需改变对输入的响应状态,所以是单增的,随输入增大而增大

梯度消失(梯度弥散):sigmoid趋近无穷时,梯度趋近于0,若某次输入过大,梯度几乎为0,导致参数几乎不更新,导致整个网络学习能力下降
sigmoid:非零均值函数→同时更新正负→神经网络不易收敛;饱和函数→梯度消失,使用tanh函数可以
梯度爆炸:使用ReLU函数时,激活值在反向传播时会与梯度相乘,会导致梯度累积,超出上限

解决梯度爆炸:梯度裁剪(限制梯度的最大值)、适当的权重初始化策略、使用批量归一化等技术,而不是替换ReLU激活函数。

批量归一化和层归一化

批量归一化(Batch Normalization, BN)和层归一化(Layer Normalization, LN)都是深度学习中用于改进神经网络训练的标准化技术,通常是在网络架构中作为特定的层来实现。

BN和LN都旨在通过标准化神经网络中的激活值来减少内部协变量偏移,加速训练并提高模型的性能。BN通过归一化一批样本中相同特征的值来实现,而LN则是对单个样本中所有特征的值进行归一化。

解决的问题

提高模型的训练效率和泛化能力,但批量归一化一般不改变模型精度
1. 内部协变量偏移(Internal Covariate Shift)

  • 问题:在训练深度神经网络时,每一层的输入分布可能会因为前面层参数的更新而改变,这种现象被称为内部协变量偏移。这导致训练过程不稳定,需要更小的学习率和更仔细的参数初始化策略。
  • 解决方式:BN通过对每一批数据的每个特征进行标准化(确保输入层的均值为0,方差为1),减少了内部协变量偏移,使得网络能够使用更高的学习率,加速训练过程。而LN通过对单个数据样本的所有特征进行标准化,也可以减少这种偏移,特别是在RNN和Transformer等模型中效果显著。

2. 梯度消失/梯度爆炸(Vanishing/Exploding Gradients)

  • 问题:在深层网络中,梯度可能随着传播逐渐变小(消失)或变得非常大(爆炸),这使得网络难以训练。
  • 解决方式:通过归一化处理,BN和LN可以在一定程度上缓解梯度消失或爆炸的问题,因为它们保证了网络中每一层的输入分布的一致性,从而有助于维持梯度的稳定。

3. 训练过程中的参数敏感性和不稳定性

  • 问题:深度网络中的参数更新可能会对后续层产生放大的效应,导致训练过程中的不稳定性。
  • 解决方式:BN和LN通过对激活进行标准化,减少了单个参数变化对整个网络的影响,从而增强了模型的稳定性,使得网络对参数初始化的敏感度降低。

4. 过拟合(Overfitting)

  • 问题:深度网络可能会过度学习训练数据中的细节,从而导致在未见过的数据上表现不佳。
  • 解决方式:虽然BN和LN的主要目标不是解决过拟合问题,但它们引入的轻微噪声(比如BN中来自小批量统计的噪声)可以带来轻微的正则化效果,有助于减少过拟合。不过,过拟合通常还需要通过其他正则化技术(如Dropout、权重衰减等)来更有效地控制。

批量归一化(Batch Normalization, BN)

  • 归一化对象:BN是对同一层内不同样本的同一特征进行归一化。对于给定的一批数据,BN分别计算这批数据在每个特征维度上的均值和方差,然后使用这些统计信息来标准化每个样本的每个特征(中心极限定理)。
  • 应用场景:BN通常用在卷积层或全连接层之后,激活函数之前。它在批量较大时表现较好,因为均值和方差的估计更为稳定。
  • 依赖批量大小:BN的性能依赖于批量的大小,当批量大小很小时,BN的性能可能会受到影响,因为均值和方差的估计会变得不准确。

层归一化(Layer Normalization, LN)

  • 归一化对象:LN是对同一样本内不同特征进行归一化。对于单个样本,LN计算所有特征的均值和方差,然后使用这些统计信息来标准化该样本的所有特征。
  • 应用场景:LN不依赖于批量的大小,因此特别适用于批量大小较小或动态变化的情况,如自然语言处理中的循环神经网络(RNN)和Transformer模型。
  • 独立于批量大小:由于LN是在样本级别上进行的,因此它的性能不受批量大小的影响,这使得LN在批量大小受限或变化较大的应用场景中更为有用。

在网络中的实现:

  1. 批量归一化(BN)

    • BN层通常置于卷积层(Convolutional Layer)或全连接层(Fully Connected Layer)之后,激活函数(如ReLU)之前。
    • 在PyTorch中,BN可以通过torch.nn.BatchNorm2d(对于2D卷积层)或torch.nn.BatchNorm1d(对于全连接层)来实现。
  2. 层归一化(LN)

    • LN层可以应用于网络中几乎任何地方,但在某些架构(如Transformer模型)中,它通常在每个子层的输出上使用,并在激活函数之前应用。
    • 在PyTorch中,LN可以通过torch.nn.LayerNorm来实现。

示例代码(PyTorch):

对于批量归一化

import torch.nn as nn

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=20, kernel_size=5)
        self.bn1 = nn.BatchNorm2d(num_features=20)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        return x

对于层归一化

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.linear1 = nn.Linear(in_features=10, out_features=20)
        self.ln1 = nn.LayerNorm([20])
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.linear1(x)
        x = self.ln1(x)
        x = self.relu(x)
        return x

拓展

批量归一化与Dropout的关系

  • Dropout:是一种正则化技术,通过在训练过程中随机“丢弃”一部分神经元(即将它们的输出设置为0)来防止模型过拟合。这种随机性有助于使模型更加健壮,减少对特定训练样本的依赖。

  • 批量归一化:主要用于加速训练和提高训练过程的稳定性,虽然有时也能起到轻微的正则化效果,但并不是其主要目的。

在使用批量归一化后,有些研究和实践经验表明,可能不那么需要依赖Dropout来防止过拟合,因为批量归一化本身就引入了一定的噪声(由于每个小批量的均值和方差的估计),这可能有助于正则化模型。此外,批量归一化使得网络能够使用更高的学习率,从而加速训练,而Dropout可能会降低训练速度。

尽管批量归一化和Dropout可以共存于同一个网络中,但在实际应用中,根据具体任务和网络结构的不同,可能会选择调整它们的使用。有时,为了简化模型并减少计算开销,如果批量归一化足以稳定训练并防止过拟合,就可能不使用Dropout。反之,在一些情况下,特别是在批量归一化不足以完全防止过拟合的情况下,仍然可以使用Dropout作为额外的正则化手段。实际操作中,这通常需要通过实验来确定最佳的策略。

分类和回归

本质都是对输入值进行预测的问题,分类输出离散的、对预测类别的置信度,回归输出连续的预测值
【ML】分类和回归
【机器学习小常识】“分类” 与 “回归”的概念及区别详解
详解逻辑回归、softmax回归和神经网络,三种模型的关联和区别
【ML】Softmax

训练集、验证集、测试集

三者必须无交集
还搞不懂什么是参数,超参数吗?三分钟快速了解参数与超参数的概念和区别!!!
训练集、测试集、验证集之间的区别及理解
训练集:通过训练自动更新参数
验证集:手动更新超参数
测试集:测试生成的模型的泛化能力

k折交叉验证:将数据集分成k份,每次拿出其中的一份作为验证集,剩下k-1份作为训练集
通过平均误差判断超参数好坏

Q&A

Q:如果loss很低,是不是就不用设置验证集了
A:在深度学习训练中,即使训练损失(loss)很低,也不意味着可以忽略验证集的设置。这里有几个原因解释为什么验证集依然很重要:

1. 过拟合(Overfitting):一个很低的训练损失可能意味着模型在训练集上表现得很好,但这也可能是过拟合的一个迹象。过拟合发生时,模型学习到了训练数据中的噪声和细节,而不是底层模式,这会导致模型在未见过的数据上表现不佳。验证集可以帮助检测过拟合情况,因为它提供了模型在非训练数据上的性能评估。

2. 模型选择(Model Selection):在开发深度学习模型时,我们通常会尝试多种不同的架构、超参数设置等。验证集用于评估这些不同设置的性能,帮助我们选择最佳模型。

3. 调参(Hyperparameter Tuning):除了选择模型外,我们还需要调整模型的超参数(如学习率、批量大小等)。验证集对于这一过程至关重要,因为它可以帮助我们了解不同超参数设置对模型性能的影响。

4. 泛化能力(Generalization Ability):最终,我们关心的是模型在实际应用中的表现,即在新的、未见过的数据上的表现。验证集提供了一个近似的泛化能力评估,帮助我们估计模型在现实世界数据上的表现。

因此,即使训练损失很低,也不应该忽视验证集的设置。验证集是深度学习训练过程中不可或缺的一部分,对于确保模型的泛化能力和避免过拟合至关重要。在模型训练的最后阶段,还应该使用独立的测试集对模型进行最终评估,以进一步验证模型的泛化能力。
Q:验证集在所有任务中都是必须的吗?
A:虽然验证集在许多深度学习和机器学习任务中非常重要,但是否“必须”使用验证集取决于具体的任务、数据的可用性以及目标。在大多数情况下,使用验证集是一种最佳实践,但也有一些情况或任务可能不那么依赖于验证集:

1. 数据量极其有限:在某些情况下,如果可用的数据非常有限,可能无法划分出单独的验证集。在这种情况下,可能会采用交叉验证的方法,这种方法将数据集分为多个小分组,然后依次将其中一个分组作为验证集,其他分组作为训练集,从而有效利用有限的数据。

2. 在线学习或持续学习:对于一些在线学习任务,模型会持续地接收数据并不断更新。在这种情况下,模型可能不会有一个固定的验证集,而是不断地用新数据评估和调整。

3. 使用预训练模型进行微调:当使用预训练模型并对其进行微调以适应特定任务时,如果任务非常接近原始预训练任务,且数据集较小,可能会直接在训练数据上进行微调而不单独设置验证集。然而,这种情况下仍然推荐使用验证集来监控过拟合和模型性能。

4. 简单任务或明确的成功标准:在一些简单的任务或当成功标准非常明确且容易评估时(如明确的数学问题),可能不需要单独的验证集来调整模型参数。

即便在这些特殊情况下,最终还是需要一个独立的测试集来评估模型的性能,确保模型能够在未见过的数据上良好工作。综上所述,虽然在某些特定场景下可以不使用验证集,但在大多数情况下,为了保证模型的泛化能力和避免过拟合,使用验证集都是一种非常重要的实践。

超参数调整
利用验证集调整超参数的一些策略

  1. 在每个epoch后或几个epoch后使用验证集验证模型的loss,确保模型权重可以被保存在本地,手动调整超参数后继续训练
  2. 使用早停技术:在每个epoch结束时评估模型在验证集上的性能,并在性能不再提升时停止训练
  3. 使用自动化超参数优化(Hyperparameter Optimization, HPO)
  4. 设置模型检查点(Model Checkpointing)

过拟合

在训练集上学习的太好,导致学到了噪声,使得在测试集上表现不佳
过拟合:认为只有和训练数据一样的才是
欠拟合:认为树也是叶子
机器学习模型的容量,过拟合与欠拟合
dropout:前向传播的时候,让某个神经元的激活值以一定的概率 p 停止工作,这样可以使模型泛化性更强,防止过拟合

过拟合解决方法
正则化、交叉验证、dropout、早停、批量归一化、调整学习率、数据增强

算法分类

机器学习算法通常根据学习方式和应用场景被分类为几大类:

  1. 监督学习(Supervised Learning):

    • 包括分类和回归任务。算法从标记的训练数据中学习,每个训练样本都有一个与之对应的标签或输出。
    • 常见的算法包括线性回归、逻辑回归、支持向量机(SVM)、决策树、随机森林、神经网络等。
  2. 无监督学习(Unsupervised Learning):

    • 在无监督学习中,算法试图从未标记的数据中找出模式。因为没有指导,所以这种类型的学习试图通过数据本身的结构来理解数据。
    • 典型的算法包括聚类算法(如K-means、层次聚类)、降维算法(如主成分分析PCA、t-SNE)、关联规则学习算法(如Apriori、Eclat)等。
  3. 半监督学习(Semi-Supervised Learning):

    • 这种学习方式介于监督学习和无监督学习之间。它使用少量的标记数据和大量的未标记数据进行训练。通过这种方式,算法可以提高其性能和准确性。
    • 半监督学习方法通常包括自训练、多视图学习、图基方法等。
  4. 强化学习(Reinforcement Learning):

    • 在强化学习中,算法(通常称为智能体)通过与环境交互来学习如何达到目标。智能体从环境中获得奖励或惩罚,并使用这些反馈来指导其未来的行为。
    • 常见的强化学习算法包括Q-learning、SARSA、深度Q网络(DQN)、策略梯度方法等。
  5. 自监督学习(Self-Supervised Learning):

    • 这是一种特殊类型的无监督学习,其中数据的一部分被用作监督信号。在自监督学习中,模型试图从数据的未标记部分预测数据的标记部分,从而在没有显式标签的情况下学习数据的表示。
    • 应用示例包括预训练的语言模型、图像特征学习等。
  6. 迁移学习(Transfer Learning):

    • 这种学习方法涉及将从一个任务中学到的知识应用到另一个不同但相关的任务上。这是通过重用预训练模型的一部分并对其进行微调来实现的,以适应新任务。
    • 这在深度学习中尤其常见,例如使用预训练的卷积神经网络(CNN)进行图像分类任务。
      【DL】模型复用
  7. 生成式对抗网络(GANs):

    • GANs是一种框架,用于通过两个网络(一个生成器和一个鉴别器)之间的对抗过程来训练生成模型。生成器生成新的数据实例,而鉴别器评估它们是来自于真实数据集还是生成器产生的。
    • GANs广泛用于图像生成、图像转换、增强现实等领域。
赞赏