• 文档 >
  • 模块代码 >
  • torch >
  • torch.ao.nn.quantized.modules.linear
快捷键

torch.ao.nn.quantized.modules.linear 的源代码

# mypy: 允许未类型化装饰器
# mypy: 允许未类型化定义
来自 collections.abc 导入 迭代器
来自 打字 导入 可选

导入 火炬
导入 torch.ao.nn.intrinsic 作为 nni
导入 torch.ao.nn.intrinsic.qat 作为 nniqat
导入 torch.nn 作为 然后
来自 torch.nn.utils.fusion 导入 fuse_linear_bn_weights
来自 torch.nn.utils.parametrize 导入 type_before_parametrizations

来自 .工具 导入 _hide_packed_params_repr, _quantize_weight, 加权量化模块


__all__ = [LinearPackedParams, "线性"]


 线性打包参数(火炬.nn.模块):
    _version = 3

    定义 初始化(自身, 数据类型=火炬.qint8):
        超级().初始化()
        自身.dtype = dtype
        如果 自身.dtype == 火炬.qint8:
            wq = 火炬._空线性量化(
                [1, 1] 比例=1.0, 零点=0, 数据类型=火炬.qint8
            )
        elif 自身.dtype == 火炬.float16:
            wq = 火炬.([1, 1] 数据类型=火炬.float)
        自身.设置权重偏差(wq, )  # type: ignore[possibly-undefined]

    @torch.算子.导出
    定义 设置权重偏差(
        自身, 重量: 火炬.张量, 偏置: 可选[火炬.张量]
    ) -> :
        如果 自身.dtype == 火炬.qint8:
            自身._packed_params = 火炬.操作.量化.线性预打包(重量, 偏置)
        elif 自身.dtype == 火炬.float16:
            自身._packed_params = 火炬.操作.量化.线性预打包 fp16(重量, 偏置)
        否则:
            抛出异常 运行时错误("在动态量化线性中不支持数据类型!")

    @torch.算子.导出
    定义 权重偏置(自身):
        如果 自身.dtype == 火炬.qint8:
            返回 火炬.操作.量化.线性解包(自身._packed_params)
        elif 自身.dtype == 火炬.float16:
            返回 火炬.操作.量化.线性解包_fp16(自身._packed_params)
        否则:
            抛出异常 运行时错误("在动态量化线性中不支持数据类型!")

    定义 前向(自身, x):
        返回 x

    # 版本 1
    #   self
    #   |--- 权重 : 张量
    # 偏置 : 张量
    #
    # 版本 2
    #   self
    #   |--- 重量 : 张量
    #   |--- 偏置 : 张量
    torch.dtype
    #
    # 版本 3
    #   self
    #   |--- _packed_params : (Tensor, Tensor) 表示 (权重, 偏置)
    #                         LinearPackedParams 的
    torch.dtype
    定义 保存到状态字典(自身, 目的地, 前缀, 保留变量):
        超级().保存到状态字典(目的地, 前缀, 保留变量)
        目的地[前缀 + "dtype"] = 自身.dtype
        目的地[前缀 + "_packed_params"] = 自身.权重偏置()

    定义 从状态字典加载(
        自身,
        state_dict,
        前缀,
        本地元数据,
        严格的,
        缺少键,
        预期之外的键,
        错误信息,
    ):
        版本 = 本地元数据.获取(版本, )
        如果 版本  None  版本 < 2:
            自身.dtype = 火炬.qint8
        否则:
            自身.dtype = state_dict[前缀 + "dtype"]
            state_dict.弹出(前缀 + "dtype")

        如果 版本  None  版本 < 3:
            自身.设置权重偏差(
                state_dict[前缀 + 权重] state_dict[前缀 + 偏置]
            )
            state_dict.弹出(前缀 + 权重)
            state_dict.弹出(前缀 + 偏置)

        如果 版本 == 3:
            重量, 偏差 = state_dict[前缀 + "_packed_params"]
            state_dict.弹出(前缀 + "_packed_params")
            自身.设置权重偏差(重量, 偏置)

        超级().从状态字典加载(
            state_dict,
            前缀,
            本地元数据,
            错误,
            缺少键,
            预期之外的键,
            错误信息,
        )

    定义 __repr__(自身):
        返回 自身.权重偏置().__repr__()


[文档] 线性(加权量化模块): r"" 一个量化线性模块,输入和输出都是量化张量。 我们采用与 `torch.nn.Linear` 相同的接口,请参阅文档。 https://pytorch.org/docs/stable/nn.html#torch.nn.Linear 查看文档。 与 :class:`~torch.nn.Linear` 相似,属性将在模块创建时随机初始化,稍后将被覆盖 权重(Tensor):模块的非可学习量化权重 属性: weight (Tensor):该模块的非可学习量化权重 形状 :math:`(\text{out\_features}, \text{in\_features})`. 偏置(Tensor):该模块的非可学习偏置,形状为 :math:`(\text{out\_features})`. 如果 :attr:`bias` 为 ``True``,则值初始化为零。 scale:输出量化张量的 `scale` 参数,类型:double `zero_point` 参数用于输出量化张量,类型:长整型 示例: >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_QENGINE) >>> m = nn.quantized.Linear(20, 30) >>> input = torch.randn(128, 20) >>> # xdoctest: +SKIP >>> input = torch.quantize_per_tensor(input, 1.0, 0, torch.quint8) >>> output = m(input) >>> 打印(output.size()) torch.Size([128, 30]) ```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) ``` _version = 3 浮点模块 = (nn.线性, nn.模块.线性.非动态量化的线性) 定义 初始化(自身, 输入特征, 输出特征, bias_=True, 数据类型=火炬.qint8): 超级().初始化() 我们在这里不与缓冲区或属性等纠缠 为了保持模块简单,*一切*都只是 Python 属性 序列化逻辑在下面的序列化和反序列化模块中显式处理 模块中进行 自身.输入特征 = 输入特征 自身.输出特征 = 输出特征 偏差 = None 如果 偏差: 偏差 = 火炬.(输出特征, 数据类型=火炬.float) 如果 dtype == 火炬.qint8: 权重 = 火炬._空线性量化( [输出特征, 输入特征] 比例=1, 零点=0, 数据类型=火炬.qint8 ) elif dtype == 火炬.float16: 权重 = 火炬.([输出特征, 输入特征] 数据类型=火炬.float) 否则: 抛出异常 运行时错误("指定的量化线性数据类型不受支持!") 自身._packed_params = 线性打包参数(数据类型) 自身._packed_params.设置权重偏差(权重, 偏置) 自身.缩放 = 1.0 自身.零点 = 0 定义 _获取名称(自身): 返回 "量化线性" 定义 额外表示(自身): 返回 ( fin_features={自身.输入特征}, out_features={自身.输出特征},缩放={自身.比例}," fzero_point={自身.零点}, 协议方案={自身.重量().q 方案()}" ) 定义 __repr__(自身): 返回 _hide_packed_params_repr(自身, 线性打包参数) 定义 前向(自身, x: 火炬.张量) -> 火炬.张量: 返回 火炬.操作.量化.线性( x, 自身._packed_params._packed_params, 自身.比例, 自身.零点 ) # ===== 序列化方法 ===== # 在这里需要特别注意,我们必须将权重解包到它们 # 序列化 QTensor 的常规形式。打包的权重不应存在于 # 创建它们的进程之外,而应从 QTensor 权重派生。 # # # 版本 1 # self # |--- 缩放 : float # |--- 零点 : int # |--- 重量 : Tensor # |--- 偏置 : Tensor # # 版本 2 # self # |--- 缩放 : float # |--- 零点 : int # |--- _packed_params : 模块 # |--- 重量 : 张量 # |--- 偏置 : 张量 # # 版本 3 # self # |--- 缩放比例 : 浮点数 # |--- 零点 : 整数 # |--- _packed_params : 模块 表示线性打包参数 C++结构体的权重和偏置的 Tensor 与序列化方法相对应,我们必须将序列化的 QTensor 权重打包成打包格式,以便由 FBGEMM 操作使用。 # 定义 保存到状态字典(自身, 目的地, 前缀, 保留变量): 超级().保存到状态字典(目的地, 前缀, 保留变量) 目的地[前缀 + "缩放"] = 火炬.张量(自身.比例) 目的地[前缀 + 零点] = 火炬.张量(自身.零点) # ===== 反序列化方法 ===== 对应于序列化方法,我们必须将序列化的 QTensor 权重打包成打包格式,以便由 FBGEMM 操作使用。 将序列化的 QTensor 权重打包成打包格式,以便由 FBGEMM 操作使用。 定义 从状态字典加载( 自身, state_dict, 前缀, 本地元数据, 严格的, 缺少键, 预期之外的键, 错误信息, ): 自身.缩放 = float(state_dict[前缀 + "缩放"]) state_dict.弹出(前缀 + "缩放") 自身.零点 = int(state_dict[前缀 + 零点]) state_dict.弹出(前缀 + 零点) 版本 = 本地元数据.获取(版本, ) 如果 版本 None 版本 == 1: 我们将参数移动到了一个 LinearPackedParameters 子模块中 权重 = state_dict.弹出(前缀 + 权重) 偏差 = state_dict.弹出(前缀 + 偏置) state_dict.更新( { 前缀 + "_packed_params.weight": 重量, 前缀 + "_packed_params.bias": 偏置, } ) 超级().从状态字典加载( state_dict, 前缀, 本地元数据, 错误, 缺少键, 预期之外的键, 错误信息, ) 函数而非属性以确保 JIT 序列化不会 将此注册为属性 定义 权重偏置(自身): 返回 自身._packed_params.权重偏置() 定义 重量(自身): 返回 自身.权重偏置()[0] 定义 偏置(自身): 返回 自身.权重偏置()[1] 定义 设置权重偏差(自身, w: 火炬.张量, b: 可选[火炬.张量]) -> : 自身._packed_params.设置权重偏差(w, b)
[文档] @classmethod 定义 从浮点数(, mod, 使用预计算的假量化=错误): r从观察到的浮点模块创建量化模块 参数: mod (模块):一个浮点模块,可以是 torch.ao.quantization 工具或由用户提供的 use_precomputed_fake_quant (布尔值): 如果为 True,模块将重用预计算伪量化的最小/最大值。 从预计算的伪量化模块中获取值。 ```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) ``` 如果 有属性(mod, "权重伪量化"): 如果 参数化前的类型(mod) == nniqat.线性 Bn1d: mod.重量, mod.偏差 = 合并线性 BN 权重( mod.重量, mod.偏置, mod.孟加拉语.运行平均值, mod.孟加拉语.运行变量, mod.孟加拉语.eps, mod.孟加拉语.重量, mod.孟加拉语.偏置, ) 权重后处理 = mod.weight_fake_quant activation_post_process = mod.activation_post_process 否则: # 此函数不参与 JIT,因此可以忽略 # 赋值中的类型不匹配问题。同时,mypy 也存在问题 # 不实现可迭代对象,因此也忽略这些。 如果 not isinstance(._FLOAT_MODULE, 迭代器): .浮点模块 = [._FLOAT_MODULE] 支持的模块 = “,”.加入( [浮点模块.__name__ 浮点模块 ._FLOAT_MODULE] ) 错误信息 = fnnq。{.__name__}.from_float 只适用于{支持的模块},但得到:{类型(mod)}" 断言 ( 参数化前的类型(mod) .浮点模块 ), 错误信息.格式() 断言 有属性( mod, qconfig ), 输入浮点模块必须定义 qconfig activation_post_process = mod.activation_post_process 如果 参数化前的类型(mod) == nni.线性 ReLU: 修饰 = mod[0] 权重后处理 = ( mod.qconfig.重量() 如果 not 有属性(mod, "权重伪量化") 否则 mod.weight_fake_quant ) 如果 not 使用预计算的假量化: 观察者可能尚未被调用 观察者可能在之前的阶段通过 PTQ 算法(例如 AdaRound)被调用 权重后处理(mod.重量) dtype = 权重后处理.dtype act_scale, act_zp = 激活后处理.计算 q 参数() 断言 dtype == 火炬.qint8, 权重观察者必须具有 torch.qint8 数据类型 权重 = _quantize_weight(mod.重量.float(), 权重后处理) q 线性 = (mod.输入特征, mod.输出特征, 数据类型=数据类型) q 线性.设置权重偏差(权重, mod.偏置) q 线性.缩放 = float(act_scale) q 线性.零点 = int(活动零偏置) 返回 qlinear
[文档] @类方法 def from_reference(cls, ref_qlinear, output_scale, output_zero_point): r"""从参考量化模块创建一个(fbgemm/qnnpack)量化模块 Args: ref_qlinear (模块): 一个引用的量化线性模块,可以是 torch.ao.quantization 工具生成的,或者由用户提供的 output_scale (浮点数): 输出张量的缩放比例 输出零点(int):输出张量的零点 """ qlinear = cls(ref_qlinear.in_features, ref_qlinear.out_features) qweight = ref_qlinear.get_quantized_weight() qlinear.set_weight_bias(qweight, ref_qlinear.bias) qlinear.scale = float(output_scale) qlinear.zero_point = int(output_zero_point) return qlinear

© 版权所有 PyTorch 贡献者。

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

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源