# mypy: 允许未类型化定义
rNAdam 算法的实现
from 打字
导入
角色,
可选,
联合
导入
火炬
from 火炬
导入
张量
from .优化器
导入 (
_可捕获文档,
默认为融合或遍历,
_可区分文档,
_如果不受支持则禁用 Dynamo,
_foreach_doc,
_获取可捕获的设备,
_获取标量数据类型,
_获取值,
_maximize_doc,
_params_doc,
_stack_if_compiling,
_use_grad_for_differentiable,
真实查看,
优化器,
参数 T,
)
全部 = ["NAdam",
nadam]
[文档]
类 NAdam(
优化器): # noqa: D101
定义 __init__(
自身,
参数:
参数 T,
学习率:
联盟[float,
张量] =
0.002,
betas: 元组[float, float] = (0.9, 0.999),
eps: 浮点数 = 1e-8,
权重衰减:
浮点数 = 0,
动量衰减:
浮点数 =
0.004,
解耦权重衰减:
布尔值 =
错误,
*,
foreach: 可选[
布尔] =
无,
最大化:
布尔值 =
错误,
可捕捉的:
布尔值 =
错误,
可微分的:
布尔值 =
错误,
): # 无需注意:D107
如果 isinstance(
学习率,
张量)
和
学习率.
元素数量() != 1:
提升 ValueError(
"Tensor lr 必须是 1 个元素")
如果
不 0.0 <=
学习率:
提升 ValueError(f
"无效的学习率:"{
学习率}")
如果
不 0.0 <= eps:
提升 ValueError(f
"无效的 epsilon 值:"{eps}")
如果
不 0.0 <= betas[0] < 1.0:
提升 ValueError(f
"在索引 0 处的无效 beta 参数:"{betas[0]}")
如果
不 0.0 <= betas[1] < 1.0:
提升 ValueError(f
"无效的 beta 参数,索引为 1:"{betas[1]}")
如果
不 0.0
≤ weight_decay:
raise ValueError(f"无效的 weight_decay 值:"{
权重衰减}")
如果
不 0.0 <=
动量衰减:
提升 ValueError(f
"无效的动量衰减值:"{
动量衰减}")
默认 =
字典(
学习率=
学习率,
betas=betas,
eps=eps,
权重衰减=
权重衰减,
动量衰减=
动量衰减,
解耦权重衰减=
解耦权重衰减,
最大化=
最大化,
foreach=foreach,
可捕捉的=
可捕捉的,
可微分的=
可微分的,
)
超级().__init__(
参数,
默认值)
定义 __setstate__(
自身,
状态):
# 无需注意:D105
超级().__setstate__(
状态)
for 群组
在
自身.
参数组:
群组.setdefault(
最大化,
错误)
群组.setdefault("foreach",
无)
群组.setdefault(
"可捕获的",
错误)
群组.setdefault(
"可区分的",
错误)
群组.setdefault(
"解耦权重衰减",
错误)
for p 在
群组[
参数]:
状态 =
自身.
状态.
获取(p,
[]
如果
长度(
状态) != 0:
如果
不
火炬.is_tensor(
状态[
步骤
)]
步骤值 = float(
状态[
步骤])
状态[
步骤] = (
火炬.
张量(
步值,
数据类型=
_获取标量数据类型(),
设备=p.
设备
)
如果
群组[
"可捕获的"]
否则
火炬.
张量(
步值,
数据类型=
_获取标量数据类型())
)
如果
不
火炬.is_tensor(
状态[
"mu 产品"
)]
mu_prod 值 =
状态[
"mu 产品"]
状态[
"mu 产品"] = (
火炬.
张量(
mu_prod_val, 数据类型=
_获取标量数据类型(),
设备=p.
设备
)
如果
群组[
"可捕获的"]
否则
火炬.
张量(mu_prod_val,
数据类型=
_获取标量数据类型())
)
定义
初始化组(
自身,
群组,
带梯度的参数,
梯度,
实验平均值,
实验平均平方值,
mu_products,
状态步数,
):
复杂的参数 =
假
for p 在
群组[
参数]:
如果 p.
梯度
是
不
无:
复杂的参数 |=
火炬.
是复杂的(p)
带梯度的参数.append(p)
如果 p.
研究生.is_sparse:
提升
运行时错误(
"NAdam 不支持稀疏梯度")
梯度.append(p.
研究生)
状态 =
自身.
状态[p]
懒惰状态初始化
如果
长度(
状态) == 0:
# note(crcrpar): [为步骤提供特殊设备托管]
# 故意将`step`和`mu_product`在`capturable`为 False 时放在 CPU 上。
因为在 CUDA 和 XLA 上内核启动代价高昂。
状态[
步骤] = (
火炬.
零值((),
数据类型=
_获取标量数据类型(),
设备=p.
设备)
如果
群组[
"可捕获的"]
否则
火炬.
张量(0.0,
数据类型=
_获取标量数据类型())
)
状态["mu_product"] = (
火炬.
一((),
数据类型=
_获取标量数据类型(),
设备=p.
设备)
如果
群组[
"可捕获的"]
否则
火炬.
张量(1.0,
数据类型=
_获取标量数据类型())
)
指数移动平均的梯度值
状态[
平均值] =
火炬.
等于零的(
p, 内存格式=
火炬.
保留格式
)
平方梯度值的指数移动平均
状态["exp_avg_sq"] =
火炬.
等于零的(
p, 内存格式=
火炬.
保留格式
)
实验平均值.append(
状态[
平均值])
实验平均平方值.append(
状态["exp_avg_sq"])
積木产品.append(
状态[
積木产品])
状态步数.append(
状态[
步骤])
返回
复杂的参数
[文档] @_use_grad_for_differentiable
定义
步长(
自身,
闭包=
无):
执行单个优化步骤。
参数:
闭包(Callable,可选):一个重新评估模型并返回损失的闭包
和返回损失。
"文档"
自身._cuda_graph_capture_health_check()
损失 =
无
如果
闭包
是
不
无:
与
火炬.
启用梯度():
损失 =
闭包()
for 群组
在
自身.
参数组:
带梯度的参数:
列表[
张量] =
输入文本为空,请提供需要翻译的文本
梯度:
列表[
张量] =
输入文本为空,请提供需要翻译的文本
实验平均值:
列表[
张量] =
输入文本为空,请提供需要翻译的文本
实验平均平方值:
列表[
张量] =
输入文本为空,请提供需要翻译的文本
mu_products: 列表[
张量] =
输入文本为空,请提供需要翻译的文本
状态步数:
列表[
张量] =
输入文本为空,请提供需要翻译的文本
beta1, beta2 = 角色(
元组[float, float
]
群组[
贝塔])
复杂的参数 =
我.
初始化组(
群组,
带梯度的参数,
梯度,
实验平均值,
实验平均平方值,
穆产品,
状态步数,
)
纳达姆(
带梯度的参数,
梯度,
实验平均值,
实验平均平方值,
穆产品,
状态步数,
beta1=beta1,
beta2=beta2,
学习率=
群组["lr"
]
权重衰减=
群组[
权重衰减
]
动量衰减=
群组[
"动量衰减"
]
eps=群组[
eps
]
最大化=
群组[
最大化
]
解耦权重衰减=
群组[
"解耦权重衰减"
]
foreach=群组["foreach"
]
可捕捉的=
群组[
"可捕获的"
]
可微分的=
群组[
"可区分的"
]
有复杂的=
有复杂的,
)
返回
损失
NAdam.__doc__ = (
r实现 NAdam 算法。
.. math::
\begin{aligned}
&\rule{110mm}{0.4pt} \\
&textbf{输入} : γ_t (学习率), β_1,β_2 (beta 参数),
θ_0 (参数), f(θ) (目标函数) \\
&\hspace{13mm} \: λ (权重衰减), \:\psi (动量衰减) \\
&\hspace{13mm} 解耦权重衰减,\:\textit{最大化} \\
初始化:m_0 ← 0(第一矩)
v_0 \leftarrow 0 \text{ (第二矩)} \\[-1.ex]
&\rule{110mm}{0.4pt} \\
for t=1 到 ... do
&\hspace{5mm}\textbf{if} \: \textit{maximize}: \\
&\hspace{10mm}g_t \leftarrow -\nabla_{\theta} f_t (\theta_{t-1}) \\
否则
&\hspace{10mm}g_t \leftarrow \nabla_{\theta} f_t (\theta_{t-1}) \\
&\hspace{5mm} \theta_t \leftarrow \theta_{t-1} \\
如果 λ 不等于 0
&\hspace{10mm}\textbf{if} \: \textit{decoupled\_weight\_decay} \\
&\hspace{15mm} \theta_t \leftarrow \theta_{t-1} - \gamma \lambda \theta_{t-1} \\
&\hspace{10mm}\textbf{else} \\
&\hspace{15mm} g_t \leftarrow g_t + \lambda \theta_{t-1} \\
&\hspace{5mm} \mu_t \leftarrow \beta_1 \big(1 - \frac{1}{2} 0.96^{t \psi} \big) \\
μ_{t+1} ← β_1(1 - \frac{1}{2} 0.96^{(t+1)ψ})
m_t ← β_1 m_{t-1} + (1 - β_1) g_t \\
v_t ← β_2 v_{t-1} + (1-β_2) g^2_t \\
\widehat{m_t} ← μ_{t+1} m_t/(1-\prod_{i=1}^{t+1}\mu_i)\\[-1.ex]
+ (1-μ_t) g_t /(1-\prod_{i=1}^{t} \mu_{i})
\widehat{v_t} ← v_t/(1-\beta_2^t \big)
&\hspace{5mm}\theta_t \leftarrow \theta_t - \gamma \widehat{m_t}/
\big(√{\widehat{v_t}} + ε \big) \\
&\规则{110 毫米}{0.4 点} \\[-1.ex]
&\bf{return} \: \theta_t \\[-1.ex]
&\规则{110 毫米}{0.4 点} \\[-1.ex]
\end{aligned}
关于算法的更多细节,请参阅《将 Nesterov 动量引入 Adam》_。
"文档"
+ rf""
参数:
{_params_doc}
lr (float, Tensor, 可选): 学习率(默认:2e-3)
betas (Tuple[float, float], 可选): 用于计算系数
运行平均梯度及其平方(默认:(0.9, 0.999))
eps (float, 可选): 添加到分母中的项,以改善
数值稳定性(默认:1e-8)
权重衰减(float,可选):权重衰减(L2 惩罚)(默认:0)
momentum_decay (浮点数,可选): 动量衰减率 momentum_decay (默认: 4e-3)
decoupled_weight_decay (布尔值,可选): 是否解耦权重
衰减如 AdamW 以获得 NAdamW。如果为 True,则算法不
累积动量和无方差中的权重衰减。(默认:False)
{_foreach_doc}
{_maximize_doc}
{_可捕获文档}
{_可区分文档}
将 Nesterov 动量融入 Adam
https://openreview.net/forum?id=OM0jvwB8jIp57ZJjtNEZ
.. _解耦权重衰减正则化
https://arxiv.org/abs/1711.05101
"文档"
)
定义
单个 Tensor_Nadam(
参数:
列表[
张量
]
梯度:
列表[
张量
]
实验平均值:
列表[
张量
]
实验平均平方值:
列表[
张量
]
慕产品:
列表[
张量
]
状态步数:
列表[
张量
]
*,
beta1: float,
beta2: float,
学习率: float,
权重衰减: float,
动量衰减: float,
eps: float,
解耦权重衰减:
布尔,
最大化:
布尔,
可捕捉的:
布尔,
可微分的:
布尔,
有复杂的:
布尔,
):
for i, 参数
在
列举(
参数):
梯度 =
梯度[i]
如果
不
最大化
否则 -
梯度[i]
指数平均值 =
实验平均值[i]
指数平均值的平方 =
实验平均平方值[i]
穆产品 = mu_products[i]
步骤_t =
状态步数[i]
如果
火炬.
是复杂的(
参数):
参数 =
火炬.
真实查看(
参数)
梯度 =
火炬.
真实查看(
研究生)
指数平均值 =
火炬.
真实查看(exp_avg)
指数平均值的平方 =
火炬.
真实查看(
指数平均平方)
如果编译,编译器将处理 cudagraph 检查,参见注释[torch.compile x capturable]
如果
不
火炬.
编译器.is_compiling()
和
可捕捉的:
可捕获支持的设备 =
_获取可捕获的设备()
断言 (
参数.
设备.
类型 == mu_product.
设备.
类型 ==
步骤_t.
设备.
类型
和
参数.
设备.
类型
在
可捕获支持的设备
), (
f如果 capturable=True,params、mu_products 和 state_steps 必须是
f"支持设备上:"{
支持捕获的设备}
。
)
# 更新步骤
步骤_t += 1
如果
可捕捉的:
步骤 =
步骤_t
else:
步骤 =
_获取值(
步骤_t)
偏差校正 2 = 1 - beta2**
步骤
如果
权重衰减 != 0:
如果
解耦权重衰减:
执行步长权重衰减
参数.mul_(1 -
左右 *
权重衰减)
else:
梯度 =
研究生.
添加(
参数,
阿尔法=
权重衰减)
计算动量缓存 \mu^{t} 和 \mu^{t+1}
mu = beta1 * (1.0 - 0.5 * (0.96 ** (步骤 *
动量衰减)))
mu_next = beta1 * (1.0 - 0.5 * (0.96 ** ((步骤 + 1) *
动量衰减)))
更新 mu_product
mu_product *= mu
# 衰减第一个和第二个矩度的运行平均值系数
exp_avg.线性插值 _(
研究生, 1 - beta1)
指数平均平方.mul_(beta2).addcmul_(
研究生,
研究生,
值=1 - beta2)
分母 =
指数平均平方.
除法(
偏差校正 2).
平方根()
如果
可微分的
或者
可捕捉的:
分母 = denom.
添加(eps)
# 让自动微分跟踪操作
通过直接更新 grad 和 exp_avg 而不是使用
# scalar "value" 参数的 addcdiv。
mu_product_next = mu 产品 *
mu 下一个
梯度 =
梯度 * (-
左右 * (1.0 -
穆) / (1.0 - mu_product))
指数平均值 =
指数平均值 * (-
左右 * mu_next / (1.0 - mu_product_next))
参数.addcdiv_(
研究生, denom)
参数.addcdiv_(exp_avg, denom)
else:
mu_product_next = _获取值(mu_product) * mu_next
denom.加_(eps)
参数.addcdiv_(
研究生, denom,
值=(-
左右 * (1.0 -
穆) / (1.0 -
_获取值(
mu 产品)))
)
参数.addcdiv_(
exp_avg, denom, 值=(-
左右 *
mu 下一个) / (1.0 -
mu 产品下一个)
)
定义
多张量 Nadam(
参数:
列表[
张量
]
梯度:
列表[
张量
]
实验平均值:
列表[
张量
]
实验平均平方值:
列表[
张量
]
穆产品:
列表[
张量
]
状态步数:
列表[
张量
]
*,
beta1: float,
beta2: float,
学习率: float,
权重衰减: float,
动量衰减: float,
eps: float,
解耦权重衰减:
布尔,
最大化:
布尔,
可捕捉的:
布尔,
可微分的:
布尔,
有复杂的:
布尔,
):
如果
长度(
参数) == 0:
返回
断言
不
可微分的,
"_foreach 操作不支持自动求导"
如果编译,编译器将处理 cudagraph 检查,参见注释[torch.compile x capturable]
如果
不
火炬.
编译器.is_compiling()
和
可捕捉的:
可捕获支持的设备 =
_获取可捕获的设备(
支持 XLA=
假
)
断言
所有(
p.设备.
类型 == mp.
设备.
类型 ==
步长.
设备.
类型
和 p.
设备.
类型
在
可捕获支持的设备
for p, mp, 步骤
在 zip(
参数,
積木产品,
状态步数)
), f如果 capturable=True,params、mu_products 和 state_steps 必须在支持的设备上:{
支持捕获的设备}
。
分组张量 =
优化器.
按设备类型和数据类型分组张量(
[参数,
梯度,
实验平均值,
实验平均平方值,
mu 产品,
状态步数] # type: ignore[list-item]
)
for (
分组参数_,
分组梯度_,
分组实验平均值_,
分组期望平均平方,
分组 mu 产品,
分组状态步骤_,
), _ 在
分组张量.
值():
分组参数 =
角色(
列表[
张量
]
分组参数_)
分组梯度 =
角色(
列表[
张量
]
分组梯度_)
分组实验平均值 =
角色(
列表[
张量
]
分组实验平均值_)
分组期望平均平方 =
角色(
列表[
张量
]
分组经验平均平方)
分组μ乘积 =
角色(
列表[
张量
]
分组μ乘积_)
分组状态步骤 =
角色(
列表[
张量
]
分组状态步骤_)
处理复杂情况
如果
有复杂的:
真实查看(
分组参数,
分组梯度,
分组实验平均值,
分组实验平均平方
)
如果
最大化:
分组梯度 =
火炬._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:
如果
解耦权重衰减:
执行步长权重衰减
火炬._foreach_mul_(
分组参数, 1 -
左右 *
权重衰减)
else:
重复使用已分配给最大化操作的中间内存(grouped_grads)
如果
最大化:
火炬._foreach_add_(
分组梯度,
分组参数,
阿尔法=
权重衰减
)
else:
分组梯度 =
火炬.
_foreach_add_(
# 类型:忽略[赋值]
分组梯度,
分组参数,
阿尔法=
权重衰减
)
衰减第一个和第二个矩度的运行平均值系数
火炬._foreach_lerp_(
分组实验平均值,
分组梯度, 1 - beta1)
火炬._foreach_mul_(
分组经验平均平方, beta2)
火炬._foreach_addcmul_(
分组经验平均平方,
分组梯度,
分组梯度, 1 - beta2
)
期望平均平方根 =
火炬.
_foreach 平方根(
分组经验平均平方)
偏差校正开平方:
并集[
元组[
张量, ...
]
列表[
张量]]
肌:
并集[
元组[
张量, ...
]
列表[
张量]]
下一个μ值:
并集[
元组[
张量, ...
]
列表[
张量]]
如果
可捕捉的:
# mus 将是 beta1 * (1 - 0.5 * 0.96 ** (步数 * 动量衰减))
指数 =
火炬._foreach_mul(
分组状态步骤,
动量衰减)
肌 =
火炬._foreach_pow(0.96,
指数)
火炬._foreach_mul_(
肌, -0.5)
火炬._foreach_add_(
肌, 1.0)
火炬._foreach_mul_(
肌, beta1)
# mu_nexts 将被 beta1 * (1 - 0.5 * 0.96 ** ((step + 1) * 动量衰减率))
火炬._foreach_add_(
指数,
动量衰减率)
mu_nexts = torch._foreach_pow(0.96, 指数)
火炬._foreach_mul_(mu_nexts, -0.5)
火炬._foreach_add_(mu_nexts, 1.0)
火炬._foreach_mul_(mu_nexts, beta1)
# 保存峰值内存,因为我们不再需要指数
删除
指数
偏差校正平方根 =
火炬._foreach_pow(beta2,
分组状态步骤)
不允许将标量作为 foreach_sub 的第一个参数
火炬._foreach_sub_(
偏差校正平方根, 1.0)
火炬._foreach_neg_(
偏差校正平方根)
火炬.
_foreach_sqrt__(
偏差校正平方根)
else:
偏差校正平方根 = [
(1 - beta2 ** _获取值(
步长)) ** 0.5 for
步骤
在
分组状态步骤
]
肌 = [
beta1 * (1.0 - 0.5 * (0.96 ** (_获取值(
步长) *
动量衰减)))
for 步骤
在
分组状态步骤
]
下一个μ值 = [
beta1
* (1.0 - 0.5 * (0.96 ** ((_获取值(
步长) + 1) *
动量衰减)))
for 步骤
在
分组状态步骤
]
# 更新 mu_products
火炬._foreach_mul_(
分组 mu_products,
肌)
火炬._foreach_div_(
指数平均平方根,
偏差校正平方根)
火炬._foreach_add_(
指数平均平方根, eps)
# 显式删除 bias_correction 引用以节省内存
删除 bias_correction_sqrt
如果
可捕捉的:
# 为 grad 构建步长乘数,重用 mus 的内存
火炬._foreach_sub_(
肌, 1.0)
火炬._foreach_mul_(
肌,
学习率)
不允许将标量作为 foreach_sub 的第一个参数
分母 =
火炬.
遍历子项(
分组_mu 产品, 1.0)
火炬._foreach_neg_(denom)
火炬._foreach_div_(
肌, denom)
# - lr * (1 - mu) / (1 - mu_product)
步长梯度 =
肌
明确删除 denom 以节省内存
删除
分母
为 exp_avg 构建步长乘数,重用 mu_nexts 的内存
分母 =
火炬._foreach_mul(
分组 mu 乘积, mu_nexts)
torch._foreach_mul_(mu_nexts, 学习率)
# foreach_sub 不允许将标量作为第一个参数,但没关系
# 我们无论如何都需要这里有一个负号
火炬._foreach_sub_(denom, 1.0)
火炬._foreach_div_(mu_nexts, denom)
# - lr * mu_next / (1 - mu_product * mu_next)
step_size_expavg = mu_nexts
# 明确删除 denom 以节省内存
删除
分母
# 我们不能原地修改 step_size_grads 因为它是一个 ScalarTensors 列表
# 并且与 grouped_grads 相乘将得到一个更大的 Tensors 列表
分子 =
火炬._foreach_mul(
步长梯度,
分组梯度)
火炬._foreach_addcmul_(
分子,
步长指数移动平均,
分组实验平均值)
# 最后,更新参数
火炬._foreach_addcdiv_(
分组参数,
分子,
指数平均平方根)
else:
步长梯度 = _stack_if_compiling(
[
(_获取值(
学习率) * (1.0 -
穆) / (1.0 -
_获取值(
mu 产品))) * -1
for mu 产品, mu
在 zip(
分组 mu 产品,
肌)
]
)
步长指数移动平均 = _stack_if_compiling(
[
(
_获取值(
学习率)
* mu_next
/ (1.0 - _获取值(mu_product) * mu_next)
)
* -1
for mu_product, mu_next 在 zip(
分组 mu 产品, mu_nexts)
]
)
火炬._foreach_addcdiv_(
分组参数,
分组梯度,
指数平均平方根,
步长梯度 # type: ignore[arg-type]
)
火炬._foreach_addcdiv_(
分组参数,
分组实验平均值,
指数平均平方根,
步长指数加权平均 # type: ignore[arg-type]
)
@_disable_dynamo_if_unsupported(单个张量函数=
_单张张量 Nadam)
定义 nadam(
参数:
列表[
张量
]
梯度:
列表[
张量
]
实验平均值:
列表[
张量
]
实验平均平方值:
列表[
张量
]
積木产品:
列表[
张量
]
状态步数:
列表[
张量
]
使用 torchscript 编译的函数不支持带默认值的只写关键字参数问题 #70627
现由 torch/distributed/optim 编译的函数 API 参数
解耦权重衰减:
布尔值 =
错误,
foreach: 可选[
布尔] =
无,
可捕捉的:
布尔值 =
错误,
可微分的:
布尔值 =
错误,
有复杂的:
布尔值 =
错误,
最大化:
布尔值 =
错误,
*,
beta1: float,
beta2: float,
学习率: float,
权重衰减: float,
动量衰减: float,
eps: float,
):
r执行 NAdam 算法计算的函数 API。
详细信息请参阅 :class:`~torch.optim.NAdam`。
"文档"
如果
不
所有(isinstance(t,
火炬.
张量) for t
在
状态步数):
提升
运行时错误(
"API 已更改,`state_steps`参数必须包含一个单例张量列表"
)
如果
不
所有(isinstance(t,
火炬.
张量) for t
在
積木产品):
提升
运行时错误(
"API 已更改,`mu_products`参数必须包含一个单例张量列表"
)
如果 foreach
是
无:
_, foreach = 默认为融合或遍历(
参数,
可微分的,
使用融合的=
假
)
如果 foreach
和
火炬.
算子.
是否正在脚本化():
提升
运行时错误(
"torch.jit.script 不支持 foreach 优化器")
如果 foreach
和
不
火炬.
算子.
是否正在脚本化():
函数 = _multi_tensor_nadam
else:
函数 = _single_tensor_nadam
函数(
参数,
梯度,
实验平均值,
实验平均平方值,
積木产品,
状态步数,
beta1=beta1,
beta2=beta2,
学习率=
学习率,
权重衰减=
权重衰减,
动量衰减=
动量衰减,
最大化=
最大化,
解耦权重衰减=
解耦权重衰减,
eps=eps,
可捕捉的=
可捕捉的,
可微分的=
可微分的,
有复杂的=
有复杂的,
)