# mypy: 允许未类型化定义
导入
数学
来自
打字
导入
类变量,
可选
导入
火炬
导入 torch.ao.nn.intrinsic
作为 nni
导入 torch.ao.nn.qat
作为 nnqat
导入 torch.nn
作为
然后
导入 torch.nn.functional
作为 F
来自 torch.nn
导入
初始化
来自
torch.nn 模块.utils
导入 _pair, _single, _triple
来自
torch.nn 参数
导入
参数
来自 torch.nn.utils
导入
熔合卷积批量归一化权重
__all__ = [
ConvBn1d,
"卷积归一化 ReLU1d",
ConvReLU1d,
ConvBn2d,
"卷积归一化 ReLU2d",
ConvReLU2d,
"卷积归一化 3d",
"卷积归一化 ReLU3d",
ConvReLU3d,
更新 BN 统计信息,
冻结 BN 统计信息,
]
_BN_CLASS_MAP = {
1: nn.批标准化 1d,
2: nn.批标准化 2d,
3: nn.批标准化 3d,
}
类 _ConvBnNd(nn.
模块.conv.
_卷积 Nd, nni.
混合模块):
_version = 2
_FLOAT_MODULE: 类变量[
类型[nn.
模块.conv.
_卷积 Nd]]
定义
初始化(
自身,
# ConvNd 参数
输入通道,
输出通道,
核心大小,
步长,
填充,
扩展率,
交换,
输出填充,
群组,
偏置,
填充模式,
# BatchNormNd 参数
# num_features: 输出通道数
eps=0.00001,
动量=0.1,
# affine: True
# track_running_stats: True
# Args for this module
冻结 BN=
错误,
qconfig=无,
暗淡=2,
):
nn.模块.conv.
_卷积 Nd.
初始化(
自身,
输入通道,
输出通道,
核心大小,
步长,
填充,
扩展率,
交换,
输出填充,
群组,
错误,
填充模式,
)
断言 qconfig,
"必须为 QAT 模块提供 qconfig"
自身.qconfig = qconfig
自身.
冻结 BN =
冻结_bn
如果
自身.
训练
否则
真实
自身.bn = _BN_CLASS_MAP[
暗淡
]
输出通道, eps,
动量, True, True)
自身.weight_fake_quant =
自身.qconfig.
重量()
如果
偏置:
自身.
偏差 =
参数(
火炬.
空的(
输出通道))
否则:
自身.
注册参数(
偏置,
无)
自身.
重置_bn 参数()
在调用 reset_bn_parameters 之后
因为它们修改了相同的状态
如果
自身.
训练:
如果
冻结批归一化:
自身.
冻结批归一化统计信息()
否则:
自身.
更新 BN 统计信息()
否则:
自身.
冻结 BN 统计信息()
自身.
启用慢路径以获得更好的数值稳定性 =
假
定义
重置运行统计量(
自身):
自身.bn.
重置运行统计量()
定义
重置 BN 参数(
自身):
自身.bn.
重置运行统计量()
初始化.
均匀的(
自身.bn.
重量)
初始化.
全 0 矩阵(
自身.bn.
偏置)
# 备注:下面实际上是用于卷积,而不是批归一化
如果
自身.
偏差
是 not
无:
风扇进, _ =
初始化.
_计算扇入和扇出(
自身.
重量)
限制 = 1 /
数学.
平方根(
风扇进)
初始化.
均匀的(
自身.
偏置, -
绑定,
绑定)
定义
重置参数(
自身):
超级().
重置参数()
定义
更新 BN 统计信息(
自身):
自身.
冻结 BN =
假
自身.bn.
训练 =
真实
返回 self
定义
冻结 BN 统计信息(
自身):
自身.
冻结 BN =
真实
自身.bn.
训练 =
假
返回 self
定义
前向(
自身,
输入):
如果
自身.
启用慢路径以获得更好的数值稳定性:
返回
自身.
慢速前向(
输入)
返回
自身.
近似前向(
输入)
定义
近似前向(
自身,
输入):
卷积和归一化融合的近似方法。它只需要一次前向传播。
conv_orig = conv / scale_factor,其中 scale_factor = bn.weight / running_std
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
断言
自身.bn.
运行变量
是 not None
运行标准差 =
火炬.
平方根(
自身.bn.
运行变量 +
自身.bn.eps)
缩放系数 =
自身.bn.
权重 /
运行标准差
权重形状 = [1] *
长度(
自身.
重量.shape)
权重形状[0] = -1
偏置形状 = [1] *
长度(
自身.
重量.shape)
偏置形状[1] = -1
缩放权重 =
自身.
权重伪量化(
自身.
权重 *
缩放因子.
重塑(
重量形状)
)
这里使用零偏置,因为原始卷积的偏置将
后期添加
如果
自身.
偏差
是 not
无:
零偏置 =
火炬.
与...相同形状的零(
自身.
偏置,
数据类型=
输入.
数据类型)
否则:
零偏差 =
火炬.
零(
自身.
输出通道,
设备=
缩放权重.
设备,
数据类型=
输入.dtype
)
卷积 =
自身.
_卷积前向(
输入,
扩放权重,
零偏置)
卷积原始 =
卷积 /
缩放因子.
重塑(
偏置形状)
如果
自身.
偏差
是 not
无:
原始对话 =
原始对话 +
自身.
偏置.
重塑(
偏置形状)
卷积 =
自身.bn(
原始对话)
返回
卷积
定义 _forward_slow(
自身,
输入):
""
一种更精确但速度较慢的卷积批归一融合计算方法,详见 https://arxiv.org/pdf/1806.08342.pdf
需要进行两次前向传播,但可以处理 bn.weight == 0 的情况
卷积:Y = WX + B_c
无偏卷积:Y0 = WX = Y - B_c,Y = Y0 + B_c
批量统计:
mean_Y = Y.mean()
= Y0.mean() + B_c
var_Y = (Y - mean_Y)^2.mean()
= (Y0 - Y0.mean())^2.mean()
BN (r: bn.weight, beta: bn.bias):
Z = r * (Y - mean_Y) / sqrt(var_Y + eps) + beta
= r * (Y0 - Y0.mean()) / sqrt(var_Y + eps) + beta
混合卷积 BN 训练(std_Y = sqrt(var_Y + eps)):
Z = (r * W / std_Y) * X + r * (B_c - mean_Y) / std_Y + beta
= (r * W / std_Y) * X - r * Y0.mean() / std_Y + beta
Fused Conv BN inference (running_std = sqrt(running_var + eps)):
Z = (r * W / running_std) * X - r * (running_mean - B_c) / running_std + beta
QAT with fused conv bn:
Z_train = fake_quant(r * W / running_std) * X * (running_std / std_Y) - r * Y0.mean() / std_Y + beta
= conv(X, fake_quant(r * W / running_std)) * (running_std / std_Y) - r * Y0.mean() / std_Y + beta
Z_inference = conv(X, fake_quant(r * W / running_std)) - r * (running_mean - B_c) / running_std + beta
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
断言
自身.bn.
运行变量
是 not None
断言
自身.bn.
运行均值
是 not None
使用零偏差此处由于原始卷积的偏差将被添加
# will be added later
零偏差 =
火炬.
零(
自身.
输出通道,
设备=
自身.
重量.
设备,
数据类型=
输入.dtype
)
权重形状 = [1] *
长度(
自身.
重量.shape)
权重形状[0] = -1
偏置形状 = [1] *
长度(
自身.
重量.shape)
偏置形状[1] = -1
如果
自身.bn.
训练:
# 需要计算批处理均值/标准差
conv_out = 自身.
_卷积前向(
输入,
自身.
重量, zero_bias)
# 更新 bn 统计信息
与
火炬.
不梯度():
卷出偏差 = (
卷出
如果
自身.
偏差
是 None
否则
卷出 +
自身.
偏置.
重塑(
偏差形状)
)
自身.bn(conv_out_bias)
# 焦融卷积+BN 无偏置,使用 BN 运行统计
运行标准差 =
火炬.
平方根(
自身.bn.
运行变量 +
自身.bn.eps)
缩放系数 =
自身.bn.
权重 /
运行标准差
扩放权重 =
自身.
权重伪量化(
自身.
权重 *
缩放因子.
重塑(
重量形状)
)
# 用于推理的无偏融合卷积: (r * W / 运行标准差) * X
卷积归一化 =
自身.
_卷积前向(
输入,
扩放权重,
零偏差)
平均维度 = [0] +
列表(
范围(2,
长度(
自身.
重量.shape)))
批量均值 =
卷积输出.
均值(
平均维度)
批量方差 =
火炬.
平方(
输出 -
批量均值.
重塑(
偏差形状)).
均值(
平均维度
)
批量标准 =
火炬.
平方根(
批量方差 +
自身.bn.eps)
# 使用批量标准进行训练模式下的缩放
# conv(X, r * W / std_Y) = conv(X, r * W / 运行标准) * (运行标准 / std_Y)
缩放因子 =
运行标准差 /
批标准差
卷积归一化 *=
缩放因子.
重塑(
偏差形状)
融合均值 =
批量均值
混合标准 =
批量标准
否则:
# 使用 BN 运行统计信息的无偏置的融合卷积+BN
运行标准 =
火炬.
平方根(
自身.bn.
运行变量 +
自身.bn.eps)
缩放系数 =
自身.bn.
权重 /
运行标准
缩放权重 =
自身.
权重伪量化(
自身.
权重 *
缩放因子.
重塑(
权重形状)
)
# 推理时无偏置的融合卷积: (r * W / 运行标准) * X
卷积批归一化 =
自身.
_卷积前向(
输入,
缩放权重,
零偏置)
融合均值 =
自身.bn.
运行均值 - (
自身.
偏差
如果
自身.
偏差
是 not None
否则 0
)
混合标准差 =
运行标准差
# 混合偏差 = beta - r * 均值 / 标准差
混合偏差 =
自身.bn.
偏差 -
自身.bn.
权重 *
融合均值 /
融合标准差
卷积归一化 +=
融合偏置.
重塑(
偏置形状)
# HACK 使卷积偏置参与损失以避免 DDP 错误(参数
# 未用于产生损失)
如果
自身.
偏差
是 not
无:
卷积归一化 += (
自身.
偏差 -
自身.
偏置).
重塑(
偏置形状)
返回
卷积归一化
定义
额外表示(
自身):
# TODO(jerryzh): 扩展
返回
超级().
额外表示()
定义
前向(
自身,
输入):
返回
自身.
前向(
输入)
定义
训练(
自身,
模式=True):
""
批归一化训练行为使用 self.training 标志。防止
如果 BN 被冻结,则更改它。这确保了在具有冻结 BN 的模型上调用`model.train()`将表现正常。
在一个具有冻结 BN 的模型上调用`model.train()`将表现正常。
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
自身.
训练 =
模式
如果 not
自身.freeze_bn:
为
模块
在
自身.
儿童():
模块.
训练(
模式)
返回 self
# ===== 序列化版本历史 =====
#
版本 1/无
# self
# |--- 重量 : 张量
# |--- 偏置 : 张量
# |--- gamma : 张量
# |--- beta : 张量
# |--- 运行均值 : 张量
# |--- 运行方差 : 张量
# |--- num_batches_tracked : 张量
#
# 版本 2
# self
# |--- 重量 : 张量
# |--- 偏置 : 张量
# |--- bn : 模块
# |--- weight : 张量(从 v1.self.gamma 迁移而来)
# |--- bias : 张量(从 v1.self.beta 迁移而来)
# |--- 运行均值:Tensor(从 v1.self.running_mean 迁移而来)
# |--- 运行方差:Tensor(从 v1.self.running_var 迁移而来)
# |--- 追踪的批次数量:Tensor(从 v1.self.num_batches_tracked 迁移而来)
定义
从状态字典加载(
自身,
state_dict,
前缀,
本地元数据,
严格的,
缺少键,
预期之外的键,
错误信息,
):
版本 =
本地元数据.
获取(
版本,
无)
如果
版本
是 None
或
版本 == 1:
# BN 相关参数和缓冲区已迁移到 v2 的 BN 模块中
v2_to_v1_names = {
"bn.weight": "gamma",
"bn.bias": beta,
"bn.运行均值":
运行均值,
"bn.运行方差":
运行方差,
"bn.已跟踪批次数量":
"已跟踪批次数量",
}
为
v2 名称,
v1 名称
在
v2 转 v1 名称.
项目():
如果
前缀 +
v1 名称
在 state_dict:
state_dict[前缀 +
v2 名称] = state_dict[
前缀 +
v1 名称]
state_dict.弹出(
前缀 +
v1 名称)
elif 前缀 + v2_name
在 state_dict:
# 此模块向前兼容性在一段时间内被破坏(在
# https://github.com/pytorch/pytorch/pull/38478 之间
# https://github.com/pytorch/pytorch/pull/38478
# and https://github.com/pytorch/pytorch/pull/38820)
# and modules emitted the v2 state_dict format while
# specifying that version == 1. This patches the forward
# compatibility issue by allowing the v2 style entries to
# be used.
通过
elif 严格的:
缺少键.
追加(
前缀 + v2_name)
超级().
从状态字典加载(
state_dict,
前缀,
本地元数据,
严格的,
缺少键,
预期之外的键,
错误信息,
)
@classmethod
定义
从浮点数(
类, mod,
使用预计算的假量化=
错误):
r从浮点模块或 qparams_dict 创建一个 qat 模块
参数:`mod` 一个浮点模块,由 torch.ao.quantization 工具生成
或直接从用户处获取
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
# _FLOAT_MODULE 是这里的 TypeVar 绑定,忽略是因为它没有 __name__(代码没问题)
# (代码正常)
断言
类型(mod) ==
类._FLOAT_MODULE, (
qat.
+ 类.__name__
+ ".from_float 仅适用于 "
+ 类._FLOAT_MODULE.__name__
)
断言
有属性(mod,
qconfig),
输入浮点模块必须定义 qconfig
断言 mod.qconfig,
输入浮点模块必须有一个有效的 qconfig
qconfig = mod.qconfig
conv, bn = mod[0] mod[1]
忽略索引
qat_convbn = 类(
conv.输入通道,
conv.输出通道,
conv.核心大小,
conv.步长,
conv.填充,
conv.扩展率,
conv.群组,
conv.偏差
是 not
无,
conv.填充模式,
bn.eps,
bn.动量,
错误,
qconfig,
)
qat_convbn.权重 = conv.
权重
qat_convbn.偏差 = conv.
偏差
qat_convbn.bn.权重 = bn.
权重
qat_convbn.bn.偏差 = bn.
偏差
qat_convbn.bn.运行均值 = bn.
运行均值
qat_convbn.bn.运行变量 = bn.
运行变量
# mypy 错误:无法确定 'num_batches_tracked' 的类型
qat_convbn.bn.跟踪的批次数量 = bn.
跟踪的批次数量
返回 qat_convbn
定义
转换为浮点数(
自身):
类 =
类型(
自身)
卷积 =
类._FLOAT_CONV_MODULE(
# 类型: 忽略[attr-defined]
自身.
输入通道,
自身.
输出通道,
自身.
核心大小,
自身.
步长,
自身.
填充,
自身.
扩展率,
自身.
群组,
自身.
偏差
是 not
无,
自身.
填充模式,
)
conv.权重 =
火炬.nn.
参数(
自身.
重量.detach())
如果
自身.
偏差
是 not
无:
conv.偏差 =
火炬.nn.
参数(
自身.
偏置.detach())
如果
类._FLOAT_BN_MODULE:
# 类型: 忽略[attr-defined]
将批归一化融合到卷积中
断言
自身.bn.
运行变量
是 not None
和
自身.bn.
运行均值
是 not None
conv.重量, conv.
偏差 =
熔合卷积归一化权重(
conv.重量,
conv.偏置,
自身.bn.
运行平均值,
自身.bn.
运行变量,
自身.bn.eps,
自身.bn.
重量,
自身.bn.
偏置,
)
如果
类.
浮点 ReLU 模块:
# 类型: 忽略[attr-defined]
模块 = []
模块.
追加(conv)
relu = 类.
浮点 ReLU 模块()
# 类型: 忽略[attr-defined]
模块.
追加(relu)
卷积 ReLU =
类.
_融合浮点模块(*
模块)
# 类型: 忽略[attr-defined]
卷积 ReLU.
训练(
自身.
训练)
返回
卷积 ReLU
否则:
conv.训练(
自身.
训练)
返回
卷积
[文档]
类 ConvBn1d(_ConvBnNd, nn.
卷积 1D):
r""
A ConvBn1d module is a module fused from Conv1d and BatchNorm1d,
附加了用于权重的 FakeQuantize 模块,
用于量化感知训练。
我们结合了 :class:`torch.nn.Conv1d` 的接口和
class:`torch.nn.BatchNorm1d`。
与 :class:`torch.nn.Conv1d` 类似,使用初始化的 FakeQuantize 模块
设置为默认。
属性:
freeze_bn:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
_FLOAT_BN_MODULE: 类变量[
类型[nn.
批标准化 1d]] = nn.BatchNorm1d
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
模块]]] = None
_FLOAT_MODULE: 类变量[
类型[nn.
模块]] = nni.ConvBn1d
# 类型:忽略[赋值]
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 1D]] = nn.Conv1d
定义
初始化(
自身,
# Conv1d 参数
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=
无,
填充模式=
零,
# BatchNorm1d 参数
# num_features: 输出通道数
eps=0.00001,
动量=0.1,
# affine: True
# track_running_stats: True
此模块的参数
冻结 BN=
错误,
qconfig=无,
):
核心大小 = _single(
核心大小)
步长 = _single(
步长)
填充 = _single(
填充)
扩展率 = _single(
扩展率)
_ConvBnNd.初始化(
自身,
输入通道,
输出通道,
核心大小,
步长,
填充,
扩展率,
错误,
_single(0),
群组,
偏置,
填充模式,
eps,
动量,
冻结 BN,
qconfig,
暗淡=1,
)
[文档]
类 ConvBnReLU1d(ConvBn1d):
r""
A ConvBnReLU1d 模块是由 Conv1d、BatchNorm1d 和 ReLU 熔合而成的模块,
并附有用于权重的 FakeQuantize 模块,
用于量化感知训练。
我们结合了 :class:`torch.nn.Conv1d` 的接口和
class:`torch.nn.BatchNorm1d` 和 :class:`torch.nn.ReLU`。
与 `torch.nn.Conv1d` 类似,FakeQuantize 模块被初始化为
默认。
属性:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
基类定义 _FLOAT_MODULE 为 "ConvBn1d"
_FLOAT_MODULE: 类变量[
类型[nn.
模块]] = nni.ConvBnReLU1d
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 1D]] = nn.Conv1d
_FLOAT_BN_MODULE: 类变量[
类型[nn.
批标准化 1d]] = nn.BatchNorm1d
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
模块]]] = nn.ReLU
# 模块类在将 bn 合并到 conv 之后
_FUSED_FLOAT_MODULE: 类变量[
可选[
类型[nn.
模块]]] = nni.ConvReLU1d
定义
初始化(
自身,
# Conv1d 参数
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=
无,
填充模式=
零,
# BatchNorm1d 参数
# num_features: 输出通道数
eps=0.00001,
动量=0.1,
# affine: True
# track_running_stats: True
# Args for this module
freeze_bn=错误,
qconfig=无,
):
超级().
初始化(
输入通道,
输出通道,
核心大小,
步长,
填充,
扩展率,
群组,
偏置,
填充模式,
eps,
动量,
freeze_bn,
qconfig,
)
定义
前向(
自身,
输入):
返回 F.relu(
自身.
前向(
输入))
@classmethod
定义
从浮点数(
类, mod,
使用预计算的假量化=
错误):
返回
超级().
从浮点数(mod,
使用预计算的假量化)
类 ConvReLU1d(nnqat.
卷积 1D, nni.
混合模块):
rA ConvReLU1d 模块是 Conv1d 和 ReLU 的融合模块,附加了用于权重的 FakeQuantize 模块
FakeQuantize 模块用于
量化感知训练。
我们将 :class:`~torch.nn.Conv1d` 的接口和
class:`~torch.nn.BatchNorm1d` 结合在一起。
属性:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
_FLOAT_MODULE: 类变量[
类型[nni.ConvReLU1d]] = nni.ConvReLU1d
# 类型:忽略[赋值]
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 1D]] = nn.Conv1d
_FLOAT_BN_MODULE: 类变量[
可选[
类型[nn.
模块]]] = None
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
模块]]] = nn.ReLU
定义
初始化(
自身,
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=True,
填充模式=
零,
qconfig=无,
):
超级().
初始化(
输入通道,
输出通道,
核心大小,
步长=
步长,
填充=
填充,
扩展率=
扩展率,
群组=
群组,
偏置=
偏置,
填充模式=
填充模式,
qconfig=qconfig,
)
断言 qconfig,
"必须为 QAT 模块提供 qconfig"
自身.qconfig = qconfig
自身.weight_fake_quant =
自身.qconfig.
重量()
定义
前向(
自身,
输入):
返回 F.relu(
自身.
_卷积前向(
输入,
自身.
权重伪量化(
自身.
重量),
自身.
偏置)
)
@classmethod
定义
从浮点数(
类, mod,
使用预计算的假量化=
错误):
返回
超级().
从浮点数(
mod, 使用预计算的假量化=
使用预计算的假量化
)
[文档]
类 ConvBn2d(_ConvBnNd, nn.
卷积 2D):
r""
A ConvBn2d 模块是由 Conv2d 和 BatchNorm2d 融合而成的模块,
并附加了用于权重的 FakeQuantize 模块,
用于量化感知训练。
我们将 :class:`torch.nn.Conv2d` 的接口与
class:`torch.nn.BatchNorm2d` 结合。
与 :class:`torch.nn.Conv2d` 类似,使用初始化的 FakeQuantize 模块
设置为默认。
属性:
冻结_bn:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
_FLOAT_MODULE: 类变量[
类型[nni.ConvBn2d]] = nni.ConvBn2d
# 类型:忽略[赋值]
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 2D]] = nn.Conv2d
_FLOAT_BN 模块:
类变量[
可选[
类型[nn.
模块]]] = nn.
批标准化 2d
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
模块]]] = None
定义
初始化(
自身,
# ConvNd 参数
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=
无,
填充模式=
零,
# BatchNorm2d 参数
# num_features: 输出通道数
eps=0.00001,
动量=0.1,
# affine: 是
# track_running_stats: True
# Args for this module
freeze_bn=错误,
qconfig=无,
):
核心大小 = _pair(
核心大小)
步长 = _pair(
步长)
填充 = _pair(
填充)
扩展率 = _pair(
扩展率)
_ConvBnNd.初始化(
自身,
输入通道,
输出通道,
核心大小,
步长,
填充,
扩展率,
错误,
_pair(0),
群组,
偏置,
填充模式,
eps,
动量,
freeze_bn,
qconfig,
暗淡=2,
)
[文档]
类 ConvBnReLU2d(ConvBn2d):
r""
ConvBnReLU2d 模块是一个由 Conv2d、BatchNorm2d 和 ReLU 融合而成的模块,
与 FakeQuantize 模块的权重附加
用于量化感知训练
我们结合了 :class:`torch.nn.Conv2d` 和
class:`torch.nn.BatchNorm2d` 以及 :class:`torch.nn.ReLU`
与 `torch.nn.Conv2d` 类似,FakeQuantize 模块已初始化
默认。
属性:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
基类定义 _FLOAT_MODULE 为 "ConvBn2d"
_FLOAT_MODULE: 类变量[
类型[nni.ConvBnReLU2d]] = nni.ConvBnReLU2d
# 类型:忽略[赋值]
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 2D]] = nn.Conv2d
_FLOAT_BN_MODULE: 类变量[
类型[nn.
批标准化 2d]] = nn.
批标准化 2d
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
模块]]] = nn.ReLU
# 将 BN 融合到卷积后的模块类
_融合浮点模块:
类变量[
可选[
类型[nni.ConvReLU2d]]] = nni.ConvReLU2d
定义
初始化(
自身,
# Conv2d 参数
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=
无,
填充模式=
零,
# BatchNorm2d 参数
# num_features: 输出通道数
eps=0.00001,
动量=0.1,
# affine: 是
# track_running_stats: 是
# 此模块的参数
冻结_bn=
错误,
qconfig=无,
):
超级().
初始化(
输入通道,
输出通道,
核心大小,
步长,
填充,
扩展率,
群组,
偏置,
填充模式,
eps,
动量,
冻结_bn,
qconfig,
)
定义
前向(
自身,
输入):
返回 F.relu(
自身.
前向(
输入))
@classmethod
定义
从浮点数(
类, mod,
使用预计算的假量化=
错误):
返回
超级().
从浮点数(mod,
使用预计算的假量化)
[文档]
类 ConvReLU2d(nnqat.
卷积 2D, nni.
混合模块):
rA ConvReLU2d 模块是 Conv2d 和 ReLU 的融合模块,附带用于权重的 FakeQuantize 模块,
量化感知训练。
的。
我们结合了 :class:`~torch.nn.Conv2d` 的接口
class:`~torch.nn.BatchNorm2d`。
属性:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
_FLOAT_MODULE: 类变量[
类型[nn.
模块]] = nni.ConvReLU2d
# 类型:忽略[赋值]
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 2D]] = nn.Conv2d
_FLOAT_BN_MODULE: 类变量[
可选[
类型[nn.
模块]]] = None
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
模块]]] = nn.ReLU
定义
初始化(
自身,
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=True,
填充模式=
零,
qconfig=无,
):
超级().
初始化(
输入通道,
输出通道,
核心大小,
步长=
步长,
填充=
填充,
扩展率=
扩展率,
群组=
群组,
偏置=
偏置,
填充模式=
填充模式,
qconfig=qconfig,
)
断言 qconfig,
"必须为 QAT 模块提供 qconfig"
自身.qconfig = qconfig
自身.weight_fake_quant =
自身.qconfig.
重量()
定义
前向(
自身,
输入):
返回 F.relu(
自身.
_卷积前向(
输入,
自身.
权重伪量化(
自身.
重量),
自身.
偏置)
)
@classmethod
定义
从浮点数(
类, mod,
使用预计算的假量化=
错误):
返回
超级().
从浮点数(
mod, 使用预计算的假量化=
使用预计算的假量化
)
[文档]
类 ConvBn3d(_ConvBnNd, nn.
卷积 3D):
r""
A ConvBn3d 模块是由 Conv3d 和 BatchNorm3d 融合而成的模块,
并附加了用于权重的 FakeQuantize 模块,
用于量化感知训练。
我们结合了 :class:`torch.nn.Conv3d` 的接口和
class:`torch.nn.BatchNorm3d`。
与 :class:`torch.nn.Conv3d` 类似,使用初始化的 FakeQuantize 模块
默认
属性:
冻结_bn:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
_FLOAT_MODULE: 类变量[
类型[nni.ConvBn3d]] = nni.ConvBn3d
# 类型:忽略[赋值]
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 3D]] = nn.Conv3d
浮点 BN 模块:
类变量[
可选[
类型[nn.
模块]]] = nn.BatchNorm3d
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
模块]]] = None
定义
初始化(
自身,
# ConvNd 参数
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=
无,
填充模式=
零,
# BatchNorm3d 参数
# num_features: 输出通道数
eps=0.00001,
动量=0.1,
# 线性相关:True
# 跟踪运行统计:True
# 此模块的参数
冻结 BN=
错误,
qconfig=无,
):
核心大小 =
_三倍_(
核心大小)
步长 =
_三倍_(
步长)
填充 =
_三倍_(
填充)
扩展率 =
_三倍_(
扩展率)
卷积批量归一化.
初始化(
自身,
输入通道,
输出通道,
核心大小,
步长,
填充,
扩展率,
错误,
_三倍_(0),
群组,
偏置,
填充模式,
eps,
动量,
冻结 bn,
qconfig,
暗淡=3,
)
[文档]
类 ConvBnReLU3d(ConvBn3d):
r""
A ConvBnReLU3d 模块是由 Conv3d、BatchNorm3d 和 ReLU 融合而成的模块,
并附带了用于权重的 FakeQuantize 模块,
用于量化感知训练。
我们结合了 :class:`torch.nn.Conv3d` 的接口和
class:`torch.nn.BatchNorm3d` 和 :class:`torch.nn.ReLU`。
与 `torch.nn.Conv3d` 类似,FakeQuantize 模块已初始化
默认。
属性:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
_FLOAT_MODULE: 类变量[
类型[nni.ConvBnReLU3d]] = nni.ConvBnReLU3d
# 类型:忽略[赋值]
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 3D]] = nn.Conv3d
_FLOAT_BN_MODULE: 类变量[
类型[nn.
批标准化 3d]] = nn.BatchNorm3d
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
ReLU 激活函数]]] = nn.ReLU
# 模块类在将 bn 融合到 conv 之后
_FUSED_FLOAT_MODULE: 类变量[
可选[
类型[nni.ConvReLU3d]]] = nni.ConvReLU3d
定义
初始化(
自身,
# Conv3d 参数
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=
无,
填充模式=
零,
# BatchNorm3d 参数
# num_features: 输出通道数
eps=0.00001,
动量=0.1,
# affine: True
# track_running_stats: True
# 该模块的参数
冻结 BN=
错误,
qconfig=无,
):
超级().
初始化(
输入通道,
输出通道,
核心大小,
步长,
填充,
扩展率,
群组,
偏置,
填充模式,
eps,
动量,
freeze_bn,
qconfig,
)
定义
前向(
自身,
输入):
返回 F.relu(ConvBn3d.
前向(
自身,
输入))
@classmethod
定义
从浮点数(
类, mod,
使用预计算的假量化=
错误):
返回
超级().
从浮点数(
mod, 使用预计算的假量化=
使用预计算的假量化
)
[文档]
类 ConvReLU3d(nnqat.
卷积 3D, nni.
混合模块):
r"""一个 ConvReLU3d 模块是 Conv3d 和 ReLU 的融合模块,附加了
伪量化模块用于权重
量化感知训练。
我们结合了 :class:`~torch.nn.Conv3d` 和
class:`~torch.nn.BatchNorm3d` 的接口。
属性:
weight_fake_quant: 权重伪量化模块
```python
# 假设输入文本为:
input_text = '"""'
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
_FLOAT_MODULE: 类变量[
类型[nni.ConvReLU3d]] = nni.ConvReLU3d
# 类型:忽略[赋值]
_FLOAT_CONV_MODULE: 类变量[
类型[nn.
卷积 3D]] = nn.Conv3d
_FLOAT_BN_MODULE: 类变量[
可选[
类型[nn.
模块]]] = None
浮点 ReLU 模块:
类变量[
可选[
类型[nn.
模块]]] = nn.ReLU
定义
初始化(
自身,
输入通道,
输出通道,
核心大小,
步长=1,
填充=0,
扩展率=1,
群组=1,
偏置=True,
填充模式=
零,
qconfig=无,
):
超级().
初始化(
输入通道,
输出通道,
核心大小,
步长=
步长,
填充=
填充,
扩展率=
扩展率,
群组=
群组,
偏置=
偏置,
填充模式=
填充模式,
qconfig=qconfig,
)
断言 qconfig,
"必须为 QAT 模块提供 qconfig"
自身.qconfig = qconfig
自身.weight_fake_quant =
自身.qconfig.
重量()
定义
前向(
自身,
输入):
返回 F.relu(
自身.
_卷积前向(
输入,
自身.
权重伪量化(
自身.
重量),
自身.
偏置)
)
@classmethod
定义
从浮点数(
类, mod,
使用预计算的假量化=
错误):
返回
超级().
从浮点数(
mod, 使用预计算的假量化=
使用预计算的假量化
)
[文档]def 更新_bn 统计数据(mod):
if type(mod) in {
ConvBnReLU1d,
ConvBnReLU2d
ConvBnReLU3d
ConvBn1d
ConvBn2d
ConvBn3d,
}:
mod.update_bn_stats()
[文档]def freeze_bn_stats(mod):
如果类型(mod)在以下范围内{
ConvBnReLU1d,
ConvBnReLU2d,
ConvBnReLU3d,
ConvBn1d
ConvBn2d
ConvBn3d
}:
mod 冻结 bn_stats()