0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

PyTorch教程-19.4. 多保真超参数优化

jf_pJlTbmA9 来源:PyTorch 作者:PyTorch 2023-06-05 15:44 次阅读

即使在中等规模的数据集上,训练神经网络也可能很昂贵。根据配置空间(第 19.1.1.2 节),超参数优化需要数十到数百次函数评估才能找到性能良好的超参数配置。正如我们在19.3 节中看到的 ,我们可以通过利用并行资源显着加快 HPO 的整体时钟时间,但这并不会减少所需的总计算量。

在本节中,我们将展示如何加速超参数配置的评估。随机搜索等方法为每个超参数评估分配相同数量的资源(例如,epoch 数、训练数据点)。图 19.4.1 描绘了一组使用不同超参数配置训练的神经网络的学习曲线。经过几个 epoch 之后,我们已经能够在视觉上区分性能良好和次优的配置。然而,学习曲线是嘈杂的,我们可能仍然需要全部 100 个 epoch 来确定表现最好的一个。

pYYBAGR9PYOAF8kfAAxEY-DeiWg543.svg

图 19.4.1随机超参数配置的学习曲线

多保真超参数优化将更多资源分配给有前途的配置,并尽早停止对性能不佳的配置的评估。这加快了优化过程,因为我们可以为相同的资源总量尝试更多的配置。

更正式地说,我们扩展了第 19.1.1 节中的定义 ,这样我们的目标函数 f(x,r)获得额外的输入 r∈[rmin,rmax], 指定我们愿意为配置评估花费的资源量x. 我们假设错误 f(x,r)随着r,而计算成本c(x,r)增加。通常, r表示训练神经网络的时期数,但它也可以是训练子集大小或交叉验证折叠数。

from collections import defaultdict
import numpy as np
from scipy import stats
from d2l import torch as d2l

d2l.set_figsize()

19.4.1。连续减半

使随机搜索适应多保真度设置的最简单方法之一是连续减半 (Jamieson 和 Talwalkar,2016 年,Karnin等人,2013 年)。基本思想是从N配置,例如从配置空间随机采样,并训练它们中的每一个 rmin只有时代。然后,我们丢弃一部分表现最差的试验,并对其余试验进行更长时间的训练。重复这个过程,更少的试验运行更长时间,直到至少有一个试验达到rmax时代。

更正式地说,考虑最低预算rmin(例如 1 个 epoch),最大预算rmax,例如 max_epochs在我们之前的例子中,还有一个减半常数 η∈{2,3,…}. 为简单起见,假设 rmax=rminηK, 和K∈I. 那么初始配置的数量是N=ηK. 让我们定义一组梯级 R={rmin,rminη,rminη2,…,rmax}.

一轮连续减半的过程如下。我们从跑步开始N试验到第一梯级rmin. 对验证错误进行排序,我们保持顶部1/η分数(相当于ηK−1配置)并丢弃所有其余的。幸存的试验被训练用于下一个梯级(rminηepochs),然后重复该过程。在每个梯级,一个1/η部分试验存活下来,他们的训练继续进行η倍大的预算。有了这个特别的选择N, 只有一个试验将被训练到全部预算rmax. 一旦这样一轮连续的减半完成,我们就会用一组新的初始配置开始下一轮,迭代直到总预算用完。

poYBAGR9PYmAFbkqAAozwWvrwco526.svg

图 19.4.2随机超参数配置的学习曲线。

我们将第 19.2 节HPOScheduler的基类子类化 ,以实现连续减半,允许通用 对象对配置进行采样(在我们下面的示例中,它将是 a )。此外,用户必须通过最少的资源HPOSearcherRandomSearcherrmin, 最大资源 rmax和η作为输入。在我们的调度程序中,我们维护一个配置队列,这些配置仍需要针对当前梯级进行评估ri. 每次我们跳到下一个梯级时,我们都会更新队列。

class SuccessiveHalvingScheduler(d2l.HPOScheduler): #@save
  def __init__(self, searcher, eta, r_min, r_max, prefact=1):
    self.save_hyperparameters()
    # Compute K, which is later used to determine the number of configurations
    self.K = int(np.log(r_max / r_min) / np.log(eta))
    # Define the rungs
    self.rung_levels = [r_min * eta ** k for k in range(self.K + 1)]
    if r_max not in self.rung_levels:
      # The final rung should be r_max
      self.rung_levels.append(r_max)
      self.K += 1
    # Bookkeeping
    self.observed_error_at_rungs = defaultdict(list)
    self.all_observed_error_at_rungs = defaultdict(list)
    # Our processing queue
    self.queue = []

一开始我们的队列是空的,我们用 n=prefact⋅ηK配置,首先在最小的梯级上进行评估rmin. 这里, prefact允许我们在不同的上下文中重用我们的代码。出于本节的目的,我们固定 prefact=1. 每次资源可用并且HPOTuner对象查询suggest函数时,我们都会从队列中返回一个元素。一旦我们完成一轮连续减半,这意味着我们评估了最高资源级别上的所有幸存配置rmax并且我们的队列是空的,我们用一组新的、随机采样的配置重新开始整个过程​​。

@d2l.add_to_class(SuccessiveHalvingScheduler) #@save
def suggest(self):
  if len(self.queue) == 0:
    # Start a new round of successive halving
    # Number of configurations for the first rung:
    n0 = int(self.prefact * self.eta ** self.K)
    for _ in range(n0):
      config = self.searcher.sample_configuration()
      config["max_epochs"] = self.r_min # Set r = r_min
      self.queue.append(config)
  # Return an element from the queue
  return self.queue.pop()

当我们收集到一个新的数据点时,我们首先更新搜索器模块。之后我们检查我们是否已经收集了当前梯级上的所有数据点。如果是这样,我们对所有配置进行排序并推顶 1η配置到队列中。

@d2l.add_to_class(SuccessiveHalvingScheduler) #@save
def update(self, config: dict, error: float, info=None):
  ri = int(config["max_epochs"]) # Rung r_i
  # Update our searcher, e.g if we use Bayesian optimization later
  self.searcher.update(config, error, additional_info=info)
  self.all_observed_error_at_rungs[ri].append((config, error))
  if ri < self.r_max:
    # Bookkeeping
    self.observed_error_at_rungs[ri].append((config, error))
    # Determine how many configurations should be evaluated on this rung
    ki = self.K - self.rung_levels.index(ri)
    ni = int(self.prefact * self.eta ** ki)
    # If we observed all configuration on this rung r_i, we estimate the
    # top 1 / eta configuration, add them to queue and promote them for
    # the next rung r_{i+1}
    if len(self.observed_error_at_rungs[ri]) >= ni:
      kiplus1 = ki - 1
      niplus1 = int(self.prefact * self.eta ** kiplus1)
      best_performing_configurations = self.get_top_n_configurations(
        rung_level=ri, n=niplus1
      )
      riplus1 = self.rung_levels[self.K - kiplus1] # r_{i+1}
      # Queue may not be empty: insert new entries at the beginning
      self.queue = [
        dict(config, max_epochs=riplus1)
        for config in best_performing_configurations
      ] + self.queue
      self.observed_error_at_rungs[ri] = [] # Reset

配置根据其在当前梯级上观察到的性能进行排序。

@d2l.add_to_class(SuccessiveHalvingScheduler) #@save
def get_top_n_configurations(self, rung_level, n):
  rung = self.observed_error_at_rungs[rung_level]
  if not rung:
    return []
  sorted_rung = sorted(rung, key=lambda x: x[1])
  return [x[0] for x in sorted_rung[:n]]

让我们看看在我们的神经网络示例中连续减半是如何进行的。我们将使用rmin=2,η=2, rmax=10, 所以梯级是2,4,8,10.

min_number_of_epochs = 2
max_number_of_epochs = 10
eta = 2
num_gpus=1

config_space = {
  "learning_rate": stats.loguniform(1e-2, 1),
  "batch_size": stats.randint(32, 256),
}
initial_config = {
  "learning_rate": 0.1,
  "batch_size": 128,
}

我们只是用新的 SuccessiveHalvingScheduler.

searcher = d2l.RandomSearcher(config_space, initial_config=initial_config)
scheduler = SuccessiveHalvingScheduler(
  searcher=searcher,
  eta=eta,
  r_min=min_number_of_epochs,
  r_max=max_number_of_epochs,
)
tuner = d2l.HPOTuner(
  scheduler=scheduler,
  objective=d2l.hpo_objective_lenet,
)
tuner.run(number_of_trials=30)

  error = 0.1623382568359375, runtime = 84.38501596450806

poYBAGR9PYuAUAhrAADuoiC26CU128.svg

pYYBAGR9PY2AT4SaAADuUFisjOQ145.svg

poYBAGR9PY-ARLW4AADuLkO_Mbo735.svg

pYYBAGR9PZGAeIEqAADt5hd506s949.svg

poYBAGR9PZOAAzaCAADt9GSOkOs988.svg

pYYBAGR9PZaAR-EdAADty-t9uFQ695.svg

poYBAGR9PZiAUnHgAADuQ6P9Gco390.svg

pYYBAGR9PZqAQFCCAADuI3eePhM029.svg

poYBAGR9PZ2ARC0bAAD8XQ_0wwE803.svg

pYYBAGR9PZ-AFo_yAADw6F47HCA645.svg

poYBAGR9PaOALcNOAADv4XdqzxY437.svg

pYYBAGR9PaWAK-0UAADxaRuWu1w366.svg

poYBAGR9PaiAMYSbAAE_tpJYd2c110.svg

pYYBAGR9PauATIsuAAE_dQNveV4670.svg

pYYBAGR9Pa2AKKxIAAF89ODTDLM921.svg

pYYBAGR9PbGAfqizAADuLZQ8urI734.svg

poYBAGR9PbOAXS-1AADfvmtq5Z0829.svg

poYBAGR9PbaAWpilAADuTPmX5fY655.svg

pYYBAGR9PbiAG3vbAADuLCjSQ0U293.svg

poYBAGR9PbuAEkilAADuK8v1jj8162.svg

pYYBAGR9Pb2AVcGuAADuRnZy_5Y411.svg

pYYBAGR9PcCAdU5_AADuQJ9KLCE625.svg

poYBAGR9PcKAbpc3AADuMlnHPs4175.svg

pYYBAGR9PcSATFXhAADwmrw0vWo534.svg

pYYBAGR9PceAEELxAADkRicCDPw706.svg

poYBAGR9PcmAQ6ccAADjq4kuymM166.svg

poYBAGR9PcuAZekgAADkcV12zHU605.svg

pYYBAGR9Pc6AHm8LAAE0otUMuSQ870.svg

pYYBAGR9PdCAIpwsAAFCYIMbcMc691.svg

poYBAGR9PdKAD7JFAAF0dI8QEpI748.svg

我们可以可视化我们评估的所有配置的学习曲线。大多数配置会提前停止,只有性能较好的配置会存活到rmax. 将此与香草随机搜索进行比较,后者将分配rmax到每个配置。

for rung_index, rung in scheduler.all_observed_error_at_rungs.items():
  errors = [xi[1] for xi in rung]
  d2l.plt.scatter([rung_index] * len(errors), errors)
d2l.plt.xlim(min_number_of_epochs - 0.5, max_number_of_epochs + 0.5)
d2l.plt.xticks(
  np.arange(min_number_of_epochs, max_number_of_epochs + 1),
  np.arange(min_number_of_epochs, max_number_of_epochs + 1)
)
d2l.plt.ylabel("validation error")
d2l.plt.xlabel("epochs")

Text(0.5, 0, 'epochs')

pYYBAGR9PdWAYdP7AAEO7gPT0n8269.svg

最后,请注意我们在 SuccessiveHalvingScheduler. 假设一名工人可以自由运行一项工作,并suggest在当前梯级几乎完全填满时被调用,但另一名工人仍在忙于评估。由于我们缺少来自该工作人员的指标值,因此我们无法确定排名靠前的1/η分数打开下一个梯级。另一方面,我们想给我们的自由工人分配一份工作,这样它就不会闲着。我们的解决方案是开始新一轮的连续减半,并​​将我们的工人分配到那里的第一次试验。然而,一旦梯级在 中完成update,我们确保在队列的开头插入新配置,因此它们优先于下一轮的配置。

19.4.2。概括

在本节中,我们介绍了多保真超参数优化的概念,我们假设可以访问目标函数的廉价评估近似值,例如在一定数量的训练时期后的验证错误作为验证错误的代理在全部的纪元之后。多保真超参数优化允许减少 HPO 的整体计算,而不仅仅是减少挂钟时间。

我们实施并评估了连续减半,这是一种简单而高效的多保真 HPO 算法

Discussions

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 保真
    +关注

    关注

    0

    文章

    4

    浏览量

    13574
  • pytorch
    +关注

    关注

    2

    文章

    803

    浏览量

    13132
收藏 人收藏

    评论

    相关推荐

    proteus仿真超声波倒车雷达

    `proteus仿真超声波倒车雷达`
    发表于 08-24 16:12

    Pytorch模型训练实用PDF教程【中文】

    ?模型部分?还是优化器?只有这样不断的通过可视化诊断你的模型,不断的对症下药,才能训练出一个较满意的模型。本教程内容及结构:本教程内容主要为在 PyTorch 中训练一个模型所可能涉及到的方法及函数,并且
    发表于 12-21 09:18

    PyTorch如何入门

    PyTorch 入门实战(一)——Tensor
    发表于 06-01 09:58

    pytorch模型转换需要注意的事项有哪些?

    ,并且可以更积极地进行优化。 支持什么格式的pytorch模型? 答:Sophon的PyTorch模型编译工具BMNETP只接受PyTorch的JIT模型JIT模型(TorchScri
    发表于 09-18 08:05

    基于PyTorch的深度学习入门教程之DataParallel使用GPU

    讲到DataParallel使用GPU。 在PyTorch中使用GPU比较简单,可以这样把模型放到GPU上。 model.gpu() 还可以复制所有的tensors到GPU上。 mytensor = my_ten
    的头像 发表于 02-15 09:55 4063次阅读

    PyTorch教程6.2之参数管理

    电子发烧友网站提供《PyTorch教程6.2之参数管理.pdf》资料免费下载
    发表于 06-05 15:24 0次下载
    <b class='flag-5'>PyTorch</b>教程6.2之<b class='flag-5'>参数</b>管理

    PyTorch教程12.1之优化和深度学习

    电子发烧友网站提供《PyTorch教程12.1之优化和深度学习.pdf》资料免费下载
    发表于 06-05 15:08 0次下载
    <b class='flag-5'>PyTorch</b>教程12.1之<b class='flag-5'>优化</b>和深度学习

    PyTorch教程13.7之参数服务器

    电子发烧友网站提供《PyTorch教程13.7之参数服务器.pdf》资料免费下载
    发表于 06-05 14:22 0次下载
    <b class='flag-5'>PyTorch</b>教程13.7之<b class='flag-5'>参数</b>服务器

    PyTorch教程14.7之单发框检测

    电子发烧友网站提供《PyTorch教程14.7之单发框检测.pdf》资料免费下载
    发表于 06-05 14:17 0次下载
    <b class='flag-5'>PyTorch</b>教程14.7之单发<b class='flag-5'>多</b>框检测

    PyTorch教程19.1之什么是超参数优化

    电子发烧友网站提供《PyTorch教程19.1之什么是超参数优化.pdf》资料免费下载
    发表于 06-05 10:25 0次下载
    <b class='flag-5'>PyTorch</b>教程19.1之什么是超<b class='flag-5'>参数</b><b class='flag-5'>优化</b>

    PyTorch教程19.2之超参数优化API

    电子发烧友网站提供《PyTorch教程19.2之超参数优化API.pdf》资料免费下载
    发表于 06-05 10:27 0次下载
    <b class='flag-5'>PyTorch</b>教程19.2之超<b class='flag-5'>参数</b><b class='flag-5'>优化</b>API

    PyTorch教程19.4之多保真超参数优化

    电子发烧友网站提供《PyTorch教程19.4之多保真超参数优化.pdf》资料免费下载
    发表于 06-05 10:45 0次下载
    <b class='flag-5'>PyTorch</b>教程<b class='flag-5'>19.4</b>之多<b class='flag-5'>保真超</b><b class='flag-5'>参数</b><b class='flag-5'>优化</b>

    HT6873丨3.5W高保真超低EMI防削顶单声道D类音频功率放大器

    HT6873是一款高保真超低EMI的,具有防削顶失真功能的单声道免滤波D类音频功率放大器。在5V电源,10% THD+N,4Ω负载条件下,输出3.5W高功率,在各类音频终端应用中维持高效率并提供AB
    的头像 发表于 07-06 15:51 785次阅读
    HT6873丨3.5W高<b class='flag-5'>保真超</b>低EMI防削顶单声道D类音频功率放大器

    2.0优化PyTorch推理与AWS引力子处理器

    2.0优化PyTorch推理与AWS引力子处理器
    的头像 发表于 08-31 14:27 572次阅读
    2.0<b class='flag-5'>优化</b><b class='flag-5'>PyTorch</b>推理与AWS引力子处理器

    如何使用PyTorch建立网络模型

    PyTorch是一个基于Python的开源机器学习库,因其易用性、灵活性和强大的动态图特性,在深度学习领域得到了广泛应用。本文将从PyTorch的基本概念、网络模型构建、优化方法、实际应用等多个方面,深入探讨使用
    的头像 发表于 07-02 14:08 352次阅读