当前位置: 首页 > news >正文

Python 中从零开始的随机梯度下降

文章目录

  • 一、说明
  • 二、了解基础知识的重要性:
    • 2.1 什么是梯度下降?
    • 2.2 梯度下降的类型:
  • 三、随机梯度下降 (SGD) 有何不同
    • 3.1 随机性的概念:
    • 3.2 SGD的优点和缺点:
  • 四、随机梯度下降的分步说明
  • 五、在 Python 中从头开始实现随机梯度下降
    • 5.1 设置环境:
    • 5.2 编写 SGD 函数:
    • 5.3 常见陷阱
  • 六、何时使用随机梯度下降 (SGD)
  • 七、与其他优化器的比较
  • 八、结论

一、说明

想象一下,在一个雾蒙蒙的早晨,你试图找到山谷中的最低点——你迈出的每一步都像是在猜测地形。在机器学习的世界中,这种 “猜测” 过程正是优化算法的作用 — 它们调整模型的参数以找到最佳结果。这就是SGD。

二、了解基础知识的重要性:

以下是您可能不知道的事情:从头开始学习实施 SGD 很像学习驾驶手动汽车。当然,有自动变速器汽车(预构建的库和优化器),但当您了解底层机制时,您将获得对机器学习模型行为方式的控制、精度和信心。通过从头开始构建,您将深入了解优化算法,从而更轻松地解决问题,甚至在未来提高性能。

2.1 什么是梯度下降?

简要说明:
将坡度下降想象成徒步下山以找到山谷中的最低点。您根据地形的坡度采取步数 — 坡度越陡,步长越大。在机器学习中,这个“谷值”是成本函数的最小值,它表示模型的表现如何。Gradient descent 就像您的指南,告诉您向哪个方向调整模型的参数(权重和偏差),以便在每次迭代中表现更好。目标是什么?尽可能降低成本功能。

2.2 梯度下降的类型:

事情变得有趣了:走下这座山的方法不止一种。您有三种主要类型的梯度下降,每种类型都有自己的个性:

批量梯度下降:此 SQL 会等到它拥有所有数据后再进行移动。这就像计算完美的步骤,但需要大量的时间和内存。
随机梯度下降 (SGD):啊,我们节目的明星。SGD 不会等待整个数据集;相反,它在每个数据点之后需要一个步骤。它快速、灵活,而且 - 就像你可能已经猜到的那样 - 有点混乱。
小批量梯度下降:一个快乐的中间地带。小批量梯度下降不是等待所有数据或在每一个点之后匆忙前进,而是以小组(小批量)的形式处理数据。它在速度和准确性之间取得了平衡。
您可能会想,“为什么 SGD 对于大型数据集如此有价值?原因如下:假设您有数百万个数据点。使用批量梯度下降意味着您将陷入处理困境,永远等待进行更新。但是,借助 SGD,您几乎可以在每个数据点到达时立即更新模型,这使其非常适合需要快速获得结果的大型数据集。

三、随机梯度下降 (SGD) 有何不同

3.1 随机性的概念:

事情是这样的:SGD 被称为“随机”,因为它将随机性引入到流程中。它不是根据您的所有数据计算梯度(就像在批量梯度下降中一样),而是一次选择一个数据点来调整参数。这种随机性为 SGD 提供了速度优势,但也使其更加不稳定 — 有时,您会朝着正确的方向迈进,有时您会稍微偏离路径。但随着时间的推移,步骤会平均化,你(希望)最终得到最优解的速度比一次计算所有内容更快。

3.2 SGD的优点和缺点:

优势:
速度:由于它会在每个数据点后更新,因此它比大型数据集的批量梯度下降要快得多。您几乎可以立即获得有关每个步骤如何影响模型的反馈。
正则化效果:SGD 引入的随机噪声可以帮助防止过拟合,起到一种隐式正则化的作用。
内存效率:一次只有一个样本加载到内存中,非常适合大型数据集。
缺点:
嘈杂的更新:由于您在每个数据点之后都进行了更改,因此通往最佳解决方案的路径可能会参差不齐且不太稳定。
在某些情况下收敛速度较慢:在某些情况下,可能需要更长的时间才能达到确切的最小值,尤其是在学习率没有得到很好的调整时。

四、随机梯度下降的分步说明

  1. 初始化参数:
    在运行模型之前,您需要从头开始 — 这意味着初始化模型的参数(权重和偏差)。想象一下,你正在开始一个没有放置任何块的拼图。你不知道最终的图片是什么样子的,所以你随机放置这些碎片,希望它们最终能形成一些有意义的东西。同样,在 SGD 中,我们随机初始化权重和偏差。

事情是这样的:当这些权重被随机初始化时,它们将在训练期间进行调整,以尽可能准确地拟合数据。对于线性回归问题,这些权重确定线的斜率,而偏差调整线的截距。在 Python 中,您可以使用正态分布中的随机值或仅使用小随机数来初始化这些值。

  1. 选择学习率:
    您可能想知道,“每个人都在谈论的这个学习率是多少?将学习率视为您在优化路径上所采取的步骤的大小。如果你的学习率太高,就像进行巨大的跳跃——你可能会超过最佳点,在目标周围弹跳而从未着陆。如果它太低,就像小步走——当然,你会到达那里,但需要令人沮丧的很长时间。

要找到最佳点,需要仔细选择学习率。一种常见的技术是使用学习率衰减,其中学习率会随着模型越来越接近最佳解决方案而降低。这样,您首先会采取较大的步骤来加快流程,但当您接近最小值时,会逐渐采取更小、更精确的步骤。

  1. 更新规则:
    训练开始后,每个数据点都会为您提供有关调整体重方式的线索。这就是魔法发生的地方。每次迭代(使用单个样本)后,您计算梯度,然后使用学习率更新参数(权重和偏差)。

交易是这样的:对于数据集中的每个样本,都会重复此更新过程,这意味着在每个数据点之后,您的模型会进行微小的调整,逐渐学习隐藏在数据中的模式。

  1. 停止标准:
    你怎么知道什么时候停止?这就像问:“画家什么时候完成他们的杰作?在 SGD 中,您可以根据以下条件停止训练:

epoch 数:纪元是指算法查看整个数据集一次的时间。您可以设置固定数量的 epoch,例如 100 或 200,以确保足够的迭代。
成本函数的收益递减:您还可以监控成本函数(您的模型有多错误),并在改进变得可以忽略不计时停止 — 当进一步的训练并没有真正使模型变得更好时。
现在我们已经有了理论基础,让我们卷起袖子开始编写代码。

五、在 Python 中从头开始实现随机梯度下降

5.1 设置环境:

要从头开始实施 SGD,我们需要能够高效处理矩阵运算的 Python 库。具体来说,您将使用:

numpy用于线性代数运算和矩阵作。
您还可以添加以可视化学习过程(例如绘制成本函数的减少)。matplotlib
现在,让我们从一个简单的线性回归模型开始,我们的目标是通过数据找到最合适的线。

5.2 编写 SGD 函数:

以下是编写 SGD 函数的方法:

初始化参数:初始化权重和偏差。在这种情况下,假设我们的权重从小的随机数开始,我们的偏差为 0。

import numpy as np# Initialize parameters
def initialize_params(n_features):weights = np.random.randn(n_features) * 0.01bias = 0.0return weights, bias
  1. 编写循环:现在,您需要一个循环来遍历每个数据样本,计算成本函数的梯度,并相应地更新权重和偏差。您还需要跟踪每个步骤的成本,以便了解模型的学习效果。
def stochastic_gradient_descent(X, y, learning_rate=0.01, epochs=100):weights, bias = initialize_params(X.shape[1])n_samples = X.shape[0]for epoch in range(epochs):for i in range(n_samples):# Select one samplex_i = X[i]y_i = y[i]# Predict the outputprediction = np.dot(x_i, weights) + bias# Calculate gradientsdw = (prediction - y_i) * x_idb = (prediction - y_i)# Update weights and biasweights -= learning_rate * dwbias -= learning_rate * db# Optionally, print the cost for trackingcost = np.mean((np.dot(X, weights) + bias - y) ** 2)print(f'Epoch {epoch+1}, Cost: {cost}')return weights, bias
  1. 跟踪成本函数:您可能希望定期打印或绘制成本函数,以监控模型的学习方式。这可能是查看您的学习率是太高(成本会大幅波动)还是太低(成本会非常缓慢地降低)的好方法。

代码演练:

让我们分解一下这里发生的事情:

initialize_params():此函数将您的权重和偏差设置为较小的初始值,以确保您的模型可以开始学习。
stochastic_gradient_descent():在这个循环中,我们:
1 单独浏览每个数据点。
2 根据当前权重和偏差进行预测。
3 计算误差 (预测与实际值的偏差)。
4 计算成本函数相对于权重和偏差的梯度。
5 使用学习率更新权重和偏差。
5 跟踪成本函数以监控进度。

5.3 常见陷阱

您可能会想,“这听起来很简单,但哪里会出错呢?以下是一些常见错误:

不对数据进行随机排序:如果您不在每个 epoch 之前对数据进行随机排序,则您的模型可能会学习数据排序中的模式,而不是数据本身的模式。始终在 epoch 之间对数据进行随机排序。
使用过高的学习率:如前所述,过高的学习率会导致模型剧烈振荡,永远无法收敛。密切关注 cost 函数 — 如果它跳动太多,请考虑降低学习率。

六、何时使用随机梯度下降 (SGD)

实际应用:

您可能想知道,“什么时候是 Stochastic Gradient Descent 我最好的选择?事情是这样的:SGD 在处理大型数据集或复杂的神经网络时真正闪耀。将其视为实时学习的首选算法,您需要快速更新,而无需等待处理整个数据集。

例如,假设您正在使用用于图像识别的深度学习模型。数据集很大 — 数百万张图像。如果您使用批量梯度下降,则必须在对模型进行任何调整之前加载和处理每张图像。但是使用 SGD 时,模型会在每张图像之后更新其参数。这使您可以立即查看进度并减少计算负载,从而使其更快、更节省内存。

在金融或电子商务等行业中,模型需要使用流数据(想想推荐系统或股票价格预测)不断更新,SGD 一次处理一个数据点的能力非常宝贵。它用于训练卷积神经网络 (CNN) 和递归神经网络 (RNN) 等大规模神经网络,这些网络为从自动驾驶汽车到语言翻译的所有功能提供支持。

七、与其他优化器的比较

现在,您可能会想,“好吧,SGD 听起来不错,但 Adam 或 RMSprop 等其他优化器呢?让我们来分析一下。

Adam (Adaptive Moment Estimation):Adam 结合了 SGD 与 momentum 和 RMSprop 的优点。它使用梯度(如 momentum)和平方梯度(如 RMSprop)的运行平均值来调整每个参数的学习率。这通常会导致更快的收敛。在训练需要平衡速度和精度的深度网络时,您可能更喜欢 Adam。
RMSprop:此优化器根据最近梯度的大小单独调整每个参数的学习率。它对于处理非平稳目标特别有用,因为在训练过程中,最佳学习率可能会发生变化。您会发现 RMSprop 对于训练 RNN 特别方便。
那么,什么时候应该坚持使用 SGD?如果您正在寻找简单性、内存效率和控制力,SGD 仍然是一个不错的选择。例如,如果您有一个非常大的数据集,并且无法承受 Adam 或 RMSprop 所需的额外内存开销,则 SGD 是一种更直接的解决方案。此外,如果您工作的环境中训练需要对每个新数据点做出更快的响应(例如在实时应用程序中),SGD 的频繁更新使其更合适。

这可能会让您感到惊讶:尽管有所有花哨的新优化器,但 SGD 仍然因其简单性和效率而受到从业者的最爱。在担心过拟合的情况下,SGD 固有的噪声(由于其频繁更新)甚至可以充当正则化器,防止模型过于完美地拟合训练数据。

八、结论

那么,这给我们留下了什么呢?让我们回顾一下:
我们首先深入研究了是什么让 Stochastic Gradient Descent 成为如此强大和高效的优化算法。从梯度下降背后的理论到在 Python 中从头开始实施 SGD,您已经看到了如何在细粒度级别控制和理解此过程中的每个步骤。您已经了解到:
SGD 提供了速度和内存效率,尤其是在处理大型数据集时。
它在神经网络和依赖快速迭代学习的行业中具有实际应用。
虽然有更高级的优化器,如 Adam 和 RMSprop,但 SGD 由于其简单性和灵活性而仍然是最受欢迎的。

相关文章:

Python 中从零开始的随机梯度下降

文章目录 一、说明二、了解基础知识的重要性:2.1 什么是梯度下降?2.2 梯度下降的类型: 三、随机梯度下降 (SGD) 有何不同3.1 随机性的概念:3.2 SGD的优点和缺点: 四、随机梯度下降的分步说明五、…...

期权隐含波动率是什么意思?

财顺小编本文主要介绍期权隐含波动率是什么意思?期权隐含波动率(Implied Volatility)是根据当前期权市场价格,利用期权定价模型(如Black-Scholes模型)推导出的关于合约标的理论上的价格波动率。它反映了市场…...

python中使用数据库sqlite3

Python使用sqlite3数据库 python3.x标准库内置了SQLite3 查看sqlite的版本 import sqlite3 sqlite_version sqlite3.sqlite_version print(f"SQLite version: {sqlite_version}") 显示 导入模块连接sqlitte3 import sqlite3 consqlite3.connect("d:/fi…...

JavaScript数组-数组的概念

在JavaScript编程中,数组(Array)是一种非常重要的数据结构,它允许我们将多个值存储在一个单独的变量中。数组可以包含任意类型的元素,如数字、字符串、对象甚至是其他数组,并提供了丰富的内置方法来操作这些…...

英语---基础词汇库

〇、动词类(常见谓语表述) 1.show,indicate,find 认为,表明 2.improve,promote,boost,enhance,increase,advocate,strength 改善,提升,促进,增强&#xff0…...

ASCII 与 Unicode:两种字符编码的定义和不同

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: Java 文章目录 💯前言💯一、ASCII编码详解1.1 ASCII的组成1.2 ASCII的局限性 💯二、Unicode编码详解2.1 Unicode编码方式2.2 Unicode的字符范围 💯三、ASCII与Unicode的…...

Linux相关概念和易错知识点(28)(线程控制、Linux下线程的底层)

目录 1.线程控制 (1)pthread和thread库 (2)线程的创建、等待和分离 ①线程创建 ②线程等待 ③线程分离 ④线程替换(不可行) (3)线程的终止和取消 ①线程终止 ②线程取消 2…...

lighten() 函数被弃用:替代方案color.scale()或者color.adjust()

在 SCSS (Sass 的一个语法) 中,lighten() 函数用于调整颜色的亮度。然而,随着 Sass 语言的不断发展,一些旧函数被标记为弃用,以鼓励使用更现代、更灵活的 API。lighten() 函数就是其中之一。 1. 弃用通知 当您看到 lighten() is…...

【leetcode】双指针:有效三角形的个数 and 和为s的两个数

文章目录 1. 有效三角形的个数1.题目2.讲解算法原理3.代码 2.和为s的两个数1.题目2.思路3.代码 1. 有效三角形的个数 1.题目 示例1解析&#xff1a; 2.讲解算法原理 3.代码 class Solution { public:int triangleNumber(vector<int>& nums) {sort(nums.begin(), …...

IDEA通过Contince接入Deepseek

Deepseek 的出色表现&#xff0c;上期【Deepseek得两种访问方式与本地部署】 安装Continue插件 第一步、下载插件 在编辑栏【File】->设置【Settiings】或快捷键【CtrlAltS】,弹窗的左侧导航树&#xff0c;选择【plugins】,在marketplace 搜索【Continue】&#xff0c;点…...

grep如何排除多个目录?

在使用 grep 进行文本搜索时&#xff0c;有时候需要排除多个目录&#xff0c;避免在这些目录下进行搜索。下面介绍几种不同的实现方式。 目录 1.使用 -r 和 --exclude-dir 选项&#xff08;GNU grep&#xff09; 2.使用扩展正则表达式和 -P 选项&#xff08;GNU grep&#x…...

Elasticsearch 数据建模:从原理到实战的降维打击指南

Elasticsearch 数据建模&#xff1a;从原理到实战的降维打击指南 &#x1f680; 第一章 数据建模的物理法则&#xff1a;倒排索引的奇妙世界 1.1 倒排索引&#xff1a;比字典更聪明的数据结构 当你在ES中存入"Hello World"时&#xff0c;背后发生了这些魔法&#…...

python defaultdict用法

摘要 使用 defaultdict 可以简化处理字典中缺失键的情况。以下是几个使用 defaultdict 的示例&#xff0c;展示了它在不同场景下的应用。 示例 1&#xff1a;分组文件 假设我们有一组文件名&#xff0c;想要根据文件扩展名将它们分组。我们可以使用 defaultdict 来实现这一点…...

Java 与设计模式(15):模板方法模式

一、定义 模板方法模式是一种行为设计模式&#xff0c;它定义了一个操作中的算法的骨架&#xff08;也就是大致的步骤和流程&#xff09;&#xff0c;而将一些具体步骤的实现延迟到子类中。这样&#xff0c;子类可以不改变算法的结构即可重新定义算法的某些特定步骤。 二、Ja…...

ubuntu更新失败:apt-get install -f Transaction failed: 软件包系统已损坏

检查您是否使用了第三方源。如果是就禁用它们&#xff0c;它们常常导致问题。 然后在终端中运行以下命令&#xff1a;apt-get install -f Transaction failed: 软件包系统已损坏下列软件包未满足的依赖关系&#xff1a;sunloginclient: Depends: libappindicator3-1 但是 %%s 没…...

16-使用QtChart创建动态图表:入门指南

QtChart是Qt框架中的一个强大模块&#xff0c;用于创建各种类型的图表&#xff0c;如折线图、柱状图、饼图等。它提供了丰富的API和灵活的配置选项&#xff0c;使得开发者能够轻松地将数据可视化集成到应用程序中。本文将介绍如何使用QtChart创建一个简单的动态折线图&#xff…...

C++ | 虚函数

在 C 面向对象编程领域&#xff0c;多态性堪称核心概念&#xff0c;而虚函数则是实现运行时多态的关键所在。 一、虚函数的概念与作用 1.1 什么是虚函数 虚函数是 C 中用于实现动态多态的成员函数。在基类中使用virtual关键字声明虚函数后&#xff0c;派生类能够重写&#x…...

单元测试整理

在国外软件开发中&#xff0c;单元测试必不可少&#xff0c;但是国内并不太重视这一块&#xff0c;一个好的单元测试可以提前发现很多问题&#xff0c;也减去和测试battle的时间 Spring单元测试 JUnit4 RunWith 指明单元测试框架 e.g. RunWith(SpringJUnit4ClassRunner.cla…...

Delphi语言的软件工程

Delphi语言的软件工程 引言 在软件工程的历史长河中&#xff0c;Delphi语言作为一种快速应用程序开发&#xff08;RAD&#xff09;的工具&#xff0c;凭借其高效的开发环境和强大的编程能力&#xff0c;一直在软件开发领域占有一席之地。本文将探讨Delphi语言的历史背景、特性…...

XSS攻击(跨站脚本攻击)详解与实战

文章目录 一、什么是XSS&#xff1f;二、XSS分类与场景三、XSS攻击实战流程四、CTF中的XSS利用五、XSS防御方案六、绕过过滤的常见技巧七、实战练习资源 一、什么是XSS&#xff1f; XSS&#xff08;Cross-Site Scripting&#xff09; 是一种通过向网页注入恶意脚本&#xff08…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...