# mypy: 允许未类型化装饰器
# mypy: 允许未类型化定义
from 打字
导入
角色,
可选,
类型检查,
联合
导入
火炬
from 火炬
导入
张量
from .优化器
导入 (
_如果不受支持则禁用 Dynamo,
_获取标量数据类型,
_maximize_doc,
_params_doc,
优化器,
参数 T,
TensorListList,
)
全部 = ["Adafactor",
adafactor]
类 Adafactor(
优化器):
定义 __init__(
我,
参数:
参数 T,
学习率:
联盟[float,
张量] =
0.01,
beta2_decay: 浮点数 = -0.8,
eps: 元组[
可选[float
] float] = (
无,
0.001),
d: 浮点数 = 1.0,
weight_decay: 浮点数 = 0.0,
*,
foreach: 可选[
布尔] =
无,
最大化:
布尔 =
错误,
):
如果 isinstance(
学习率,
张量)
并且
学习率.
元素数量() != 1:
raise ValueError("Tensor lr 必须是 1 个元素")
如果
不 0.0
≤
学习率:
raise ValueError(f"学习率应该大于等于 0,但却是:"{
学习率}")
如果
不 0.0 >= beta2_decay:
raise ValueError(f"beta2_decay 应该小于等于 0,但却是:"{beta2_decay}")
如果 eps[0]
是
不
无
并且
不 0.0
≤ eps[0
]
raise ValueError(f"epsilon1 应该 >= 0 但却是:"{eps[0]}")
如果
不 0.0
≤ eps[1
]
raise ValueError(f"epsilon2 应该 >= 0 但却是:"{eps[1]}")
如果
不 1.0
≤ d:
raise ValueError(f"剪裁阈值 d 应该 >= 1 但却是:"{d}")
如果
不 0.0
≤ weight_decay:
raise ValueError(f"权重衰减应该 >= 0 但却是:"{weight_decay}")
默认 =
字典(
学习率=
学习率,
beta2 衰变=
beta2 衰变,
eps=eps,
d=d,
weight_decay=weight_decay,
foreach=foreach,
最大化=
最大化,
)
超级().__init__(
参数,
默认值)
定义 __setstate__(
我,
状态):
超级().__setstate__(
状态)
for 组
在
我.
参数组:
群组.setdefault(
foreach,
无)
for p 在
群组[
参数
]
状态 =
我.
状态.
获取(p,
[]
如果
长度(p_state) != 0
并且
不
火把.is_tensor(p_state[
步骤
)]
步骤值 = float(p_state[
步骤])
p_state[步骤] =
火把.
张量(
步值,
数据类型=
_获取标量数据类型())
定义
初始化组(
我,
群组,
带梯度的参数,
梯度,
行变量,
列变量,
方差,
状态步数,
):
for p 在
群组[
参数
]
如果 p.
梯度
是
无:
continue
如果
火把.
是复杂的(p):
raise 运行时错误(
Adafactor 不支持复杂数据)
如果 p.
研究生.is_sparse:
raise 运行时错误(
Adafactor 不支持稀疏梯度)
带梯度的参数.append(p)
梯度.append(p.
研究生)
状态 =
我.
状态[p]
状态初始化
如果
长度(
状态) == 0:
# note(crcrpar): 故意将 `step` 放在 CPU 上,如果可捕获和融合都关闭。
因为在 CUDA 和 XLA 上内核启动代价高昂。
状态[
步骤] = torch.
张量(0.0,
数据类型=
_获取标量数据类型())
如果 p.
研究生.
暗() > 1:
行形状 =
列表(p.
研究生.
形状)
行形状[-1] = 1
# 行方差因子,与 grads 的形状不同(将在最后一个维度上减少)
状态[
"行方差"] = p.
研究生.
新零(
行形状)
列形状 =
列表(p.
研究生.
形状)
列形状[-2] = 1
# 方差列因子,与 grads 的形状不同(将在倒数第二维上减少)
状态[
col_var] = p.
研究生.
新零(
列形状)
else:
状态[
方差] = torch.
等于零的(
p.研究生,
内存格式=torch.
保留格式
)
行变量.append(
状态.
获取(
行变量,
无))
列变量.append(
状态.
获取(
"列变量",
无))
方差.append(
状态.
获取(
"方差",
无))
状态步数.append(
状态[
步骤])
返回
假
复杂的
[文档] @torch.
不梯度()
定义
步长(
我,
闭包=
无):
r执行单个优化步骤。
参数:
闭包(Callable,可选):一个重新评估模型并返回损失的闭包
和返回损失。
"文档"
我._cuda_graph_capture_health_check()
损失 =
无
如果
闭包
是
不
无:
与
火把.
启用梯度():
损失 =
闭包()
for 组
在
我.
参数组:
带梯度的参数:
列表[
张量] =
输入文本为空,请提供需要翻译的文本
梯度:
列表[
张量] =
输入文本为空,请提供需要翻译的文本
行变量:
列表[
可选[
张量]] =
输入文本为空,请提供需要翻译的文本
列变量:
列表[
可选[
张量]] =
输入文本为空,请提供需要翻译的文本
方差:
列表[
可选[
张量]] =
输入文本为空,请提供需要翻译的文本
状态步数:
列表[
张量] =
输入文本为空,请提供需要翻译的文本
eps1, eps2 = 群组[
eps]
复杂的参数 =
我.
初始化组(
群组,
带梯度的参数,
梯度,
行变量,
列变量,
方差,
状态步数,
)
adafactor(
带梯度的参数,
梯度,
行变量,
列变量,
变异,
状态步数,
d=群组["d"
]
学习率=
群组["lr"
]
beta2 衰变=
群组[
"beta2 衰变"
]
weight_decay=群组[
权重衰减
]
eps1=eps1,
eps2=eps2,
foreach=群组[
foreach],
最大化=
群组[
最大化],
梯度缩放=getattr(
我, "grad_scale",
无),
找到无穷大=getattr(
我,
"发现感染",
无),
有复杂的=
有复杂的,
)
返回
损失
Adafactor.__doc__ = (
r"实现了 Adafactor 算法。"
.. math::
\begin{aligned}
&\rule{110mm}{0.4pt} \\
输入:\gamma \text{(lr)}, \: \tau
(\beta_2\text{衰减}), \: \theta_0 \text{(参数)}, \: f(\theta) \text{(目标函数)} \\
&\hspace{15mm} \: ε_1, ε_2(epsilon),\: d(裁剪阈值),\\
&\hspace{15mm} λ(权重衰减)
最大化
初始化:\( R_0 \leftarrow 0 \)(二阶矩行因子)
\( C_0 \leftarrow 0 \) (第二矩系数),\\
\( \widehat{V}_0 \leftarrow 0 \) (向量的第二矩)\\[-1.ex]
&\rule{110mm}{0.4pt} \\
for t=1 到 ... do
&\hspace{5mm}\textbf{if} \: \textit{maximize}: \\
\( G_t \leftarrow -\nabla_{\theta} f_t (\theta_{t-1}) \)
否则
\( G_t \leftarrow \nabla_{\theta} f_t (\theta_{t-1}) \)
\hspace{5mm}\widehat{\beta}_{2_t} \leftarrow 1 - t^{\tau}
\hspace{5mm}\rho_t \leftarrow min(lr, \frac{1}{\sqrt{t}})
\hspace{5mm}\alpha_t \leftarrow max(\epsilon_2,
\text{RMS}(\theta_{t-1}))\rho_t
&\hspace{5mm}\theta_t \leftarrow \theta_{t-1} - \gamma \lambda \theta_{t-1} \\
&\hspace{5mm}\textbf{if} \: \text{dim}(G_t) > 1: \\
&\hspace{10mm}R_t \leftarrow \widehat{\beta}_{2_t}R_{t-1}+
(1-\widehat{\beta}_{2_t})(G_t \odot G_t) \cdot 1_m \\
C_t ← \widehat{\beta}_{2_t}C_{t-1}+
(1-\widehat{\beta}_{2_t}) 1^\top_n ⋅ (G_t \odot G_t) \\
\widehat{V}_t ←
\frac{R_t ⋅ C_t}{max(1^\top_n ⋅ R_t, \epsilon_1)} \\
否则
&\hspace{10mm}\widehat{V}_t \leftarrow \widehat{\beta}_{2_t}\widehat{V}_{t-1}+
(1-\widehat{\beta}_{2_t}) \cdot (G_t \odot G_t) \\
&\hspace{5mm}U_t \leftarrow
\frac{G_t}{max(\sqrt{\widehat{V}_t}, \epsilon_1)} \\
&\hspace{5mm}\widehat{U}_t \leftarrow \frac{U_t}{\text{max}(1, \frac{\text{RMS}(U_t)}{d})} \\
&\hspace{5mm}\theta_t \leftarrow \theta_{t-1} - \alpha_t \widehat{U}_t \\
&\规则{110 毫米}{0.4 点} \\[-1.ex]
&\bf{return} \: \theta_t \\[-1.ex]
&\规则{110 毫米}{0.4 点} \\[-1.ex]
\end{aligned}
关于算法的更多细节,请参阅《Adafactor:具有亚线性内存成本的自适应学习率》_。
"文档"
+ rf""
参数:
{_params_doc}
lr (float, Tensor, 可选): 与其他优化器不同,Adafactor 不需要
学习率,Shazeer、Noam 和 Mitchell Stern 完全不使用 lr。
偏离论文,此实现使用 lr 来应用权重
衰减,并且作为相对步长ρ_t 的最大值。注意,在
该论文中,将 0.01 作为一个相对最大值常数使用
步长,因此我们将 0.01 设为默认值。(默认:1e-2)
beta2_decay (float, 可选): beta2 的衰减率。beta2 通常指的是
用于计算梯度运行平均的系数
平方。 (默认:-0.8)
eps (Tuple[float, float], optional): epsilon1 是加到分母的项
更新计算以提高数值稳定性。这种对 epsilon1 的使用
偏离了论文中写的算法!见下文注释以获取更多详细信息。
epsilon2 是应用时避免权重更新过小的术语
参数缩放。(默认:(None, 1e-3))
d(浮点数,可选):裁剪阈值,用于避免超出期望的更新。
更新。
weight_decay(浮点数,可选):权重衰减系数(默认:1e-2)
foreach (bool, 可选): 是否使用优化器的 foreach 实现。注意
foreach 实现比 for-loop 版本多使用 ~ sizeof(params) 的峰值内存,因为中间变量是一个 tensorlist 而不是单个 tensor。
由于中间变量是 tensorlist 而不是单个 tensor,因此 foreach 实现比 for-loop 版本多使用 ~ sizeof(params) 的峰值内存。
由于 Adafactor 通常在内存受限时使用,因此 Adafactor 将默认
除非此标志被明确设置,否则将使用较慢的单张量循环实现
确实。这种行为与其他优化器相反,它们会尝试使用默认值
使用 CUDA 对 foreach 进行优化以提高运行时速度。(默认:无)
{_maximize_doc}""
+ r""
.. 注意::
Adafactor 的实现与 Shazeer、Noam 和 Mitchell Stern 有所不同
并且在一些其他框架中的实现,以及其使用学习率的方法
ε1
关于学习率超参数:Shazeer,Noam,以及 Mitchell Stern 不
使用 lr 全部,因为所述算法使用:ρt 并更新剪裁
影响步长。
此实现允许 `lr` 影响参数 :math:`\rho_t` 的最大值:
.. math::
\begin{对齐}
&\hspace{5mm}ρ_t ← min(lr, ...){1}
{E}{t}})
\end{对齐}
这与 Shazeer、Noam 和 Mitchell Stern 不同,他们使用 0.01 作为ρ_t 的最大值
的最大值
.. math::
\begin{对齐}
空格
5 毫米
ρ_t ← min(0.01, ...){1}
{E}{t}})
\end{对齐}
沙泽尔、诺亚姆和米切尔·斯特恩没有对如何执行权重衰减提出意见
计算,因此我们将学习率作为解耦权重的系数
衰减,类似于在《解耦权重衰减正则化》_中建议的。
关于使用:math:`\epsilon_1`:实现尝试复制
Shazeer、Noam 和 Mitchell Stern 使用:math:`\epsilon_1`作为
当平方梯度变得很小时的一个稳定项。
这种稳定可以表示为
.. math::
\begin{对齐}
&\hspace{5 毫米}
R_t ← β̂_{2_t}R_{t-1}+
(1-β̂){2_t}
)(G_t ⨝ G_t + 1_n ⋅ 1_m^T) ⋅ 1_m \\
&空格
{5 毫米}
C_t ← β̂_{2_t}C_{t-1}+
(1-β̂){2_t}
) 1^T_n · (G_t ⊙ G_t + 1_n · 1^T_m) \\
&空格
{5 毫米}\widehat{V}
_t ←
\frac{R_t \cdot C_t}{max(1^\top_n \cdot R_t, \epsilon_1)} \\
&\hspace{5mm}U_t \leftarrow \frac{G_t}{max(√^hat{V}, ε_1)}{V}
_t}, ε_1)}
\end{对齐}
梯度平方的行和列因子 :math:`R_t` 和 :math:`C_t` 被保留不变,我们在方差估计 :math:`\widehat
的最终计算中应用 :math:`\epsilon_1`
上{V}
_t` 和更新 :math:`U_t`。
这与 Shazeer、Noam、Mitchell Stern 以及其他框架形成对比。
将 \(\epsilon_1\) 应用到平方梯度的行和列因子上,但在计算之后:
不再计算
.. math::
\begin{对齐}
&\hspace{5mm}R_t ← β̂_{2_t}R_{t-1}+
(1-β̂_){2_t}
(G_t ⨝ G_t + ε_1 1_n ⋅ 1_m^T) ⋅ 1_m \\
&空格
{5 毫米}
C_t ← β̂{2_t}C_{t-1}+
(1-β̂)
{2_}
) 1^上_n · (G_t · G_t + ε_1 1_n · 1^上_m) \\
&空格
{5 毫米}
等号{V}
_t ← (R_t · C_t) / (1_n^⊤ · R_t)
&\hspace{5 毫米}
U_t ← \frac{G_t}
{\sqrt{\widehat}{V}_t}} \\
\end{对齐}
.. _Adafactor: 自适应学习率与亚线性内存成本
https://arxiv.org/pdf/1804.04235
.. _解耦权重衰减正则化
https://arxiv.org/abs/1711.05101
"文档"
)
定义 _single_tensor_adafactor(
参数:
列表[
张量
]
梯度:
列表[
张量
]
如果梯度是一维的(即向量),则不需要分解
因此,row_var 和 col_var 将为 None,而方差将被填充。
相反,对于具有多个维度的梯度,我们将沿着最后一个
2 个维度进行分解,因此 row_var 和 col_var 将被填充,而方差将为 None。
行变量:
列表[
可选[
张量]],
列变量:
列表[
可选[
张量]],
方差:
列表[
可选[
张量]],
状态步数:
列表[
张量
]
梯度缩放:
可选[
张量
]
找到无穷大:
可选[
张量
]
*,
d: float,
学习率:
联盟[
张量, float
]
beta2 衰减: float,
weight_decay: float,
eps1: 可选的[float
]
eps2: float,
最大化:
布尔,
有复杂的:
布尔,
):
断言 (
梯度缩放
是
无
和
发现信息
是
无
), "梯度缩放应在 optimizer.step()之外发生"
如果
火把.
算子.
是否正在脚本化():
此断言是因为即时编译器愚蠢,没有意识到下面的操作
# 具有处理浮点数和 Tensor lrs 的重载,所以我们只需断言它是
# 一个浮点数,因为大多数使用即时编译(JIT)的人都在使用浮点数
断言 isinstance(
学习率, float)
for i, 参数
在
列举(
参数):
梯度 =
梯度[i]
如果
不
最大化
否则 -
梯度[i]
步骤_t =
状态步数[i]
行变量 =
行变量[i]
列变量 =
列变量名[i]
方差 =
方差[i]
如果 eps1
是
无:
eps1 = 火把.finfo(
参数.
数据类型).eps
# 更新步骤
步骤_t += 1
step_float = 步骤_t.
项目()
one_minus_beta2_t = step_float**β²衰变
ρ_t =
最小(
学习率, 1 / (
步长浮点**0.5))
alpha = 最大值(
ε²,
参数.
归一化(2).
项目() / (
参数.
元素数量() ** 0.5)) *
ρ_t
执行步长权重衰减
如果
权重衰减 != 0:
参数.mul_(1 -
左右 * weight_decay)
如果
研究生.
暗淡() > 1:
断言 (
行变量
是
不
无
和 col_var
是
不
无
), 当 grad 是多维时,应定义 row_var 和 col_var
# 与(g * g).mean(dim=-1)相同,无需创建中间尺寸的 g
行均值 = (
torch.归一化(
研究生,
暗=-1,
保持维度=
是).
正方形_().div_(
研究生.
尺寸(-1))
)
行变量.
线性插值 _(
行均值,
1 减去 beta2t)
# 相当于 (g * g).mean(dim=-2) 而不生成一个中间大小 g
列均值 = (
torch.归一化(
研究生,
暗=-2,
保持维度=
是).
平方_().div_(
研究生.
尺寸(-2))
)
列方差.
线性插值 _(
列均值,
一减 beta2t)
方差估计 =
行方差 @
列变量
变量估计.div_(
行变量.
均值(
暗=-2,
保持维度=
是).clamp_(
最小=eps1))
else:
断言 (
方差
是
不
无
), 当 grad 是一个向量时,方差应该被定义
grad 平方 =
梯度 *
梯度
方差.
线性插值 _(
grad 平方, one_minus_beta2_t)
避免在更新期间写入方差
变量估计 =
方差.
克隆()
由于之后要开方,所以平方 eps1 以保持 eps1 的幅度
更新 =
变量估计.clamp_(
最小=eps1 * eps1).rsqrt_()
更新.mul_(
研究生)
分母 =
最大值(1.0,
更新.
归一化(2).
项目() / ((
更新.
元素数量() ** 0.5) * d))
参数.
加_(
更新,
阿尔法=-alpha / denom)
定义 _group_tensors_by_device_dtype_and_is_multidim(
tensorlists: TensorListList,
)
输入文本:
->
翻译:
-> 字典[
元组[
可选[
火把.
设备
]
可选[
火把.
数据类型
]
布尔
]
列表[
列表[
可选[
张量
]],
]
"""将张量按设备、数据类型和多维性分组,无论该张量是多维的还是有单维(是向量)。这允许 Adafactor 的 foreach 实现假设每个参数组要么被分解,要么不被分解。"""
has multiple dims or just one dim (is a vector). This allows the foreach impl of
Adafactor to assume that every group of params will either be factored or not.
分组张量 =
优化器.
按设备类型和数据类型分组张量(
张量列表)
超分组张量:
字典[
元组[
可选[
火把.
设备
]
可选[
火把.
数据类型
]
布尔
]
列表[
列表[
可选[
张量
]],
] = {}
for (设备,
数据类型), (
张量列表, _)
在
分组张量.
项目():
矩阵键 = (
设备,
数据类型,
是)
向量键 = (
设备,
数据类型,
错误)
# 假设 grad 是第二个张量列表
for j, 张量
在
列举(
张量列表[1
)]
断言
张量
是
不
无,
"梯度不应为 None"
如果
张量.
暗() > 1:
如果
矩阵键
不
在
超分组张量:
超级分组张量[
矩阵键] = [[] for _
在
张量列表]
for i 在
范围(
长度(
张量列表)):
超分组张量[
矩阵键
]
[i].append(张量列表[i
]
[j])
else:
如果
矢量键
不
在
超级分组张量:
超级分组张量[
矢量键] =
空列表 for _
在
张量列表]
for i 在
范围(
长度(
张量列表)):
超分组张量[
矢量键
]
[i].append(张量列表[i
]
[j])
返回
超分组张量
定义
多张量 ADAFactor(
参数:
列表[
张量
]
梯度:
列表[
张量
]
如果梯度是一维的(即向量),则不需要分解
因此,row_var 和 col_var 将为 None,而方差将被填充。
相反,对于具有多个维度的梯度,我们将沿着最后一个
2 个维度进行分解,因此 row_var 和 col_var 将被填充,而方差将为 None。
行变量:
列表[
可选[
张量]],
列变量:
列表[
可选[
张量]],
方差:
列表[
可选[
张量]],
状态步数:
列表[
张量
]
梯度缩放:
可选[
张量
]
找到无穷大:
可选[
张量
]
*,
d: float,
学习率:
联盟[
张量, float
]
β²衰变: float,
weight_decay: float,
eps1: 可选的[float
]
eps2: float,
最大化:
布尔,
有复杂的:
布尔,
):
如果
长度(
参数) == 0:
返回
断言 (
梯度缩放
是
无
和
发现信息
是
无
), 梯度缩放应在 optimizer.step()之外发生
分组张量 =
根据设备、数据类型和多维度将张量分组(
[参数,
梯度,
行变量,
列变量,
变量,
状态步数] # type: ignore[list-item]
)
for (_, 数据类型,
是否多维), (
(
设备参数_,
device_grads_,
设备行变量_,
设备列变量_,
设备差异,
设备状态步骤_,
)
) 在
分组张量.
项目():
设备参数 =
角色(
列表[
张量
]
设备参数_)
设备梯度 =
角色(
列表[
张量
] device_grads_)
设备状态步骤 =
角色(
列表[
张量
]
设备状态步骤_)
如果 eps1
是
无:
断言 (
dtype 是
不
无
), 当 eps1 未设置时,需要 dtype 来计算 eps1
eps1 = 火把.finfo(
数据类型).eps
如果
类型检查:
断言
设备状态步骤[0]
是
不
无
如果
最大化:
设备梯度 =
火把._foreach_neg(
设备梯度)
# 类型:忽略[赋值]
# 更新步骤
# 如果步骤在 CPU 上,foreach 将回退到慢速路径,即通过循环调用 t.add(1)
#然后 1 会被反复包裹成 Tensor,这比只包裹一次要慢。
#alpha 是必须的,以确保我们进入正确的重载。
如果
不
火把.
编译器.is_compiling()
和
设备状态步骤[0].
是 CPU:
火把._foreach_add_(
设备状态步骤,
火把.
张量(1.0,
设备="cpu"),
阿尔法=1.0
)
else:
火把._foreach_add_(
设备状态步骤, 1.0)
one_minus_beta2_ts = 输入文本为空,请提供需要翻译的文本
beta2_ts = 输入文本为空,请提供需要翻译的文本
rho_ts = 输入文本为空,请提供需要翻译的文本
for s 在
设备状态步骤:
one_minus_beta2_ts.append(s.项目() ** beta2_decay)
beta2_ts.append(1 - s.项目() **
beta2_decay
贝塔 2 衰变)
ρ_ts.append(
最小(
学习率, 1 / (s.
项目() ** 0.5)))
αλφα = [
最大值(
ε², p.
归一化(2).
项目() / (p.
元素数量() ** 0.5)) * r
for p, r 在 zip(
设备参数,
ρ_ts)
]
执行步长权重衰减
如果
权重衰减 != 0:
火把._foreach_mul_(
设备参数, 1 -
左右 * weight_decay)
如果
多维:
设备行变量 =
角色(
列表[
张量
]
设备行变量)
设备列变量 =
角色(
列表[
张量],
设备列变量_)
断言 (
设备行变量[0]
是
不
无
并且
设备列变量[0]
是
不
无
), "当 grad 是多维时,row_var 和 col_var 应该被定义"
# 与(g * g).mean(dim=-1)相同,无需创建中间大小为 g 的变量
行均值 = [
火把.
归一化(
研究生,
暗淡=-1,
保持维度=
是) for
梯度
在
设备梯度
]
火把._foreach_mul_(
行均值,
行均值)
火把._foreach_div_(
行均值, [
研究生.
尺寸(-1) for
梯度
在
设备梯度])
火把._foreach_lerp_(
设备行变量,
行均值, one_minus_beta2_ts)
删除 row_means
# 与(g * g).mean(dim=-2)相同,无需生成中间尺寸的 g
col_means = [
火把.
归一化(
研究生,
暗淡=-2,
保持维度=
是) for
梯度
在
设备梯度
]
火把._foreach_mul_(
列均值,
列均值)
火把._foreach_div_(
列均值, [
研究生.
尺寸(-2) for
梯度
在
设备梯度])
火把._foreach_lerp_(
设备列变量,
列均值,
一减 beta2 时间序列)
删除
列均值
方差估计 = [
行变量 @
列变量
for 行变量,
列变量
在 zip(
设备行变量,
设备列变量)
]
行变量均值 = [
行变量.
均值(
暗淡=-2,
保持维度=
是) for
行变量
在
设备行变量
]
火把._foreach_clamp_min_(
行变量均值, eps1)
火把._foreach_div_(
变量估计,
行变量均值)
删除
行变量均值
else:
设备方差 =
角色(
列表[
张量
]
设备差异_)
断言 (
设备差异[0]
是
不
无
), 当 grad 是一个向量时,应定义差异
梯度平方 =
火把._foreach_mul(
设备梯度,
设备梯度)
火把._foreach_lerp_(
设备差异,
梯度平方,
一减 beta2 的 t 统计量)
删除
梯度平方
避免在更新期间写入方差
变量估计 = [v.
克隆() for v
在
设备方差]
# 将 eps1 平方,因为我们之后要开根号以保持 eps1 的幅度
火把.
每次限制最小值(
变量估计, eps1 * eps1)
火把._foreach_rsqrt_(
变量估计)
火把._foreach_mul_(
变量估计,
设备梯度)
更新 =
变量估计
系数α = [
-a / (最大值(1.0,
更新.
归一化(2).
项目() / ((
更新.
元素数量() ** 0.5) * d)))
for a, 更新
在 zip(
αλφα,
更新)
]
火把._foreach_mul_(
更新,
测试版)
火把._foreach_add_(
设备参数,
更新)
@_disable_dynamo_if_unsupported(单个张量函数=
_单张张量_adafactor)
定义
ada 因子(
参数:
列表[
张量
]
梯度:
列表[
张量
]
行变量:
列表[
可选[
张量]],
列变量:
列表[
可选[
张量]],
方差:
列表[
可选[
张量]],
状态步数:
列表[
张量
]
使用 torchscript 编译的函数不支持带默认值的只写关键字参数问题 #70627
现由 torch/distributed/optim 编译的函数 API 参数
foreach: 可选[
布尔] =
无,
梯度缩放:
可选[
张量] =
无,
找到无穷大:
可选[
张量] =
无,
有复杂的:
布尔 =
错误,
*,
d: float,
学习率:
联盟[float,
张量
]
beta2 衰减: float,
weight_decay: float,
eps1: float,
eps2: float,
最大化:
布尔,
):
r执行 Adafactor 算法计算的函数式 API。
详细信息请参阅 :class:`~torch.optim.Adafactor`。
"文档"
如果
不
火把.
编译器.is_compiling()
并且
不
所有(
isinstance(t, 火把.
张量) for t
在
状态步骤
):
raise 运行时错误(
"`state_steps`参数必须包含一个单例张量列表"。
)
如果 foreach:
函数 = _multi_tensor_adafactor
else:
函数 =
单个张量 Adafactor
函数(
参数,
梯度,
行变量,
列变量,
方差,
状态步数,
d=d,
学习率=
学习率,
beta2 衰减=
beta2 衰减,
weight_decay=weight_decay,
eps1=eps1,
eps2=eps2,
最大化=
最大化,
梯度缩放=
梯度缩放,
找到无穷大=
找到无穷大,
有复杂的=
有复杂的,
)