机器学习面试题汇总与解析——优化函数

本章讲解知识点

    1. 什么是优化函数?
    1. 为什么要使用优化函数?
    1. 详细讲解优化函数
    1. 优化函数总结
    1. 梯度下降算法的 batch size 总结


  • 本专栏适合于Python已经入门的学生或人士,有一定的编程基础。
  • 本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。
  • 本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。这才是一份面试题总结的正确打开方式。这样才方便背诵
  • 如专栏内容有错漏,欢迎在评论区指出或私聊我更改,一起学习,共同进步。
  • 相信大家都有着高尚的灵魂,请尊重我的知识产权,未经允许严禁各类机构和个人转载、传阅本专栏的内容。

  • 关于机器学习算法书籍,我强烈推荐一本《百面机器学习算法工程师带你面试》,这个就很类似面经,还有讲解,写得比较好。

  • 关于深度学习算法书籍,我强烈推荐一本《解析神经网络——深度学习实践手册》,简称 CNN book,通俗易懂。



1. 什么是优化函数?

1.1 定义与作用

前一篇讲了损失函数,损失函数是用来度量模型预测值真实值间的偏差,偏差越小,模型越好,所以我们需要最小化损失函数。如何求最小值呢?高中知识告诉我们,对于凸函数可以直接求导可以找到最值,但是神经网络的损失函数往往是非凸函数,我们并不能直接求导。所以优化函数就可以帮助我们解决这个问题,优化函数就是用来最小化我们的损失函数的

优化函数(Optimization Function)是用于训练机器学习模型的算法,用于调整模型的参数以最小化(或最大化)一个定义良好的目标函数——损失函数或成本函数(Loss/Cost Function)。优化函数通过迭代的方式,根据模型的预测输出和真实标签之间的差异,逐步更新模型参数,使得模型能够更好地拟合训练数据并在未见过的数据上表现良好。

在机器学习和深度学习中,优化函数的目标通常是最小化损失函数,以使模型的预测结果与真实值尽可能接近。不同的优化函数有不同的算法策略和特点,可以根据具体任务和模型选择合适的优化函数。

1.2 常见的优化函数

  • 梯度下降法(Gradient Descent)及其变种:梯度下降法是一种迭代优化算法,通过计算目标函数对模型参数的梯度方向,并以梯度的相反方向更新参数,逐步降低损失函数的值。

  • 随机梯度下降法(Stochastic Gradient Descent,SGD):SGD是梯度下降法的一种变种,每次迭代随机选择一部分训练样本(mini-batch)计算梯度,并更新参数。它具有计算效率高的优点,特别适用于大规模数据集和深度神经网络的训练。

  • 动量优化算法(Momentum Optimization):动量算法通过引入动量项来加速收敛,并减少梯度更新的震荡。它在更新参数时考虑了之前的梯度信息,有助于在参数空间中跳出局部最优解。

  • 自适应学习率算法(Adaptive Learning Rate Algorithms):自适应学习率算法根据梯度的情况自动调整学习率,使得在训练的不同阶段能够有更好的收敛性能。常见的自适应学习率算法包括 Adagrad、RMSProp 和 Adam 等。


2. 为什么要使用优化函数?

我们在前面的章节已经讲述了回归问题和损失函数的概念。我们回到农场主为了预测水果价格的例子上:

假设有一个农场主,他种植着各种水果,包括苹果、橙子和梨。这位农场主非常注重水果的质量,并希望能够根据水果的大小和成熟程度来预测它们的价格。他决定使用机器学习来构建一个模型,以便根据水果的特征预测它们的价格。

为了训练模型,农场主收集了大量的数据,包括水果的大小、成熟程度和对应的实际价格。他决定使用线性回归模型,因为它能够对连续值进行预测。

img

然而,农场主面临一个挑战:模型怎么知道自己的预测与实际价格之间的差异呢?必须要有一个东西来衡量预测与实际价格之间的差异,再将这个差异告诉模型,模型才知道自己预测的方向是否正确,它才能调整自己的参数,以使自己预测的更加准确。这个东西就是损失函数,衡量模型是否预测准确的指标。

农场主选择了均方误差(MSE)作为损失函数。他计算每个样本的预测价格与实际价格之间的差值的平方,并将这些差值进行求和或平均。这个损失函数表示了模型预测与真实价格之间的平均误差

通过计算损失函数,农场主能够得到模型在训练集上的损失值。他希望尽量减小这个损失值,因为这意味着模型的预测结果与实际价格更接近

农场主使用梯度下降等优化算法来最小化损失函数。他根据损失函数的梯度,调整模型的参数和权重,以减小预测与实际价格之间的差异。随着训练的进行,模型逐渐优化,损失值逐渐减小。

几乎所有用于深度学习的优化算法都属于随机梯度下降法。它们是迭代算法,以步骤训练网络。训练的一个步骤是这样的:

  1. 对一些训练数据进行采样,通过网络进行预测
  2. 衡量预测值和真实值之间的损失
  3. 最后,调整权重,使损失变小。

然后反复这样做,直到损失小到你想要的程度为止(或者直到它不会再减少)。渐变趋势图可以看下图:

image

用随机梯度下降法训练神经网络

  • 每次迭代的训练数据样本称为小批(mini-batch)处理(常说“批处理”),而一次完整的训练数据一轮称为 epoch。你训练的 epoch 的数量是网络将看到每个训练示例的次数。
  • 动图显示了第 1 个中的线性模型正在用 SGD 进行训练。淡红色的点表示整个训练集,而实红色的点是小批量。每一次 SGD 看到一个新的小批,它就会将权重(ww 是斜率,bbyy 轴截距)移向该批上的正确值。一批又一批,直线最终收敛到它的最佳拟合。可以看到,随着权重越来越接近它们的真实值,损失会越来越小。

最终,农场主得到了一个经过训练的模型,它能够根据水果的大小和成熟程度预测它们的价格。通过使用损失函数,农场主能够衡量模型的性能并指导模型的训练过程,以使预测结果尽可能地接近实际价格。


3. 详细讲解优化函数

好,我们一个个分析:

1. 梯度下降法(gradient descent)

梯度下降(gradient descent)在机器学习中应用十分的广泛,不论是在线性回归还是 Logistic 回归中,它的主要目的是通过迭代找到目标函数的最小值,或者收敛到最小值。

假设待优化的目标函数 J(w)J(w) 是具有一阶连续偏导的函数,现在的目标是要求取最小的 J(w)J(w),即 minJ(w)min J(w)

梯度下降的核心思想:负梯度方向是使函数值下降最快的方向,在迭代的每一步根据负梯度的方向更新 ww 的值,从而求得最小的 J(w)J(w)。因此我们的目标就转变为求取 J(w)J(w) 的梯度

基本思想可以这样理解:我们从山上的某一点出发,找一个最陡的坡走一步(也就是找梯度方向),到达一个点之后,再找最陡的坡,再走一步,直到我们不断的这么走,走到最“低”点(最小花费函数收敛点)。

img

J(w)J(w)凸函数的时候,用梯度下降的方法取得的最小值是全局最优解。但神经网络的损失函数往往是非凸函数,所以梯度下降法往往找到的是局部最优解

下图左边是凸函数,如均方误差损失函数,存在全局最优解,如山谷的最底部就是函数的最小值,而右边则类似神经网络的损失函数了,是非凸函数,很难找到全局最优解,更容易找到局部最优解

img

假设 h(x)h(x) 是我们的模型函数, nn 表示参数个数, mm 表示训练集的样本个数,J(w)J(w) 是我们的损失函数,即待优化的目标函数。

h(x)=j=0nwjxjJ(w)=12mi=1m(yihw(xi))2(.)h(x) =\sum_{j=0}^n {w}_j x_j \\ J(w) =\frac{1}{2m} \sum_{i=1}^m (y^i-h_{w}(x^i) )^2 \\ \tag{.}

ww 求偏导,可以得到每个 ww 对应的梯度:

wj=J(w)wj=1mi=1m(yihw(xi))xji(.)\nabla_{w_j}=\frac{\partial J(w)}{\partial {w}_j} =-\frac{1}{m} \sum_{i=1}^m (y^i-h_{w}(x^i) )x_j^i \\ \tag{.}

接着按每个 ww负梯度来更新每个 ww

wj=wj+ηwj(.){w}_j^{*} =w_j + \eta \cdot \nabla_{w_j} \\ \tag{.}

η\eta 是学习率,根据计算得到的梯度信息,按照一定的学习率(learning rate)确定参数更新的步长,然后更新模型的参数。一般来说,学习率需要小于 1,控制参数更新的幅度,避免参数变化过快。可以看出,在梯度下降法中,因为每次都遍历了完整的训练集,其能保证结果为全局最优(优点),但是也因为我们需要对于每个参数求偏导,且在对每个参数求偏导的过程中还需要对训练集遍历一次,当训练集(mm)很大时,计算费时(缺点)。

同时梯度下降法无法很好地选择合适的学习率、处理局部最优解和鞍点,为了克服这些问题,可以采用学习率衰减、动量优化、自适应学习率等策略,结合其他优化算法来改进梯度下降法的性能。

2. 批次梯度下降法(batch gradient descent)

批次梯度下降法(Batch Gradient Descent)通过计算所有样本的梯度来更新模型的参数,而不是只计算单个样本的梯度。在批次梯度下降法中,每次更新模型参数时都使用整个训练数据集

θj=θj+θj=θj+ηi=1m(yiθiTxi)xji(.){\theta}_j^{*} =\theta_j + \nabla_{\theta_j} \\ =\theta_j + \eta \cdot \sum_{i=1}^m (y_i-\theta_i^Tx_i )x_j^i \\ \tag{.}

写成伪代码如下:

for i in range(nb_epochs):
    params_grad = evaluate_gradient(loss_function, data, params)
    params = params - learning_rate * params_grad

批次梯度下降法的缺点也是很明显的。首先,它需要将所有的训练数据都载入内存,这在处理大规模数据集时可能会导致内存不足。其次,由于它需要在每个批次上计算梯度,因此在每个训练迭代中需要进行大量的计算,这会降低训练速度。最后,批次梯度下降法很容易陷入局部最优解,因为它只是通过对所有样本的平均梯度进行更新,而忽略了每个样本的特异性。

3. 随机梯度下降(stochastic gradient descent)

随机梯度下降(Stochastic Gradient Descent,SGD)是梯度下降法的一种变体,它在每次更新参数时只使用一个样本的梯度信息。相比于批次梯度下降法,随机梯度下降法具有更快的收敛速度和更低的内存要求。

其每次对 ww 的更新,都是针对单个样本数据,并没有遍历完整的参数。当样本数据很大时,可能到迭代完成,也只不过遍历了样本中的一小部分。因此,其速度较快(优点),但是其每次的优化方向不一定是全局最优的(缺点)。

θj=θj+θj=θj+η(yiθiTxi)xji(.){\theta}_j^{*} =\theta_j + \nabla_{\theta_j} \\ =\theta_j + \eta \cdot (y_i-\theta_i^Tx_i )x_j^i \\ \tag{.}

写成伪代码如下:

for i in range(nb_epochs):
    np.random.shuffle(data)
    for example in data:
        params_grad = evaluate_gradient(loss_function , example ,params)
        params = params - learning_rate * params_grad

然而,随机梯度下降法也存在一些问题。由于使用单个样本计算梯度,因此每次梯度的估计可能存在较大的方差,导致参数更新的不稳定性。因为误差,所以每一次迭代的梯度受抽样的影响比较大,也就是说梯度含有比较大的噪声,不能很好的反映真实梯度,并且SGD有较高的方差,其波动较大。为了缓解这个问题,可以引入学习率衰减、动量优化等技术。

因为每一次迭代的梯度受抽样的影响比较大,学习率需要逐渐减少,否则模型很难收敛。在实际操作中,一般采用线性衰减:

ηk=(1α)η0+αητα=kτ(.)\eta_k =(1-\alpha)\eta_0 + \alpha \eta_{\tau} \\ \alpha =\frac{k}{\tau} \\ \tag{.}

η0\eta_0 是初始学习率,ητ\eta_{\tau} 是最后一次迭代的学习率,τ\tau 代表自然迭代次数,ητ\eta_{\tau} 设为 η0\eta_0 的 1%。kk 我们一般设为 100 的倍数。

为了权衡批次梯度下降和随机梯度下降的优劣,还出现了一种折中的方法,称为小批量梯度下降(Mini-batch Gradient Descent)。小批量梯度下降每次使用一小批样本来计算梯度和更新参数,既可以获得一定的收敛速度和稳定性,又能够更好地利用计算资源。

小批量梯度下降法是是对于 m 个样本,我们采用 x 个样子来迭代,1<x<m。一般可以取 x=10,当然根据样本的数据,可以调整这个 x 的值。

我们来总结一下梯度下降的优化方法,SGD 最为常用。

优点: 收敛速度快。

缺点:1. 训练不稳定。2. 选择适当的学习率可能很困难。 太小的学习率会导致收敛性缓慢,而学习速度太大可能会妨碍收敛,并导致损失函数在最小点波动。3. 无法逃脱鞍点。

在神经网络中,鞍点(Saddle Point)是指损失函数在某个点处既不是极小值也不是极大值的位置。在鞍点处,沿着某些方向的梯度为零,但沿着其他方向的梯度不为零。这种情况可能导致优化算法在训练过程中出现停滞,使得模型参数更新变得困难。

鞍点的存在是由于高维空间中的复杂性。在高维空间中,优化问题往往非常复杂,具有多个局部极小值、局部最大值和鞍点。尤其是在深层神经网络中,参数的数量庞大,增加了找到全局最优解的难度。

鞍点对于优化算法来说是一个挑战,因为在鞍点处梯度为零,导致优化算法难以继续更新参数。一种常见的解决方法是使用更复杂的优化算法,例如动量优化、自适应学习率方法(如Adam)等。这些算法能够帮助跳出鞍点并继续优化模型。下图中的红点就是一个鞍点。

img

所以后面发展了不少其他的优化方法改进了 SGD。

4. Momentum 随机梯度下降法

Momentum 随机梯度下降法(Momentum Stochastic Gradient Descent)是一种优化算法,结合了随机梯度下降法(SGD)和动量(Momentum)的思想。它在更新参数时利用历史梯度信息,以加速收敛并提高优化的稳定性

具体来说,Momentum 随机梯度下降法在更新参数时引入了一个动量项,用于模拟物体在梯度下降过程中的动量。它通过累积历史梯度的指数加权平均来决定参数更新的方向和步长。

核心思想:Momentum 借用了物理中的动量概念,即前一次的梯度也会参与运算。为了表示动量,引入了一阶动量 mm(momentum)。mm 是之前的梯度的累加,但是每回合都有一定的衰减。公式如下:

mt=βmt1+(1β)gtwt+1=wtηmt(.)m_t=\beta m_{t-1} + (1- \beta) \cdot g_t \\ w_{t+1} = w_{t}- \eta \cdot m_t \tag{.}

gtg_t 表示第 tt 次 epoch 计算的梯度, β\beta 表示动量因子,一般取 0.9,所以当前权值的改变受上一次改变的影响,类似加上了惯性

  • 在梯度方向改变时,momentum 能够降低参数更新速度,从而减少震荡;

  • 在梯度方向相同时,momentum 可以加速参数更新, 从而加速收敛。

总而言之,momentum 能够加速 SGD 收敛,抑制震荡。并且动量有机会逃脱局部极小值(鞍点)。

5. Nesterov 动量型随机梯度下降法

Nesterov 动量型随机梯度下降法是在 momentum 更新梯度时加入对当前梯度的校正,让梯度“多走一步”,可能跳出局部最优解:

wt=βmt1+wtmt=βmt1+(1β)gtwt+1=wtηmt(.)w_{t}^*=\beta m_{t-1} + w_{t} \\ m_t=\beta m_{t-1} + (1- \beta) \cdot g_t \\ w_{t+1} = w_{t}^*- \eta \cdot m_t \tag{.}

相比 momentum 动量法,Nesterov 动量型随机梯度下降法对于凸函数在收敛性证明上有更强的理论保证。

6. Adagrad法

我们上面讲到了 SGD 的学习率是线性更新的,每次更新的差值一样。后面的优化法开始围绕自适应学习率进行改进。Adagrad 法引入二阶动量,根据训练轮数的不同,对学习率进行了动态调整:

vt=τ=1tgτ2+ϵηt=ηglobalvtwt+1=wtηtgt(.)v_t=\sqrt{\sum_{\tau=1}^tg_{\tau}^2 +\epsilon} \\ \eta_t=\frac{\eta_{global}}{v_t} \\ w_{t+1} = w_{t}- \eta_t \cdot g_t \tag{.}

公式中, gtg_t 表示第 tt 次 epoch 计算的梯度, ϵ\epsilon 为一个小常数(通常设定为 10610^6 数量级)以防止分母为零。在网络训练的前期,由于分母中梯度的累加(vtv_t)较小,所以一开始的学习率 ηt\eta_t 比较大;随着训练后期梯度累加较大时,ηt\eta_t 逐渐减小,而且是自适应地减小。

Adagrad 的基本思想是根据每个参数的历史梯度值来自适应地调整学习率。具体而言,它为每个参数维护一个累积梯度平方和的累积变量,并将其用作学习率的分母。这样,参数的学习率会随着时间的推移逐渐减小,且在梯度较大的方向上具有较小的学习率,在梯度较小的方向上具有较大的学习率。

但缺点是 Adagrad 法仍然需要人为指定一个合适的全局学习率 ηglobal\eta_{global},同时网络训练到一定轮次后,分母上梯度累加过大使得学习率为 0 而导致训练提前结束。

7. Adadelta法

Adadelta 法是对 Adagrad 法的扩展,通过引入衰减因子 ρ\rho 消除 Adagrad 法对全局学习率的依赖,具体可表示为:

vt=ρvt1+(1ρ)gt2ηt=st1+ϵvt+ϵst=ρst1+(1ρ)(ηtgt)2(.)v_t=\rho \cdot v_{t-1} + (1-\rho) \cdot g_t^2 \\ \eta_t = \frac{\sqrt{s_{t-1}+\epsilon}}{\sqrt{v_t+\epsilon}} \\ s_t=\rho \cdot s_{t-1} + (1-\rho) \cdot (\eta_t \cdot g_t)^2 \\ \tag{.}

其中,ρ\rho 为区间 [0,1] 间的实值:较大的 ρ\rho 会促进网络更新;较小的 ρ\rho 值会抑制更新。两个超参数的推荐设定为 ρ=0.95\rho=0.95ϵ=106\epsilon=10^{-6}。可以看出,Adadelta 法确实避免了对全局学习率的依赖。而且只用了部分梯度加和而不是所有,这样避免了梯度累加过大使得学习率为 0 而导致训练提前结束。

8. RMSProp法

AdaGrad 算法在迭代后期由于学习率过小,可能较难找到一个有用的解。为了解决这一问题,RMSprop 算法对 Adagrad 算法做了一点小小的修改,RMSprop 使用指数衰减只保留过去给定窗口大小的梯度,使其能够在找到凸碗状结构后快速收敛。RMSProp 法可以视为 Adadelta 法的一个特例,即依然使用全局学习率替换掉 Adadelta 法中的 sts_t

vt=ρvt1+(1ρ)gt2ηt=ηglobalvt+ϵwt+1=wtηtgt(.)v_t=\rho \cdot v_{t-1} + (1-\rho) \cdot g_t^2 \\ \eta_t = \frac{\eta_{global}}{\sqrt{v_t+\epsilon}} \\ w_{t+1} = w_{t}- \eta_t \cdot g_t \tag{.}

实际使用中推荐参数为 ηglobal=1\eta_{global}=1ρ=0.9\rho=0.9ϵ=106\epsilon=10^{-6}。RMSProp 法缺陷在于依然使用了全局学习率,需要根据实际情况来设定。可以看出分母不再是一味的增加,它会重点考虑距离它较近的梯度(指数衰减的效果)。优点是只用了部分梯度加和而不是所有,这样避免了梯度累加过大使得学习率为 0 而导致训练提前结束。

9. Adam法

Adam 法本质上是带有动量项的 RMSProp 法,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率,具体而言,它为每个参数维护两个状态变量:一阶矩估计(动量)和二阶矩估计(累积梯度平方和)。Adam 法主要的优点在于经过偏置校正后,每一次迭代学习率都有一个确定范围,这样可以使得参数更新比较平稳。

mt=β1mt1+(1β1)gtvt=β2vt1+(1β2)gt2mt=mt1β1tvt=vt1β2twt+1=wtηmtvt+ϵ(.)m_t=\beta_1 \cdot m_{t-1} + (1-\beta_1) \cdot g_t \\ v_t = \beta_2 \cdot v_{t-1} + (1-\beta_2) \cdot g_t^2 \\ m_t^* = \frac{m_t}{1-\beta_1^t} \\ v_t^* = \frac{v_t}{1-\beta_2^t} \\ w_{t+1} = w_{t} - \eta \frac{m_t^*}{\sqrt{v_t^*}+\epsilon} \\ \tag{.}

可以看出,Adam 法依然需要指定学习率 η\eta,对于其中的超参数,一般设定为:β1=0.9\beta_1=0.9β2=0.999\beta_2=0.999ϵ=108\epsilon=10^{-8}η=0.001\eta=0.001。可以看出,每一次迭代学习率都有一个确定范围,即 mtvt+ϵ-\frac{m_t^*}{\sqrt{v_t^*}+\epsilon}

Adam(Adaptive Moment Estimation)是一种自适应学习率的优化算法,结合了动量法(Momentum)和RMSprop的思想。它在训练神经网络时能够有效地调整学习率,并具有较好的收敛性和泛化能力。


4. 优化函数总结

4.1 小结

我们来总结一下

从优化器发展历程可以看出,有两个参数很重要。一个是优化方向,决定“前进的方向是否正确”,在优化器中反映为梯度或动量。另一个是步长,决定“每一步迈多远”,在优化器中反映为学习率

待优化参数:ww,目标函数:J(w)J(w),初始学习率:η\eta,迭代 epoch:tt

参数更新步骤如下:

1. 计算目标函数关于当前参数的梯度

gt=J(wt)(.)g_t=\nabla J(w_t) \tag{.}

2. 根据历史梯度计算一阶动量和二阶动量

mt=ϕ(g1,g2,...,gt)vt=i=0tgi2(.)m_t=\phi (g_1,g_2,...,g_t) \\ v_t=\sum_{i=0}^t g_i^2 \tag{.}

3. 计算当前时刻的下降梯度

=ηmtvt(.)\nabla = \eta \cdot \frac{m_t}{\sqrt{v_t}} \tag{.}

4. 根据下降梯度进行参数更新

wt+1=wt(.)w_{t+1}=w_t - \nabla \tag{.}

优化器的步骤基本都是以上流程,差异体现在第一步和第二步上。SGD 没有利用动量,MSGD 在 SGD 基础上增加了一阶动量,AdaGrad、AdaDelta 和 RMSProp法在 SGD 基础上增加了二阶动量。Adam 把一阶动量和二阶动量都用起来了

4.2 对优化算法进行可视化

img

从上面的动画可以看出,自适应算法能很快收敛,并快速找到参数更新中正确的目标方向;而标准的 SGD、NAG 和动量项等方法收敛缓慢,且很难找到正确的方向。

4.3 使用哪种优化器?

在构建神经网络模型时,选择出最佳的优化器,以便快速收敛并正确学习,同时调整内部参数,最大程度地最小化损失函数。

Adam 在实际应用中效果良好,超过了其他的自适应技术。

那种优化器最好?该选择哪种优化算法?目前还没能够达达成共识。Schaul et al (2014)展示了许多优化算法在大量学习任务上极具价值的比较。虽然结果表明,具有自适应学习率的优化器表现的很鲁棒,不分伯仲,但是没有哪种算法能够脱颖而出。

在实际应用中,选择哪种优化器应结合具体问题;同时,优化器的选择也取决于使用者对优化器的熟悉程度(比如参数的调节等等)。目前使用最为广泛的优化函数是 SGD 和 Adam。甚至多种优化函数配合使用,比如前期使用 Adam 快速收敛,后期使用 SGD 进一步调优


5. 梯度下降算法的 batch size 总结

5.1 定义与作用

在神经网络训练中,Batch Size(批大小)是指每次迭代中同时处理的样本数量。Batch Size 是一个重要的超参数,对模型的训练速度和性能有着影响。

以下是 Batch Size 的一些常见取值及其特点:

  • Batch Size = 1(随机梯度下降):每次迭代只使用一个样本进行参数更新。这种方式具有最高的随机性,每次迭代的梯度估计具有较大的方差,更新过程中会有较大的波动。优点是占用的内存较少,适用于大规模数据集。缺点是更新过程噪声较大,收敛速度较慢。

  • Batch Size > 1:每次迭代使用多个样本进行参数更新。较小的 Batch Size 可以减小噪声,更快地收敛,但带来的问题是梯度估计的方差较大,可能导致训练过程不稳定。较大的 Batch Size 可以减小梯度估计的方差,提供更稳定的训练过程,但可能占用更多的内存和计算资源。

  • Batch Size = 训练集大小(全批量梯度下降):每次迭代使用整个训练集进行参数更新。这种方式可以得到最准确的梯度估计,但也需要占用较大的内存和计算资源,训练速度较慢,不适用于大规模数据集。

选择合适的Batch Size需要综合考虑以下因素:

  • 内存和计算资源:较小的 Batch Size 可以降低内存和计算需求,适用于资源受限的情况。较大的 Batch Size 可能需要更多的内存和计算资源。

  • 收敛速度:较小的 Batch Size 可能收敛速度更快,但也容易陷入局部最小值。较大的 Batch Size 可能提供更稳定的收敛性能,但可能需要更多的迭代次数。

  • 梯度估计的方差:较小的 Batch Size 具有更大的方差,可能导致训练过程不稳定。较大的 Batch Size 可以减小方差,提供更稳定的训练过程。

一般来说,选择合适的 Batch Size 是一个经验性的过程,需要通过实验和验证来确定最佳取值。在实际应用中,常见的 Batch Size 取值范围通常在几十到几千之间,具体取决于数据集的大小和计算资源的可用性。

5.2 深入理解

Batch 的选择,决定的是下降的方向

在合理范围内,增大 Batch_Size 有何好处?

  • 内存利用率提高了,大矩阵乘法的并行化效率提高。
  • 跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
  • 在一定范围内,一般来说 Batch_Size 越大,其确定的下降方向越准,引起训练震荡越小。

盲目增大 Batch_Size 有何坏处?

  • 内存利用率提高了,但是内存容量可能撑不住了。
  • 跑完一次 epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的 Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化,可能陷入局部最优解。

调节 Batch_Size 对训练效果影响到底如何?

这里跑一个 LeNet 在 MNIST 数据集上的效果。MNIST 是一个手写体标准库,使用的是 Theano 框架。这是一个 Python 的深度学习库。训练效果如图所示:

img

运行结果与上文分析相印证:

  • Batch_Size 太小,算法在 200 epoches 内不收敛。
  • 随着 Batch_Size 增大,处理相同数据量的速度越快。
  • 随着 Batch_Size 增大,达到相同精度所需要的 epoch 数量越来越多。

由于上述两种因素的矛盾, Batch_Size 增大到某个时候,达到时间上的最优。由于最终收敛精度会陷入不同的局部极值,因此 Batch_Size 增大到某些时候,达到最终收敛精度上的最优



面试题

1. 说一下你了解的优化函数?⭐⭐⭐⭐⭐

参考回答

1. 梯度下降法

梯度下降法是原始的优化方法,梯度下降的核心思想负梯度方向是使函数值下降最快的方向,因此我们的目标就是求取目标函数的负梯度

在梯度下降法中,因为每次都遍历了完整的训练集,其能保证结果为全局最优(优点),但是也因为我们需要对于每个参数求偏导,且在对每个参数求偏导的过程中还需要对训练集遍历一次,当训练集很大时,计算费时(缺点)

2. 批次梯度下降法

批次梯度下降法(Batch Gradient Descent)通过计算所有样本的梯度来更新模型的参数,而不是只计算单个样本的梯度。

批次梯度下降法的缺点也是很明显的。首先,它需要将所有的训练数据都载入内存,这在处理大规模数据集时可能会导致内存不足。其次,由于它需要在每个批次上计算梯度,因此在每个训练迭代中需要进行大量的计算,这会降低训练速度。最后,批次梯度下降法很容易陷入局部最优解,因为它只是通过对所有样本的平均梯度进行更新,而忽略了每个样本的特异性。

3. 随机梯度下降法

再极端一点,就是随机梯度下降法,即每次从训练集中随机抽取一个数据来计算梯度。其每次对 ww 的更新,都是针对单个样本数据,并没有遍历完整的参数。当样本数据很大时,可能到迭代完成,也只不过遍历了样本中的一小部分。因此,其速度较快(优点),但是其每次的优化方向不一定是全局最优的(缺点)。

随机梯度下降法也存在一些问题。由于使用单个样本计算梯度,因此每次梯度的估计可能存在较大的方差,导致参数更新的不稳定性。因为误差,所以每一次迭代的梯度受抽样的影响比较大,也就是说梯度含有比较大的噪声,不能很好的反映真实梯度,并且SGD有较高的方差,其波动较大。为了缓解这个问题,可以引入学习率衰减、动量优化等技术。

4. Momentum 随机梯度下降法

Momentum 借用了物理中的动量概念,即前一次的梯度也会参与运算。为了表示动量,引入了一阶动量 mm(momentum)。mm 是之前的梯度的累加,但是每回合都有一定的衰减。

总而言之,momentum 能够加速 SGD 收敛,抑制震荡。并且动量有机会逃脱局部极小值(鞍点)

5. Nesterov动量型随机梯度下降法

Nesterov 动量型随机梯度下降法是在 momentum 更新梯度时加入对当前梯度的校正,让梯度“多走一步”,可能跳出局部最优解。

相比 momentum 动量法,Nesterov 动量型随机梯度下降法对于凸函数在收敛性证明上有更强的理论保证。

6. Adagrad法

SGD 的学习率是线性更新的,每次更新的差值一样。后面的优化法开始围绕自适应学习率进行改进。Adagrad 法引入二阶动量,根据训练轮数的不同,对学习率进行了动态调整。

但缺点是 Adagrad 法仍然需要人为指定一个合适的全局学习率,同时网络训练到一定轮次后,分母上梯度累加过大使得学习率为 0而导致训练提前结束。

7. Adadelta法

Adadelta 法是对 Adagrad 法的扩展,通过引入衰减因子 ρ\rho 消除 Adagrad 法对全局学习率的依赖

Adadelta 法避免了对全局学习率的依赖。而且只用了部分梯度加和而不是所有,这样避免了梯度累加过大使得学习率为 0 而导致训练提前结束。

8. RMSProp法

AdaGrad 算法在迭代后期由于学习率过小,可能较难找到一个有用的解。为了解决这一问题,RMSprop 算法对 Adagrad 算法做了一点小小的修改,RMSprop 使用指数衰减只保留过去给定窗口大小的梯度,使其能够在找到凸碗状结构后快速收敛。RMSProp 法可以视为 Adadelta 法的一个特例

RMSProp 法缺陷在于依然使用了全局学习率,需要根据实际情况来设定。可以看出分母不再是一味的增加,它会重点考虑距离它较近的梯度(指数衰减的效果)。优点是只用了部分梯度加和而不是所有,这样避免了梯度累加过大使得学习率为 0 而导致训练提前结束。

9. Adam法

Adam 法本质上是带有动量项的 RMSProp 法,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam 法主要的优点在于经过偏置校正后,每一次迭代学习率都有一个确定范围,这样可以使得参数更新比较平稳。

Adam(Adaptive Moment Estimation)是一种自适应学习率的优化算法,结合了动量法(Momentum)和RMSprop的思想。它在训练神经网络时能够有效地调整学习率,并具有较好的收敛性和泛化能力。

2. SGD 和 Adam 谁收敛的比较快?谁能达到全局最优解?⭐⭐⭐⭐⭐

参考回答

SGD 算法没有动量的概念,SGD 和 Adam 相比,缺点是下降速度慢,对学习率要求严格。

而 Adam 引入了一阶动量和二阶动量,下降速度比 SGD 快,Adam 可以自适应学习率,所以初始学习率可以很大。

SGD 相比 Adam,更容易达到全局最优解。主要是后期 Adam 的学习率太低,影响了有效的收敛。

我们可以前期使用 Adam,后期使用 SGD 进一步调优。

3. 说说常见的优化器以及优化思路,写出他们的优化公式⭐⭐⭐⭐⭐

回答与第一题类似。

4. 深度学习中的优化算法总结 Optimizer⭐⭐⭐⭐⭐

回答与第一题类似。

5. adam 用到二阶矩的原理是什么⭐⭐⭐⭐⭐

参考回答

Adam 法本质上是带有动量项的 RMSProp 法,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam 算法的主要思想是综合考虑梯度的一阶矩估计(均值)和二阶矩估计(方差)来动态调整参数的学习率。具体而言,它为每个参数维护两个状态变量:一阶矩估计(动量)和二阶矩估计(累积梯度平方和)。

二阶矩的原理是:引入二阶动量,根据训练轮数的不同,对学习率进行了动态调整:

vt=τ=1tgτ2+ϵvt+1=β2vt+(1β2)gt+12(.)v_t=\sqrt{\sum_{\tau=1}^tg_{\tau}^2 +\epsilon} \\ v_{t+1 }= \beta_2 \cdot v_{t} + (1-\beta_2) \cdot g_{t+1}^2 \\ \tag{.}

可以看出来,公式将前面的训练梯度平方加和,在网络训练的前期,由于分母中梯度的累加(vtv_t)较小,所以一开始的学习率 ηt\eta_t 比较大;随着训练后期梯度累加较大时,ηt\eta_t 逐渐减小,而且是自适应地减小。

6. Batch size 的大小如何选择,过大的 batch size 和过小的 batch size 分别有什么影响⭐⭐⭐⭐⭐

参考回答

Batch 选择时尽量采用 2 的幂次,如 8、16、32 等

在合理范围内,增大 Batch_size 的好处

  • 内存利用率提高了,大矩阵乘法的并行化效率提高。
  • 跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
  • 在一定范围内,一般来说 Batch_Size 越大,引起训练震荡越小。可以提供更稳定的梯度估计,降低噪声,从而使训练过程更稳定。

盲目增大Batch_size的坏处

  • 提高了内存利用率,但是内存容量可能不足。

  • 跑完一次 epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加,从而对参数的修正也就显得更加缓慢。

  • Batch_size 增大到一定程度,其确定的下降方向已经基本不再变化。较大的 Batch Size 可能导致模型更容易陷入局部最小值,而较小的 Batch Size 更容易逃离局部最小值,从而获得更好的泛化能力。

Batch_size 过小的影响

  • 内存需求低:较小的 Batch Size 占用较少的内存,适用于资源受限的情况。
  • 训练速度慢:较小的 Batch Size 需要更多的迭代次数才能达到相同的训练轮数,因此训练速度较慢。
  • 较大的随机性:较小的 Batch Size 提供较大的随机性,每个 Batch 的梯度估计可能会有较大的方差。
  • 精度可能更高。较小的 Batch Size 更容易逃离局部最小值,从而获得更好的泛化能力。

选择合适的Batch Size通常需要根据具体的问题和数据集进行实验和验证。一般来说,合理的 Batch Size 取值范围在几十到几百之间,具体取决于数据集的大小、模型的复杂度和计算资源的可用性。通过尝试不同的 Batch Size,并观察模型在验证集上的性能,可以找到最佳的 Batch Size 取值。

7. 梯度下降的思想⭐⭐⭐⭐⭐

参考回答

梯度下降法是原始的优化方法,梯度下降的核心思想负梯度方向是使函数值下降最快的方向,因此我们的目标就是求取目标函数的负梯度

基本思想可以这样理解:我们从山上的某一点出发,找一个最陡的坡走一步(也就是找梯度方向),到达一个点之后,再找最陡的坡,再走一步,直到我们不断的这么走,走到最“低”点(最小花费函数收敛点)。

在梯度下降法中,因为每次都遍历了完整的训练集,其能保证结果为全局最优(优点),但是也因为我们需要对于每个参数求偏导,且在对每个参数求偏导的过程中还需要对训练集遍历一次,当训练集很大时,计算费时(缺点)

8. Momentum 随机梯度下降法的基本步骤⭐⭐⭐⭐⭐

以下是 Momentum 随机梯度下降法的基本步骤:

  1. 初始化模型参数:首先,需要初始化模型的参数,可以是随机初始化或者根据经验设置。

  2. 初始化动量:初始化一个动量变量 v 为 0,用于存储历史梯度信息。

  3. 随机选择一个样本:从训练数据集中随机选择一个样本。

  4. 计算损失函数梯度:对于选定的样本,计算其损失函数关于各个参数的偏导数(梯度)。

  5. 更新动量:根据当前梯度和历史梯度的加权平均,更新动量变量 vv。可以使用指数加权平均的方式计算动量更新的公式为:v=βv+(1β)gradientv = β * v + (1 - β) * gradient,其中 ββ 是动量的衰减因子,控制历史梯度对当前梯度的影响程度。

  6. 更新参数:根据计算得到的动量和学习率(learning rate),确定参数更新的步长和方向。更新参数的公式为:wt+1=wtηvtw_{t+1} = w_{t}- \eta \cdot v_t

  7. 重复步骤3到步骤6:重复随机选择样本、计算梯度、更新动量和更新参数的过程,直到满足停止条件。

Momentum 随机梯度下降法的优势在于它在参数更新时利用了历史梯度的信息,可以加速收敛并提高优化的稳定性。通过累积历史梯度的影响,它可以在梯度方向变化较小的情况下保持较大的更新步长,有助于跳出局部极小值和鞍点。

9. 什么是优化函数,常见的优化器有哪些?⭐⭐⭐⭐⭐

优化函数(Optimization Function)是用于训练机器学习模型的算法,用于调整模型的参数以最小化(或最大化)一个定义良好的目标函数——损失函数或成本函数(Loss/Cost Function)。优化函数就是用来最小化我们的损失函数的

常见的优化函数

  • 梯度下降法(Gradient Descent)及其变种:梯度下降法是一种迭代优化算法,通过计算目标函数对模型参数的梯度方向,并以梯度的相反方向更新参数,逐步降低损失函数的值。

  • 随机梯度下降法(Stochastic Gradient Descent,SGD):SGD是梯度下降法的一种变种,每次迭代随机选择一部分训练样本(mini-batch)计算梯度,并更新参数。它具有计算效率高的优点,特别适用于大规模数据集和深度神经网络的训练。

  • 动量优化算法(Momentum Optimization):动量算法通过引入动量项来加速收敛,并减少梯度更新的震荡。它在更新参数时考虑了之前的梯度信息,有助于在参数空间中跳出局部最优解。

  • 自适应学习率算法(Adaptive Learning Rate Algorithms):自适应学习率算法根据梯度的情况自动调整学习率,使得在训练的不同阶段能够有更好的收敛性能。常见的自适应学习率算法包括 Adagrad、RMSProp 和 Adam 等。

10. 批次梯度下降法和随机梯度下降法的区别⭐⭐⭐⭐⭐

1.更新方式:

  • 批次梯度下降法:在每次迭代中,使用整个训练集的所有样本计算梯度,并在计算完梯度后更新模型的参数。
  • 随机梯度下降法:在每次迭代中,仅使用一个样本(或一个小批量样本)计算梯度,并立即更新模型的参数。

2.训练速度:

  • 批次梯度下降法:由于需要计算整个训练集的梯度,每次迭代的计算代价较高,训练速度相对较慢。
  • 随机梯度下降法:每次迭代仅计算一个样本(或一个小批量样本)的梯度,因此计算代价较低,训练速度相对较快。

3.梯度更新的稳定性:

  • 批次梯度下降法:由于使用整个训练集的梯度进行更新,梯度更新的方向相对稳定,收敛过程相对平滑。
  • 随机梯度下降法:由于仅使用一个样本(或一个小批量样本)的梯度进行更新,梯度更新的方向较为随机,收敛过程可能会有一定的波动。

4.内存占用:

  • 批次梯度下降法:由于使用整个训练集的梯度进行更新,占用内存多。
  • 随机梯度下降法:由于仅使用一个样本(或一个小批量样本)的梯度进行更新,占用内存少。

11. 什么是鞍点,如何跨过鞍点⭐⭐⭐⭐⭐

在神经网络中,鞍点(Saddle Point)是指损失函数在某个点处既不是极小值也不是极大值的位置。在鞍点处,沿着某些方向的梯度为零,但沿着其他方向的梯度不为零。这种情况可能导致优化算法在训练过程中出现停滞,使得模型参数更新变得困难。

鞍点的存在是由于高维空间中的复杂性。在高维空间中,优化问题往往非常复杂,具有多个局部极小值、局部最大值和鞍点。尤其是在深层神经网络中,参数的数量庞大,增加了找到全局最优解的难度。

鞍点对于优化算法来说是一个挑战,因为在鞍点处梯度为零,导致优化算法难以继续更新参数。一种常见的解决方法是使用更复杂的优化算法,例如动量优化、自适应学习率方法(如Adam)等。这些算法能够帮助跳出鞍点并继续优化模型。

12. 说说优化器的发展过程⭐⭐⭐⭐⭐

从优化器发展历程可以看出,有两个参数很重要。一个是优化方向,决定“前进的方向是否正确”,在优化器中反映为梯度或动量。另一个是步长,决定“每一步迈多远”,在优化器中反映为学习率

待优化参数:ww,目标函数:J(w)J(w),初始学习率:η\eta,迭代 epoch:tt

参数更新步骤如下:

1. 计算目标函数关于当前参数的梯度

gt=J(wt)(.)g_t=\nabla J(w_t) \tag{.}

2. 根据历史梯度计算一阶动量和二阶动量

mt=ϕ(g1,g2,...,gt)vt=i=0tgi2(.)m_t=\phi (g_1,g_2,...,g_t) \\ v_t=\sum_{i=0}^t g_i^2 \tag{.}

3. 计算当前时刻的下降梯度

=ηmtvt(.)\nabla = \eta \cdot \frac{m_t}{\sqrt{v_t}} \tag{.}

4. 根据下降梯度进行参数更新

wt+1=wt(.)w_{t+1}=w_t - \nabla \tag{.}

优化器的步骤基本都是以上流程,差异体现在第一步和第二步上。SGD 没有利用动量,MSGD 在 SGD 基础上增加了一阶动量,AdaGrad、AdaDelta 和 RMSProp法在 SGD 基础上增加了二阶动量。Adam 把一阶动量和二阶动量都用起来了

13. 优化器如何选择⭐⭐⭐⭐⭐

在构建神经网络模型时,选择出最佳的优化器,以便快速收敛并正确学习,同时调整内部参数,最大程度地最小化损失函数。

在实际应用中,选择哪种优化器应结合具体问题;同时,优化器的选择也取决于使用者对优化器的熟悉程度(比如参数的调节等等)。目前使用最为广泛的优化函数是 SGD 和 Adam。甚至多种优化函数配合使用,比如前期使用 Adam 快速收敛,后期使用 SGD 进一步调优

14. 什么是梯度下降法?它的优缺点是什么?⭐⭐⭐⭐⭐

梯度下降(gradient descent)在机器学习中应用十分的广泛,不论是在线性回归还是 Logistic 回归中,它的主要目的是通过迭代找到目标函数的最小值,或者收敛到最小值。

基本思想可以这样理解:我们从山上的某一点出发,找一个最陡的坡走一步(也就是找梯度方向),到达一个点之后,再找最陡的坡,再走一步,直到我们不断的这么走,走到最“低”点(最小花费函数收敛点)。

优点: 1. 收敛性:在合适的学习率下,梯度下降法可以收敛到局部最优解或全局最优解。2. 简单直观:梯度下降法易于理解和实现。3. 广泛适用:梯度下降法可以用于训练各种机器学习模型,包括线性模型和神经网络等。

缺点:1. 训练不稳定。2. 选择适当的学习率可能很困难。 太小的学习率会导致收敛性缓慢,而学习速度太大可能会妨碍收敛,并导致损失函数在最小点波动。3. 可能陷入局部最优解:无法逃脱鞍点。

15. 什么是自适应学习率优化算法?请举例说明。⭐⭐⭐⭐⭐

自适应学习率优化算法是一类针对梯度下降法中学习率的自动调整算法。它们通过根据模型参数的历史梯度信息来自适应地调整学习率,以加速模型训练过程并提高收敛性能。

以下是一些常见的自适应学习率优化算法:

  • AdaGrad(Adaptive Gradient):AdaGrad 根据参数的历史梯度信息自适应地调整学习率。具体来说,它会根据参数的梯度平方和的累积来缩放学习率,使得对于频繁出现的梯度较大的参数,学习率会相对较小,而对于不经常出现的梯度较大的参数,学习率会相对较大。

  • RMSprop(Root Mean Square Propagation):RMSprop 也是一种基于梯度平方的自适应学习率算法。它计算参数梯度平方的移动平均,并根据移动平均的大小来调整学习率。相比于 AdaGrad,RMSprop 引入了一个衰减系数,以减少历史梯度的影响。

  • Adam(Adaptive Moment Estimation):Adam 算法结合了动量优化和 RMSprop 的思想。它不仅考虑了梯度的一阶矩(平均)信息,还考虑了梯度的二阶矩(方差)信息。通过综合考虑梯度的平均和方差,Adam 可以自适应地调整学习率,并在不同的参数上提供更准确的更新方向。

16. 什么是学习率衰减(Learning Rate Decay)?为什么要使用学习率衰减?⭐⭐⭐⭐⭐

学习率衰减(Learning Rate Decay)是一种在模型训练过程中逐渐减小学习率的技术。学习率衰减的目的是在训练的后期阶段逐渐减小学习率,以使模型在接近收敛时更加稳定和精确。

学习率衰减的原理是在模型训练过程中逐渐降低学习率的大小。最常见的学习率衰减方式是线性衰减、指数衰减和阶梯衰减等。

为什么要使用学习率衰减呢?主要有以下几个原因:

  • 收敛性:随着训练的进行,模型的性能逐渐接近最优值,此时较大的学习率可能导致训练过程震荡甚至发散。通过学习率衰减,可以使学习率逐渐减小,使模型在接近收敛时更加稳定,有助于达到更好的收敛性。

  • 更小的步长:较大的学习率可能导致参数更新过大,错过了更细微的模型调整。逐渐减小学习率可以使参数更新的步长逐渐缩小,更好地探索模型参数空间。

  • 适应数据分布变化:在训练过程中,数据分布可能会发生变化,特别是在深度学习任务中。学习率衰减可以帮助模型适应不同的数据分布,从而提高模型的泛化能力。

  • 加速训练:初始阶段,较大的学习率可以加快模型的收敛速度。随着训练的进行,通过学习率衰减,可以使模型在接近收敛时进行更精细的调整,从而加速训练过程。

17. 什么是梯度剪裁(Gradient Clipping)?为什么要使用梯度剪裁?⭐⭐⭐⭐⭐

梯度剪裁(Gradient Clipping)是一种在训练深度神经网络时常用的技术,用于限制梯度的大小。梯度剪裁的目的是防止梯度爆炸或梯度消失的问题,以提高模型的稳定性和训练效果。

梯度剪裁的基本思想是设置一个阈值,当梯度的范数(或者某个特定方向的梯度)超过这个阈值时,就将梯度进行裁剪,使其范数不超过阈值。这样可以限制梯度的大小,防止梯度过大或过小对模型训练的不良影响。

18. 什么是Adam优化算法?它与其他优化算法相比有什么优势?⭐⭐⭐⭐⭐

Adam(Adaptive Moment Estimation)是一种自适应学习率优化算法,结合了动量优化算法和自适应学习率的特性。Adam算法利用梯度的一阶矩估计(均值)和二阶矩估计(方差)来自适应地调整学习率,以实现高效的模型参数更新。

Adam算法相对于其他优化算法(如随机梯度下降、动量优化算法等)具有以下优势:

  • 自适应学习率:Adam算法根据梯度的一阶矩和二阶矩来自适应地调整学习率。这使得在训练过程中,学习率能够在不同参数和不同时间步骤下进行自动调节,从而更好地适应问题的特征和梯度的变化。

  • 动量项:Adam算法引入了动量项,可以加速收敛过程并减小震荡。动量项在更新参数时考虑了之前步骤的梯度方向,从而在梯度变化较大或方向变化较频繁的情况下,提供了更稳定的更新方向。

  • 适用于大规模数据和复杂模型:Adam 算法对于大规模数据和复杂模型的训练效果较好。它可以自适应地调整学习率,适应不同的参数尺度和数据分布,从而更好地应对复杂的优化问题。

  • 相对较少的超参数:Adam算法相对于其他优化算法,例如学习率衰减和动量优化算法,有较少的超参数需要调整。通常只需要设置学习率和动量参数即可,减少了调参的负担。