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

torch.ao.nn.quantizable.modules.rnn 的源代码

""
我们将重新创建所有 RNN 模块,因为我们需要的模块需要被分解
深入到其基本组成部分以便能够观察。
""

# mypy: 允许未类型化定义

导入 数字
导入 警告
来自 打字 导入 可选

导入 火炬
来自 火炬 导入 张量


__all__ = [LSTM 单元, "长短期记忆网络"]


 LSTMCell(火炬.nn.模块):
    r可量化的长短期记忆(LSTM)单元。

对于描述和参数类型,请参阅:class:`~torch.nn.LSTMCell`。

`split_gates`:指定为 True 以分别计算输入/遗忘/细胞/输出门。
避免中间张量随后被分块。这种优化对设备上的推理延迟有益。此标志从父类级联下来。
适用于设备上推理延迟的优化。此标志从父类级联下来。
来自父类。

示例:

>>> 导入 torch.ao.nn.quantizable 作为 nnqa
        >>> rnn = nnqa.LSTMCell(10, 20)
        >>> input = torch.randn(6, 10)
        >>> hx = torch.randn(3, 20)
        >>> cx = torch.randn(3, 20)
        >>> output = []
        >>> for i in range(6):
        ...     hx, cx = rnn(input[i], (hx, cx))
        ...     output.append(hx)
```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)
```
    浮点模块 = 火炬.nn.LSTMCell
    常量 = ["split_gates"]  # for jit.script

    def 初始化(
        自身,
        输入维度: int,
        隐藏维度: int,
        偏差: 布尔类型 = True,
        设备=,
        数据类型=,
        *,
        分割门=错误,
    ) -> :
        工厂参数 = {"设备": 设备, "dtype": 数据类型}
        超级().初始化()
        自身.输入大小 = 输入维度
        自身.hidden_size = 隐藏维度
        自身.bias = bias
        自身.分割门 = 分裂门

        如果 not 分割门:
            自身.igates: 火炬.nn.模块 = 火炬.nn.线性(
                输入维度, 4 * 隐藏维度, 偏差=偏差, **工厂参数
            )
            自身.hgates: 火炬.nn.模块 = 火炬.nn.线性(
                隐藏维度, 4 * 隐藏维度, 偏差=偏差, **工厂参数
            )
            自身.罗格斯: 火炬.nn.模块 = 火炬.ao.nn.量化.浮点功能()
        否则:
            每个门保持独立的线性层
            自身.网格 = 火炬.nn.ModuleDict()
            自身.网格 = 火炬.nn.ModuleDict()
            自身. = 火炬.nn.ModuleDict()
             g  [输入, 忘记, 细胞, 输出]:
                # pyre-fixme[29]: `Union[torch._tensor.Tensor, torch.nn.modules.module.Module]`
                自身.igates[g] = 火炬.nn.线性(
                    输入维度, 隐藏维度, 偏差=偏差, **工厂参数
                )
                # pyre-fixme[29]: `Union[torch._tensor.Tensor, torch.nn.modules.module.Module]`
                自身.hgates[g] = 火炬.nn.线性(
                    隐藏维度, 隐藏维度, 偏差=偏差, **工厂参数
                )
                # pyre-fixme[29]: `Union[torch._tensor.Tensor, torch.nn.modules.module.Module]`
                自身.门控[g] = 火炬.ao.nn.量化.浮点功能()

        自身.输入门 = 火炬.nn.Sigmoid()
        自身.遗忘门 = 火炬.nn.Sigmoid()
        自身.单元门 = 火炬.nn.双曲正切函数()
        自身.输出门 = 火炬.nn.Sigmoid()

        自身.fgate_cx = 火炬.ao.nn.量化.浮点功能()
        自身.igate_cgate = 火炬.ao.nn.量化.浮点功能()
        自身.fgate_cx_igate_cgate = 火炬.ao.nn.量化.浮点功能()

        自身.ogate_cy = 火炬.ao.nn.量化.浮点功能()

        自身.initial_hidden_state_qparams: 元组[float, int] = (1.0, 0)
        自身.initial_cell_state_qparams: 元组[float, int] = (1.0, 0)
        自身.隐藏状态数据类型: 火炬.dtype = 火炬.无符号 8 位整数
        自身.细胞状态数据类型: 火炬.dtype = 火炬.无符号 8 位整数

    def 前向(
        自身, x: 张量, 隐藏: 可选[元组[张量, 张量]] = None
    ) -> 元组[张量, 张量]:
        如果 隐藏  None  隐藏[0]  None  隐藏[1]  :
            隐藏 = 自身.初始化隐藏层(x.shape[0] x.是否量化)
        hx, cx = 隐藏

        如果 not 自身.分裂门:
            网格 = 自身.网格(x)
            网格 = 自身.网格(hx)
            罗格斯 = 自身.罗格斯.添加(igates, hgates)  # type: ignore[operator]

            输入门, 遗忘门, 细胞门, 出口门 = .数据块(4, 1)

            输入门 = 自身.输入门(输入门)
            遗忘门 = 自身.遗忘门(忘却门)
            单元门 = 自身.单元门(单元门)
            出口门 = 自身.输出门(出口门)
        否则:
            # 应用每个输入 + 隐藏投影并相加
             = {}
             (, 闸门), 逻辑门, 高速闸门  压缩(
                自身.罗格斯.项目(),  # type: ignore[operator]
                自身.igates.(),  # type: ignore[operator]
                自身.hgates.(),  # type: ignore[operator]
            ):
                [] = 罗格斯.添加(igates(x), hgates(hx))

            输入门 = 自身.输入门([输入])
            遗忘门 = 自身.遗忘门(闸门[忘记])
            细胞门 = 自身.细胞门(闸门[细胞])
            输出闸门 = 自身.输出门([输出])

        fgate_cx = 自身.fgate_cx.(忘记门, cx)
        igate_cgate = 自身.逻辑门.(输入门, 单元门)
        F 门_CX_逻辑门_输入门 = 自身.前门_中继门_后门.添加(前门_中继门, 中继门_后门)
        电流 = fgate_cx_igate_cgate

        # TODO: 将 tanh 作为模块的成员,以便可以配置其 qparams
        tanh_cy = 火炬.双曲正切(cy)
        hy = 自身.出口_希.(出口, 湍流_希)
        返回 hy, cy

    def 初始化隐藏(
        自身, 批处理大小: int, 是否量化: 布尔类型 = 
    ) -> 元组[张量, 张量]:
        h, c = 火炬.((批处理大小, 自身.隐藏层大小)), 火炬.(
            (批处理大小, 自身.隐藏层大小)
        )
        如果 是否量化:
            (h_scale, h_zp) = 自身.initial_hidden_state_qparams
            (c_scale, c_zp) = 自身.初始细胞状态参数
            h = 火炬.按张量量化(
                h, 比例=h 比例, 零点=h_zp, 数据类型=自身.隐藏状态数据类型
            )
            c = 火炬.按张量量化(
                c, 比例=c_scale, 零点=c_zp, 数据类型=自身.细胞状态数据类型
            )
        返回 h, c

    def _获取名称(自身):
        返回 "可量化的 LSTM 单元"

    @classmethod
    def from_params(, wi, wh, bi=, bh=, 分裂门=错误):
        使用权重和偏置创建新的 LSTM 单元。

参数:
wi, wh:输入层和隐藏层的权重
输入和隐藏层的偏差
```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)
```
        断言 (bi  ) == (bh  )  # 要么两者都为空,要么两者都有值
        输入大小 = wi.shape[1]
        hidden_size = 无法翻译,输入内容为空.shape[1]
        细胞 = (
            输入维度=输入大小,
            隐藏维度=隐藏层大小,
            偏差=(双向  not ),
            分裂门=分裂门,
        )

        如果 not 分裂门:
            细胞.逻辑门.权重 = 火炬.nn.参数(wi)
            如果 双极  not :
                细胞.线路.bias = 火炬.nn.参数()
            细胞.高速.权重 = 火炬.nn.参数(线)
            如果 bh  not :
                细胞.hgate.bias = 火炬.nn.参数(bh)
        否则:
            # 分割权重/偏差
             w, b,   压缩([wi, ] [, ] [细胞.线路, 细胞.线路门)]
                 w_块,   压缩(w.数据块(4, 暗淡=0), 窗户.()):  # type: ignore[operator]
                    .权重 = 火炬.nn.参数(w 块)

                如果 b  not :
                     b 块, 闸门  压缩(b.数据块(4, 暗淡=0), 闸门们.()):  # type: ignore[operator]
                        闸门.bias = 火炬.nn.参数(b 块)

        返回 细胞

    @classmethod
    def 从浮点数(, 其他, 使用预计算的假量化=错误, 分裂门=错误):
        断言 类型(其他) == .浮点模块
        断言 有属性(其他, qconfig), "浮点模块必须具有 'qconfig'"
        观察 = .从参数(
            其他.输入层权重,
            其他.weight_hh,
            其他.偏差_ih,
            其他.隐藏层偏置,
            分裂门=分裂门,
        )
        观察.qconfig = 其他.qconfig
        观察.逻辑门.qconfig = 其他.qconfig
        观察.高速门.qconfig = 其他.qconfig
        如果 分割门:
            # 也直接将 qconfig 应用到线性模块
             g  观察.纬度.():
                g.qconfig = 其他.qconfig
             g  观察.经度.():
                g.qconfig = 其他.qconfig
        返回 观察


 _LSTMSingleLayer(火炬.nn.模块):
    r“一个单向 LSTM 层。

层和单元的区别在于层可以处理
序列,而细胞只期望一个瞬时的值。
```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)
```

    def 初始化(
        自身,
        输入维度: int,
        隐藏维度: int,
        偏差: 布尔类型 = True,
        设备=,
        数据类型=,
        *,
        分割门=错误,
    ) -> :
        工厂参数 = {"设备": 设备, "dtype": 数据类型}
        超级().初始化()
        自身.细胞 = LSTMCell(
            输入维度, 隐藏维度, 偏差=偏置, 分裂门=分裂门, **工厂参数
        )

    定义 前向(自身, x: 张量, 隐藏: 可选[元组[张量, 张量]] = ):
        结果 = []
        序列长度 = x.shape[0]
         i  范围(序列长度):
            隐藏 = 自身.细胞(x[i] 隐藏)
            结果.追加(隐藏[0])  忽略索引
        结果张量 = 火炬.(结果, 0)
        返回 结果张量, 隐藏

    @classmethod
    def 从参数(, *参数, **kwargs):
        细胞 = LSTMCell.从参数(*参数, **kwargs)
         = (
            细胞.输入大小, 细胞.隐藏层大小, 细胞.偏差, 分割门=细胞.分割门
        )
        .细胞 = 细胞
        返回 


 LSTM 层(火炬.nn.模块):
    r“这是一个单向 LSTM 层。”

    def 初始化(
        自身,
        输入维度: int,
        隐藏维度: int,
        偏差: 布尔类型 = True,
        批量优先: 布尔类型 = 错误,
        双向的: 布尔类型 = 错误,
        设备=,
        数据类型=,
        *,
        分裂门=错误,
    ) -> :
        工厂参数 = {"设备": 设备, "dtype": 数据类型}
        超级().初始化()
        自身.批量优先 = 批量优先
        自身.双向 = 双向
        自身.层前向 = _LSTMSingleLayer(
            输入维度, 隐藏维度, 偏差=偏差, 分割门=分割门, **工厂参数
        )
        如果 自身.双向的:
            自身.层位宽 = _LSTMSingleLayer(
                输入维度,
                隐藏维度,
                偏差=偏差,
                分裂门=分割门,
                **工厂参数,
            )

    def 前向(自身, x: 张量, 隐藏: 可选[元组[张量, 张量]] = ):
        如果 自身.批量优先:
            x = x.转置(0, 1)
        如果 隐藏  :
            水平翻转, 环形翻转 = (, )
        否则:
            水下前向, 中心前向 = 隐藏
        隐藏黑波: 可选[元组[张量, 张量]] = None
        如果 自身.双向的:
            如果 水下前向  :
                hx_bw = None
            否则:
                hx_bw = hx_fw[1]
                hx_fw = 水下前向[0]
            如果 中心前向  :
                中心后向 = None
            否则:
                中心后向 = cx_fw[1]
                cx_fw = cx_fw[0]
            如果 hx_bw  not None  cx_bw  not :
                hidden_bw = hx_bw, cx_bw
        如果 火焰前部  None  火焰中心  :
            隐藏火焰前部 = None
        否则:
            隐藏火焰前部 = 火炬.算子.解包可选(水下飞行器), 火炬.算子.解包可选(
                水下推进器
            )
        结果飞行器, 隐藏飞行器 = 自身.层面防火墙(x, 隐藏防火墙)

        如果 有属性(自身, "层面后向")  自身.双向的:
            X 反向 = x.翻转(0)
            黑白结果, 隐藏的黑白 = 自身.图层黑白(X 反转, 隐藏黑白色)
            黑白色结果 = 黑白色结果.翻转(0)

            结果 = 火炬.([灰度结果, 黑白结果] 彩色结果.暗淡() - 1)
            如果 隐藏彩色  None  隐藏黑白  :
                h = None
                c = None
            elif 隐藏式前向  :
                (h, c) = 火炬.算子.解包可选(隐藏式后向)
            elif 隐藏式后向  :
                (h, c) = 火炬.算子.解包可选(隐藏式前向)
            否则:
                h = 火炬.([隐藏式前向[0] 隐藏式后向[0]], 0)  # type: ignore[list-item]
                c = 火炬.([隐藏式前向[1] 隐藏式后向[1]], 0)  # type: ignore[list-item]
        否则:
            结果 = 结果前缀
            h, c = 火炬.算子.解包可选(隐藏前缀)  # 类型:忽略[赋值]

        如果 自身.批量优先:
            结果.转置 _(0, 1)

        返回 结果, (h, c)

    @classmethod
    def 从浮点数(, 其他, 层索引=0, qconfig=, **kwargs):
        r""
这个类没有 FP 等效。此函数只是在这里
模拟 `torch.ao.quantization` 中 `prepare` 的行为

```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)
```
        断言 有属性(其他, qconfig)  (qconfig  not )

        输入大小 = kwargs.获取(输入大小, 其他.输入大小)
        hidden_size = kwargs.获取(隐藏层大小, 其他.隐藏层大小)
        bias = kwargs.获取(偏置, 其他.偏差)
        批量优先 = kwargs.获取("batch_first", 其他.批量优先)
        双向 = kwargs.获取(双向, 其他.双向的)
        分割门 = kwargs.获取("分割门", 错误)

         = (
            输入大小,
            隐藏层大小,
            偏差,
            批量优先,
            双向的,
            分割门=分割门,
        )
        .qconfig = getattr(其他, qconfig, qconfig)
        wi = getattr(其他, fweight_ih_l{层索引}")
        wh = getattr(其他, fweight_hh_l{层索引}")
        双向 = getattr(其他, fbias_ih_l{层索引}", )
        沉浸式翻译 = getattr(其他, fbias_hh_l{层索引}", )

        .层级防火墙 = _LSTMSingleLayer.从参数(
            wi, wh, bi, bh, 分裂门=分割栅格
        )

        如果 其他.双向的:
            wi = getattr(其他, fweight_ih_l{层索引}_反向")
            wh = getattr(其他, fweight_hh_l{层索引}反转)
             = getattr(其他, fbias_ih_l{层索引}反转, )
            沉浸式翻译 = getattr(其他, fbias_hh_l{层索引}_reverse", )
            .层位宽 = _LSTMSingleLayer.from_params(
                wi, what, , 两者, 分裂门=分裂门
            )
        返回 


[文档] 长短期记忆网络(火炬.nn.模块): r可量化的长短期记忆(LSTM) 关于描述和参数类型,请参阅:class:`~torch.nn.LSTM` 属性: 层:_LSTMLayer 实例 .. 注意:: 要访问权重和偏差,需要逐层访问。 查看以下示例。 示例: >>> 导入 torch.ao.nn.quantizable 作为 nnqa >>> rnn = nnqa.LSTM(10, 20, 2) >>> input = torch.randn(5, 3, 10) >>> h0 = torch.randn(2, 3, 20) >>> c0 = torch.randn(2, 3, 20) 输出,(hn,cn) = rnn(input, (h0,c0)) >>> # 获取权重: >>> # xdoctest: +SKIP >>> print(rnn.layers[0].weight_ih) tensor([[...]]) >>> print(rnn.layers[0].weight_hh) AssertionError: There is no reverse path in the non-bidirectional layer ```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) ``` 浮点模块 = 火炬.nn.LSTM def 初始化( 自身, 输入大小: int, 隐藏层大小: int, 层数: 整型 = 1, 偏差: 布尔类型 = True, 批量优先: 布尔类型 = 错误, dropout: 浮点数 = 0.0, 双向的: 布尔类型 = 错误, 设备=, 数据类型=, *, 分裂门: 布尔类型 = 错误, ) -> : 工厂参数 = {"设备": 设备, "dtype": 数据类型} 超级().初始化() 自身.输入大小 = 输入大小 自身.hidden_size = hidden_size 自身.层数 = 层数 自身.偏差 = bias 自身.批量优先 = 批量优先 自身.dropout = float(dropout) 自身.双向 = 双向 自身.训练 = 默认为评估模式。如果我们想进行训练,我们将明确设置为训练模式。 如果 ( not isinstance(dropout, 数字.数字) not 0 dropout 1 isinstance(dropout, 布尔) ): 抛出异常 ValueError( "dropout 应该是一个在 [0, 1] 范围内的数字" 表示一个元素被置零的概率 零化 ) 如果 dropout > 0: warnings.警告( "量化 LSTM 的 dropout 选项被忽略。" "如果您正在训练,请使用 nn.LSTM 版本 " "之后是 `准备` 步骤。" ) 如果 层数 == 1: warnings.警告( "dropout 选项在所有层之后添加 dropout,但最后一个层除外,因此非零 dropout 期望" "循环层之后,所以非零 dropout 期望" f"num_layers 的值大于 1,但得到了 dropout="{dropout} " fand num_layers={层数}" ) = [ _LSTMLayer( 自身.输入大小, 自身.隐藏层大小, 自身.偏差, 批量优先=错误, 双向的=自身.双向的, 分割门=分割门, **factory_kwargs, ) ] .扩展( LSTM 层( 自身.隐藏层大小, 自身.隐藏层大小, 自身.偏差, 批量优先=错误, 双向的=自身.双向的, 分裂门=分割门, **工厂参数, ) _ 范围(1, 层数) ) 自身. = 火炬.nn.模块列表() def 前向(自身, x: 张量, 隐藏: 可选[元组[张量, 张量]] = ): 如果 自身.批量优先: x = x.转置(0, 1) 最大批量大小 = x.尺寸(1) 方向数量 = 2 如果 自身.双向 否则 1 如果 隐藏 : 零值 = 火炬.( 方向数量, 最大批量大小, 自身.隐藏层大小, 数据类型=火炬.float, 设备=x.设备, ) .挤压_(0) 如果 x.是否量化: 零值 = 火炬.按张量量化( , 比例=1.0, 零点=0, 数据类型=x.dtype ) 恶心 = [, ) _ 范围(自身.层数] 否则: 隐藏非优化 = 火炬.算子.解包可选(隐藏) 如果 isinstance(隐藏非优化[0] 张量): hx = 隐藏非优化[0].重塑( 自身.层数, 方向数量, 最大批量大小, 自身.hidden_size ) cx = 隐藏非优化[1].重塑( 自身.层数, 方向数量, 最大批量大小, 自身.hidden_size ) hxcx = [ (hx[索引].挤压(0), cx[索引].挤压(0)) 索引 范围(自身.层数) ] 否则: 恶心 = 隐藏非优化 恶心列表 = [] 创意列表 = [] 索引, 列举(自身.): x, (h, c) = (x, 恶心[索引]) 恶心列表.追加(火炬.算子.解包可选(h)) 刺激列表.追加(火炬.算子.解包可选(c)) 恶心张量 = 火炬.(hx 列表) cx 张量 = 火炬.(cx 列表) # 我们为双向案例创建另一个维度 需要合并 hx_tensor = hx_tensor.重塑(-1, hx_tensor.shape[-2] hx 张量.shape[-1]) cx 张量 = cx 张量.重塑(-1, cx_tensor.shape[-2] cx_tensor.shape[-1]) 如果 自身.批量优先: x = x.转置(0, 1) 返回 x, (hx_tensor, cx_tensor) def _获取名称(自身): 返回 可量化的 LSTM @classmethod def 从浮点数(, 其他, qconfig=, 分割门=错误): 断言 isinstance(其他, ._FLOAT_MODULE) 断言 有属性(其他, qconfig) qconfig 观察 = ( 其他.输入大小, 其他.隐藏层大小, 其他.层数, 其他.偏差, 其他.批量优先, 其他.dropout, 其他.双向的, 分裂门=分割门, ) 观察.qconfig = getattr(其他, qconfig, qconfig) 索引 范围(其他.层数): 观察.[索引] = LSTM 层.从浮点数( 其他, 索引, qconfig, 批量优先=错误, 分裂门=分裂门 ) # 准备模型 如果 其他.训练: 观察.训练() 观察 = 火炬.ao.量化.准备量化加速训练(观察, 内置=True) 否则: 观察.评估() 观察 = 火炬.ao.量化.prepare(观察, 内置=True) 返回 观察 @classmethod def 来自观察(, 其他): 整个流程是浮点数 -> 观察到 -> 量化 这个类只做浮点数 -> 观察到 抛出异常 不支持的操作异常( "看起来您正在尝试转换一个" "无法量化的 LSTM 模块。请参阅" "可量化 LSTMs 的示例。" )

© 版权所有 PyTorch 贡献者。

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

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源