快捷键

源代码 for torch.optim.rprop

# mypy: 允许未类型化定义
r实现鲁棒反向传播。
from 打字 导入 角色, 可选, 联合

导入 火炬
from 火炬 导入 张量

from .优化器 导入 (
    _可捕获文档,
    默认为融合或遍历,
    _可区分文档,
    _如果不受支持则禁用 Dynamo,
    _foreach_doc,
    _获取可捕获的设备,
    _获取标量数据类型,
    _maximize_doc,
    _params_doc,
    _use_grad_for_differentiable,
    真实查看,
    优化器,
    参数 T,
)


全部 = [Rprop, rprop]


[文档] Rprop(优化器): # 无需注意:D101 定义 __init__( , 参数: 参数 T, 学习率: 并集[float, 张量] = 0.01, etas: 元组[float, float] = (0.5, 1.2), 步长大小: 元组[float, float] = (1e-6, 50), *, 可捕捉的: 布尔值 = 错误, foreach: 可选[布尔] = , 最大化: 布尔值 = 错误, 可微分的: 布尔值 = 错误, ): # 无需注意:D107 如果 isinstance(学习率, 张量) 学习率.元素数量() != 1: 提升 ValueError("Tensor lr 必须是 1 个元素") 如果 0.0 <= 学习率: 提升 ValueError(f"无效的学习率:"{学习率}") 如果 0.0 < etas[0] < 1.0 < etas[1]: 提升 ValueError(f无效的预计到达时间值:{etas[0]}, {etas[1]}") 默认 = 字典( 学习率=学习率, etas=etas, 步长大小=步长大小, foreach=foreach, 最大化=最大化, 可微分的=可微分的, 可捕捉的=可捕捉的, ) 超级().__init__(参数, 默认值) 定义 __setstate__(, 状态): # 无需注意:D105 超级().__setstate__(状态) for .参数组: 群组.setdefault(foreach, ) 群组.setdefault(最大化, 错误) 群组.setdefault(可微分的, 错误) 群组.setdefault("可捕获的", 错误) for p 群组[参数]: 状态 = .状态.获取(p, [] 如果 长度(状态) != 0 torch.is_tensor(状态[步骤)] 步骤值 = float(状态[步骤]) 状态[步骤] = ( torch.张量( 步值, 数据类型=_获取标量数据类型(), 设备=p.设备 ) 如果 群组["可捕获的"] 否则 torch.张量(步值, 数据类型=_获取标量数据类型()) ) 定义 初始化组(, 群组, 参数, 梯度, 前者, 步长大小, 状态步数): 复杂的参数 = for p 群组[参数]: 如果 p.梯度 : continue 复杂的参数 |= torch.是复杂的(p) 参数.append(p) 梯度 = p.梯度 如果 研究生.is_sparse: 提升 运行时错误(Rprop 不支持稀疏梯度) 梯度.append(研究生) 状态 = .状态[p] # 状态初始化 如果 长度(状态) == 0: 状态[步骤] = ( torch.零值((), 数据类型=_获取标量数据类型(), 设备=p.设备) 如果 群组["可捕获的"] 否则 torch.零值((), 数据类型=_获取标量数据类型()) ) 状态[prev] = torch.等于零的(p, 内存格式=torch.保留格式) 如果 p.数据类型.是复杂的: 复数应该像两个独立的实数一样处理。 因此,步长不应该为零,对于虚部来说。 状态[步长] = torch.完全一样( 研究生, 复杂(群组["lr"] 群组["lr"]) ) else: 状态[步长] = torch.完全一样(研究生, 群组["lr"]) 前面.append(状态[前一个]) 步长大小.append(状态[步长]) 状态步数.append(状态[步骤]) 返回 复杂的参数
[文档] @_use_grad_for_differentiable def 步(self, closure=None): 执行单次优化步骤。 参数: 闭包(Callable,可选):一个重新评估模型并返回损失的闭包。 并返回损失。 "注释" self._cuda_graph_capture_health_check() loss = None if closure is not None: with torch.enable_grad(): loss = closure() for group in self.param_groups: params: list[Tensor] = [] grads: 列表[Tensor] = [] prevs: 列表[Tensor] = [] step_sizes: 列表[Tensor] = [] state_steps: 列表[Tensor] = [] etaminus, etaplus = group["etas"] step_size_min, step_size_max = group["step_sizes"] foreach = group["foreach"] maximize = group["maximize"] has_complex = self._init_group( group, params, grads, prevs, step_sizes, state_steps ) rprop( params, grads, prevs, step_sizes, state_steps, step_size_min=step_size_min, step_size_max=step_size_max, etaminus=etaminus, etaplus=etaplus, foreach=foreach, maximize=maximize, differentiable=group["differentiable"], capturable=group["capturable"] has_complex=has_complex ) 返回损耗
Rprop.__doc__ = ( r实现了鲁棒反向传播算法。 .. math:: \begin{aligned} &\rule{110mm}{0.4pt} \\ 输入 &\textbf{input} : \theta_0 \in \mathbf{R}^d \text{ (params)},f(\theta) \text{ (目标函数)}, \\ &\hspace{13mm} \eta_{+/-} \text{ (etaplus, etaminus)}, \Gamma_{max/min} &\hspace{13mm} \eta_{+/-}(etaplus,etaminus),\Gamma_{max/min} (步长) 初始化:g^0_{prev} ← 0 \eta_0 \leftarrow \text{学习率 (lr)} &\rule{110mm}{0.4pt} \\ for t=1 到 ... do g_t ← ∇_θ f_t (θ_{t-1}) \\ for i = 0, 1, ..., d-1 do 如果 g^i_{prev} g^i_t 大于 0 &\hspace{15mm} \eta^i_t \leftarrow \mathrm{min}(\eta^i_{t-1} \eta_{+}, Γ_{max}) \\ &\hspace{10mm} \textbf{else if} \: g^i_{prev} g^i_t < 0 \\ &\hspace{15mm} \eta^i_t \leftarrow \mathrm{max}(\eta^i_{t-1} \eta_{-}, \Gamma_{min}) \\ &\hspace{15mm} g^i_t \leftarrow 0 \\ &\hspace{10mm} 否则 \: \\ &\hspace{15mm} \eta^i_t \leftarrow \eta^i_{t-1} \\ &\hspace{5mm}\theta_t \leftarrow \theta_{t-1}- \eta_t \mathrm{sign}(g_t) \\ &\hspace{5mm}g_{prev} \leftarrow g_t \\ &\规则{110 毫米}{0.4 点} \\[-1.ex] &\bf{return} \: \theta_t \\[-1.ex] &\规则{110 毫米}{0.4 点} \\[-1.ex] \end{aligned} 关于算法的更多细节,请参阅论文 一种用于更快反向传播学习的直接自适应方法:RPROP 算法 "文档" + rf"" 参数: {_params_doc} lr(float,可选):学习率(默认:1e-2) etas(元组[浮点数,浮点数],可选):一对(etaminus,etaplus),表示 可乘性增加和减少因子 (默认:(0.5, 1.2)) step_sizes(元组[浮点数,浮点数],可选):一对最小和 最大允许的步长(默认:(1e-6, 50)) {_可捕获文档} {_foreach_doc} {_maximize_doc} {_可区分文档} "文档" ) 定义 _单张张量_rprop( 参数: 列表[张量] 梯度: 列表[张量] 前值: 列表[张量] 步长大小: 列表[张量] 状态步数: 列表[张量] *, 步长最小值: float, 步长最大值: float, eta 减: float, eta 加: float, 最大化: 布尔, 可捕捉的: 布尔, 可微分的: 布尔, 有复杂的: 布尔, ): for i, 参数 列举(参数): 梯度 = 梯度[i] 梯度 = 梯度 如果 最大化 否则 -梯度 上一个 = 前置[i] 步长 = 步长[i] 步骤 = 状态步数[i] 如果编译,编译器将处理 cudagraph 检查,参见注释[torch.compile x capturable] 如果 torch.编译器.is_compiling() 可捕捉的: 可捕获支持的设备 = _获取可捕获的设备() 断言 ( 参数.设备.类型 == 步长.设备.类型 参数.设备.类型 可捕获支持的设备 ), f如果 capturable=True,则 params 和 state_steps 必须在支持的设备上:{支持捕获的设备} 步骤 += 1 如果 torch.是复杂的(参数): 梯度 = torch.真实查看(研究生) 上一个 = torch.真实查看(上一页) 参数 = torch.真实查看(参数) 步长 = torch.真实查看(步长) 如果 可微分的: 符号 = 研究生.(上一页.克隆()).符号() else: 符号 = 研究生.(上一页).符号() 如果 可捕捉的: 符号.复制_(torch.哪里(符号.gt(0), etaplus, 符号)) 符号.复制_(torch.哪里(符号.lt(0), etaminus, 符号)) 符号.复制_(torch.哪里(符号.eq(0), 1, 符号)) else: 符号[符号.gt(0)] = etaplus 符号[符号.lt(0)] = etaminus 符号[符号.eq(0)] = 1 使用步长更新更新步长 步长.mul_(符号).clamp_(步长最小值, 步长最大值) # 对于 dir<0,dfdx=0 # 对于 dir>=0 dfdx=dfdx 梯度 = 研究生.克隆(内存格式=torch.保留格式) 如果 可捕捉的: 研究生.复制_(torch.哪里(符号.eq(etaminus), 0, 研究生)) else: 研究生[符号.eq(etaminus)] = 0 更新参数 参数.addcmul_(研究生.符号(), 步长, =-1) 上一页.复制_(研究生) 定义 _多张量 Rprop( 参数: 列表[张量] 梯度: 列表[张量] 前置: 列表[张量] 步长大小: 列表[张量] 状态步数: 列表[张量] *, 步长最小值: float, 步长最大值: float, 乙胺负: float, 乙胺正: float, 最大化: 布尔, 可捕捉的: 布尔, 可微分的: 布尔, 有复杂的: 布尔, ): 如果 长度(参数) == 0: 返回 断言 可微分的, "_foreach 操作不支持自动求导" 如果编译,编译器将处理 cudagraph 检查,参见注释[torch.compile x capturable] 如果 torch.编译器.is_compiling() 可捕捉的: 可捕获支持的设备 = _获取可捕获的设备() 断言 所有( p.设备.类型 == 步长.设备.类型 p.设备.类型 可捕获支持的设备 for p, 步骤 zip(参数, 状态步数) ), f如果 capturable=True,则 params 和 state_steps 必须在支持的设备上:{支持捕获的设备} 分组张量 = 优化器.按设备类型和数据类型分组张量( [参数, 梯度, 前值, 步长大小, 状态步数] # type: ignore[list-item] ) for ( 分组参数_, 分组梯度_, 分组前值_, 分组步长大小_, 分组状态步骤_, ), _ 分组张量.(): 分组参数 = 角色(列表[张量] 分组参数_) 分组梯度 = 角色(列表[张量] 分组梯度_) 分组前项 = 角色(列表[张量] 分组前项_) 分组步长 = 角色(列表[张量] 分组步长_) 分组状态步骤 = 角色(列表[张量] 分组状态步骤_) # 更新步骤 # 如果步骤在 CPU 上,foreach 将回退到慢速路径,即通过循环调用 t.add(1) #然后 1 会被反复包裹成 Tensor,这比只包裹一次要慢。 #alpha 是必须的,以确保我们进入正确的重载。 如果 torch.编译器.is_compiling() 分组状态步骤[0].是 CPU: torch._foreach_add_( 分组状态步骤, torch.张量(1.0, 设备="cpu"), 阿尔法=1.0 ) else: torch._foreach_add_(分组状态步骤, 1) 处理复杂参数 如果 有复杂的: 真实查看( 分组参数, 分组梯度, 分组前值, 分组步长 ) 符号 = torch._foreach_mul(分组梯度, 分组前项) 如果 最大化: torch._foreach_neg_(标记) # 步骤结束时,分组前项将包含当前梯度,因此我们重用 # 分组前项的内存而不是创建一个新的缓冲区,但为了清晰起见,我们重新分配 # 保持对缓冲区的引用,称为 grouped_grads。 torch._foreach_copy_(grouped_prevs, 分组梯度) 如果 最大化: torch._foreach_neg_(grouped_prevs) 分组梯度 = grouped_prevs torch.每个符号(符号) 如果 可捕捉的: for 符号 符号: 符号.复制_(torch.哪里(符号.gt(0), etaplus, 符号)) 符号.复制_(torch.哪里(符号.lt(0), etaminus, 符号)) 符号.复制_(torch.哪里(符号.eq(0), 1, 符号)) else: for 符号 标记: 符号[符号.gt(0)] = etaplus 符号[符号.lt(0)] = etaminus 符号[符号.eq(0)] = 1 使用步长更新更新步长 torch._foreach_mul_(分组步长, 符号) for 步长 分组步长: 步长.clamp_(步长最小值, 最大步长) # 对于 dir<0,dfdx=0 # 对于 dir>=0 dfdx=dfdx 分组梯度 = 列表(分组梯度) for i 范围(长度(分组梯度)): 分组梯度[i].复制_( torch.哪里(标志[i].eq(乙胺), 0, 分组梯度[i]) ) 明确删除符号,因为它在这里之后不再使用以节省内存 删除 符号 更新参数 梯度符号 = [研究生.符号() for 梯度 分组梯度] torch._foreach_addcmul_( 分组参数, 梯度符号, 分组步长, =-1 ) # 从逻辑上讲,你可能期望 grouped_prevs 被更新为 grouped_grads,但实际上 # 已经发生了,因为我们一直在使用 grouped_prevs 的内存来存储 # 更新了分组梯度! @_disable_dynamo_if_unsupported(单个张量函数=_单个张量 Rprop) 定义 rprop( 参数: 列表[张量] 梯度: 列表[张量] 前置: 列表[张量] 步长大小: 列表[张量] 状态步数: 列表[张量] 使用 torchscript 编译的函数不支持带默认值的只写关键字参数问题 #70627 现由 torch/distributed/optim 编译的函数 API 参数 foreach: 可选[布尔] = , 可捕捉的: 布尔值 = 错误, 最大化: 布尔值 = 错误, 可微分的: 布尔值 = 错误, 有复杂的: 布尔值 = 错误, *, 步长最小值: float, 最大步长: float, etaminus: float, etaplus: float, ): r执行 rprop 算法计算的函数式 API。 查看 :class:`~torch.optim.Rprop` 以获取详细信息。 "文档" 此检查在编译期间较慢,因此我们跳过它。 如果确实需要,我们可以在 dynamo 中添加此检查。 如果 torch.编译器.is_compiling() 所有( isinstance(t, torch.张量) for t 状态步骤 ): 提升 运行时错误( "API 已更改,`state_steps`参数必须包含一个单例张量列表" ) 如果 foreach : _, foreach = 默认为融合或遍历( 参数, 可微分的, 使用融合的= ) 如果 foreach torch.算子.是否正在脚本化(): 提升 运行时错误("torch.jit.script 不支持 foreach 优化器") 如果 foreach torch.算子.是否正在脚本化(): 函数 = 多张张量_rprop else: 函数 = 单张张量_rprop 函数( 参数, 梯度, 前面, 步长大小, 状态步数, 步长最小值=步长最小值, 步长最大值=步长最大值, 乙胺负=乙胺负, 乙胺正=乙胺正, 可捕捉的=可捕捉的, 最大化=最大化, 可微分的=可微分的, 有复杂的=有复杂的, )

© 版权所有 PyTorch 贡献者。

使用 Sphinx 构建,并使用 Read the Docs 提供的主题。

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

深入了解初学者和高级开发者的教程

查看教程

资源

查找开发资源,获取您的疑问解答

查看资源