深度学习之-“深入理解梯度下降”

梯度下降是机器学习和深度学习的核心优化算法,几乎所有的模型训练都离不开它。然而,梯度下降并不是一个单一的算法,而是一个庞大的家族,包含了许多变体和改进方法。本文将从最基础的梯度下降开始,逐步深入学习,并通过代码进一步理解每个算法的实现细节。

梯度下降的基本原理

梯度下降的核心思想是通过迭代的方式,沿着目标函数的负梯度方向逐步调整参数,最终找到函数的最小值。这个过程可以类比为一个盲人下山的过程:盲人无法看到整个山的地形,但可以通过脚下的坡度来判断下山的方向,并一步步向山脚移动。

一维梯度下降

让我们从一个简单的例子开始:一维函数 f(x)=x^2。这个函数的导数为 f′(x)=2x,因此梯度下降的更新规则为:
在这里插入图片描述

其中,η是学习率,控制着每一步的步长。以下是一个简单的 Python 实现:

def gradient_descent_1d(start, lr=0.1, epochs=100):x = starthistory = []for _ in range(epochs):grad = 2 * x  # 计算梯度x -= lr * grad  # 更新参数history.append(x)return history# 测试
start_value = 10.0
learning_rate = 0.1
result = gradient_descent_1d(start_value, lr=learning_rate, epochs=50)
print("最终结果:", result[-1])

在这个例子中,我们从初始值 x=10.0开始,经过 50 次迭代后,x的值会逐渐趋近于 0,即函数的最小值。
在这里插入图片描述

其中,学习率的选择对结果有重要影响,过大的学习率可能导致震荡,而过小的学习率则会导致收敛速度过慢。

二维梯度下降

接下来,我们考虑一个二维函数 f(x,y)=x2+2y2。这个函数的梯度为 ∇f=[2x,4y],因此梯度下降的更新规则为:
在这里插入图片描述

以下是二维梯度下降的 Python 实现:

def gradient_descent_2d(start, lr=0.1, epochs=100):x, y = starthistory = []for _ in range(epochs):grad_x = 2 * x  # x 方向的梯度grad_y = 4 * y  # y 方向的梯度x -= lr * grad_x  # 更新 xy -= lr * grad_y  # 更新 yhistory.append((x, y))return history# 测试
start_value = (5.0, 5.0)
learning_rate = 0.1
result = gradient_descent_2d(start_value, lr=learning_rate, epochs=50)
print("最终结果:", result[-1])

运行结果如下:
在这里插入图片描述

在这个例子中,我们可以看到梯度下降在不同维度上的收敛速度是不同的。由于y方向的梯度是x方向的两倍,因此在y方向上的收敛速度会更快。这种差异在某些情况下会导致优化路径呈现出椭圆形的轨迹。

随机梯度下降(SGD)

在实际的机器学习问题中,目标函数通常是基于大量数据的损失函数。传统的梯度下降需要计算整个数据集的梯度,这在数据量较大时会变得非常耗时。为了解决这个问题,随机梯度下降(Stochastic Gradient Descent, SGD)应运而生。

SGD 的基本原理

SGD 的核心思想是每次迭代只使用一个随机样本或一个小批量样本来估计梯度。虽然这种估计会引入噪声,但它在实践中通常能够显著加快收敛速度,尤其是在大规模数据集上。
以下是 SGD 的 Python 实现:

import numpy as npdef sgd(data, start, lr=0.1, epochs=100, batch_size=1):x, y = starthistory = []n_samples = len(data)for _ in range(epochs):# 随机打乱数据np.random.shuffle(data)for i in range(0, n_samples, batch_size):batch = data[i:i + batch_size]grad_x = 2 * x  # 假设梯度计算grad_y = 4 * y  # 假设梯度计算x -= lr * grad_x  # 更新 xy -= lr * grad_y  # 更新 yhistory.append((x, y))return history# 测试
data = np.random.randn(100, 2)  # 生成随机数据
start_value = (5.0, 5.0)
learning_rate = 0.1
result = sgd(data, start_value, lr=learning_rate, epochs=10, batch_size=10)
print("最终结果:", result[-1])

运行结果如下:
在这里插入图片描述

SGD 的优缺点

SGD 的主要优点是计算效率高,尤其是在大规模数据集上。然而,由于每次迭代只使用部分数据,SGD 的更新方向可能会引入较大的噪声,导致收敛路径不稳定。为了缓解这个问题,通常会采用学习率衰减策略,即在训练过程中逐渐减小学习率。

动量机制

尽管 SGD 在大规模数据上表现良好,但它仍然存在一些问题,尤其是在优化路径中存在大量震荡或噪声时。为了改善这种情况,动量机制(Momentum)被引入到梯度下降中。

动量的基本原理

动量机制的核心思想是引入一个速度变量,使得参数更新不仅依赖于当前的梯度,还依赖于之前的速度。具体来说,动量机制的更新规则为:
在这里插入图片描述

其中,γ是动量系数,通常取值在 0.9 左右。当γ=0时,退化为普通的SGD。以下是动量机制的 Python 实现:

def momentum(start, lr=0.1, gamma=0.9, epochs=100):x, y = startvx, vy = 0, 0  # 初始化速度history = []for _ in range(epochs):grad_x = 2 * x  # 计算梯度grad_y = 4 * yvx = gamma * vx + lr * grad_x  # 更新速度vy = gamma * vy + lr * grad_yx -= vx  # 更新参数y -= vyhistory.append((x, y))return history# 测试
start_value = (5.0, 5.0)
learning_rate = 0.1
momentum_coeff = 0.9
result = momentum(start_value, lr=learning_rate, gamma=momentum_coeff, epochs=100)
print("最终结果:", result[-1])

运行结果如下:
在这里插入图片描述

涅斯捷洛夫动量

涅斯捷洛夫动量(Nesterov Momentum)是动量机制的一个改进版本。它的核心思想是先根据当前的速度预估未来的参数位置,然后在该位置计算梯度。这种前瞻性的梯度计算能够进一步提高收敛速度。具体来说,其更新规则为:
在这里插入图片描述

以下是涅斯捷洛夫动量的 Python 实现:

import numpy as npdef nesterov_momentum(gradient, theta_init, learning_rate=0.1, momentum=0.9, num_iters=100):"""涅斯捷洛夫动量梯度下降算法实现参数:- gradient: 梯度函数,接受参数 theta,返回梯度值- theta_init: 初始参数值- learning_rate: 学习率 (默认 0.1)- momentum: 动量系数 (默认 0.9)- num_iters: 迭代次数 (默认 100)返回:- theta_history: 参数更新历史- loss_history: 损失函数值历史"""theta = theta_init  # 初始化参数v = np.zeros_like(theta)  # 初始化速度theta_history = [theta.copy()]  # 记录参数更新历史loss_history = []  # 记录损失函数值历史for i in range(num_iters):# 计算前瞻位置的梯度lookahead_theta = theta + momentum * vgrad = gradient(lookahead_theta)# 更新速度v = momentum * v - learning_rate * grad# 更新参数theta += v# 记录历史theta_history.append(theta.copy())loss = theta[0]**2 + 2 * theta[1]**2  # 计算损失函数值loss_history.append(loss)return theta_history, loss_history# 定义目标函数的梯度
def gradient_function(theta):x, y = thetareturn np.array([2 * x, 4 * y])# 初始参数值
theta_init = np.array([5.0, 5.0])  # 初始点 (x, y) = (5, 5)# 运行涅斯捷洛夫动量梯度下降
theta_history, loss_history = nesterov_momentum(gradient_function, theta_init, learning_rate=0.1, momentum=0.9, num_iters=50)# 输出结果
print("最终参数值:", theta_history[-1])
print("最终损失值:", loss_history[-1])# 可视化损失函数值的变化
import matplotlib.pyplot as plt
plt.plot(loss_history)
plt.xlabel("Iteration")
plt.ylabel("Loss")
plt.title("Loss over Iterations")
plt.show()

运行结果如下:
在这里插入图片描述
绘制出的loss曲线如下:
在这里插入图片描述

自适应梯度下降

随着深度学习模型的复杂性不断增加,传统的梯度下降方法在某些情况下可能表现不佳。为了应对这一问题,自适应梯度下降方法应运而生。这些方法通过动态调整每个参数的学习率,使得优化过程更加高效。

RMSprop

RMSprop 是一种常用的自适应梯度下降方法,它通过维护一个指数衰减的梯度平方均值来调整学习率。以下是 RMSprop 的 Python 实现:

def rmsprop(start, lr=0.1, decay_rate=0.9, eps=1e-8, epochs=100):x, y = startcache_x, cache_y = 0, 0  # 初始化缓存history = []for _ in range(epochs):grad_x = 2 * x  # 计算梯度grad_y = 4 * ycache_x = decay_rate * cache_x + (1 - decay_rate) * grad_x ** 2  # 更新缓存cache_y = decay_rate * cache_y + (1 - decay_rate) * grad_y ** 2x -= lr * grad_x / (np.sqrt(cache_x) + eps)  # 更新参数y -= lr * grad_y / (np.sqrt(cache_y) + eps)history.append((x, y))return history# 测试
start_value = (5.0, 5.0)
learning_rate = 0.1
decay_rate = 0.9
result = rmsprop(start_value, lr=learning_rate, decay_rate=decay_rate, epochs=100)
print("最终结果:", result[-1])

运行结果如下:
在这里插入图片描述

Adam

Adam(Adaptive Moment Estimation)是目前最流行的自适应梯度下降方法之一。它结合了动量机制和 RMSprop 的优点,通过维护两个指数衰减的均值来调整学习率。以下是 Adam 的 Python 实现:

def adam(start, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8, epochs=100):x, y = startm_x, m_y = 0, 0  # 初始化一阶矩v_x, v_y = 0, 0  # 初始化二阶矩history = []for t in range(1, epochs + 1):grad_x = 2 * x  # 计算梯度grad_y = 4 * ym_x = beta1 * m_x + (1 - beta1) * grad_x  # 更新一阶矩m_y = beta1 * m_y + (1 - beta1) * grad_yv_x = beta2 * v_x + (1 - beta2) * grad_x ** 2  # 更新二阶矩v_y = beta2 * v_y + (1 - beta2) * grad_y ** 2# 偏差修正m_x_hat = m_x / (1 - beta1 ** t)m_y_hat = m_y / (1 - beta1 ** t)v_x_hat = v_x / (1 - beta2 ** t)v_y_hat = v_y / (1 - beta2 ** t)x -= lr * m_x_hat / (np.sqrt(v_x_hat) + eps)  # 更新参数y -= lr * m_y_hat / (np.sqrt(v_y_hat) + eps)history.append((x, y))return history# 测试
start_value = (5.0, 5.0)
learning_rate = 0.1
result = adam(start_value, lr=learning_rate, epochs=100)
print("最终结果:", result[-1])

运行结果如下:
在这里插入图片描述
可见Adam的收敛速度较慢。将epochs改为500,运行结果如下:
在这里插入图片描述

优化器选择指南

优化器的选择与特定的数据集有关。对于大多数的深度学习任务,Adam表现良好。但有时候,使用SGD也能调试出很好的结果。下面是关于优化器选择的总结:

优化器优点缺点适用场景
SGD简单、易于调参收敛慢、易陷入局部最优小数据集、简单任务
SGD+Momentum加速收敛、减少振荡需要调参大数据集、复杂任务
NAG比 Momentum 更快收敛实现稍复杂需要快速收敛的任务
Adam自适应学习率、默认参数表现良好可能在某些任务上过拟合大多数深度学习任务
RMSProp自适应学习率、适合非平稳目标需要调参RNN、非平稳目标函数
Adagrad适合稀疏数据学习率单调下降、可能过早停止稀疏数据集(如 NLP)
Adadelta无需设置初始学习率收敛速度较慢需要自适应学习率且不想调参的场景

总结

梯度下降作为机器学习和深度学习的核心优化算法,经历了从基础到现代的不断演进。从最简单的梯度下降,到随机梯度下降、动量机制,再到自适应梯度下降方法,每一步的改进都使得优化过程更加高效和稳定。
在实际应用中,选择合适的优化算法需要根据具体问题的特点来决定。对于简单的凸优化问题,传统的梯度下降或动量机制可能已经足够;而对于复杂的深度学习模型,Adam 等自适应方法则往往能够提供更好的性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/71454.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣-字符串

字符串不能被修改,所以如果有想修改字符串的行为,需要转换为StringBuilder StringBuilder里也有很多封装方法String没有,比如reverse() StringBuilder sb new StringBuilder();// 添加字符串 sb.append("Hello"); sb.append(&qu…

flink重启策略

一、重启策略核心意义 Flink 重启策略(Restart Strategy)是容错机制的核心组件,用于定义作业在发生故障时如何恢复执行。其核心目标为: 最小化停机时间:快速恢复数据处理,降低业务影响。平衡资源消耗&…

Java TCP 通信:实现简单的 Echo 服务器与客户端

TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输层协议。与 UDP 不同,TCP 保证了数据的顺序、可靠性和完整性,适用于需要可靠传输的应用场景,如文件传输、网页浏览等。本文将基于 Java 实现一个简单的…

Ollama+Deepseek-R1+Continue本地集成VScode

一、OllamaDeepseek-R1Continue本地集成VScode 1)安装前知识点 Continue 介绍 详情可参照官网: continue官网 Continue 是 Visual Studio Code 和 JetBrains 中领先的开源 AI 代码助手。 •在侧边栏中进行聊天以理解和迭代代码。 •自动补全&#…

风虎云龙R87与RH87八卡服务器震撼首发

在科技迅猛发展的今天,人工智能(AI)领域正以前所未有的速度改变着世界。从内容创作的智能化,到智能客服的广泛应用,AI技术已经深入到我们生活的方方面面。而这一切的背后,都离不开高性能算力设备的强大支撑…

18.分布式任务调度

固定的时间点去执行固定的任务,这就是任务调度。

Element UI-Select选择器结合树形控件终极版

Element UI Select选择器控件结合树形控件实现单选和多选&#xff0c;并且通过v-model的方式实现节点的双向绑定&#xff0c;封装成vue组件&#xff0c;文件名为electricity-meter-tree.vue&#xff0c;其代码如下&#xff1a; <template><div><el-select:valu…

多线程-定时任务线程池源码

定时任务线程池 ScheduledThreadPoolExecutor&#xff0c;可以执行定时任务的线程池。这里学习它的基本原理。 定时任务线程池&#xff0c;和普通线程池不同的地方在于&#xff0c;它使用一个延迟队列&#xff0c;延迟队列使用最小堆作为它的数据结构&#xff0c;它会按照任务…

系统盘还原成正常U盘

选择格式化,等格式化完毕就完了 点击还原设备的默认值格式化就完了

Linux系统下安装配置 Nginx 超详细图文教程_linux安装nginx

#安装当前路径下所有安装包 rpm -Uvh *.rpm --nodeps --force2.2、安装Nginx 找到Nginx的安装包进行解压 #解压安装包 tar -zxvf nginx-1.24.0.tar.gz进入解压之后的nginx目录下&#xff1a; #进入nginx目录 cd /usr/local/nginx-1.24.0执行配置脚本&#xff0c;–prefix是指…

【玩转正则表达式】替换与正则表达式的结合

在文本处理和数据分析的领域中&#xff0c;正则表达式&#xff08;Regular Expressions&#xff0c;简称regex&#xff09;是一种强大而灵活的工具。它能够帮助用户匹配、搜索、替换和编辑字符串中的特定模式。而光能匹配可能在实际使用场景中还不是很足够&#xff0c;有时候我…

如何排查服务器内存泄漏问题

服务器内存泄漏是一种常见的问题&#xff0c;可能导致系统性能下降甚至系统崩溃。以下是一般情况下用于排查服务器内存泄漏问题的步骤&#xff1a; 排查服务器内存泄漏问题的步骤&#xff1a; 监控系统资源&#xff1a; 使用系统监控工具&#xff08;如top、htop、free&#x…

Linux使用笔记:Find Tree 命令

Tree 命令的使用 使用-I 参数&#xff0c;过滤掉不想展未的目录或文件使用-L参数&#xff0c;指定展示的目录层级个数 arsenaltxzq1899:~/Workspace/vue-application$ tree -I node_modules/ -I public/ -L 2 . ├── components.json ├── Dockerfile ├── ecosystem.c…

山东大学计算机科学与技术学院软件工程实验日志

--- Author: "Inori_333" Date: 2025-03-04 --- 实验一 团队建立、阅读开源软件 1.队伍创建与分工 队伍最终确定由5人组成&#xff0c;小组成员之间进行了高效的沟通&#xff0c;并确定了各自的负责的部分内容。 2.代码复现与分析 写在前面&#xff1a;由于“…

深入 Vue.js 组件开发:从基础到实践

深入 Vue.js 组件开发&#xff1a;从基础到实践 Vue.js 作为一款卓越的前端框架&#xff0c;其组件化开发模式为构建高效、可维护的用户界面提供了强大支持。在这篇博客中&#xff0c;我们将深入探讨 Vue.js 组件开发的各个方面&#xff0c;从基础概念到高级技巧&#xff0c;助…

历年杭州电子科技大学计算机考研复试上机真题

历年杭州电子科技大学计算机考研复试机试真题 在线评测&#xff1a;https://app2098.acapp.acwing.com.cn/ 最大公约数和最小公倍数 题目描述 输入两个正整数 m 和 n&#xff0c;求其最大公约数和最小公倍数。 输入格式 两个整数 输出格式 最大公约数&#xff0c;最小公…

单片机入门(一)

一、单片机的内部资源 Flash&#xff1a;程序存储空间 RAM&#xff1a; 数据存储空间 SFR: 特殊功能寄存器的简称。它存在于单片机的内部存储空间中&#xff0c;用于存储控制单片机各种硬件模块工作的数据。这些寄存器具有特定的功能&#xff0c;控制着单片机的各种操作&#…

将 MySQL 数据高效导入 Redis

目录 1. RESP 协议 &#xff08;1&#xff09;RESP 协议的优点 &#xff08;2&#xff09;RESP 支持的 5 种数据类型 &#xff08;3&#xff09;RESP 的用途 &#xff08;4&#xff09;RESP 协议示例 2. redis-cli 的 pipe 模式 &#xff08;1&#xff09;pipe 模式的作…

mybatis映射文件相关的知识点总结

mybatis映射文件相关的知识点总结 mybatis官网地址 英文版&#xff1a;https://mybatis.org/mybatis-3/index.html 中文版&#xff1a;https://mybatis.p2hp.com/ 搭建环境 /* SQLyog Ultimate v10.00 Beta1 MySQL - 8.0.30 : Database - mybatis-label *****************…

SQLAlchemy系列教程:SQLAlchemy快速入门示例项目

SQLAlchemy是与数据库交互的Python开发人员不可或缺的库。这个强大的ORM允许使用python结构进行简单的数据库操作。设置过程很简单&#xff0c;并且允许可扩展的数据库应用程序开发。本文通过入门项目完整介绍SQLAlchemy的应用过程&#xff0c;包括安装依赖包&#xff0c;创建连…