login
深度解析4种优化算法
2025/05/22·StepFun can make mistakes, check important info.
在一个 toy 问题上比较全梯度、SGD、SVRG, SVRG++ 效果,真跑 python 做实验

为了更好地帮助您完成在toy问题上比较不同优化算法的实验,我需要了解以下几点关键信息:

  1. 您希望使用什么类型的toy问题进行实验?(例如:凸优化问题如线性回归/逻辑回归,非凸问题如神经网络训练,或者其他特定函数优化问题)

  2. 您关注的主要评估指标是什么?(例如:收敛速度、计算时间、最终精度、迭代次数与误差关系等)

  3. 对于实验设置,您是否有特定的数据集大小、维度或其他参数要求?

1. 都选一个 2. all 3. toy 级即可

好的,我理解您的任务是要在toy问题上比较不同优化算法的效果,具体包括全梯度下降法、随机梯度下降法(SGD)、随机方差减小梯度下降法(SVRG)以及SVRG++算法,并使用Python实际运行实验。

我将为您准备:

  1. 选择一个凸优化问题和一个非凸优化问题作为toy问题
  2. 比较这四种算法在所有关键指标上的表现,包括收敛速度、计算时间、最终精度等
  3. 使用适当规模的toy级数据集进行实验

我会通过Python代码实现这些算法,运行实验,并提供详细的比较分析和可视化结果。

Deep Research

问题拆解

  1. 核心任务: 在“toy”级别的问题上,通过实际运行Python实验,比较全梯度下降(Full Gradient Descent)、随机梯度下降(SGD)、随机方差缩减梯度下降(SVRG)以及SVRG++这四种优化算法的效果。
  2. 实验问题选择: 需要选择至少一个凸优化问题和一个非凸优化问题作为实验对象。
  3. 评估维度: 对算法的评估需要全面,涵盖所有关键指标,例如收敛速度(迭代次数或时间衡量)、计算时间(总运行时间或单位迭代时间)、最终达到的精度(如损失函数值、准确率等)、以及迭代次数与误差之间的关系曲线。
  4. 实验规模: 实验应在“toy”级别进行,意味着数据集的大小、特征维度等可以相对简单,便于快速迭代和验证。
  5. 输出成果: 最终产出应为一个完善全面、逻辑清晰的研究报告,包含实验设计、过程、结果和分析。

行动计划

  1. 理论基础与算法理解深化:

    • 深入研究全梯度下降、SGD、SVRG 和 SVRG++ 算法的数学原理、更新规则、收敛特性、各自的优缺点以及它们之间的演进关系。
    • 关注 SVRG 和 SVRG++ 中关于方差缩减的关键机制和参数(如内循环次数 m)的选取原则。
    • 信息来源: 权威的机器学习教科书、优化领域的相关学术论文(例如 SVRG 和 SVRG++ 的原始论文)、顶会(如 NeurIPS, ICML)的教程材料、知名大学的公开课件(如斯坦福、CMU 的优化或机器学习课程)。
  2. 实验方案设计与准备:

    • 问题选择与构建:
      • 精心挑选或设计一个典型的凸优化“toy”问题(例如,具有解析解或易于分析的线性回归或逻辑回归模型)。
      • 精心挑选或设计一个典型的非凸优化“toy”问题(例如,一个小型神经网络在简单分类任务上的训练,或一个经典的非凸测试函数优化)。
    • 数据集生成/选取:
      • 为所选的“toy”问题生成或选取规模适中的合成数据集或标准小规模数据集,明确数据特征(如样本量、维度、噪声水平、类别分布等)。
    • 评估指标体系确立:
      • 明确量化各项评估指标的具体计算方法,例如:损失函数值随迭代次数/CPU时间的变化曲线、梯度范数随迭代次数/CPU时间的变化曲线、达到预定目标精度所需的迭代次数/CPU时间、最终收敛时的损失值/准确率(若适用)。
    • 超参数设定与调优策略:
      • 梳理各算法的关键超参数(如学习率、SVRG/SVRG++的内循环次数 m、批量大小(针对SGD)等)。
      • 初步规划超参数的调整范围和敏感性分析策略。
  3. 算法编码实现与测试:

    • 使用Python及常用的科学计算库(如NumPy)从零开始或基于已有框架清晰地实现四种优化算法的核心逻辑。
    • 实现所选“toy”问题的目标函数及其梯度(或随机梯度)的计算模块。
    • 对每个算法模块进行单元测试,确保其正确性。
  4. 实验执行与数据系统收集:

    • 在搭建好的实验环境下,针对选定的凸优化和非凸优化问题,分别运行四种优化算法。
    • 系统性地进行实验,记录不同算法在不同超参数设置下的表现,确保实验的可复现性。
    • 详细记录每次运行的关键数据,包括但不限于:每次迭代(或每个epoch)的损失函数值、梯度范数(若适用)、累计运行时间、以及其他预设的评估指标。
  5. 实验结果整合分析与可视化呈现:

    • 对收集到的原始实验数据进行清洗、整理和统计分析。
    • 利用可视化工具(如Matplotlib, Seaborn)生成清晰、有洞察力的图表,直观对比不同算法在各项评估指标上的表现。例如:
      • 收敛曲线(损失函数 vs. 迭代次数/时间)。
      • 最终性能对比(如最低损失、最高准确率)。
      • 计算效率对比(如达到某一目标所需的总时间)。
    • 深入分析实验结果,解释观察到的现象,例如不同算法的收敛速度差异、对噪声的鲁棒性、对超参数的敏感性等,并结合算法理论进行讨论。
  6. 研究报告框架构建与内容撰写:

    • 引言: 概述研究背景、动机、比较的算法以及报告结构。
    • 算法原理回顾: 简明扼要地介绍全梯度、SGD、SVRG、SVRG++的核心思想和数学表述。
    • 实验设计与设置: 详细描述所选的“toy”问题(包括其数学形式)、数据集的生成方式和特性、各算法的具体实现细节、超参数的选择和调整过程、以及评价指标的定义。
    • 实验结果与讨论: 系统展示通过图表和数据得到的实验结果,对结果进行深入的比较分析和讨论,阐明各算法在不同场景下的表现及其原因。
    • 结论与展望: 总结本研究的主要发现,提炼出各算法在“toy”问题上的相对优劣和适用条件,并可对未来可能的研究方向进行展望。
    • 参考文献与附录(可选): 列出引用的重要文献;可选择性附上核心Python代码片段。

让我开始编写代码实现这些算法并进行实验。

执行代码

执行代码

python

Python version: 3.13.2 (main, Mar 18 2025, 03:30:45) [GCC 12.2.0]
NumPy version: 2.2.5
Matplotlib version: 3.10.1
Seaborn version: 0.13.2
Scikit-learn version: 1.6.1

All required libraries are available.

很好,所有必要的库都已经安装好了。现在我将实现四种优化算法(全梯度下降、SGD、SVRG和SVRG++)并在凸优化和非凸优化问题上进行比较实验。

首先,我会定义一个凸优化问题(线性回归)和一个非凸优化问题(简单的神经网络),然后实现这四种优化算法,并进行实验比较。

执行代码

执行代码

python

生成数据集...
线性回归数据集: 800 训练样本, 200 测试样本, 20 特征
分类数据集: 800 训练样本, 200 测试样本, 20 特征, 2 类别

数据集生成完成!

数据集已经成功生成。现在我将实现四种优化算法:全梯度下降(Full Gradient Descent)、随机梯度下降(SGD)、随机方差减小梯度下降(SVRG)和SVRG++。然后,我将在生成的线性回归(凸优化问题)和神经网络分类(非凸优化问题)数据集上运行这些算法。

执行代码

执行代码

python

我注意到出现了一个错误,变量X_train_linear未定义。这是因为我们在不同的代码块中执行,需要重新加载之前生成的数据集。让我们修复这个问题,并继续实现和测试优化算法。

执行代码

执行代码

python

生成数据集...
线性回归数据集: 800 训练样本, 200 测试样本, 20 特征
分类数据集: 800 训练样本, 200 测试样本, 20 特征, 2 类别

数据集生成完成!
测试优化算法...

优化算法测试完成!

已掌握的信息

  1. 任务目标:在一个toy问题上比较全梯度下降(Full Gradient Descent)、随机梯度下降(SGD)、随机方差减小梯度下降(SVRG)和SVRG++算法的效果,并通过Python实际运行实验。
  2. 实验问题类型:已确定使用一个凸优化问题(线性回归)和一个非凸优化问题(简单神经网络进行二分类)。
  3. 数据集
    • 线性回归数据集:800个训练样本,200个测试样本,20个特征。
    • 分类数据集(用于神经网络):800个训练样本,200个测试样本,20个特征,2个类别。
    • 数据集特征已进行标准化处理。
  4. 模型定义
    • LinearRegression 类:实现了均方误差损失函数 (loss)、全梯度计算 (gradient) 和随机梯度计算 (gradient_sample)。参数为权重向量 w
    • SimpleNN 类:实现了一个包含一个隐藏层的简单神经网络,使用Sigmoid激活函数和Softmax输出层。实现了交叉熵损失函数 (loss)、全梯度计算 (gradient)、随机梯度计算 (gradient_sample),以及参数获取 (get_params) 和设置 (set_params) 的方法。
  5. 优化算法初步实现
    • 已初步编码实现 full_gradient_descent, sgd, svrg, 和 svrg_plus_plus 四种优化算法。
    • 这些算法接受模型对象、数据、学习率、最大迭代次数等参数,并返回损失历史和时间历史。
    • SVRG++ 的实现中,内循环次数 m 会在每个外层epoch后翻倍。
    • 算法实现已通过在小型数据集上的初步运行测试,未报告具体运行结果,但代码执行完成。
  6. 评估指标方向:用户要求比较算法在所有关键指标上的表现,例如收敛速度、计算时间、最终精度、迭代次数与误差关系等。

行动计划

  1. 详细审阅与验证算法实现

    • 仔细检查SVRG和SVRG++算法中方差缩减项(grad_w - grad_w_tilde + mu)的计算逻辑和参数更新步骤,确保其与理论一致。
    • 确认神经网络模型中参数的展平和重塑(get_params, set_params)在所有优化算法中均能正确工作。
    • 验证随机梯度的计算 (gradient_sample) 对于单样本和批处理样本的处理是否正确。
  2. 确定详细的实验超参数

    • 为每个优化算法(全梯度、SGD、SVRG、SVRG++)和每个问题(线性回归、神经网络分类)分别设定或选择一组初始超参数。
      • 学习率 (learning_rate):为不同算法和问题选择合适的初始学习率。可能需要基于经验或少量初步试验来确定一个合理的范围。例如,全梯度可能需要较小的学习率,而SVRG/SVRG++理论上可以容忍较大的学习率。
      • 最大迭代次数 (max_epochs):设置足够大的迭代次数以观察算法的收敛行为,同时考虑实验效率。
      • 收敛容忍度 (tol):设定一个合理的损失变化阈值,用于提前终止迭代。
      • SGD的批量大小 (batch_size):选择一个或几个代表性的批量大小进行测试(例如,1 和 32)。
      • SVRG/SVRG++的内循环次数 (m/m_0):根据训练样本数量(N=800),为SVRG选择一个固定的 m 值(例如,m = 2*Nm = N)。为SVRG++选择一个初始 m_0 值(例如,m_0 = N/10 或一个较小常数)。
      • SVRG/SVRG++的随机梯度批量大小 (batch_size):在内循环中计算随机梯度时使用的批量大小,通常设为1。
    • 记录所有选定的超参数,以便在报告中说明。
  3. 执行凸优化问题(线性回归)的对比实验

    • 初始化线性回归模型。
    • 分别使用全梯度下降、SGD、SVRG、SVRG++算法训练模型。
    • 对于每种算法,记录以下数据:
      • 每次迭代(或外层epoch)后的训练损失。
      • 每次迭代(或外层epoch)结束时的累计CPU运行时间。
      • (可选)每次迭代后的梯度范数。
    • 确保每个算法在开始训练前都使用相同的初始模型参数。
  4. 执行非凸优化问题(神经网络分类)的对比实验

    • 初始化简单神经网络模型。
    • 分别使用全梯度下降、SGD、SVRG、SVRG++算法训练模型。
    • 对于每种算法,记录以下数据:
      • 每次迭代(或外层epoch)后的训练损失。
      • 每次迭代(或外层epoch)结束时的累计CPU运行时间。
      • (可选)每次迭代后的训练准确率和测试准确率(以评估泛化能力)。
    • 确保每个算法在开始训练前都使用相同的初始模型参数。
  5. 结果整理、分析与可视化

    • 数据汇总:将收集到的所有实验数据(损失、时间、准确率等)整理成易于分析的格式。
    • 性能比较
      • 收敛速度:绘制损失函数值 vs. 迭代次数的曲线图,以及损失函数值 vs. CPU时间的曲线图,对比四种算法的收敛速度。
      • 最终性能:比较各算法在达到最大迭代次数或收敛后的最终损失值(和准确率,如果适用)。
      • 计算效率:分析达到相似损失水平时,不同算法所需的计算时间。
    • 特定算法分析
      • 分析SVRG和SVRG++相比于SGD在方差减小和收敛稳定性上的表现。
      • 讨论SVRG++中动态调整内循环次数 m 的效果。
    • 图表生成:使用清晰的图表(如折线图)来可视化比较结果。确保图表包含标题、轴标签和图例。
  6. 构建并撰写研究报告框架

    • 引言:简述研究背景(比较优化算法)、目的、所比较的算法及其重要性。
    • 算法原理:简要介绍全梯度下降、SGD、SVRG和SVRG++的核心思想、更新公式和关键特性。
    • 实验设置
      • 描述所用的toy问题(线性回归和神经网络的数学模型)。
      • 详细说明数据集的生成方式、规模和特性。
      • 列出各优化算法的具体实现细节和所选用的超参数。
      • 明确所使用的评估指标及其计算方法。
    • 实验结果与讨论
      • 展示通过图表和数据呈现的实验结果。
      • 对结果进行详细的比较分析,讨论不同算法在凸优化和非凸优化问题上的表现差异。
      • 解释观察到的现象,例如SVRG/SVRG++为何以及何时优于SGD或全梯度。
      • 分析超参数对算法性能的可能影响(如果进行了敏感性分析)。
    • 结论:总结研究的主要发现,概括各算法在所测试的toy问题上的相对优劣和适用场景。
    • (可选)附录:可以包含核心的Python代码片段或更详细的实验数据。
  7. (可选,若初步结果不理想)超参数调优与迭代实验

    • 如果初步实验结果未能清晰展示算法间的差异或算法收敛不佳,则需要回顾超参数的选择,进行调整并重新运行实验。
    • 可以针对学习率、SVRG的 m 值等关键参数进行小范围的搜索。

通过以上步骤,旨在系统地完成实验、分析结果,并最终形成一份全面的研究报告。

让我们继续实现实验,首先在线性回归问题上比较四种优化算法的性能。

执行代码

执行代码

python

我注意到出现了一个错误,变量LinearRegression未定义。这是因为我们在不同的代码块中执行,需要重新定义模型类。让我们修复这个问题,并继续实验。

执行代码

执行代码

python

生成数据集...
线性回归数据集: 800 训练样本, 200 测试样本, 20 特征
分类数据集: 800 训练样本, 200 测试样本, 20 特征, 2 类别

数据集生成完成!
在线性回归问题上运行优化算法...

运行全梯度下降...
Epoch 10/100, Loss: 2307.379778
Epoch 20/100, Loss: 298.811067
Epoch 30/100, Loss: 41.640838
Epoch 40/100, Loss: 7.088303
Epoch 50/100, Loss: 2.231988
Epoch 60/100, Loss: 1.518973
Epoch 70/100, Loss: 1.409647
Epoch 80/100, Loss: 1.392141
Epoch 90/100, Loss: 1.389215
Epoch 100/100, Loss: 1.388705

运行SGD...
Epoch 10/100, Loss: 135.231939
Epoch 20/100, Loss: 2.614703
Epoch 30/100, Loss: 1.403256
Epoch 40/100, Loss: 1.388843
Epoch 50/100, Loss: 1.388624
Epoch 60/100, Loss: 1.388619
Converged at epoch 69 with loss 1.388607

运行SVRG...
Converged at epoch 8 with loss 1.388591

运行SVRG++...
Converged at epoch 9 with loss 1.388591

线性回归实验完成!

测试集上的损失:
全梯度下降: 1.434298
SGD: 1.434271
SVRG: 1.433175
SVRG++: 1.433207

收敛信息:
全梯度下降: 100 次迭代, 最终损失 1.388705, 用时 0.0015 秒
SGD: 69 次迭代, 最终损失 1.388607, 用时 0.0108 秒
SVRG: 8 次迭代, 最终损失 1.388591, 用时 0.1664 秒
SVRG++: 9 次迭代, 最终损失 1.388591, 用时 1.0587 秒
生成的图片链接: linear_regression_comparison.png

现在让我们在神经网络分类问题上比较这四种优化算法的性能。

执行代码

执行代码

python

我注意到出现了一个错误,变量np未定义。这是因为我们在不同的代码块中执行,需要重新导入numpy。让我们修复这个问题,并继续实验。

执行代码

执行代码

python

已掌握的信息

  1. 任务目标:在一个toy问题上比较全梯度下降(Full Gradient Descent)、随机梯度下降(SGD)、随机方差减小梯度下降(SVRG)和SVRG++算法的效果,并通过Python实际运行实验。
  2. 实验问题类型:已确定使用一个凸优化问题(线性回归)和一个非凸优化问题(简单神经网络进行二分类)。
  3. 数据集
    • 线性回归数据集:800个训练样本,200个测试样本,20个特征。
    • 分类数据集(用于神经网络):800个训练样本,200个测试样本,20个特征,2个类别。
    • 数据集特征已进行标准化处理。
  4. 模型定义
    • LinearRegression 类:实现了均方误差损失函数 (loss)、全梯度计算 (gradient) 和随机梯度计算 (gradient_sample)。
    • SimpleNN 类:实现了一个包含一个隐藏层的简单神经网络(输入层-Sigmoid隐藏层-Softmax输出层)。实现了交叉熵损失函数 (loss)、全梯度计算 (gradient)、随机梯度计算 (gradient_sample),以及参数获取 (get_params) 和设置 (set_params) 的方法。
  5. 优化算法实现
    • 已编码实现 full_gradient_descent, sgd, svrg, 和 svrg_plus_plus 四种优化算法。
    • 这些算法接受模型对象、数据、学习率、最大迭代次数等参数,并返回损失历史和时间历史。
    • SVRG++ 的实现中,内循环次数 m 会在每个外层epoch后翻倍。
  6. 凸优化问题(线性回归)实验结果
    • 全梯度下降: 100 次迭代, 最终训练损失 1.388705, 用时 0.0015 秒, 测试集损失 1.434298。
    • SGD: 69 次迭代 (提前收敛), 最终训练损失 1.388607, 用时 0.0108 秒, 测试集损失 1.434271。
    • SVRG: 8 次迭代 (提前收敛), 最终训练损失 1.388591, 用时 0.1664 秒, 测试集损失 1.433175。
    • SVRG++: 9 次迭代 (提前收敛), 最终训练损失 1.388591, 用时 1.0587 秒, 测试集损失 1.433207。
    • 已生成线性回归实验的损失对比图 (linear_regression_comparison.png)。
  7. 非凸优化问题(神经网络分类)实验尝试
    • 上一次执行神经网络分类实验时,由于执行时间过长,导致了 504 Gateway Time-out 错误。
    • 当时的超参数设置:learning_rate_gd = 0.5, learning_rate_sgd = 0.1, learning_rate_svrg = 0.5, learning_rate_svrg_pp = 0.5, max_epochs = 100, batch_size = 32 (用于SGD和SVRG/SVRG++的内循环随机梯度), hidden_dim = 10, m_svrg = 800 (等于训练样本数), m0_svrg_pp = 80 (训练样本数的1/10), tol = 1e-6
    • 所有神经网络模型被设计为使用相同的随机种子和初始权重以保证公平比较。

行动计划

  1. 调整非凸优化实验参数并重新运行

    • 鉴于上次非凸优化实验超时,首要任务是调整实验参数以减少计算时间,确保实验能够顺利完成。主要调整方向包括:
      • 显著减少最大迭代次数 (max_epochs),例如从100减少到20或30,以便快速观察初步结果和运行时间。
      • 适当减小SVRG的内循环次数 m (例如,m = N/2N/4,其中N为训练样本数)。
      • 适当减小SVRG++的初始内循环次数 m_0 (例如,m_0 = N/20N/40)。
      • (可选)考虑为SVRG++的内循环次数 m 设置一个上限,防止其增长过快导致后期计算量爆炸。
      • (可选)SVRG/SVRG++内循环中计算随机梯度时,可以尝试将 batch_size 减小到1,这更符合其理论描述,也可能减少单次梯度计算时间。
    • 使用调整后的参数,重新执行神经网络分类问题的对比实验,确保所有算法使用相同的初始模型参数。
    • 收集训练过程中的损失、时间、以及最终在测试集上的损失和准确率。
  2. 结果分析与可视化(非凸优化)

    • 成功获取非凸优化实验结果后,进行数据整理。
    • 绘制损失函数值 vs. 迭代次数(外层epoch)的曲线图。
    • 绘制损失函数值 vs. CPU时间的曲线图。
    • 考虑使用对数尺度 (semilogy) 绘制损失曲线,以便更清晰地观察收敛初期的快速下降和后期的细微变化。
    • 比较四种算法在训练损失、测试损失和测试准确率上的最终表现。
    • 分析各算法的收敛速度和计算效率。
  3. 综合结果分析与讨论

    • 对比四种优化算法在凸优化问题(线性回归)和非凸优化问题(神经网络)上的表现异同。
    • 讨论SVRG和SVRG++相对于SGD在方差减小、收敛速度和稳定性方面的优势,以及它们相对于全梯度下降在计算效率(尤其是在大数据集上,尽管本实验是toy问题)方面的潜力。
    • 分析SVRG++中动态调整内循环次数 m 的策略对收敛行为和计算成本的影响。
    • 讨论超参数(如学习率、mbatch_size)对各算法性能的敏感性(基于实验观察或理论推断)。
    • 指出各算法在“toy”级别问题上的局限性和潜在优势。
  4. 构建并撰写研究报告

    • 引言:阐述研究背景、目的,简要介绍被比较的四种优化算法及其在机器学习中的重要性。
    • 算法原理:清晰、简洁地回顾全梯度下降、SGD、SVRG和SVRG++的核心数学原理、更新规则、关键特性(如方差缩减机制)以及各自的理论优缺点。
    • 实验设计与设置
      • 详细描述所选用的凸优化(线性回归)和非凸优化(简单神经网络)“toy”问题的数学模型。
      • 说明数据集的生成方法、规模(训练集/测试集大小、特征维度、类别数等)和预处理步骤(如标准化)。
      • 列出各优化算法的具体实现要点和所有关键超参数的最终选定值及其选择依据(或调整过程)。
      • 明确定义用于评估算法性能的各项指标(如训练损失、测试损失、测试准确率、收敛所需迭代次数/时间)。
    • 实验结果与讨论
      • 系统地展示实验结果,包括清晰的图表(损失vs迭代次数,损失vs时间,均包含线性和对数尺度)和关键性能数据表格。
      • 对凸优化和非凸优化问题上的实验结果分别进行深入的比较分析和讨论。
      • 结合算法理论,解释观察到的现象,例如不同算法的收敛轨迹差异、计算效率差异、对问题类型的适应性等。
      • 讨论SVRG/SVRG++在减少梯度方差方面的效果,以及SVRG++动态调整策略的实际表现。
    • 结论与展望
      • 总结本研究在“toy”问题上比较四种优化算法的主要发现和核心结论。
      • 提炼出在所测试场景下,各算法的相对优势、劣势和可能的适用条件。
      • 可以简要展望未来可能的研究方向,例如在大规模问题上的验证、更复杂的模型结构、或其他方差缩减技术等。
    • 参考文献(若有):列出在算法原理回顾或实验设计中参考的重要文献。
    • 附录(可选):可包含核心的Python代码片段或更详细的原始实验数据图表。

通过以上步骤,旨在克服之前的技术障碍,全面完成实验,并基于实验结果产出一份逻辑清晰、内容详实的研究报告。

让我们重新运行神经网络分类问题的实验,但这次我们将减少最大迭代次数和内循环次数,以避免超时错误。

执行代码

执行代码

python

生成数据集...
分类数据集: 800 训练样本, 200 测试样本, 20 特征, 2 类别

数据集生成完成!
在神经网络分类问题上运行优化算法...

运行全梯度下降...
Epoch 5/30, Loss: 0.693041
Epoch 10/30, Loss: 0.692959
Epoch 15/30, Loss: 0.692824
Epoch 20/30, Loss: 0.692565
Epoch 25/30, Loss: 0.692047
Epoch 30/30, Loss: 0.690998

运行SGD...
Epoch 5/30, Loss: 0.691948
Epoch 10/30, Loss: 0.655640
Epoch 15/30, Loss: 0.470042
Epoch 20/30, Loss: 0.380910
Epoch 25/30, Loss: 0.357870
Epoch 30/30, Loss: 0.350124

运行SVRG...
Epoch 5/30, Loss: 0.155328
Epoch 10/30, Loss: 0.074743
Epoch 15/30, Loss: 0.047467
Epoch 20/30, Loss: 0.032298
Epoch 25/30, Loss: 0.023899
Epoch 30/30, Loss: 0.018408

运行SVRG++...
Epoch 5/30, Loss: 0.272115, Inner loop size: 400
Epoch 10/30, Loss: 0.052353, Inner loop size: 400
Epoch 15/30, Loss: 0.023258, Inner loop size: 400
Epoch 20/30, Loss: 0.013383, Inner loop size: 400
Epoch 25/30, Loss: 0.008921, Inner loop size: 400
Epoch 30/30, Loss: 0.006558, Inner loop size: 400

神经网络分类实验完成!

测试集上的损失:
全梯度下降: 0.691883, 准确率: 0.4900
SGD: 0.405370, 准确率: 0.7950
SVRG: 0.334868, 准确率: 0.8950
SVRG++: 0.322978, 准确率: 0.9150

收敛信息:
全梯度下降: 30 次迭代, 最终损失 0.690998, 用时 0.0092 秒
SGD: 30 次迭代, 最终损失 0.350124, 用时 0.0376 秒
SVRG: 30 次迭代, 最终损失 0.018408, 用时 0.6609 秒
SVRG++: 30 次迭代, 最终损失 0.006558, 用时 1.1611 秒
生成的图片链接: neural_network_comparison.png

现在我们已经成功完成了线性回归(凸优化问题)和神经网络分类(非凸优化问题)上的四种优化算法比较实验。让我们基于实验结果进行综合分析,并提供一个完整的报告。

优化算法比较研究:全梯度下降、SGD、SVRG 和 SVRG++ 在 Toy 问题上的实验分析

1. 引言

在机器学习和优化领域,梯度下降类算法是最常用的优化方法。本研究通过实际 Python 实验,在"toy"级别的问题上比较了四种重要的优化算法:全梯度下降(Full Gradient Descent)、随机梯度下降(SGD)、随机方差减小梯度下降(SVRG)以及其改进版本 SVRG++。这些算法在理论上各有优势,但在实际应用中的表现差异值得深入研究。

本实验选择了一个凸优化问题(线性回归)和一个非凸优化问题(简单神经网络分类)作为测试场景,通过比较这些算法在收敛速度、计算效率和最终精度等方面的表现,为算法选择提供实证参考。

2. 算法原理

2.1 全梯度下降 (Full Gradient Descent)

全梯度下降算法在每次迭代中使用整个训练集计算梯度,更新规则为:

text

其中,η 是学习率,∇f(w_t) 是在当前参数 w_t 处使用全部训练样本计算的梯度。

优点:收敛稳定,理论保证好
缺点:每次迭代计算成本高,尤其是在大规模数据集上

2.2 随机梯度下降 (SGD)

SGD 在每次迭代中随机选择一个或一小批样本计算梯度,更新规则为:

text

其中,∇f_i(w_t) 是在随机选择的样本或小批量上计算的梯度。

优点:计算效率高,适用于大规模数据集
缺点:收敛波动大,收敛速度可能较慢

2.3 随机方差减小梯度下降 (SVRG)

SVRG 结合了全梯度和随机梯度的优点,通过引入方差减小技术提高收敛稳定性。算法分为两层循环:

  1. 外层循环:计算当前参数 w̃ 处的全梯度 μ
  2. 内层循环:执行 m 次迭代,每次使用修正的随机梯度更新参数:
text

优点:比 SGD 更稳定,理论收敛速度更快
缺点:需要额外存储参考点和计算全梯度

2.4 SVRG++

SVRG++ 是 SVRG 的改进版本,主要区别在于动态调整内循环次数 m。具体而言,SVRG++ 从一个较小的 m₀ 开始,每次外循环后将 m 翻倍:

text

优点:初期计算效率更高,后期收敛更稳定
缺点:内循环次数增长过快可能导致后期计算量过大

3. 实验设计

3.1 问题设置

本实验选择了两个典型的机器学习问题:

  1. 凸优化问题:线性回归

    • 数据集:800 个训练样本,200 个测试样本,20 个特征
    • 损失函数:均方误差 (MSE)
  2. 非凸优化问题:简单神经网络二分类

    • 网络结构:单隐藏层神经网络(20-10-2),Sigmoid 激活函数,Softmax 输出层
    • 数据集:800 个训练样本,200 个测试样本,20 个特征,2 个类别
    • 损失函数:交叉熵损失

3.2 实验参数设置

线性回归实验参数

  • 学习率:全梯度下降 = 0.1,SGD = 0.01,SVRG = 0.1,SVRG++ = 0.1
  • 最大迭代次数:100
  • 批量大小(SGD/SVRG/SVRG++):32
  • SVRG 内循环次数:800(等于训练样本数)
  • SVRG++ 初始内循环次数:80(训练样本数的 1/10)
  • 收敛阈值:1e-6

神经网络实验参数

  • 学习率:全梯度下降 = 0.5,SGD = 0.1,SVRG = 0.5,SVRG++ = 0.5
  • 最大迭代次数:30
  • 批量大小(SGD/SVRG/SVRG++):32
  • SVRG 内循环次数:200(训练样本数的 1/4)
  • SVRG++ 初始内循环次数:20(训练样本数的 1/40)
  • SVRG++ 最大内循环次数:400
  • 收敛阈值:1e-6

4. 实验结果与分析

4.1 线性回归问题(凸优化)结果

收敛情况

  • 全梯度下降:100 次迭代,最终训练损失 1.388705,用时 0.0015 秒
  • SGD:69 次迭代(提前收敛),最终训练损失 1.388607,用时 0.0108 秒
  • SVRG:8 次迭代(提前收敛),最终训练损失 1.388591,用时 0.1664 秒
  • SVRG++:9 次迭代(提前收敛),最终训练损失 1.388591,用时 1.0587 秒

测试集性能

  • 全梯度下降:测试损失 1.434298
  • SGD:测试损失 1.434271
  • SVRG:测试损失 1.433175
  • SVRG++:测试损失 1.433207

分析

  1. 收敛速度:SVRG 和 SVRG++ 在迭代次数上表现最佳,仅需 8-9 次迭代即可收敛,而全梯度下降需要 100 次迭代,SGD 需要 69 次迭代。
  2. 计算效率:尽管 SVRG 和 SVRG++ 迭代次数少,但由于每次迭代的计算量较大(特别是内循环计算),实际运行时间反而较长。全梯度下降在这个小规模问题上计算时间最短。
  3. 最终精度:四种算法最终都达到了相似的损失值,但 SVRG 和 SVRG++ 在测试集上的损失略低,表明泛化性能略好。

4.2 神经网络分类问题(非凸优化)结果

收敛情况

  • 全梯度下降:30 次迭代,最终训练损失 0.690998,用时 0.0092 秒
  • SGD:30 次迭代,最终训练损失 0.350124,用时 0.0376 秒
  • SVRG:30 次迭代,最终训练损失 0.018408,用时 0.6609 秒
  • SVRG++:30 次迭代,最终训练损失 0.006558,用时 1.1611 秒

测试集性能

  • 全梯度下降:测试损失 0.691883,准确率 0.4900
  • SGD:测试损失 0.405370,准确率 0.7950
  • SVRG:测试损失 0.334868,准确率 0.8950
  • SVRG++:测试损失 0.322978,准确率 0.9150

分析

  1. 收敛速度:在非凸优化问题上,SVRG 和 SVRG++ 表现出明显优势,损失下降速度远快于全梯度下降和 SGD。
  2. 最终精度:SVRG++ 达到了最低的训练损失 (0.006558) 和最高的测试准确率 (91.50%),SVRG 紧随其后。全梯度下降表现最差,测试准确率仅为 49.00%。
  3. 计算效率:与线性回归问题类似,SVRG 和 SVRG++ 的计算时间较长,但考虑到它们的精度优势,这种时间成本是值得的。
  4. 泛化性能:SVRG 和 SVRG++ 在测试集上表现出色,说明它们不仅收敛更快,而且泛化能力更强。

5. 讨论

5.1 凸优化 vs 非凸优化

  1. 算法表现差异:在凸优化问题(线性回归)上,四种算法最终都收敛到相似的损失值,差异主要体现在收敛速度和计算效率上。而在非凸优化问题(神经网络)上,算法间的性能差异显著,SVRG 和 SVRG++ 明显优于全梯度下降和 SGD。

  2. 收敛稳定性:在非凸问题上,全梯度下降几乎没有收敛(损失值从 0.693041 仅下降到 0.690998),这可能是因为它容易陷入局部最小值或鞍点。相比之下,具有随机性的 SGD、SVRG 和 SVRG++ 能够更好地探索参数空间,避开不良局部最优解。

5.2 方差减小技术的效果

  1. 收敛加速:实验结果明确显示了方差减小技术的有效性。SVRG 和 SVRG++ 在两个问题上都表现出更快的收敛速度,特别是在非凸问题上,优势更为明显。

  2. 计算成本权衡:尽管 SVRG 和 SVRG++ 在每次迭代中需要更多计算(计算全梯度和内循环),但它们所需的总迭代次数显著减少,在大规模问题上可能更有优势。

  3. SVRG++ 的动态调整策略:SVRG++ 通过动态增加内循环次数,在初期快速探索参数空间,后期更精细地收敛,在非凸问题上表现出色。在本实验中,我们限制了最大内循环次数为 400,避免了计算量过大的问题。

5.3 实际应用考虑

  1. 问题规模:本实验使用的是"toy"级别的问题(800 个训练样本),在这种规模下,全梯度下降在计算时间上可能具有优势。但在大规模问题上,SGD、SVRG 和 SVRG++ 的优势会更加明显。

  2. 问题类型:对于简单的凸优化问题,全梯度下降和 SGD 可能已经足够;但对于复杂的非凸问题(如深度神经网络),SVRG 和 SVRG++ 的方差减小技术能带来显著收益。

  3. 计算资源:SVRG 和 SVRG++ 需要额外的存储空间(存储参考点和全梯度),在内存受限的环境中可能不是最佳选择。

6. 结论

本研究通过在"toy"级别的凸优化和非凸优化问题上比较四种优化算法,得出以下结论:

  1. 全梯度下降:在小规模凸优化问题上计算效率高,但在非凸问题上容易陷入局部最优,表现较差。

  2. SGD:计算效率较高,在非凸问题上表现优于全梯度下降,但收敛速度不如 SVRG 和 SVRG++。

  3. SVRG:通过方差减小技术显著提高了收敛速度和稳定性,特别是在非凸问题上表现出色,但计算成本较高。

  4. SVRG++:动态调整内循环次数的策略进一步提高了算法性能,在非凸问题上达到了最佳的收敛结果和测试准确率,但计算时间最长。

总体而言,对于小规模凸优化问题,全梯度下降可能是最简单有效的选择;而对于非凸优化问题,特别是当精度要求高时,SVRG 和 SVRG++ 尽管计算成本较高,但其收敛速度和最终精度的优势使它们成为更好的选择。

7. 未来工作

  1. 在更大规模的数据集和更复杂的模型上验证这些算法的性能差异。
  2. 探索学习率调度策略对各算法性能的影响。
  3. 研究 SVRG++ 内循环次数增长策略的优化,寻找更高效的动态调整方法。
  4. 将这些算法与其他现代优化方法(如 Adam、RMSProp 等)进行比较。