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

试试这4种深度学习中的高级优化技术吧

ztj100 2024-11-11 15:14 15 浏览 0 评论

来源:DeepHub IMBA

本文约3700字,建议阅读10+分钟

本文将介绍四种高级优化技术,这些技术在某些任务中可能优于传统方法,特别是在面对复杂优化问题时。


在深度学习领域,优化器的选择对模型性能至关重要。虽然PyTorch中的标准优化器如SGD、Adam和AdamW被广泛应用,但它们并非在所有情况下都是最优选择。本文将介绍四种高级优化技术,这些技术在某些任务中可能优于传统方法,特别是在面对复杂优化问题时。


我们将探讨以下算法:


  • 序列最小二乘规划(SLSQP)
  • 粒子群优化(PSO)
  • 协方差矩阵自适应进化策略(CMA-ES)
  • 模拟退火(SA)


这些方法的主要优势包括:


  • 无梯度优化:适用于非可微操作,如采样、取整和组合优化。
  • 仅需前向传播:通常比传统方法更快,且内存效率更高。
  • 全局优化能力:有助于避免局部最优解。


需要注意的是,这些方法最适合优化参数数量较少(通常少于100-1000个)的情况。它们特别适用于优化关键参数、每层特定参数或超参数。


实验准备


在开始实验之前,我们需要设置环境并定义一些辅助函数。以下是必要的导入和函数定义:


 from functools import partial

 from collections import defaultdict

 import torch

 import torch.nn as nn

 import torch.optim as optim

 import torch.nn.functional as F

 import numpy as np

 import scipy.optimize as opt

 import matplotlib.pyplot as plt

 

 # 设置随机种子以确保结果可复现

 torch.manual_seed(42) 

 np.random.seed(42)  

 

 # 辅助函数:在PyTorch模型和NumPy向量之间转换权重

 def set_model_weights_from_vector(model, numpy_vector):

     weight_vector = torch.tensor(numpy_vector, dtype=torch.float64)

     model[0].weight.data = weight_vector[0:4].reshape(2, 2)

     model[2].weight.data = weight_vector[4:8].reshape(2, 2)

     model[2].bias.data = weight_vector[8:10]

     return model

 

 def get_vector_from_model_weights(model):

     return torch.cat([

         model[0].weight.data.view(-1), 

         model[2].weight.data.view(-1), 

         model[2].bias.data]

    ).detach().numpy()

 

 # 用于跟踪和更新损失的函数

 def update_tracker(loss_tracker, optimizer_name, loss_val):

     loss_tracker[optimizer_name].append(loss_val)

     if len(loss_tracker[optimizer_name]) > 1:

         min_loss = min(loss_tracker[optimizer_name][-2], loss_val)

         loss_tracker[optimizer_name][-1] = min_loss

     return loss_tracker


这些函数将用于在不同的优化算法之间转换模型权重,并跟踪优化过程中的损失。

接下来定义目标函数和PyTorch优化循环:


 def objective(x, model, input, target, loss_tracker, optimizer_name):

     model = set_model_weights_from_vector(model, x)

     loss_val = F.mse_loss(model(input), target).item()

     loss_tracker = update_tracker(loss_tracker, optimizer_name, loss_val)  

     return loss_val

 

 def pytorch_optimize(x, model, input, target, maxiter, loss_tracker, optimizer_name="Adam"):

     set_model_weights_from_vector(model, x)

     optimizer = optim.Adam(model.parameters(), lr=1.) 

 

     # 训练循环

     for iteration in range(maxiter):  

         loss = F.mse_loss(model(input), target)

         optimizer.zero_grad()  

         loss.backward()        

         optimizer.step()

         loss_tracker = update_tracker(loss_tracker, optimizer_name, loss.item())  

     final_x = get_vector_from_model_weights(model)

     return final_x, loss.item()


最后设置实验所需的通用变量:


 model = nn.Sequential(nn.Linear(2, 2, bias=False), nn.ReLU(), nn.Linear(2, 2, bias=True)).double()

 input_tensor = torch.randn(32, 2).double()  # 随机输入张量

 input_tensor[:, 1] *= 1e3  # 增加一个变量的敏感度

 target = input_tensor.clone() # 目标是输入本身(恒等函数)

 num_params = 10

 maxiter = 100

 x0 = 0.1 * np.random.randn(num_params)

 loss_tracker = defaultdict(list)


这些设置为我们的实验创建了一个简单的神经网络模型、定义了输入、目标和初始参数。


在下一部分中,我们将开始实现和比较不同的优化技术。


优化技术比较


1. PyTorch中的Adam优化器


作为基准,我们首先使用PyTorch的Adam优化器。Adam是一种自适应学习率优化算法,在深度学习中广泛使用。


 optimizer_name = "PyTorch Adam"

 result = pytorch_optimize(x0, model, input_tensor, target, maxiter, loss_tracker, optimizer_name)

 print(f'Adam优化器最终损失: {result[1]}')


运行此代码后,我们得到以下结果:


 Adam优化器最终损失: 91.85612831226527

考虑到初始损失值约为300,000,这个结果在100次优化步骤后已经有了显著改善。


2. 序列最小二乘规划 (SLSQP)


序列最小二乘规划(SLSQP)是一种强大的优化算法,特别适用于具有连续参数的问题。它通过在每一步构建二次近似来逼近最优解。


 optimizer_name = "slsqp"

 args = (model, input_tensor, target, loss_tracker, optimizer_name)

 result = opt.minimize(objective, x0, method=optimizer_name, args=args, options={"maxiter": maxiter, "disp": False, "eps": 0.001})

 print(f"SLSQP优化器最终损失: {result.fun}")


运行SLSQP算法,我们获得以下结果:


 SLSQP优化器最终损失: 3.097042282788268

SLSQP的性能明显优于Adam,这表明在某些情况下,非传统优化方法可能更有效。


3. 粒子群优化 (PSO)


粒子群优化(PSO)是一种基于群体智能的优化算法,其灵感来自于鸟群和鱼群的社会行为。PSO在非连续和非光滑的问题上表现尤为出色。


 from pyswarm import pso

 

 lb = -np.ones(num_params)

 ub = np.ones(num_params)

 optimizer_name = 'pso'

 args = (model, input_tensor, target, loss_tracker, optimizer_name)

 result_pso = pso(objective, lb, ub, maxiter=maxiter, args=args)

 print(f"PSO优化器最终损失: {result_pso[1]}")


PSO的优化结果如下:


 PSO优化器最终损失: 1.0195048385714032

PSO的表现进一步超越了SLSQP,这凸显了在复杂优化问题中探索多种算法的重要性。


4. 协方差矩阵自适应进化策略 (CMA-ES)


协方差矩阵自适应进化策略(CMA-ES)是一种高度复杂的优化算法,特别适用于难以处理的非凸优化问题。它通过自适应地学习问题的协方差结构来指导搜索过程。

 from cma import CMAEvolutionStrategy

 

 es = CMAEvolutionStrategy(x0, 0.5, {"maxiter": maxiter, "seed": 42})

 optimizer_name = 'cma'

 args = (model, input_tensor, target, loss_tracker, optimizer_name)

 while not es.stop():

     solutions = es.ask()

     object_vals = [objective(x, *args) for x in solutions]

     es.tell(solutions, object_vals)

 print(f"CMA-ES优化器最终损失: {es.result[1]}")


CMA-ES的优化结果如下:


 (5_w,10)-aCMA-ES (mu_w=3.2,w_1=45%) in dimension 10 (seed=42, Thu Oct 12 22:03:53 2024)  

 CMA-ES优化器最终损失: 4.084718909553896


虽然CMA-ES在这个特定问题上没有达到最佳性能,但它在处理复杂的多模态优化问题时通常表现出色。


5. 模拟退火 (SA)


模拟退火(SA)是一种受冶金学启发的优化算法,它模拟了金属冷却和退火过程。SA在寻找全局最优解方面特别有效,能够避免陷入局部最优解。


 from scipy.optimize import dual_annealing

 bounds = [(-1, 1)] * num_params

 optimizer_name = 'simulated_annealing'

 args = (model, input_tensor, target, loss_tracker, optimizer_name)

 result = dual_annealing(objective, bounds, maxiter=maxiter, args=args, initial_temp=1.)

 print(f"SA优化器最终损失: {result.fun}")


SA的优化结果如下:


 SA优化器最终损失: 0.7834294257939689


可以看到,针对我们的问题SA表现最佳,这突显了其在复杂优化问题中的潜力。


下面我们来可视化这些优化器的性能,并讨论结果的含义。


结果可视化与分析


为了更好地理解各种优化算法的性能,我们将使用matplotlib库来可视化优化过程中的损失变化。


 plt.figure(figsize=(10, 6))

 line_styles = ['-', '--', '-.', ':']

 for i, (optimizer_name, losses) in enumerate(loss_tracker.items()):

     plt.plot(np.linspace(0, maxiter, len(losses)), losses, 

              label=optimizer_name, 

              linestyle=line_styles[i % len(line_styles)], 

              linewidth=5,

    )

 plt.xlabel("Iteration", fontsize=20)

 plt.ylabel("Loss", fontsize=20)

 plt.ylim(1e-1, 1e7)

 plt.yscale('log')

 plt.title("Loss For Different Optimizers", fontsize=20)

 plt.grid(True, linestyle='--', alpha=0.6)

 plt.legend(loc='upper right', fontsize=20)

 plt.tight_layout()

 plt.savefig('optimizers.png')

 plt.show()


执行上述代码后,我们得到了以下可视化结果:



结果分析


  • Adam优化器:作为基准Adam表现稳定但收敛速度相对较慢。这反映了在某些复杂问题中,传统梯度下降方法可能不是最优选择。
  • SLSQP:序列最小二乘规划表现出快速的初始收敛,这表明它在处理具有连续参数的问题时非常有效。
  • PSO:粒子群优化展示了良好的全局搜索能力,能够迅速找到较好的解。这凸显了其在非凸优化问题中的潜力。
  • CMA-ES:虽然在本实验中收敛较慢,但协方差矩阵自适应进化策略通常在处理高度复杂和多模态的问题时表现出色。其性能可能在更复杂的优化场景中更为突出。
  • 模拟退火:我们这个特定问题SA表现最为出色,仅用几次迭代就达到了最低损失。这突显了其在避免局部最优解并快速找到全局最优解方面的优势。


需要注意的是,每种算法的"迭代"定义可能不同,因此直接比较迭代次数可能不够公平。例如SA的每次迭代可能包含多次目标函数评估。


总结


在特定问题上,非传统优化方法可能比标准的梯度下降算法(如Adam)表现更好。然而,这并不意味着这些方法在所有情况下都优于传统方法。选择最适合的优化算法应基于具体问题的特性:


  • 对于参数数量较少(100-1000个)的优化问题,考虑尝试本文介绍的高级优化技术。
  • 在处理非可微操作或复杂的损失景观时,无梯度方法(如PSO、CMA-ES和SA)可能更有优势。
  • 对于需要满足复杂约束的优化问题,SLSQP可能是一个很好的选择。
  • 在计算资源有限的情况下,考虑使用仅需前向传播的方法,如PSO或SA。
  • 对于高度非凸的问题,CMA-ES和SA可能更容易找到全局最优解。


最后,建议在实际应用中对多种优化方法进行比较和测试,以找到最适合特定问题的算法。同时要注意这些高级方法在大规模问题(参数数量超过1000)上可能面临计算效率的挑战。


未来研究方向


  • 探索这些高级优化技术在更复杂的深度学习模型中的应用。
  • 研究如何有效地将这些方法与传统的梯度下降算法结合,以开发混合优化策略。
  • 开发更高效的并行化实现,以提高这些算法在大规模问题上的适用性。
  • 探索这些方法在特定领域(如强化学习、神经架构搜索)中的潜在应用。


通过深入理解和灵活运用这些高级优化技术,研究者和工程师可以在面对复杂优化问题时拓展解决方案的范围,potentially unlocking新的性能水平和应用可能性。


参考文献


  1. Hansen, N. (2016). The CMA Evolution Strategy: A Tutorial. arXiv preprint arXiv:1604.00772.
  2. Kennedy, J., & Eberhart, R. (1995). Particle swarm optimization. Proceedings of ICNN'95 - International Conference on Neural Networks, 4, 1942-1948.
  3. Nocedal, J., & Wright, S. J. (1999). Numerical Optimization. New York: Springer.
  4. Tsallis, C., & Stariolo, D. A. (1996). Generalized simulated annealing. Physica A: Statistical Mechanics and its Applications, 233(1-2), 395-406.
  5. Kingma, D. P., & Ba, J. (2014). Adam: A Method for Stochastic Optimization. arXiv preprint arXiv:1412.6980.
  6. Ruder, S. (2016). An overview of gradient descent optimization algorithms. arXiv preprint arXiv:1609.04747.

相关推荐

30天学会Python编程:16. Python常用标准库使用教程

16.1collections模块16.1.1高级数据结构16.1.2示例...

强烈推荐!Python 这个宝藏库 re 正则匹配

Python的re模块(RegularExpression正则表达式)提供各种正则表达式的匹配操作。...

Python爬虫中正则表达式的用法,只讲如何应用,不讲原理

Python爬虫:正则的用法(非原理)。大家好,这节课给大家讲正则的实际用法,不讲原理,通俗易懂的讲如何用正则抓取内容。·导入re库,这里是需要从html这段字符串中提取出中间的那几个文字。实例一个对...

Python数据分析实战-正则提取文本的URL网址和邮箱(源码和效果)

实现功能:Python数据分析实战-利用正则表达式提取文本中的URL网址和邮箱...

python爬虫教程之爬取当当网 Top 500 本五星好评书籍

我们使用requests和re来写一个爬虫作为一个爱看书的你(说的跟真的似的)怎么能发现好书呢?所以我们爬取当当网的前500本好五星评书籍怎么样?ok接下来就是学习python的正确姿...

深入理解re模块:Python中的正则表达式神器解析

在Python中,"re"是一个强大的模块,用于处理正则表达式(regularexpressions)。正则表达式是一种强大的文本模式匹配工具,用于在字符串中查找、替换或提取特定模式...

如何使用正则表达式和 Python 匹配不以模式开头的字符串

需要在Python中使用正则表达式来匹配不以给定模式开头的字符串吗?如果是这样,你可以使用下面的语法来查找所有的字符串,除了那些不以https开始的字符串。r"^(?!https).*&...

先Mark后用!8分钟读懂 Python 性能优化

从本文总结了Python开发时,遇到的性能优化问题的定位和解决。概述:性能优化的原则——优化需要优化的部分。性能优化的一般步骤:首先,让你的程序跑起来结果一切正常。然后,运行这个结果正常的代码,看看它...

Python“三步”即可爬取,毋庸置疑

声明:本实例仅供学习,切忌遵守robots协议,请不要使用多线程等方式频繁访问网站。#第一步导入模块importreimportrequests#第二步获取你想爬取的网页地址,发送请求,获取网页内...

简单学Python——re库(正则表达式)2(split、findall、和sub)

1、split():分割字符串,返回列表语法:re.split('分隔符','目标字符串')例如:importrere.split(',','...

Lavazza拉瓦萨再度牵手上海大师赛

阅读此文前,麻烦您点击一下“关注”,方便您进行讨论和分享。Lavazza拉瓦萨再度牵手上海大师赛标题:2024上海大师赛:网球与咖啡的浪漫邂逅在2024年的上海劳力士大师赛上,拉瓦萨咖啡再次成为官...

ArkUI-X构建Android平台AAR及使用

本教程主要讲述如何利用ArkUI-XSDK完成AndroidAAR开发,实现基于ArkTS的声明式开发范式在android平台显示。包括:1.跨平台Library工程开发介绍...

Deepseek写歌详细教程(怎样用deepseek写歌功能)

以下为结合DeepSeek及相关工具实现AI写歌的详细教程,涵盖作词、作曲、演唱全流程:一、核心流程三步法1.AI生成歌词-打开DeepSeek(网页/APP/API),使用结构化提示词生成歌词:...

“AI说唱解说影视”走红,“零基础入行”靠谱吗?本报记者实测

“手里翻找冻鱼,精心的布局;老漠却不言语,脸上带笑意……”《狂飙》剧情被写成歌词,再配上“科目三”背景音乐的演唱,这段1分钟30秒的视频受到了无数网友的点赞。最近一段时间随着AI技术的发展,说唱解说影...

AI音乐制作神器揭秘!3款工具让你秒变高手

在音乐创作的领域里,每个人都有一颗想要成为大师的心。但是面对复杂的乐理知识和繁复的制作过程,许多人的热情被一点点消磨。...

取消回复欢迎 发表评论: