百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

一文带您了解随机梯度下降(SGD):python代码示例

wptr33 2025-02-27 16:56 22 浏览

在机器学习领域,梯度下降扮演着至关重要的角色。随机梯度下降(Stochastic Gradient Descent,SGD)作为一种优化算法,在机器学习和优化领域中显得尤为重要,并被广泛运用于模型训练和参数优化的过程中。

梯度下降是一种优化算法,通过迭代沿着由梯度定义的最陡下降方向,以最小化函数。类似于图中的场景,可以将其比喻为站在山巅,希望找到通往山脚最低点的最佳路径。梯度下降就如同引导您寻找下山的最优路线一样。

梯度下降算法之所以美妙,是因为它的简洁和优雅。其工作原理简述如下:从函数上的一个随机点开始,比如山巅的随机起点。接着,计算该点处函数的梯度(斜率),类似于在山上四处寻找最陡的坡度。一旦确定了方向,就向该方向迈进一步,然后重新计算坡度。反复进行这个过程直至到达底部。

每一步的大小由学习率(the learning rate)来决定。然而,如果学习率太小,可能需要很长时间才能到达底部;反之,如果太大,可能会越过最低点。找到正确的平衡是算法成功的关键。

梯度下降另一个优点是其通用性。它几乎可以应用于任何函数,尤其是那些无法通过解析方法求解的函数。这使得梯度下降在解决各类机器学习问题时(从简单的线性回归到复杂的神经网络)表现出难以置信的多功能性。

"随机(Stochastic)"在随机梯度下降(SGD)的作用

随机梯度下降(Stochastic Gradient Descent,SGD)为传统梯度下降方法增添了一些新意。术语‘随机’指的是与随机概率相关的系统或过程。因此,这种随机性被引入到梯度计算的方式中,与标准梯度下降相比,显著改变了其行为和效率。

在传统的批量梯度下降中,你需要计算整个训练集的损失函数梯度。可以想象,对于大型数据集而言,这可能是计算密集和耗时的。这时就轮到SGD登场了。与其使用整个数据集来计算梯度,SGD在每次迭代中随机选择一些数据点来计算梯度。

想象一下这个过程,就好比你在浓雾中下山,视野有限。与其全景观察来决定下一步该往哪走,不如基于你的脚下踏实的地方选择下山方向。这一步虽然小而随机,但它重复迭代进行,每次都微调你的路径,以响应于脚下的瞬时地形。

SGD随机性带来了几个好处:

  • 速度:每一次迭代只使用小数据子集,SGD在减小损失方面可以取得快速进展,尤其对于大型数据集而言。
  • 避免局部最小值:随机性有助于SGD潜在地避免局部最小值,这是复杂优化问题中常见的问题。
  • 在线学习:由于其能够增量更新模型,SGD非常适合在线学习,当新数据到来时需要更新模型。

然而,这种随机性也引入了收敛路径的变异性。算法不会平滑地朝最小值降低;相反,它采用更为蜿蜒的路径,有时使得收敛过程显得不规律。

随机梯度下降(SGD)的机制

随机梯度下降(Stochastic Gradient Descent,SGD)算法其实相当直观。以下是迭代步骤,帮助理解SGD的工作原理:

初始化(步骤1)

首先,您初始化模型的参数(权重)。这可以通过随机方式或其他初始化技术来完成。SGD的起始点至关重要,因为它影响算法将要采取的路径。

随机选择(步骤2)

在每次训练迭代中,SGD从整个数据集中随机选择一个数据点(或一个小批量的数据点)。这种随机性使其成为“随机”的一部分。

计算梯度(步骤3)

计算损失函数的梯度,但仅针对随机选择的数据点(或数据点集)。梯度是一个指向损失函数最陡增加方向的矢量。在SGD的上下文中,它告诉您如何调整参数,使模型对于那个特定数据点更准确。

?θJ(θ)代表损失函数J(θ)相对于参数θ的梯度。这个梯度是一个偏导数的向量,向量的每个分量是相对于θ中对应参数的损失函数的偏导数。

更新参数(步骤4)

根据梯度的反方向调整模型参数。学习率η在这里扮演关键角色。更新每个参数的公式为:

  • θnew表示更新后的参数。
  • θold表示更新前的当前参数。
  • η是学习率,一个正标量,确定沿着负梯度方向的步长大小。
  • ?θJ(θ)是损失函数J(θ)相对于参数θ的梯度。

学习率决定了您向最小值迈出的步幅大小。如果太小,算法将很慢;如果太大,可能会超过最小值。

重复直到收敛(步骤5)

重复步骤2至4,进行一定数量的迭代,或者直到模型性能不再提升。每次迭代提供一个稍微更新的模型。

理想情况下,经过多次迭代,SGD收敛到一组使损失函数最小化的参数,尽管由于其随机性,达到收敛的路径并不像批量梯度下降那样平滑,可能会在最小值周围波动。

理解学习率

在随机梯度下降(Stochastic Gradient Descent,SGD)算法中,最关键的超参数之一是学习率(the learning rate)。这个超参数能够显著影响模型的性能和收敛性。理解并选择正确的学习率是有效使用SGD的一个关键步骤。

什么是学习率?

在SGD中,学习率决定了算法朝损失函数最小值迈出的步幅大小。它是一个标量,调整梯度的大小,决定在每次更新中调整模型权重的程度。如果将损失函数想象成一个山谷,学习率决定您在每次迭代中向下走时迈出的步幅大小。

学习率过高

如果学习率过高,所采取的步幅可能过大。这可能导致越过最小值,使得算法发散或者在找不到稳定点的情况下狂乱振荡。可以将其想象成在山谷中跳跃,可能一遍又一遍地跳过最低点。

学习率过低

另一方面,学习率过低导致步幅非常小。虽然看起来可能是安全的,但它会显著减慢收敛过程。在最糟糕的情况下,算法可能会陷入局部最小值,甚至在达到最小值之前停止改进。可以想象成在山谷中移动得太慢,要么卡住了,要么需要不切实际的长时间才能到达谷底。

找到合适的平衡

理想的学习率既不会过高也不会过低,而是取得平衡,使得算法能够有效地收敛到全局最小值。通常,学习率通过实验选择,并且通常设置为随时间减小。这种方法被称为学习率退火或调度。

学习率调整策略:

常见的策略包括:

  1. 基于时间的衰减: 学习率在每次更新时减小。
  2. 阶梯衰减: 在一定数量的迭代后以某个因子减小学习率。
  3. 指数衰减: 按指数方式减小学习率。
  4. 自适应学习率: 例如AdaGrad、RMSProp和Adam等方法会在训练过程中自动调整学习率。

scikit-learn 中的 SGD

可以通过 scikit-learn(机器学习)等流行库中的几行代码直接调用 SGD。我们看一下scikit-learn 官方分类示例:

import matplotlib.pyplot as plt
import numpy as np


from sklearn import datasets
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.linear_model import SGDClassifier


# import some data to play with
iris = datasets.load_iris()


# we only take the first two features. We could
# avoid this ugly slicing by using a two-dim dataset
X = iris.data[:, :2]
y = iris.target
colors = "bry"


# shuffle
idx = np.arange(X.shape[0])
np.random.seed(13)
np.random.shuffle(idx)
X = X[idx]
y = y[idx]


# standardize
mean = X.mean(axis=0)
std = X.std(axis=0)
X = (X - mean) / std


clf = SGDClassifier(alpha=0.001, max_iter=100).fit(X, y)
ax = plt.gca()
DecisionBoundaryDisplay.from_estimator(
    clf,
    X,
    cmap=plt.cm.Paired,
    ax=ax,
    response_method="predict",
    xlabel=iris.feature_names[0],
    ylabel=iris.feature_names[1],
)
plt.axis("tight")


# Plot also the training points
for i, color in zip(clf.classes_, colors):
    idx = np.where(y == i)
    plt.scatter(
        X[idx, 0],
        X[idx, 1],
        c=color,
        label=iris.target_names[i],
        cmap=plt.cm.Paired,
        edgecolor="black",
        s=20,
    )
plt.title("Decision surface of multi-class SGD")
plt.axis("tight")


# Plot the three one-against-all classifiers
xmin, xmax = plt.xlim()
ymin, ymax = plt.ylim()
coef = clf.coef_
intercept = clf.intercept_




def plot_hyperplane(c, color):
    def line(x0):
        return (-(x0 * coef[c, 0]) - intercept[c]) / coef[c, 1]


    plt.plot([xmin, xmax], [line(xmin), line(xmax)], ls="--", color=color)




for i, color in zip(clf.classes_, colors):
    plot_hyperplane(i, color)
plt.legend()
plt.show()

SGD的优势与挑战

SGD的优势:

  • 高效处理大型数据集: SGD的主要优势之一是其在处理大规模数据时的高效性。由于它每次只使用一个数据点(或小批量),更新参数的内存占用明显较低,远远少于需要整个数据集进行每次更新的算法。通过频繁地更新模型参数,SGD能够更快地收敛到一个良好的解决方案,尤其是在数据集庞大的情况下。
  • 灵活性与适应性: SGD能够增量更新模型,使其非常适用于在线学习,即模型需要不断适应新数据的情况。对于随时间变化的数据集,SGD的增量更新方法可以更有效地适应这些变化,相比批处理方法更具优势。
  • 克服局部最小值的挑战:SGD的随机性有助于其潜在地避免陷入局部最小值,这是许多优化问题中的一个重要挑战。随机波动使得算法能够探索更广泛的解空间。
  • 普适性:SGD可以应用于各种问题,不受模型类型的限制。这种广泛适用性使得它成为机器学习工具箱中一种多才多艺的工具。
  • 简单易用:尽管其效果显著,但SGD仍然相对简单易懂和易于实现。这种易用性对于初学者尤其有吸引力。
  • 改善泛化效果:通过以高度变化的方式频繁更新模型,SGD通常能够产生在未见数据上更好泛化的模型。这是因为该算法不太可能过度拟合训练数据中的噪声。
  • 与先进技术兼容:SGD与各种增强和扩展技术兼容,如动量、学习率调度以及Adam等自适应学习率方法,这进一步提高了其性能和多功能性。

SGD的挑战:

虽然随机梯度下降(SGD)是一种强大且强适应性的优化算法,但它也面临一系列挑战。了解这些难题并知道如何克服它们可以极大地提高SGD在实际应用中的性能和可靠性。

  • 选择正确的学习率:选择适当的学习率对于SGD至关重要。如果太高,算法可能会发散;如果太低,可能需要很长时间才能收敛或陷入局部最小值。使用学习率调度或自适应学习率方法。像学习率退火这样的技术,其中学习率随时间减小,可以帮助找到平衡点。
  • 处理噪声引起的波动:SGD的随机性和噪声数据导致算法的波动、不太稳定且收敛时间较长。实施小批量SGD,其中梯度是在数据的小子集上计算而不是单个数据点。这种方法可以降低噪声数据引起的误差。
  • 局部最小值和鞍点的风险:在复杂的模型中,SGD可能会陷入局部最小值或鞍点,特别是在高维空间中。使用动量或Nesterov加速梯度等技术,帮助算法穿越平坦区域并避免陷入局部最小值。
  • 特征缩放的敏感性:SGD对特征的缩放敏感,不同尺度的特征可能使优化过程效率低下。标准化或归一化输入特征,使其在相似尺度上。这一做法可以显著提高SGD的性能。
  • 超参数调优:SGD需要仔细调整超参数,不仅仅是学习率,还有动量和小批量的大小等参数。利用网格搜索、随机搜索或更高级的方法,如贝叶斯优化,找到最佳的超参数组合。
  • 过拟合:与任何机器学习算法一样,存在过拟合的风险,即模型在训练数据上表现良好但在未见数据上表现差。使用正则化技术,如L1或L2正则化,并使用保留集或交叉验证来验证模型。

以上这些建议旨在帮助充分利用SGD的优势,并克服其在实际应用中可能遇到的挑战。通过合理选择超参数、增加鲁棒性,以及采用适当的技巧,可以使SGD在各种场景中发挥更好的效果。


随机梯度下降(SGD)是机器学习中重要的优化算法,通过随机选择数据点计算梯度,高效处理大规模数据。其灵活性、适应性、普适性以及简单易用的特点使其成为多种问题的首选。然而,正确选择学习率、处理噪声影响、克服局部最小值等挑战仍需注意。SGD在实际应用中需谨慎调优超参数、防止过拟合,通过适当方法克服难题,发挥最佳效果。

相关推荐

MySQL进阶五之自动读写分离mysql-proxy

自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...

Postgres vs MySQL_vs2022连接mysql数据库

...

3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?

引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...

一文由浅入深带你完全掌握MySQL的锁机制原理与应用

本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...

验证Mysql中联合索引的最左匹配原则

后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...

MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)

目录1.索引基础...

你会看 MySQL 的执行计划(EXPLAIN)吗?

SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...

MySQL 从入门到精通(四)之索引结构

索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...

mysql总结——面试中最常问到的知识点

mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...

mysql总结——面试中最常问到的知识点(2)

首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...

MySQL基础全知全解!超详细无废话!轻松上手~

本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...

深入剖析 MySQL 中的锁机制原理_mysql 锁详解

在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...

Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析

引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...

MySQL基础篇:DQL数据查询操作_mysql 查

一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...

MySql:索引的基本使用_mysql索引的使用和原理

一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...