梯度下降法与牛顿法在机器学习中的应用及对比

2 阅读13分钟

一、梯度/最速下降法

1.1 梯度下降法介绍

无约束优化问题是机器学习/深度学习中最普遍的优化问题:

image.png

梯度下降示例图

image.png

因为在迭代初期,函数值下降得比较快,但在接近目标值时仍然按照较大的步长迭代的话,会产生震荡。

震荡示例图

由于样本量往往很庞大,梯度下降法在深度学习中的应用,又可以分为三种[3]:

Ø 批量梯度下降(Batch Gradient Descent):在这种方法中,我们计算整个训练集的梯度。这种方法的优点是可以得到全局最优解,但当数据集很大时,每一步的计算都会非常耗时,时间空间成本大。

Ø 随机梯度下降(Stochastic Gradient Descent, SGD):与批量梯度下降不同,SGD在每一步只选择一个样本来计算梯度。这样做的好处是计算速度快,而且添加了一定的随机性,有助于跳出局部最小值。不过,这也可能导致优化路径变得非常嘈杂,易受样本噪声影响。

Ø 小批量梯度下降(Mini-batch Gradient Descent):这种方法介于上述两者之间,它每次计算一小批样本的梯度。这种方法既利用了数据的局部性,又保持了一定程度的计算效率。

1.2 梯度下降在机器学习深度学习中的应用

梯度下降在机器学习和深度学习中的应用是多样且广泛的,本质上,它是一种优化算法,用于最小化模型在训练过程中的损失函数。以下是梯度下降算法在不同领域的具体应用案例。

在机器学习中,线性回归是最简单的应用之一。假设我们有一组数据点,我们想要找到一条直线,这条直线可以尽可能地接近所有的数据点。这里的“接近”是通过均方误差(MSE)损失函数来量化的。梯度下降帮助我们找到直线的斜率和截距,使得MSE最小。在每次迭代中,我们计算损失函数关于斜率和截距的梯度,并更新这两个参数,直到找到损失函数的最小值。

在逻辑回归中,我们使用交叉熵损失函数,并通过梯度下降来调整决策边界的参数。每次迭代,我们更新参数以减少损失,最终得到一个良好的分类模型。

在深度学习中,神经网络包含了许多层,每层都有大量的参数需要优化。梯度下降在这里的作用是至关重要的。以卷积神经网络(CNN)为例,CNN通过卷积层来提取图像的特征,然后通过全连接层来进行分类。梯度下降在这里用于优化卷积核参数和全连接层的权重,以减少分类错误。

在自然语言处理(NLP)中,模型如循环神经网络(RNN)和Transformer被用于处理序列数据。例如,在机器翻译中,梯度下降被用来优化模型的参数,以便更准确地将一种语言翻译成另一种语言。通过调整网络中的权重,梯度下降帮助模型学习语言的语法和语义规则。

在强化学习中,梯度下降也扮演了重要角色。例如,在训练一个深度Q网络(DQN)时,我们使用梯度下降来优化网络的权重,使得代理能够在环境中采取最优策略以最大化累积奖励。

在机器学习的实践中,模型的性能不仅取决于参数的优化,还取决于超参数的选择。虽然梯度下降本身不直接用于超参数的选择,但相关的技术,如基于梯度的超参数优化方法(如Bayesian optimization),可以利用梯度信息来更高效地搜索超参数空间。

在无监督学习中,梯度下降可以用于特征学习。例如,在自编码器中,我们使用梯度下降来优化网络的权重,使得网络能够学习到数据的有效表示(特征)。通过最小化输入和输出之间的差异,自编码器能够发现数据中的结构和模式。

在计算机视觉中,梯度下降用于训练可以进行图像识别、目标检测和图像分割的深度学习模型。例如,使用梯度下降优化的卷积神经网络能够识别图像中的物体、人脸或其他特定模式。

在语音识别应用中,梯度下降用于训练深度学习模型,如长短期记忆网络(LSTM),以识别和转录语音数据。通过优化网络的权重,模型能够学习到语音信号中的模式,实现从语音到文本的转换。

梯度下降作为一种优化算法,在机器学习和深度学习的各个领域都有着广泛的应用。它通过迭代过程逐渐调整模型参数,以最小化损失函数,从而提升模型的性能。随着研究的深入,出现了许多梯度下降的变种和改进算法,这些算法在不同的应用中展现出了它们的优势。梯度下降不仅是理解机器学习核心概念的重要一环,也是推动实际应用向前发展的动力。

二、牛顿法的两种视角

2.1 解方程零点的视角

image.png

image.png

2.2 泰勒展开拟合二次函数的视角

image.png

泰勒拟合函数示意图

image.png

image.png

2.3 牛顿法收敛速度

image.png

2.4 牛顿法在机器学习深度学习中的应用

在机器学习和深度学习中,牛顿法的应用通常涉及以下几个方面:

优化问题:牛顿法在机器学习中可以用于参数优化,尤其是在目标函数是凸函数且Hessian矩阵容易计算的情况下。例如,在逻辑回归和支持向量机(SVM)中,当数据集不是特别大时,牛顿法可以有效地用于优化目标函数,找到最优的参数。(详见代码附件)

牛顿法来优化逻辑回归模型的参数

深度学习中的二阶优化方法:虽然牛顿法在深度学习中不如梯度下降法常用,但它启发了一系列二阶优化算法,如拟牛顿法(如BFGS和L-BFGS)。这些算法尝试在不直接计算Hessian矩阵的情况下近似牛顿法的更新步骤,以此来加速收敛。

神经网络的训练:在神经网络的训练过程中,牛顿法的变种也被用来加速训练。例如,Hessian-Free优化是一种二阶优化方法,它不直接计算整个Hessian矩阵,而是使用共轭梯度法来近似牛顿更新步。这种方法尤其适用于大规模神经网络的训练。

解决约束优化问题:在机器学习中,有时需要解决带约束的优化问题。牛顿法可以与拉格朗日乘数法结合使用,解决这类优化问题。例如,在训练具有等式或不等式约束的神经网络时,牛顿法可以用于求解拉格朗日对偶问题,从而找到满足约束的最优解。

特征选择和稀疏学习:在特征选择和稀疏学习领域,牛顿法可以应用于L1正则化问题,如Lasso回归。通过结合牛顿法和坐标下降法,可以有效地求解带有L1惩罚项的优化问题,进而实现特征的稀疏选择。

尽管牛顿法在某些问题上非常有效,但它也有一些局限性,特别是在深度学习中:牛顿法需要计算Hessian矩阵和它的逆,对于参数数量非常多的深度学习模型来说,这是非常耗时且内存消耗巨大的。当目标函数非凸时,牛顿法可能会收敛到局部最大值或鞍点。牛顿法对初始点的选择比较敏感,不恰当的初始点可能导致不收敛。

因此,在实际应用中,尤其是在处理大规模深度学习问题时,通常会选择梯度下降法或其变种,如Adam、RMSprop等,因为它们更适合处理大规模数据集和模型参数。

总的来说,牛顿法在机器学习中的应用相对有限,主要是因为其计算成本高和适用范围的限制。尽管如此,牛顿法及其变种在某些特定问题中仍然是非常有价值的工具,特别是在模型较小或者数据集较小时。此外,牛顿法的思想也启发了许多先进的优化技术,对优化理论和实践都有着重要的影响。

三、两种方法的总结与对比

在机器学习和深度学习的优化问题中,选择合适的算法对于模型的训练效率和性能至关重要。梯度下降法和牛顿法是两种常用的优化算法,它们在理论和实践中有着截然不同的特征和表现。

3.1 收敛速度的对比

梯度下降法:通常具有线性收敛速度,这意味着它需要更多的迭代次数来接近最优解。尤其是在接近最小值点时,由于步长(学习率)的限制,其收敛速度会显著下降。

牛顿法:理论上具有二阶收敛速度,在最优解附近时,收敛速度非常快。但这种快速收敛依赖于较为精确的初始点选择,如果初始点选得不好,牛顿法可能会表现出不稳定性,甚至发散。

3.2 计算复杂度的对比

梯度下降法:每次迭代只需要计算函数的梯度,对于每个参数,这是一个一阶导数的计算。对于大规模问题,这种一阶方法的计算成本相对较低。

牛顿法:需要计算函数的Hessian矩阵以及其逆矩阵,这在参数维度很高时变得非常昂贵。对于包含数百万参数的深度神经网络,这种计算是不切实际的。

3.3 稳定性和局部最优的风险对比

梯度下降法:容易受到学习率选择的影响,如果学习率太大,可能会导致震荡甚至发散;如果学习率太小,又会导致收敛速度慢,并有可能陷入局部最优。

牛顿法:由于使用了二阶信息,理论上可以更准确地调整每一步的方向和大小,从而减少震荡的风险。然而,当面对非凸优化问题时,牛顿法也可能会被局部最优所困扰。

简单来说,牛顿法拟合点不能离目标极小点太远,否则可能拟合出没有极小值的凸函数。

梯度下降法在距离目标极小点较远时能快速下降,但在越接近极小点附近越容易震荡;而牛顿法越接近目标极小点越好。

拟合出没有极小值的凸函数

3.4 在深度学习中的实际应用对比

梯度下降法:由于其简单性和可扩展性,在深度学习中得到了广泛的应用。特别是其变体,如随机梯度下降(SGD)及其带动量的版本,是训练深度神经网络的标准工具。

牛顿法:虽然在小到中等规模的机器学习问题中表现优异,但在深度学习中由于计算和存储的限制,很少直接使用。相反,一些基于牛顿法的近似方法,如拟牛顿法,有时会被考虑。

3.5 结合使用的可能性

梯度下降法:在优化问题的早期阶段,使用梯度下降法能够快速地接近最优解的区域。

牛顿法:一旦接近最优解,切换到牛顿法可能会加速收敛,尤其是在参数的精细调整阶段。

这是比较理想的情况,目前大多数情况下,深度学习中还是通过衰减梯度下降步长/学习率来减少震荡的发生。

在实践中,优化算法的选择需要根据具体问题的性质和可用资源来做出。尽管牛顿法在理论上具有优越的收敛性质,但在深度学习的背景下,梯度下降法因其实现简单和对大规模数据集的适应性而更为常用。针对不同的优化阶段和问题规模,这两种方法可以被灵活地结合使用,以充分利用它们的优势。最终,了解每种方法的内在机制和它们在实际应用中的表现是做出明智选择的关键。

参考:

[1] 清华numbda课题组数值算法交互演示系统(交互算法演示Java程序)numbda.cs.tsinghua.edu.cn/~yuwj/na.ht…

[2] 动手学习深度学习
zh-v2.d2l.ai/

[3] 深度学习的数学基础
www.bilibili.com/video/BV1Eg…

代码(牛顿法的实现及简单应用演示):

牛顿法的实现

%matplotlib inline
import numpy as np
import torch
from d2l import torch as d2l
import matplotlib.pyplot as plt
def show_trace(results, f):
    n = max(abs(min(results)), abs(max(results)))
    f_line = torch.arange(-n, n, 0.01)
    d2l.set_figsize()
    d2l.plot([f_line, results], [[f(x) for x in f_line], [
        f(x) for x in results]], 'x', 'f(x)', fmts=['-', '-o'])

给定一个凸双曲余弦函数,其中为某些常数, 可以看到经过几次迭代后,得到了处的全局最小值

c = torch.tensor(0.5)

def f(x):  # O目标函数
    return torch.cosh(c * x)

def f_grad(x):  # 目标函数的梯度
    return c * torch.sinh(c * x)

def f_hess(x):  # 目标函数的Hessian
    return c**2 * torch.cosh(c * x)

def newton(eta=1):
    x = 10.0
    results = [x]
    for i in range(10):
        x -= eta * f_grad(x) / f_hess(x)
        results.append(float(x))
    print('epoch 10, x:', x)
    return results

show_trace(newton(), f)
epoch 10, x: tensor(0.)

output_4_1.svg

优化问题

牛顿法在机器学习中可以用于参数优化,尤其是在目标函数是凸函数且Hessian矩阵容易计算的情况下。例如,在逻辑回归,当数据集不是特别大时,牛顿法可以有效地用于优化目标函数,找到最优的参数。

image.png

# 逻辑回归的假设函数 h(x)
def h(theta, X):
    return 1.0 / (1 + np.exp(-np.dot(X, theta)))

# 逻辑回归的成本函数 J(theta)
def cost_function(theta, X, y):
    m = len(y)
    term1 = np.dot(-np.array(y).T, np.log(h(theta, X)))
    term2 = np.dot((1 - np.array(y)).T, np.log(1 - h(theta, X)))
    return np.sum(term1 - term2) / m

# 梯度计算
def gradient(theta, X, y):
    m = len(y)
    return np.dot(X.T, h(theta, X) - y) / m

# Hessian 矩阵计算
def hessian(theta, X, y):
    m = len(y)
    _h = h(theta, X)
    diag = _h * (1 - _h)
    return np.dot(np.dot(X.T, np.diag(diag)), X) / m

# 牛顿法
def newton_method(theta, X, y, num_iters):
    m = len(y)
    for i in range(num_iters):
        grad = gradient(theta, X, y)
        H = hessian(theta, X, y)
        theta -= np.linalg.inv(H).dot(grad)
    return theta
# 展示优化过程
def plot_newton_method(theta, X, y, num_iters=10):
    # 为了可视化,假设 X 只有两个特征
    x_plot = np.linspace(min(X[:,1]), max(X[:,1]), 100)
    y_plot = -(theta[0] + theta[1]*x_plot) / theta[2]

    plt.figure()
    plt.scatter(X[:,1], X[:,2], c=y, cmap=plt.cm.Set1)
    plt.plot(x_plot, y_plot, 'b-')
    plt.xlabel('Feature 1')
    plt.ylabel('Feature 2')
    plt.title('Newton Method Optimization Process')
    plt.show()
# 模拟数据
np.random.seed(0)
X = np.random.randn(100, 2)
y = (X[:,0] + X[:,1] > 0) * 1  # 简单的线性可分数据集

# 添加截距项
X_with_intercept = np.hstack((np.ones((X.shape[0], 1)), X))
theta_initial = np.zeros(X_with_intercept.shape[1])

# 运行牛顿法
theta_optimized = newton_method(theta_initial, X_with_intercept, y, num_iters=10)

# 展示优化过程
plot_newton_method(theta_optimized, X_with_intercept, y)

output_9_0.svg