【深度学习-Day 16】梯度下降法 - 如何让模型自动变聪明?

Langchain系列文章目录

01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来

Python系列文章目录

PyTorch系列文章目录

机器学习系列文章目录

深度学习系列文章目录

Java系列文章目录

JavaScript系列文章目录

深度学习系列文章目录

01-【深度学习-Day 1】为什么深度学习是未来?一探究竟AI、ML、DL关系与应用
02-【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
03-【深度学习-Day 3】搞懂微积分关键:导数、偏导数、链式法则与梯度详解
04-【深度学习-Day 4】掌握深度学习的“概率”视角:基础概念与应用解析
05-【深度学习-Day 5】Python 快速入门:深度学习的“瑞士军刀”实战指南
06-【深度学习-Day 6】掌握 NumPy:ndarray 创建、索引、运算与性能优化指南
07-【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战
08-【深度学习-Day 8】让数据说话:Python 可视化双雄 Matplotlib 与 Seaborn 教程
09-【深度学习-Day 9】机器学习核心概念入门:监督、无监督与强化学习全解析
10-【深度学习-Day 10】机器学习基石:从零入门线性回归与逻辑回归
11-【深度学习-Day 11】Scikit-learn实战:手把手教你完成鸢尾花分类项目
12-【深度学习-Day 12】从零认识神经网络:感知器原理、实现与局限性深度剖析
13-【深度学习-Day 13】激活函数选型指南:一文搞懂Sigmoid、Tanh、ReLU、Softmax的核心原理与应用场景
14-【深度学习-Day 14】从零搭建你的第一个神经网络:多层感知器(MLP)详解
15-【深度学习-Day 15】告别“盲猜”:一文读懂深度学习损失函数
16-【深度学习-Day 16】梯度下降法 - 如何让模型自动变聪明?



前言

在上一篇文章中,我们探讨了如何使用损失函数来衡量模型预测的好坏。我们知道,一个好的模型应该有尽可能低的损失值。但这引出了一个核心问题:我们如何才能找到一组模型的参数(权重和偏置),使得损失函数的值最小化呢?手动去调整成千上万甚至上亿的参数显然是不现实的。幸运的是,我们有一种强大的数学工具——梯度下降法 (Gradient Descent),它能像一位聪明的向导,带领我们自动地走向损失函数的“谷底”。本文将深入浅出地为您揭开梯度下降法的神秘面纱,理解它是如何驱动神经网络学习的。

一、梯度下降:下山的比喻

想象一下,您正站在一座连绵起伏的大山上(这座山就代表我们的损失函数曲面),您的目标是尽快到达山谷的最低点(损失函数的最小值)。然而,山上雾气弥漫,您无法直接看到最低点在哪里,只能感知到自己当前位置的坡度。那么,最明智的策略是什么呢?

1.1 核心思想:寻找最陡峭的下坡路

最直观的想法是:每一步都沿着当前位置最陡峭的下坡方向走一小步。不断重复这个过程,理论上您就能一步步接近,甚至最终到达山谷的最低点。

这就是梯度下降法的核心思想!在数学中,“坡度”这个概念可以用梯度 (Gradient) 来精确描述。

1.2 梯度是什么?

在之前的数学基础篇中,我们接触过导数和偏导数。对于一个多元函数(比如我们的损失函数,它依赖于多个模型参数),梯度就是由所有偏导数组成的向量。

假设我们的损失函数是 L ( w 1 , w 2 , . . . , w n ) L(w_1, w_2, ..., w_n) L(w1​,w2​,...,wn​),其中 w i w_i wi​ 是模型的参数。那么,损失函数 L L L 的梯度 $ \nabla L $ 就是:

∇ L = ( ∂ L ∂ w 1 , ∂ L ∂ w 2 , . . . , ∂ L ∂ w n ) \nabla L = \left( \frac{\partial L}{\partial w_1}, \frac{\partial L}{\partial w_2}, ..., \frac{\partial L}{\partial w_n} \right) ∇L=(∂w1​∂L​,∂w2​∂L​,...,∂wn​∂L​)

这个梯度向量有一个非常重要的特性:它指向函数值增长最快的方向。

1.3 如何下山?

既然梯度指向的是上坡最陡的方向,那么我们只需要沿着梯度的相反方向前进,就能找到下坡最陡的方向。这就是梯度下降的核心操作。

我们需要不断地更新模型的参数 w w w,更新规则如下:

w n e w = w o l d − α ∇ L w_{new} = w_{old} - \alpha \nabla L wnew​=wold​−α∇L

其中:

  • w n e w w_{new} wnew​ 是更新后的参数。
  • w o l d w_{old} wold​ 是当前的参数。
  • ∇ L \nabla L ∇L 是损失函数在 w o l d w_{old} wold​ 处的梯度。
  • α \alpha α (alpha) 是一个非常重要的超参数,我们称之为学习率 (Learning Rate)。

二、学习率:步子迈多大?

在下山的比喻中,我们决定了每一步的方向(梯度的反方向),但还有一个关键问题:每一步应该迈多大?这个“步长”就是由学习率 α \alpha α 控制的。

2.1 学习率的重要性

学习率的选择对模型的训练过程至关重要:

  • 学习率过小 (Too Small): 想象一下,您每一步只挪动一小点。虽然方向是对的,但您需要花费非常非常长的时间才能到达山底。在模型训练中,这意味着收敛速度过慢,需要更多的训练迭代次数,消耗更多计算资源。
  • 学习率过大 (Too Large): 想象一下,您一步迈得太大,直接跨过了山谷,甚至可能跑到了对面更高的山坡上。在模型训练中,这会导致损失函数的值在最低点附近来回震荡,无法收敛,甚至可能直接发散(损失值越来越大)。

2.2 如何选择学习率?

选择合适的学习率是一门艺术,也是深度学习实践中的一个挑战。

  • 经验法则:通常我们会从一些常用的值开始尝试,如 0.1, 0.01, 0.001, 0.0001。
  • 学习率衰减 (Learning Rate Decay):在训练开始时使用较大的学习率,随着训练的进行逐渐减小学习率,这有助于模型在开始时快速下降,在接近最低点时精细调整。
  • 自适应学习率算法:后续我们会介绍更高级的优化算法(如 Adam, RMSprop),它们可以自动调整学习率。

目前,我们只需要理解学习率的核心作用即可。

三、批量梯度下降 (BGD)

我们现在知道了梯度下降的核心思想和学习率的重要性。但还有一个细节:我们应该在什么时候计算梯度并更新参数呢?批量梯度下降 (Batch Gradient Descent, BGD) 给出了一种最直接的答案。

3.1 BGD 的工作流程

BGD 的策略是:在每一次参数更新时,都使用 整个 训练数据集来计算损失函数的梯度。

其具体步骤如下:

  1. 初始化模型参数 w w w(随机初始化或使用预设值)。
  2. 重复以下步骤,直到满足停止条件(例如达到最大迭代次数,或损失值变化很小):
    • 在整个训练数据集上计算损失函数 L L L。
    • 计算损失函数 L L L 相对于所有参数 w w w 的梯度 ∇ L \nabla L ∇L。
    • 使用梯度和学习率 α \alpha α 更新参数: w = w − α ∇ L w = w - \alpha \nabla L w=w−α∇L。

3.2 BGD 的优点

  • 方向准确:由于每次都使用所有数据计算梯度,所以得到的梯度方向更能代表全局的趋势,更新方向比较稳定,通常能朝着最小值前进。
  • 易于理解和实现:概念简单,实现直接。
  • 理论保证:对于凸函数 (Convex Function),BGD 理论上可以保证收敛到全局最小值;对于非凸函数(神经网络通常是非凸的),它可以收敛到一个局部最小值或鞍点。

3.3 BGD 的缺点

  • 计算成本高:这是 BGD 最大的问题。当训练数据集非常大时(在深度学习中这很常见,可能有数百万甚至数十亿样本),每次迭代都要计算所有样本的梯度,这将消耗巨大的计算资源和时间。
  • 无法进行在线学习:它要求一次性获取所有数据,不适合数据流式到来的场景。
  • 内存占用大:需要将整个数据集加载到内存中进行计算。

由于这些缺点,纯粹的 BGD 在实际的深度学习应用中并不常用,但它是理解其他更高效梯度下降变种(如 SGD 和 Mini-batch GD)的基础。

3.4 简单的 Python 概念示例

下面是一个非常简化的概念性代码,展示 BGD 的思想(假设我们有一个简单的线性回归模型和均方误差损失)。

import numpy as np

# 假设的训练数据 (X) 和标签 (y)
X = np.array([[1], [2], [3], [4]])
y = np.array([[2], [4], [6], [8]])
# 添加偏置项 x0=1
X_b = np.c_[np.ones((4, 1)), X]

# 初始化参数 (w0, w1)
w = np.random.randn(2, 1)

# 设置学习率和迭代次数
learning_rate = 0.01
n_iterations = 1000
m = len(X_b) # 样本数量

print(f"初始参数 w: {w.ravel()}")

# --- BGD 核心循环 ---
for iteration in range(n_iterations):
    # 1. 计算所有样本的预测值 (前向传播)
    predictions = X_b.dot(w)

    # 2. 计算所有样本的误差
    errors = predictions - y

    # 3. 计算整个批次的梯度 (这里使用了 MSE 损失的梯度公式)
    # 梯度 = (2/m) * X_b^T * (X_b * w - y)
    gradients = 2/m * X_b.T.dot(errors)

    # 4. 更新参数 w
    w = w - learning_rate * gradients

    # (可选) 打印损失值,观察下降过程
    if iteration % 100 == 0:
        loss = np.mean(errors**2)
        print(f"迭代 {iteration}: 损失 = {loss:.4f}, 梯度 = {gradients.ravel()}")

print(f"--- 训练完成 ---")
print(f"最终参数 w: {w.ravel()}") # 理想值应接近 [0, 2]

注意:这只是一个概念演示,实际应用中我们会使用深度学习框架(如 PyTorch 或 TensorFlow)来自动计算梯度。

五、常见问题与展望

5.1 局部最小值与鞍点

虽然我们希望梯度下降能带我们到全局最小值,但对于复杂的非凸函数(如神经网络的损失曲面),梯度下降可能会陷入局部最小值 (Local Minima) 或 鞍点 (Saddle Points)。

  • 局部最小值:一个区域内的最低点,但不是全局最低点。到达这里后,梯度为零,模型可能停止更新。
  • 鞍点:在一个方向上是最小值,但在另一个方向上是最大值。梯度也为零,同样可能导致模型停止更新。

幸运的是,在高维空间中,真正的局部最小值相对较少,而鞍点更常见。后续我们将学习的更高级优化算法(如 Momentum, Adam)在一定程度上能帮助我们“逃离”这些陷阱。

5.2 为什么 BGD 不常用?

如前所述,BGD 的计算成本太高。在下一篇文章中,我们将介绍两种更常用、更高效的变种:随机梯度下降 (Stochastic Gradient Descent, SGD) 和 小批量梯度下降 (Mini-batch Gradient Descent),它们通过牺牲一部分梯度的准确性来换取更快的更新速度和更低的计算开销。

六、总结

本文我们深入探讨了驱动神经网络学习的核心引擎——梯度下降法。以下是关键要点:

  1. 目标:梯度下降法是一种优化算法,旨在通过迭代地调整模型参数来最小化损失函数。
  2. 核心思想:如同下山,每一步都沿着当前位置最陡峭的下坡方向(即梯度的反方向)移动。
  3. 梯度:损失函数对所有参数的偏导数构成的向量,指向函数值增长最快的方向。
  4. 更新规则: w n e w = w o l d − α ∇ L w_{new} = w_{old} - \alpha \nabla L wnew​=wold​−α∇L。
  5. 学习率 ( α \alpha α):控制每一步更新的步长,其选择至关重要,过小导致收敛慢,过大可能导致震荡或发散。
  6. 批量梯度下降 (BGD):每次更新都使用全部训练数据计算梯度。优点是方向准、稳定,缺点是计算成本高,不适用于大数据集。
  7. 挑战:BGD 面临计算效率问题,并且可能陷入局部最小值或鞍点。

理解了梯度下降法,我们才算真正掌握了模型“学习”的本质。在接下来的文章中,我们将学习反向传播算法(如何高效计算梯度)以及更先进的优化算法,让我们的模型训练得更快、更好!


深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴师兄大模型

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值