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

torch.nn.modules.rnn 的源代码

# mypy: 允许未类型化装饰器
# mypy: 允许未类型化定义
导入 数学
导入 数字
导入 警告
导入 弱引用
来自 打字 导入 可选, 超载
来自 typing_extensions 导入 已弃用

导入 火炬
来自 火炬 导入 _VF, 张量
来自 torch.nn 导入 初始化
来自 torch.nn 参数 导入 参数
来自 torch.nn.utils.rnn 导入 PackedSequence

来自 .模块 导入 模块


__all__ = [
    RNNBase,
    "循环神经网络",
    "长短期记忆网络",
    "门控循环单元",
    "RNNCellBase",
    RNN 单元,
    LSTM 单元,
    GRU 单元,
]

_rnn 实现 = {
    RNN_TANH: _VF.RNN-Tanh,
    RNN_RELU: _VF.RNN-ReLU,
}


def _apply_permutation(张量: 张量, 线性排列: 张量, 暗淡: 整型 = 1) -> 张量:
    返回 张量.索引选择(暗淡, 排列)


@deprecated(
    "`apply_permutation` 已弃用,请使用 `tensor.index_select(dim, permutation)` 代替",
    分类=未来警告,
)
def apply_permutation(张量: 张量, 排列: 张量, 暗淡: 整型 = 1) -> 张量:
    返回 应用置换(张量, 置换, 暗淡)


[文档] RNNBase(模块): rRNN 模块(RNN、LSTM、GRU)的基类。 实现了 RNN、LSTM 和 GRU 类共有的方面,例如模块初始化 以及参数存储管理的实用方法。 .. 注意:: RNNBase 类没有实现前向方法。 .. 注意:: LSTM 和 GRU 类覆盖了 RNNBase 类实现的一些方法。 "源代码" 常量 = [ 模式, 输入大小, 隐藏层大小, 层数数量, 偏置, "batch_first", 随机失活率, 双向, 项目大小, ] __jit_unused_properties__ = [所有权重] 模式: 字符串 输入大小: 整型 隐藏层大小: 整型 层数: 整型 偏差: 布尔类型 批量优先: 布尔类型 dropout: 浮点数 双向的: 布尔类型 投影大小: 整型 def 初始化( self, 模式: 字符串, 输入大小: int, 隐藏层大小: int, 层数: 整型 = 1, 偏差: 布尔类型 = True, 批量优先: 布尔类型 = 错误, dropout: 浮点数 = 0.0, 双向的: 布尔类型 = 错误, 投影大小: 整型 = 0, 设备=, 数据类型=, ) -> : 工厂参数 = {"设备": 设备, "dtype": 数据类型} 超级().初始化() self.模式 = 模式 self.输入大小 = 输入大小 self.隐藏层大小 = 隐藏大小 self.层数数量 = 层数数量 self.bias = bias self.批量优先 = 批量优先 self.dropout = float(dropout) self.双向的 = 双向的 self.项目大小 = 项目大小 self._平面重量引用: 列表[可选[弱引用.参考类型[参数]]] = [] 方向数量 = 2 如果 双向 否则 1 如果 ( not isinstance(dropout, 数字.数字) not 0 dropout 1 isinstance(dropout, 布尔) ): 提升 ValueError( "dropout 应该是一个在 [0, 1] 范围内的数字" 表示一个元素被置零的概率 零化 ) 如果 dropout > 0 层数数量 == 1: warnings.警告( "dropout 选项在所有层之后添加 dropout,但最后一个层除外,因此非零 dropout 期望" "循环层之后,所以非零 dropout 期望" f"num_layers 的值大于 1,但得到了 dropout="{dropout} f"num_layers="{层数}" ) 如果 not isinstance(隐藏层大小, int): 提升 类型错误( f"hidden_size 应该是 int 类型,实际得到:"{类型(隐藏层大小).__name__}" ) 如果 hidden_size 0: 提升 ValueError("hidden_size 必须大于零") 如果 num_layers 0: 提升 ValueError("num_layers 必须大于零") 如果 项目大小 < 0: 提升 ValueError( proj_size 应该是一个正整数或零以禁用投影 ) 如果 项目大小 >= 隐藏层大小: 提升 ValueError("项目大小必须小于隐藏大小") 如果 模式 == LSTM: 门大小 = 4 * 隐藏层大小 elif 模式 == GRU: 门大小 = 3 * 隐藏层大小 elif 模式 == RNN_TANH: 门大小 = 隐藏层大小 elif 模式 == RNN_RELU: 网格大小 = 隐藏层大小 否则: 提升 ValueError(识别不到的 RNN 模式: + 模式) self._扁平化权重名称 = [] self.所有权重 = [] 范围(层数): 方向 范围(方向数量): 实数隐藏层大小 = 投影大小 如果 项目大小 > 0 否则 隐藏层大小 层输入大小 = ( 输入大小 如果 == 0 否则 实际隐藏层大小 * 数量方向 ) w_ih = 参数( 火炬.空的((网格大小, 层输入大小), **工厂参数) ) 网格_hh = 参数( 火炬.空的((门大小, 实际隐藏大小), **工厂参数) ) b_ih = 参数(火炬.空的(网格大小, **工厂参数)) # 第二个偏置向量包含以兼容 CuDNN。只需要一个 # 偏置向量在标准定义中即可。 b_hh = 参数(火炬.空的(网格大小, **工厂参数)) 层参数: 元组[张量, ...] = () 如果 self.投影大小 == 0: 如果 偏差: 层参数 = (我_ih, 我_hh, 你_ih, 你_hh) 否则: 层参数 = (我_ih, 我_hh) 否则: w_hr = 参数( 火炬.空的((投影大小, 隐藏层大小), **工厂参数) ) 如果 偏差: 层参数 = (我_ih, 我_hh, 你_ih, 你_hh, w_hr) 否则: 层参数 = (我_ih, 我_hh, w_hr) 后缀 = "_reverse" 如果 方向 == 1 否则 请提供需要翻译的文本 参数名称 = ["weight_ih_l"{}{}", "weight_hh_l"{}{}"] 如果 偏差: 参数名称 += [bias_ih_l{}{}", bias_hh_l{}{}"] 如果 self.proj_size > 0: 参数名称 += [weight_hr_l{}{}"] 参数名称 = [x.格式(, 后缀) x 参数名称] 名称, 参数 压缩(参数名称, 层参数): setattr(self, 名称, 参数) self._扁平权重名称.扩展(参数名称) self.所有权重.追加(参数名称) self.初始化扁平权重() self.重置参数() def 初始化扁平权重(self): self.扁平权重 = [ getattr(self, wn) 如果 有属性(self, wn) 否则 wn self._平面权重名称 ] self.平面重量引用 = [ 弱引用.ref(w) 如果 w not 否则 w self.平面重量 ] self.展平参数() def __setattr__(self, 属性, ): 如果 有属性(self, _flat_weights_names) 属性 self._flat_weights_names: # 保持 self._flat_weights 在 self.weight = ...时更新 索引 = self._flat_weights_names.索引(属性) self.平坦权重[索引] = value 超级().__setattr__(属性, )
[文档] def 展平参数(self) -> : 重置参数数据指针,以便它们可以使用更快的代码路径。 目前,这仅在模块位于 GPU 上且启用 cuDNN 时才有效。 否则就是空操作。 "源代码" 如果_flat_weights 只部分实例化,则短路。 如果 长度(self._flat_weights) != 长度(self._flat_weights_names): 返回 w self._flat_weights: 如果 not isinstance(w, 张量): 返回 # 如果 self._flat_weights 中的任何张量不符合 cuDNN 的要求,则短路 # 或者_flat_weights 中的张量数据类型不同 first_fw = self._平面权重[0] # 类型:忽略[联合属性] dtype = 第一个 fw.dtype # 类型:忽略[联合属性] fw self._平面权重: 如果 ( not isinstance(外文, 张量) not (外文.dtype == 数据类型) not fw.is_cuda not 火炬.后端.cudnn.is_acceptable(fw) ): 返回 如果任何参数别名,我们将回退到较慢的复制代码路径。这是一个 足够的检查,因为重叠的参数缓冲区如果不完全 # 别名会破坏唯一性检查的假设 # Module.named_parameters() 唯一数据指针 = { p.数据指针() p self._扁平权重 # 类型:忽略[联合属性] } 如果 长度(唯一数据指针) != 长度(self._扁平权重): 返回 火炬.cuda.设备的(首个固件): 导入 torch.backends.cudnn.rnn 作为 rnn # 注意:由于 _cudnn_rnn_flatten_weight 是一个对 self._flat_weights 的就地操作,因此需要使用 no_grad() # 在 self._flat_weights 上进行就地操作 火炬.不梯度(): 如果 火炬.使用_cudnn_rnn_flatten_weight(): 权重数量 = 4 如果 self.bias 否则 2 如果 self.投影大小 > 0: 权重数量 += 1 火炬._cudnn_rnn_flatten_weight( self._flat_weights, # type: ignore[arg-type] num_weights, self.输入大小, rnn.获取_cudnn 模式(self.模式), self.隐藏层大小, self.项目大小, self.层数, self.批量优先, 布尔(self.双向的), )
def 应用(self, 函数, 递归=True): self._flat_weight_refs = [] 返回 = 超级().应用(函数, 递归) 重置_flat_weights 注意:在删除此内容之前请格外小心,因为第三方设备类型可能依赖于此行为来正确地使用 LSTM 等模块。 很可能依赖于此行为来正确地使用 LSTM 等模块。 self._init_flat_weights() 返回 返回 def 重置参数(self) -> : stdv = 1.0 / 数学.平方根(self.隐藏层大小) 如果 self.隐藏大小 > 0 否则 0 权重 self.参数(): 初始化.均匀的(重量, -stdv, stdv) def 检查输入(self, 输入: 张量, batch_sizes: 可选[张量]) -> : 如果 not 火炬.算子.是否正在脚本化(): 如果 ( 输入.dtype != self._flat_weights[0].dtype # 类型:忽略[联合属性] not 火炬._C._is_any_autocast_enabled() ): 提升 ValueError( f输入必须具有类型{self._flat_weights[0].数据类型}, 获取类型{输入.数据类型}" # 类型:忽略[联合属性] ) 预期输入维度 = 2 如果 批处理大小 not 否则 3 如果 输入.暗淡() != 预期输入维度: 提升 运行时错误( f"输入必须具有"{期望的输入维度}维度,实际得到{输入.暗淡()}" ) 如果 self.输入大小 != 输入.尺寸(-1): 提升 运行时错误( f"input.size(-1)必须等于 input_size。期望"{self.输入大小},获得{输入.尺寸(-1)}" ) def 获取期望的隐藏尺寸( self, 输入: 张量, batch_sizes: 可选[张量] ) -> 元组[int, int, int]: 如果 批大小 not : 小批量 = int(batch_sizes[0]) 否则: 小批量 = 输入.尺寸(0) 如果 self.批量优先 否则 输入.尺寸(1) 数量方向 = 2 如果 self.双向的 否则 1 如果 self.项目大小 > 0: 预期隐藏层大小 = ( self.层数数量 * 方向数量, 小批量, self.项目大小, ) 否则: 预期隐藏层大小 = ( self.层数数量 * 方向数量, 微批, self.隐藏层大小, ) 返回 预期隐藏层大小 def 检查隐藏层大小( self, hx: 张量, 预期隐藏层大小: 元组[int, int, int] 信息: 字符串 = 预期隐藏大小{},获得{}", ) -> : 如果 hx.尺寸() != expected_hidden_size: 提升 运行时错误(信息.格式(expected_hidden_size, 列表(hx.尺寸()))) def 权重已更改(self): # 返回 True,如果自上次前向传递以来权重张量已更改。 # 这是在使用 torch.func.functional_call()等情况下发生的。 weights_changed = ref, 名称 压缩(self._平面重量引用, self._平面重量名称): 权重 = getattr(self, 名称) 如果 有属性(self, 名称) 否则 如果 权重 not 分支 not ref() not 重量: 权重已更改 = 真实 断开 返回 权重已更改 def 检查前向参数( self, 输入: 张量, 隐藏: 张量, batch_sizes: 可选[张量] ): self.检查输入(输入, batch_sizes) 预期隐藏大小 = self.获取预期隐藏大小(输入, batch_sizes) self.检查隐藏大小(隐藏, 预期隐藏大小) def 隐藏排列(self, hx: 张量, 排列: 可选[张量)] 如果 排列 : 返回 hx 返回 _应用排列(hx, 排列) def 额外表示(self) -> 字符串: s = "输入大小, 隐藏大小" 如果 self.项目大小 != 0: s += ", proj_size="{proj_size}" 如果 self.num_layers != 1: s += ", num_layers="{层数}" 如果 self.bias not True: s += ", 偏置="{偏置}" 如果 self.批量优先 not 错误: s += ", batch_first="{batch_first}" 如果 self.dropout != 0: s += ", dropout="{dropout}" 如果 self.双向 not 错误: s += ", 双向="{双向}" 返回 s.格式(**self.字典) def _更新平坦权重(self): 如果 not 火炬.算子.是否正在脚本化(): 如果 self.权重已更改(): self.初始化扁平权重() def __getstate__(self): 如果权重已更改,请在此处更新 __getstate__ 中的 _flat_weights。 self.更新扁平权重() 不要序列化权重引用。 状态 = self.字典.复制() 删除 状态[_flat_weight_refs] 返回 状态 def __setstate__(self, d): 超级().__setstate__(d) 如果 所有权重 d: self._所有权重 = d[所有权重] 在 PyTorch 1.8 版本中,我们为 LSTM 添加了一个 proj_size 成员变量。 在 PyTorch 1.8 之前通过 torch.save(module) 序列化的 LSTM 没有它,为了保持兼容性,我们在这里设置 proj_size 如果 proj_size not d: self.proj_size = 0 如果 not isinstance(self.所有权重[0] [0] 字符串): 层数 = self.层数 方向数 = 2 如果 self.双向的 否则 1 self._flat_weights_names = [] self._all_weights = [] 范围(层数): 方向 范围(num_directions): 后缀 = "_reverse" 如果 方向 == 1 否则 请提供需要翻译的文本 权重 = [ weight_ih_l{}{}", weight_hh_l{}{}", bias_ih_l{}{}", bias_hh_l{}{}", 重量_hr_l{}{}", ] 权重 = [x.格式(, 后缀) x 权重] 如果 self.偏差: 如果 self.项目大小 > 0: self.所有权重 += [权重] self._扁平权重名称.扩展(权重) 否则: self.所有权重 += [权重[4]] self._扁平权重名称.扩展(权重[4]) 否则: 如果 self.proj_size > 0: self.所有权重 += [权重[2]] + [权重[-1]] self._扁平权重名称.扩展( 权重[2] + [权重[-1]] ) 否则: self.所有权重 += [权重[2]] self._扁平权重名称.扩展(权重[2]) self.平坦权重 = [ getattr(self, wn) 如果 有属性(self, wn) 否则 wn self._flat_weights_names ] self._flat_weight_refs = [ 弱引用.ref(w) 如果 w not 否则 w self.扁平权重 ] @property def 所有权重(self) -> 列表[列表[参数]] 返回 [ [getattr(self, 重量) 权重 权重] 权重 self.__所有权重 ] def _为数据并行复制(self): 复制品 = 超级()._为数据并行复制() # 需要复制这些缓存,否则副本将共享相同的 # 平坦的权重列表。 复制品.扁平权重 = 复制品._平面权重[] 复制品._平面权重名称 = 复制品._扁平权重名称[] 返回 复制品
[文档] RNN(RNNBase): r"""__init__(input_size,hidden_size,num_layers=1,nonlinearity='tanh',bias=True,batch_first=False,dropout=0.0,bidirectional=False,device=None,dtype=None)""" 应用多层 Elman RNN,非线性函数为::math:`\tanh` 或 :math:`\text{ReLU}` 将非线性函数应用于输入序列。对于输入序列中的每个元素, 每一层计算以下函数: .. math:: h_t = tanh(x_t W_{ih}^T + b_{ih} + h_{t-1}W_{hh}^T + b_{hh}) 其中 :math:`h_t` 是时间 `t` 的隐藏状态,:math:`x_t` 是 时间 `t` 的输入,而 :math:`h_{(t-1)}` 是 上一个时间步`t-1`的层或时间`0`的初始隐藏状态。 如果:attr:`非线性`是`'relu'`,则使用 ReLU 代替 tanh。 .. 代码块 :: python # 等效的效率实现,但 bidirectional=False def forward(x, hx=None): 如果 batch_first: x = x.transpose(0, 1) seq_len, batch_size, _ = x.size() 如果 hx 是 None: hx = torch.zeros(num_layers, batch_size, hidden_size) h_t_minus_1 = hx h_t = hx output = [] for t in range(seq_len): for layer in range(num_layers): h_t[layer] = torch.tanh( x[t] @ weight_ih[layer].T + 偏置_ih[layer] + h_t_minus_1[layer] @ 权重_hh[layer].T + 偏置_hh[layer] ) output.append(h_t[-1]) h_t_minus_1 = h_t output = torch.stack(output) if batch_first: output = output.transpose(0, 1) 返回输出,h_t Args: 输入大小:输入 `x` 中期望的特征数量 隐藏层大小:隐藏状态 `h` 中的特征数量 num_layers:循环层的数量。例如,设置 `num_layers=2` 将意味着将两个 RNN 堆叠起来形成一个`堆叠 RNN`, 第二个 RNN 接收第一个 RNN 的输出并 计算最终结果。默认:1 非线性:要使用的非线性函数。可以是``'tanh'``或``'relu'``。默认:``'tanh'`` 如果为 ``False``,则该层不使用偏置权重 `b_ih` 和 `b_hh`。 默认:``True`` batch_first:如果为 ``True``,则输入和输出张量以(batch,seq,feature)的形式提供。 以 `(batch, seq, feature)` 的形式,而不是 `(seq, batch, feature)`。 注意,此规则不适用于隐藏状态或细胞状态。详细信息请参见下面的输入/输出部分。默认:``False`` 默认:``False`` dropout:如果非零,则在每个输出的基础上引入一个`Dropout`层 RNN 层除了最后一层,具有等于的 dropout 概率 :attr:`dropout`. 默认值:0 双向:如果为 ``True``,则变为双向 RNN。默认:``False`` 输入:输入,hx * **输入**:形状为 :math:`(L, H_{in})` 的张量,用于未批处理的输入, 当 ``batch_first=False`` 时为 :math:`(L, N, H_{in})`, 当 ``batch_first=True`` 时为 :math:`(N, L, H_{in})`,包含特征 输入序列。输入也可以是一个打包的可变长度序列。 请参阅 :func:`torch.nn.utils.rnn.pack_padded_sequence` 或 func:`torch.nn.utils.rnn.pack_sequence` 以获取详细信息。 * **hx**: 形状为 :math:`(D * \text{num\_layers}, H_{out})` 的张量,用于未批处理的输入或 (D * num_layers, N, H_out) 包含初始隐藏状态 状态用于输入序列批次。如未提供,则默认为零。 其中: .. math:: \begin{aligned} N ={} & \text{批量大小} \\ L ={} & 序列长度 \\ D ={} & 2(如果 bidirectional=True 否则 1)\\ H_{in} ={} & 输入大小 \\ H_{out} ={} & 隐藏层大小 \end{aligned} 输出:output, h_n * **output**: 对于非批处理输入,形状为 :math:`(L, D * H_{out})` 的张量 当 `batch_first=False` 时为 `(L, N, D * H_{out})` 当 `batch_first=True` 时为 `(N, L, D * H_{out})`,包含输出特征 对于每个 `t`,从 RNN 的最后一层 `(h_t)` 中提取 如果输入为 `:class:`torch.nn.utils.rnn.PackedSequence`,则输出 也将是一个紧凑的序列。 * **h_n**: 形状为 :math:`(D * \text{num\_layers}, H_{out})` 的张量,用于未批处理的输入或 math:`(D * \text{num\_layers}, N, H_{out})` 包含每个批处理元素的最后隐藏状态 的张量。 属性: weight_ih_l[k]: 第 k 层的可学习输入-隐藏权重, 形状为 `(hidden_size, input_size)` 对于 `k = 0`。否则,形状为 `(hidden_size, num_directions * hidden_size)` weight_hh_l[k]: 第 k 层的可学习隐藏-隐藏权重, 形状为 `(hidden_size, hidden_size)` bias_ih_l[k]: 第 k 层的可学习输入-隐藏偏差, 形状为 `(hidden_size)` bias_hh_l[k]: 第 k 层的可学习隐藏-隐藏偏差, 形状为 `(hidden_size)` .. 注意:: 所有权重和偏置都初始化为 :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` 其中 :math:`k = \frac{1}{\text{hidden\_size}}` .. 注意:: 对于双向 RNN,正向和反向的方向分别是 0 和 1。 当 ``batch_first=False`` 时输出层拆分的示例: ``output.view(seq_len, batch, num_directions, hidden_size)``. .. 注意:: 对于非批处理输入,``batch_first`` 参数将被忽略。 .. include:: ../cudnn_rnn_determinism.rst .. include:: ../cudnn_persistent_rnn.rst 示例: >>> rnn = nn.RNN(10, 20, 2) >>> input = torch.randn(5, 3, 10) >>> h0 = torch.randn(2, 3, 20) >>> output, hn = rnn(input, h0) "源代码" @overload def 初始化( self, 输入大小: int, 隐藏层大小: int, 层数: 整型 = 1, 非线性: 字符串 = 双曲正切, 偏差: 布尔类型 = True, 批量优先: 布尔类型 = 错误, dropout: 浮点数 = 0.0, 双向的: 布尔类型 = 错误, 设备=, 数据类型=, ) -> : ... @overload def 初始化(self, *参数, **kwargs): ... def 初始化(self, *参数, **kwargs): 如果 "proj_size" kwargs: 提升 ValueError( "proj_size 参数仅支持 LSTM,不支持 RNN 或 GRU" ) 如果 长度(参数) > 3: self.非线性 = 参数[3] args = 参数[3] + 参数[4] 否则: self.非线性 = kwargs.弹出(非线性, 双曲正切) 如果 self.非线性 == 双曲正切: 模式 = "RNN_TANH" elif self.非线性 == ReLU: 模式 = "RNN_RELU" 否则: 提升 ValueError( f"未知非线性"{self.非线性}请从 'tanh' 或 'relu' 中选择。 ) 超级().初始化(模式, *参数, **kwargs) @overload @torch._jit_internal.超载方法 # noqa: F811 def 前向( self, 输入: 张量, hx: 可选[张量] = ) -> 元组[张量, 张量]: 通过 @overload @torch._jit_internal.超载方法 # noqa: F811 def 前向( self, 输入: PackedSequence, hx: 可选[张量] = ) -> 元组[PackedSequence, 张量]: 通过 def 前向(self, 输入, hx=): # noqa: F811 self.更新平坦权重() 方向数量 = 2 如果 self.双向的 否则 1 原始输入 = 输入 如果 isinstance(原始输入, PackedSequence): 输入, batch_sizes, 排序索引, 未排序索引 = 输入 最大批量大小 = batch_sizes[0] # 脚本在条件分支中遇到最大批量大小类型不同时会不高兴,所以我们进行复制 如果 hx : hx = 火炬.( self.num_layers * 方向数量, 最大批量大小, self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备, ) 否则: # 每个隐藏状态的批量应与用户认为他/她正在传递的输入序列相匹配。 # 用户认为他/她正在传递的。 hx = self.排列隐藏(hx, 排序索引) 否则: 批处理大小 = 如果 输入.暗淡() not (2, 3): 提升 ValueError( f"RNN:期望输入为 2D 或 3D,但得到 D 张量"{输入.暗淡()}的错误" ) 批处理 = 输入.暗淡() == 3 批处理维度 = 0 如果 self.批量优先 否则 1 如果 not 批处理: 输入 = 输入.展平(批处理维度) 如果 hx not : 如果 hx.暗淡() != 2: 提升 运行时错误( f对于未批处理的 2-D 输入,hx 也应为 2-D,但得到了{hx.暗淡()}-D 张量 ) hx = hx.展平(1) 否则: 如果 hx not hx.暗淡() != 3: 提升 运行时错误( f对于批处理的 3-D 输入,hx 也应该为 3-D,但得到了{hx.暗淡()}-D 张量 ) 最大批量大小 = 输入.尺寸(0) 如果 self.批量优先 否则 输入.尺寸(1) 排序索引 = 未排序索引 = 如果 hx : hx = 火炬.( self.层数 * 方向数量, 最大批量大小, self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备, ) 否则: # 每个隐藏状态的批次应与用户认为他/她正在传递的输入序列相匹配。 # 用户认为他/她正在传递的输入序列相匹配。 hx = self.排序隐藏(hx, 排序索引) 断言 hx not self.检查前向参数(输入, hx, batch_sizes) 断言 self.模式 == RNN_TANH self.模式 == RNN_RELU 如果 批处理大小 : 如果 self.模式 == RNN_TANH: 结果 = _VF.RNN-Tanh( 输入, hx, self._flat_weights, # type: ignore[arg-type] self.偏差, self.层数, self.dropout, self.训练, self.双向的, self.批量优先, ) 否则: 结果 = _VF.RNN-ReLU( 输入, hx, self._flat_weights, # type: ignore[arg-type] self.偏差, self.层数, self.dropout, self.训练, self.双向的, self.批量优先, ) 否则: 如果 self.模式 == RNN_TANH: 结果 = _VF.RNN-Tanh( 输入, batch_sizes, hx, self._flat_weights, # type: ignore[arg-type] self.偏差, self.层数, self.dropout, self.训练, self.双向的, ) 否则: 结果 = _VF.RNN-ReLU( 输入, batch_sizes, hx, self._flat_weights, # type: ignore[arg-type] self.偏差, self.层数, self.dropout, self.训练, self.双向的, ) 输出 = 结果[0] 隐藏 = 结果[1] 如果 isinstance(原始输入, PackedSequence): 输出打包 = PackedSequence( 输出, batch_sizes, 排序索引, 未排序索引 ) 返回 输出打包, self.隐藏排列(隐藏, 未排序索引) 如果 not 批处理: # type: ignore[possibly-undefined] 输出 = 输出.挤压(批处理维度) # type: ignore[possibly-undefined] 隐藏 = 隐藏.挤压(1) 返回 输出, self.排列隐藏(隐藏, 未排序的索引)
# XXX:LSTM 和 GRU 的实现与 RNNBase 不同,这是因为: 我们希望在 TorchScript 中支持 nn.LSTM 和 nn.GRU,以及当前的 TorchScript 状态无法支持 Python 的 Union Type 或 Any Type 因此,TorchScript 的静态类型不允许在 Dict 的值中使用 Function 或 Callable 类型,所以我们不得不单独调用_VF 而不是使用_rnn_impls 2. TorchScript 的静态类型不允许在 Dict 的值中使用 Function 或 Callable 类型 所以我们不得不单独调用_VF 而不是使用_rnn_impls 这只是临时的,处于我们想要实现的过渡状态 确保按时发布 # 更多讨论细节请见 https://github.com/pytorch/pytorch/pull/23266 # TODO:当 TorchScript 移除时,删除 LSTM 和 GRU 的覆盖实现 支持一般性地表达这两个模块。
[文档] 长短期记忆网络(RNNBase): r"__init__(输入大小,隐藏层大小,层数=1,偏置=True,批处理第一=False,dropout=0.0,双向=False,投影大小=0,设备=None,数据类型=None)" 将多层长短期记忆(LSTM)循环神经网络(RNN)应用于输入序列。 对于输入序列中的每个元素,每一层都计算以下内容 函数: .. math:: \begin{array}{ll} \\ \end{array} i_t = σ(W_{ii} x_t + b_{ii} + W_{hi} h_{t-1} + b_{hi}) f_t = σ(W_{if} x_t + b_{if} + W_{hf} h_{t-1} + b_{hf}) g_t = \tanh(W_{ig} x_t + b_{ig} + W_{hg} h_{t-1} + b_{hg}) \\ o_t = \sigma(W_{io} x_t + b_{io} + W_{ho} h_{t-1} + b_{ho}) \\ c_t = f_t \odot c_{t-1} + i_t \odot g_t \\ h_t = o_t \odot \tanh(c_t) \\ \end{array} `h_t` 是时间 `t` 的隐藏状态,`c_t` 是细胞 状态在时间`t`时,:math:`x_t`是时间`t`的输入,:math:`h_{t-1}` 是时间`t-1`层的隐藏状态或初始隐藏状态 状态在时间 `0`,以及 :math:`i_t`,:math:`f_t`,:math:`g_t`, math:`o_t` 是输入、遗忘、细胞和输出门,分别。 math:`σ` 是 sigmoid 函数,而 :math:`⊙` 是 Hadamard 积。 在多层 LSTM 中,第 :math:`l` 层的输入 :math:`x^{(l)}_t` (:math:`l ≥ 2`)是前一层隐藏状态 :math:`h^{(l-1)}_t` 乘以 dropout :math:`\delta^{(l-1)}_t` 其中每个 :math:`\delta^{(l-1)}_t` 是一个伯努利随机变量 变量以概率 :attr:`dropout` 为 :math:`0` 如果指定了 `proj_size > 0`,则将使用具有投影的 LSTM。这将以以下方式改变 LSTM 单元。 首先,:math:`h_t` 的维度将从 ``hidden_size`` 到 ``proj_size``(:math:`W_{hi}` 的维度将相应改变)。 其次,每一层的输出隐藏状态将被一个可学习的投影矩阵相乘::math:`h_t = W_{hr}h_t`。注意,由此产生的结果,LSTM 网络的输出形状也将不同。具体请参见下面的输入/输出部分。 矩阵::math:`h_t = W_{hr}h_t`。请注意,由于这个原因,LSTM 网络的输出形状也将不同。具体请参见下面的输入/输出部分。 LSTM 网络的输出形状也将不同。具体请参见下面的输入/输出部分。 所有变量的维度。更多详情请见 https://arxiv.org/abs/1402.1128。 Args: input_size: 输入 `x` 预期特征的数量 hidden_size: 隐藏状态 `h` 中的特征数量 num_layers: 循环层的数量。例如,设置 ``num_layers=2`` 将意味着将两个 LSTM 堆叠起来形成一个`堆叠 LSTM`, 第二个 LSTM 接收第一个 LSTM 的输出并 计算最终结果。默认:1 偏置:如果为`False`,则该层不使用偏置权重`b_ih`和`b_hh`。 默认:``True`` batch_first:如果为 ``True``,则输入和输出张量以(batch,seq,feature)的形式提供。 以`(batch, seq, feature)`代替`(seq, batch, feature)`。 请注意,此规则不适用于隐藏状态或单元格状态。查看 以下部分为详细信息。默认:``False`` dropout:如果非零,则在每个输出的基础上引入一个`Dropout`层 LSTM 层除了最后一层,具有等于的 dropout 概率 attr:`dropout`。默认值:0 bidirectional:如果为 True,则变为双向 LSTM。默认值:`False` proj_size:如果`> 0`,将使用对应大小投影的 LSTM。默认值:0 输入:输入,(h_0, c_0) * **输入**:形状为 :math:`(L, H_{in})` 的张量,用于非批处理输入, 当 ``batch_first=False`` 时为 :math:`(L, N, H_{in})`, 当 ``batch_first=True`` 时为 :math:`(N, L, H_{in})`,包含特征 输入序列。输入也可以是一个打包的可变长度序列。 请参阅 :func:`torch.nn.utils.rnn.pack_padded_sequence` 或 func:`torch.nn.utils.rnn.pack_sequence` 以获取详细信息。 * **h_0**:对于非批处理输入,形状为 :math:`(D * \text{num\_layers}, H_{out})` 的张量 `(D * num_layers, N, H_out)` 包含的 每个输入序列元素中的初始隐藏状态。 如果未提供 (h_0, c_0),则默认为零。 * **c_0**:形状为 (D * num_layers, H_cell) 的张量,用于未批处理的输入或 `(D * num_layers, N, H_cell)` 包含的 输入序列中每个元素的初始细胞状态。 如果未提供 (h_0, c_0),则默认为零。 其中: .. math:: \begin{aligned} N ={} & \text{批量大小} \\ L ={} & 序列长度 \\ D ={} & 2 \text{ 如果 bidirectional=True 否则 } 1 \\ H_{in} ={} & \text{输入大小} \\ H_{cell} ={} & \text{隐藏层大小} \\ H_{out} ={} & \text{如果 proj\_size}>0 则 proj\_size 否则 hidden\_size} \\ \end{aligned} 输出:输出,(h_n, c_n) * **输出**:对于未批处理的输入,形状为 :math:`(L, D * H_{out})` 的张量, 当 ``batch_first=False`` 时为 :math:`(L, N, D * H_{out})`, 当 ``batch_first=True`` 时为 :math:`(N, L, D * H_{out})`,包含输出特征 来自 LSTM 最后一层的 `(h_t)`,对于每个 `t`。 如果输入为 :class:`torch.nn.utils.rnn.PackedSequence`,输出也将是一个打包序列。当 `bidirectional=True` 时,`output` 将包含序列中每个时间步的正向和反向隐藏状态。 将也会是一个打包序列。当 `bidirectional=True` 时,`output` 将包含序列中每个时间步的正向和反向隐藏状态的拼接。 当 `bidirectional=True` 时,`output` 将包含序列中每个时间步的正向和反向隐藏状态的拼接。 * **h_n**: 形状为 :math:`(D * \text{num\_layers}, H_{out})` 的张量,用于未批处理的输入或 `(D * num_layers, N, H_out)` 包含的 序列中每个元素的最终隐藏状态。当 `bidirectional=True` 时, `h_n` 将包含最终正向和反向隐藏状态的拼接。 * **c_n**: 对于未批处理的输入,形状为 :math:`(D * \text{num\_layers}, H_{cell})` 的张量 math:`(D * \text{num\_layers}, N, H_{cell})` 包含每个序列元素的最终细胞状态。 当 ``bidirectional=True`` 时, `c_n` 将包含最终正向和反向细胞状态的连接。 属性: weight_ih_l[k]:第 k 层的可学习输入-隐藏权重。 `(W_ii|W_if|W_ig|W_io)`,形状为 `(4*hidden_size, input_size)`,对于 `k = 0`。 否则,形状为 `(4*hidden_size, num_directions * hidden_size)`。如果 指定了 ``proj_size > 0``,则形状将为 对于 `k > 0`,形状为 `(4*hidden_size, num_directions * proj_size)` weight_hh_l[k]:第 :math:`\text{k}^{th}` 层的可学习隐藏-隐藏权重 `(W_hi|W_hf|W_hg|W_ho)`,形状为 `(4*hidden_size, hidden_size)`。如果 ``proj_size > 0`` 指定后,形状将为 `(4*hidden_size, proj_size)`。 bias_ih_l[k]:第 :math:`\text{k}^{th}` 层的可学习输入-隐藏偏差 `(b_ii|b_if|b_ig|b_io)`,形状为 `(4*hidden_size)` bias_hh_l[k]:第 :math:`\text{k}^{th}` 层的可学习隐藏-隐藏偏差 `(b_hi|b_hf|b_hg|b_ho)`,形状为`(4*hidden_size)` weight_hr_l[k]:第:math:`k`层的可学习投影权重 形状为`(proj_size, hidden_size)`。仅在`proj_size > 0`时存在。 已指定。 weight_ih_l[k]_reverse: 与 `weight_ih_l[k]` 在反向方向上的类似。 只有当 ``bidirectional=True`` 时才存在。 weight_hh_l[k]_reverse: 与 `weight_hh_l[k]` 在反向方向上的类似。 只有当 ``bidirectional=True`` 时才存在。 bias_ih_l[k]_reverse: 与 `bias_ih_l[k]` 在反向方向上的类似。 仅当 ``bidirectional=True`` 时存在。 bias_hh_l[k]_reverse: 与 `bias_hh_l[k]` 在反向方向上的类似。 仅当 ``bidirectional=True`` 时存在。 weight_hr_l[k]_reverse:与`weight_hr_l[k]`在反向方向上的类似。 仅当指定了`bidirectional=True`和`proj_size > 0`时存在。 .. 注意:: 所有权重和偏置都初始化为:math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` 其中:math:`k = \frac{1}{\text{hidden\_size}}` .. 注意:: 对于双向 LSTM,正向和反向分别对应方向 0 和 1。 当 ``batch_first=False`` 时输出层拆分的示例: 输出视图(seq_len, 批量, 方向数, 隐藏层大小) .. 注意:: 对于双向 LSTMs,`h_n` 不等于 `output` 的最后一个元素 前者包含最终的向前和向后隐藏状态,而后者包含 最终前向隐藏状态和初始反向隐藏状态。 .. 注意:: 对于非批处理输入,"batch_first" 参数被忽略。 .. 注意:: "proj_size" 应小于 "hidden_size"。 .. include:: ../cudnn_rnn_determinism.rst .. 包含 :: ../cudnn_persistent_rnn.rst 示例: >>> rnn = nn.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)) "源代码" @overload def 初始化( self, 输入大小: int, 隐藏层大小: int, 层数: 整型 = 1, 偏差: 布尔类型 = True, 批量优先: 布尔类型 = 错误, dropout: 浮点数 = 0.0, 双向的: 布尔类型 = 错误, 项目大小: 整型 = 0, 设备=, 数据类型=, ) -> : ... @overload def 初始化(self, *参数, **kwargs): ... def 初始化(self, *参数, **kwargs): 超级().初始化(LSTM, *参数, **kwargs) def 获取预期单元格大小( self, 输入: 张量, batch_sizes: 可选[张量] ) -> 元组[int, int, int]: 如果 批处理大小 not : 小批量 = int(batch_sizes[0]) 否则: 小批量 = 输入.尺寸(0) 如果 self.批量优先 否则 输入.尺寸(1) 方向数 = 2 如果 self.双向的 否则 1 预期隐藏层大小 = ( self.层数 * 方向数量, 微批, self.隐藏层大小, ) 返回 预期隐藏层大小 未来我们应该防止 mypy 在这里应用逆变规则 查看 torch/nn/modules/module.py 中的 _forward_unimplemented def 检查前向参数( self, 输入: 张量, 隐藏: 元组[张量, 张量] # 类型:忽略[覆盖] batch_sizes: 可选[张量] ): self.检查输入(输入, batch_sizes) self.检查隐藏层大小( 隐藏[0] self.获取期望的隐藏层大小(输入, batch_sizes), 预期隐藏层[0]大小{},获得{}", ) self.检查隐藏层大小( 隐藏[1] self.获取期望的单元格大小(输入, batch_sizes), 预期隐藏[1]大小{},获得{}", ) 与上面相同,见 torch/nn/modules/module.py::_forward_unimplemented def 排列隐藏( # 类型:忽略[覆盖] self, hx: 元组[张量, 张量] 排列: 可选[张量] ) -> 元组[张量, 张量]: 如果 排列 : 返回 h5 返回 应用置换(hx[0] 排列), 应用排列( hx[1] 排列 ) # 与上面相同,见 torch/nn/modules/module.py::_forward_unimplemented @overload # 类型:忽略[覆盖] @torch._jit_internal.超载方法 # noqa: F811 def 前向( self, 输入: 张量, hx: 可选[元组[张量, 张量]] = ) -> 元组[张量, 元组[张量, 张量]] # noqa: F811 通过 与上述相同,请参阅 torch/nn/modules/module.py::_forward_unimplemented @overload @torch._jit_internal.超载方法 # noqa: F811 def 前向( self, 输入: PackedSequence, hx: 可选[元组[张量, 张量]] = ) -> 元组[PackedSequence, 元组[张量, 张量]] # noqa: F811 通过 def 前向(self, 输入, hx=): # noqa: F811 self.更新平坦权重() 原始输入 = 输入 对于 TorchScript 编译,isinstance 检查需要在条件中进行 批处理大小 = 方向数量 = 2 如果 self.双向的 否则 1 实际隐藏层大小 = self.proj_size 如果 self.proj_size > 0 否则 self.隐藏层大小 如果 isinstance(原始输入, PackedSequence): 输入, batch_sizes, 排序索引, 未排序索引 = 输入 最大批量大小 = batch_sizes[0] 如果 水平方向 : 零填充 = 火炬.( self.层数 * 方向数量, 最大批量大小, 实际隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备, ) c_零 = 火炬.( self.层数 * num_directions, 最大批量大小, self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备, ) 水平方向 = (水平零点, 纵向零点) 否则: 每个隐藏状态的批次应与用户认为他/她正在传递的输入序列相匹配。 用户认为他/她正在传递的输入序列。 hx = self.打乱隐藏状态(hx, 排序索引) 否则: 如果 输入.暗淡() not (2, 3): 提升 ValueError( fLSTM:期望输入为 2D 或 3D,实际得到{输入.暗淡()}而不是 D ) 批处理 = 输入.暗淡() == 3 批处理维度 = 0 如果 self.批量优先 否则 1 如果 not 批处理: 输入 = 输入.展平(批处理维度) 最大批量大小 = 输入.尺寸(0) 如果 self.批量优先 否则 输入.尺寸(1) 排序索引 = 未排序索引 = 如果 hx : h_zeros = 火炬.( self.层数 * num_directions, 最大批量大小, 真实隐藏大小, 数据类型=输入.数据类型, 设备=输入.设备, ) c_零 = 火炬.( self.层数 * num_directions, 最大批量大小, self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备, ) hx = (h_zeros, c_zeros) self.检查前向参数(输入, hx, batch_sizes) 否则: 如果 批处理: 如果 hx[0].暗淡() != 3 hx[1].暗淡() != 3: msg = ( "对于批处理的 3-D 输入,hx 和 cx 也应该" f"也是 3-D 的,但是得到了("{hx[0].暗淡()}-D,{hx[1].暗淡()}-D)张量 ) 提升 运行时错误(信息) 否则: 如果 hx[0].暗淡() != 2 hx[1].暗淡() != 2: msg = ( "对于未分批的 2-D 输入,hx 和 cx 也应该" f"也应该是 2-D 的,但得到了("{hx[0].暗淡()}-D,{hx[1].暗淡()}-D) 张量" ) 提升 运行时错误(信息) hx = (hx[0].展平(1), hx[1].展平(1)) # 每个隐藏状态的批量应与用户认为他/她正在传递的输入序列相匹配。 # 用户认为他/她正在传递的。 self.检查前向参数(输入, hx, batch_sizes) hx = self.隐藏排列(hx, 排序索引) 如果 批处理大小 : 结果 = _VF.lstm( 输入, hx, self.平坦权重, # type: ignore[arg-type] self.偏差, self.层数, self.dropout, self.训练, self.双向的, self.批量优先, ) 否则: 结果 = _VF.lstm( 输入, batch_sizes, hx, self._平面权重, # type: ignore[arg-type] self.偏差, self.层数, self.dropout, self.训练, self.双向的, ) 输出 = 结果[0] 隐藏 = 结果[1] # xxx:isinstance 检查需要放在条件语句中以便 TorchScript 编译 如果 isinstance(原始输入, PackedSequence): 输出打包 = PackedSequence( 输出, batch_sizes, 排序索引, 未排序索引 ) 返回 输出打包, self.隐藏排列(隐藏, 未排序索引) 否则: 如果 not 批处理: # type: ignore[possibly-undefined] 输出 = 输出.挤压(批处理维度) # type: ignore[possibly-undefined] 隐藏 = (隐藏[0].挤压(1), 隐藏[1].挤压(1)) 返回 输出, self.隐藏排列(隐藏, 未排序索引)
[文档] GRU(RNNBase): r"__init__(输入大小,隐藏层大小,层数=1,偏置=True,批处理第一=False,dropout=0.0,双向=False,设备=None,数据类型=None)" 将多层门控循环单元(GRU)RNN 应用于输入序列。 对于输入序列中的每个元素,每一层计算以下函数: 函数: .. math:: \begin{array}{ll} r_t = σ(W_{ir} x_t + b_{ir} + W_{hr} h_{(t-1)} + b_{hr}) z_t = σ(W_{iz} x_t + b_{iz} + W_{hz} h_{(t-1)} + b_{hz}) n_t = tanh(W_{in} x_t + b_{in} + r_t ⊙ (W_{hn} h_{(t-1)}+ b_{hn})) h_t = (1 - z_t) ⊙ n_t + z_t ⊙ h_{(t-1)} \end{array} 在时间`t`,:math:`h_t`是隐藏状态,:math:`x_t`是输入 在时间`t`,:math:`h_{(t-1)}`是层的隐藏状态 在时间`t-1`或时间`0`的初始隐藏状态,以及:math:`r_t`, math:`z_t`,:math:`n_t`分别是重置、更新和新门 σ是 Sigmoid 函数,而⊙是 Hadamard 积。 在多层 GRU 中,第 l 层的输入 x^(l)_t (l≥2)是前一层隐藏状态 h^(l-1)_t 乘以 dropout δ^(l-1)_t,其中每个δ^(l-1)_t 是一个伯努利随机 变量以概率:attr:`dropout`取值为:math:`0`。 Args: 输入大小: 输入 `x` 中期望的特征数量。 隐藏层大小: 隐藏状态 `h` 中的特征数量。 层数数量: 循环层的数量。例如,设置 ``num_layers=2``。 这意味着将两个 GRU 堆叠起来形成一个`堆叠 GRU`, 第二个 GRU 接收第一个 GRU 的输出并 计算最终结果。默认:1 偏置:如果为`False`,则该层不使用偏置权重`b_ih`和`b_hh`。 默认:``True`` batch_first:如果为 ``True``,则输入和输出张量以(batch,seq,feature)的形式提供。 以`(batch, seq, feature)`代替`(seq, batch, feature)`。 请注意,此规则不适用于隐藏状态或单元格状态。查看 以下部分为详细信息。默认:``False`` dropout:如果非零,则在每个输出的基础上引入一个`Dropout`层 GRU 层除了最后一层,dropout 概率相等 attr:`dropout`。默认值:0 bidirectional:如果为 True,则变为双向 GRU。默认值:`False` 输入:input,h_0 * **输入**: 形状为 :math:`(L, H_{in})` 的张量,对于非批处理输入, math:`(L, N, H_{in})` 当 `batch_first=False` 时或 math:`(N, L, H_{in})` 当 `batch_first=True` 时,包含输入序列的特征。 输入也可以是可变长度的打包序列。 查看 :func:`torch.nn.utils.rnn.pack_padded_sequence` 或 func:`torch.nn.utils.rnn.pack_sequence` 以获取详细信息。 * **h_0**: 形状为 :math:`(D * \text{num\_layers}, H_{out})` 或 math:`(D * \text{num\_layers}, N, H_{out})` 包含输入序列的初始隐藏状态。如未提供,则默认为零。 其中: .. math:: \begin{aligned} N ={} & \text{批量大小} \\ \( L ={} \) & \text{序列长度} \\ \( D ={} \) & 2 \text{ 如果 bidirectional=True 否则 } 1 \\ \( H_{in} ={} \) & \text{输入\_大小} \\ H_{out} ={} & 隐藏层大小 \end{aligned} 输出:输出,h_n * **output**: 形状为 :math:`(L, D * H_{out})` 的张量,对于非批处理输入, math:`(L, N, D * H_{out})` 当 ``batch_first=False`` 时 当 `batch_first=True` 时,包含输出特征 `(N, L, D * H_{out})` 来自 GRU 的最后一层的 `(h_t)`,对于每个 `t` 如果输入为 `:class:`torch.nn.utils.rnn.PackedSequence`,输出也将是一个打包序列 将也会是一个打包序列 * **h_n**: 形状为 :math:`(D * \text{num\_layers}, H_{out})` 或 math:`(D * \text{num\_layers}, N, H_{out})` 包含输入序列的最终隐藏状态 属性: weight_ih_l[k]:第 k 层的可学习输入-隐藏权重。 (W_ir|W_iz|W_in),形状为 `(3*hidden_size, input_size)`,对于 `k = 0` 。 否则,形状为 `(3*hidden_size, num_directions * hidden_size)` weight_hh_l[k]:第 :math:`\text{k}^{th}` 层的可学习隐藏-隐藏权重 (W_hr|W_hz|W_hn),形状为 `(3*hidden_size, hidden_size)` bias_ih_l[k]:第 :math:`\text{k}^{th}` 层的可学习输入-隐藏偏置 (b_ir|b_iz|b_in),形状为 `(3*hidden_size)` bias_hh_l[k]:第 :math:`\text{k}^{th}` 层的可学习隐藏-隐藏偏置 (b_hr|b_hz|b_hn),形状为 `(3*hidden_size)` .. 注意:: 所有权重和偏置都初始化为 :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` 其中 :math:`k = \frac{1}{\text{hidden\_size}}` .. 注意:: 双向 GRU 中,正向和反向分别对应方向 0 和 1。 当 ``batch_first=False`` 时输出层拆分的示例: ``output.view(seq_len, batch, num_directions, hidden_size)``. .. 注意:: 对于非批处理输入,``batch_first`` 参数将被忽略。 .. 注意:: 新门 :math:`n_t` 的计算与原始论文和其他框架略有不同。 在原始实现中,在乘以权重矩阵之前,先进行 :math:`r_t` 和前一个隐藏状态 :math:`h_{(t-1)}` 的 Hadamard 积 :math:`(\odot)`。 在原始实现中,在乘以权重矩阵之前,先进行 :math:`r_t` 和前一个隐藏状态 :math:`h_{(t-1)}` 的 Hadamard 积 :math:`(\odot)`。 `W` 和偏置项的添加: .. math:: \begin{aligned} n_t = tanh(W_{in} x_t + b_{in} + W_{hn} ( r_t \odot h_{(t-1)} ) + b_{hn}) \end{aligned} 这与 PyTorch 实现不同,PyTorch 是在 :math:`W_{hn} h_{(t-1)}` 之后进行的 .. math:: \begin{aligned} n_t = tanh(W_{in} x_t + b_{in} + r_t \odot (W_{hn} h_{(t-1)}+ b_{hn})) \end{aligned} 故意这样实现以提高效率。 .. include:: ../cudnn_persistent_rnn.rst 示例: >>> rnn = nn.GRU(10, 20, 2) >>> input = torch.randn(5, 3, 10) >>> h0 = torch.randn(2, 3, 20) 输出,hn = rnn(input, h0) "源代码" @overload def 初始化( self, 输入大小: int, 隐藏层大小: int, 层数: 整型 = 1, 偏差: 布尔类型 = True, 批量优先: 布尔类型 = 错误, dropout: 浮点数 = 0.0, 双向的: 布尔类型 = 错误, 设备=, 数据类型=, ) -> : ... @overload def 初始化(self, *参数, **kwargs): ... def 初始化(self, *参数, **kwargs): 如果 proj_size kwargs: 提升 ValueError( "proj_size 参数仅支持 LSTM,不支持 RNN 或 GRU" ) 超级().初始化(GRU, *参数, **kwargs) @overload # 类型:忽略[覆盖] @torch._jit_internal.超载方法 # noqa: F811 def 前向( self, 输入: 张量, hx: 可选[张量] = ) -> 元组[张量, 张量]: # noqa: F811 通过 @overload @torch._jit_internal.超载方法 # noqa: F811 def 前向( self, 输入: PackedSequence, hx: 可选[张量] = ) -> 元组[PackedSequence, 张量]: # noqa: F811 通过 def 前向(self, 输入, hx=): # noqa: F811 self.更新平坦权重() 原始输入 = 输入 # xxx:isinstance 检查需要放在条件语句中以便 TorchScript 编译 如果 isinstance(原始输入, PackedSequence): 输入, batch_sizes, 排序索引, 未排序索引 = 输入 最大批量大小 = batch_sizes[0] 如果 h5 : 方向数量 = 2 如果 self.双向的 否则 1 h5 = 火炬.( self.层数 * num_directions, 最大批量大小, self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备, ) 否则: # 每个隐藏状态的批量应与用户认为他/她正在传递的输入序列相匹配。 # 用户认为他/她正在传递的。 h5 = self.隐藏排列(hx, 排序索引) 否则: 批处理大小 = 如果 输入.暗淡() not (2, 3): 提升 ValueError( f"GRU: 预期输入为 2D 或 3D,但得到的是"{输入.暗淡()}而不是 D ) 批处理 = 输入.暗淡() == 3 批处理维度 = 0 如果 self.批量优先 否则 1 如果 not 批处理: 输入 = 输入.展平(批处理维度) 如果 h5 not : 如果 hx.暗淡() != 2: 提升 运行时错误( f对于未批处理的 2-D 输入,hx 也应为 2-D,但得到了{hx.暗淡()}-D 张量 ) h5 = hx.展平(1) 否则: 如果 h5 not hx.暗淡() != 3: 提升 运行时错误( f"对于批处理的 3-D 输入,hx 也应该为 3-D,但得到的是"{hx.暗淡()}-D 张量 ) 最大批量大小 = 输入.尺寸(0) 如果 self.批量优先 否则 输入.尺寸(1) 排序索引 = 未排序索引 = 如果 h5 : 方向数量 = 2 如果 self.双向的 否则 1 h5 = 火炬.( self.层数 * num_directions, 最大批量大小, self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备, ) 否则: # 每个隐藏状态的批量应与用户认为他/她正在传递的输入序列相匹配。 # 用户认为他/她正在传递的。 h5 = self.隐藏排列(hx, 排序索引) self.检查前向参数(输入, hx, batch_sizes) 如果 批处理大小 : 结果 = _VF.gru( 输入, hx, self._扁平权重, # type: ignore[arg-type] self.偏差, self.层数, self.dropout, self.训练, self.双向的, self.批量优先, ) 否则: 结果 = _VF.gru( 输入, batch_sizes, hx, self._扁平权重, # type: ignore[arg-type] self.偏差, self.层数, self.dropout, self.训练, self.双向的, ) 输出 = 结果[0] 隐藏 = 结果[1] # xxx:isinstance 检查需要放在条件语句中以便 TorchScript 编译 如果 isinstance(原始输入, PackedSequence): 输出打包 = PackedSequence( 输出, batch_sizes, 排序索引, 未排序索引 ) 返回 输出打包, self.排列隐藏(隐藏, 未排序索引) 否则: 如果 not 批处理: # type: ignore[possibly-undefined] 输出 = 输出.挤压(批处理维度) # type: ignore[possibly-undefined] 隐藏 = 隐藏.挤压(1) 返回 输出, self.隐藏排列(隐藏, 未排序索引)
RNNCellBase(模块): 常量 = [输入大小, 隐藏层大小, 偏置] 输入大小: 整型 隐藏层大小: 整型 偏差: 布尔类型 隐藏层到输入层权重: 张量 weight_hh: 张量 # 警告:bias_ih 和 bias_hh 故意在此未定义。 # 请参阅 https://github.com/pytorch/pytorch/issues/39670 def 初始化( self, 输入大小: int, 隐藏层大小: int, 偏差: 布尔, num_chunks: int, 设备=, 数据类型=, ) -> : 工厂参数 = {"设备": 设备, "dtype": 数据类型} 超级().初始化() self.输入大小 = 输入大小 self.隐藏层大小 = 隐藏层大小 self.bias = bias self.weight_ih = 参数( 火炬.空的((num_chunks: 分块数量 * 隐藏层大小, 输入大小), **工厂参数) ) self.权重_hh = 参数( 火炬.空的((num_chunks: 分块数量 * 隐藏层大小, 隐藏层大小), **工厂参数) ) 如果 偏差: self.偏置_ih = 参数( 火炬.空的(num_chunks: 分块数量 * 隐藏层大小, **工厂参数) ) self.偏置_hh = 参数( 火炬.空的(num_chunks: 分块数量 * 隐藏层大小, **工厂参数) ) 否则: self.注册参数("偏置_ih", ) self.注册参数("偏差_hh", ) self.重置参数() def 额外表示(self) -> 字符串: s = "{输入大小}, {隐藏层大小}" 如果 偏差 self.字典 self.bias not True: s += ", 偏置="{偏置}" 如果 "非线性" self.字典 self.非线性 != 双曲正切: s += 非线性={非线性}" 返回 s.格式(**self.字典) def 重置参数(self) -> : 标准差 = 1.0 / 数学.平方根(self.隐藏层大小) 如果 self.隐藏层大小 > 0 否则 0 权重 self.参数(): 初始化.均匀的(重量, -stdv, stdv)
[文档] RNN 单元(RNNCellBase): r一个具有 tanh 或 ReLU 非线性函数的 Elman RNN 单元。 .. math:: h' = \tanh(W_{ih} x + b_{ih} + W_{hh} h + b_{hh}) 如果 :attr:`nonlinearity` 是 `'relu'`,则使用 ReLU 代替 tanh。 Args: input_size: 输入 `x` 中期望的特征数量 hidden_size: 隐藏状态 `h` 中的特征数量 偏置:如果为`False`,则该层不使用偏置权重`b_ih`和`b_hh`。 默认:``True`` 非线性:要使用非线性函数。可以是 ``'tanh'`` 或 ``'relu'``。默认:``'tanh'`` 输入:input, hidden - **input**:包含输入特征的张量 - **hidden**:包含初始隐藏状态的张量 默认情况下,如果没有提供则设置为 0。 输出:h' - **h'** 的形状为 `(batch, hidden_size)`:包含下一个隐藏状态的张量 对于批处理中的每个元素 形状: 输入::math:`(N, H_{in})` 或 :math:`(H_{in})` 张量,包含输入特征, math:`H_{in}` = `input_size`。 输入::math:`(N, H_{out})` 或 :math:`(H_{out})` 张量,包含初始隐藏状态, math:`H_{out}` = `hidden_size`。如果未提供,默认为零。 - 输出::math:`(N, H_{out})` 或 :math:`(H_{out})` 张量,包含下一个隐藏状态。 属性: weight_ih:可学习的输入-隐藏权重,形状为 `(hidden_size, input_size)` weight_hh:可学习的隐藏-隐藏权重,形状为 `(hidden_size, hidden_size)` bias_ih:可学习的输入-隐藏偏置,形状为`(hidden_size)` bias_hh:可学习的隐藏-隐藏偏置,形状为`(hidden_size)` .. 注意:: 所有权重和偏置都初始化为 :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` 其中 :math:`k = \frac{1}{\text{hidden\_size}}` 示例: >>> rnn = nn.RNNCell(10, 20) >>> input = torch.randn(6, 3, 10) >>> hx = torch.randn(3, 20) >>> output = [] >>> for i in range(6): ... hx = rnn(input[i], hx) ... output.append(hx) "源代码" 常量 = [输入大小, 隐藏层大小, 偏置, 非线性] 非线性: 字符串 def 初始化( self, 输入大小: int, 隐藏层大小: int, 偏差: 布尔类型 = True, 非线性: 字符串 = 双曲正切, 设备=, 数据类型=, ) -> : 工厂参数 = {"设备": 设备, "dtype": 数据类型} 超级().初始化(输入大小, 隐藏层大小, 偏差, num_chunks=1, **工厂参数) self.非线性 = 非线性 def 前向(self, 输入: 张量, hx: 可选[张量] = ) -> 张量: 如果 输入.暗淡() not (1, 2): 提升 ValueError( f"RNNCell:期望输入为 1D 或 2D,实际得到"{输入.暗淡()}而不是 D ) 如果 h5 not hx.暗淡() not (1, 2): 提升 ValueError( f"RNNCell:期望隐藏状态为 1D 或 2D,实际得到"{hx.暗淡()}而不是 D ) 批处理 = 输入.暗淡() == 2 如果 not 批处理: 输入 = 输入.展平(0) 如果 h5 : h5 = 火炬.( 输入.尺寸(0), self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备 ) 否则: h5 = hx.展平(0) 如果 not 批处理 否则 h5 如果 self.非线性 == 双曲正切: 返回 = _VF.rnn_tanh_cell( 输入, hx, self.输入层权重, self.隐藏层权重, self.输入层偏置, self.隐藏层偏置, ) elif self.非线性 == ReLU: 返回 = _VF.RNN-ReLU 单元( 输入, hx, self.输入层权重, self.隐藏层权重, self.输入层偏置, self.隐藏层偏置, ) 否则: 返回 = 输入 # TODO: 当 jit 支持异常流程时删除 提升 运行时错误(f"未知非线性:"{self.非线性}") 如果 not 批处理: 返回 = 返回.挤压(0) 返回 返回
[文档] LSTMCell(RNNCellBase): r"一个长短期记忆(LSTM)单元。" .. math:: \begin{array}{ll} i = σ(W_{ii} x + b_{ii} + W_{hi} h + b_{hi}) \\ f = σ(W_{if} x + b_{if} + W_{hf} h + b_{hf}) g = tanh(W_{ig} x + b_{ig} + W_{hg} h + b_{hg}) o = σ(W_{io} x + b_{io} + W_{ho} h + b_{ho}) c' = f ⊙ c + i ⊙ g h' = o ⊙ tanh(c') \end{array} 其中 :math:`σ` 是 sigmoid 函数,:math:`⊙` 是 Hadamard 积。 Args: 输入大小:输入 `x` 预期特征的数量 隐藏大小:隐藏状态 `h` 中的特征数量 偏置:如果为 ``False``,则该层不使用偏置权重 `b_ih` `b_hh`. 默认值:``True`` 输入:input, (h_0, c_0) - **input** 形状为 `(batch, input_size)` 或 `(input_size)`:包含输入特征的张量 - **h_0** 形状为 `(batch, hidden_size)` 或 `(hidden_size)`:包含初始隐藏状态的张量 - **c_0** 形状为 `(batch, hidden_size)` 或 `(hidden_size)`:包含初始细胞状态的张量 如果 `(h_0, c_0)` 未提供,则 **h_0** 和 **c_0** 默认为零。 输出:(h_1, c_1) - **h_1** 形状为 `(batch, hidden_size)` 或 `(hidden_size)`:包含下一个隐藏状态的张量 - **c_1** 的形状为 `(batch, hidden_size)` 或 `(hidden_size)`:包含下一个细胞状态的张量 属性: weight_ih:可学习的输入-隐藏权重,形状为 `(4*hidden_size, input_size)` weight_hh:可学习的隐藏-隐藏权重,形状为 `(4*hidden_size, hidden_size)` bias_ih: 可学习的输入-隐藏偏置,形状为 `(4*hidden_size)` bias_hh: 可学习的隐藏-隐藏偏置,形状为 `(4*hidden_size)` .. 注意:: 所有权重和偏置都初始化为 :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` 其中 :math:`k = \frac{1}{\text{hidden\_size}}` 在某些 ROCm 设备上,当使用 float16 输入时,此模块将使用:ref:`不同精度`进行反向操作。 示例: >>> rnn = nn.LSTMCell(10, 20) # (input_size, hidden_size) >>> input = torch.randn(2, 3, 10) # (时间步长,批量,输入大小) >>> hx = torch.randn(3, 20) # (批量,隐藏层大小) >>> cx = torch.randn(3, 20) >>> output = [] >>> for i in range(input.size()[0]): ... hx, cx = rnn(input[i], (hx, cx)) ... output.append(hx) >>> output = torch.stack(output, dim=0) "源代码" def 初始化( self, 输入大小: int, 隐藏层大小: int, 偏差: 布尔类型 = True, 设备=, 数据类型=, ) -> : 工厂参数 = {"设备": 设备, "dtype": 数据类型} 超级().初始化(输入大小, 隐藏层大小, 偏差, num_chunks=4, **工厂参数) def 前向( self, 输入: 张量, hx: 可选[元组[张量, 张量]] = ) -> 元组[张量, 张量]: 如果 输入.暗淡() not (1, 2): 提升 ValueError( fLSTMCell:期望输入为 1D 或 2D,实际得到{输入.暗淡()}而不是 D ) 如果 h5 not : 索引, value 列举(hx): 如果 .暗淡() not (1, 2): 提升 ValueError( fLSTMCell:期望 hx[{索引}]为 1D 或 2D,实际得到{.暗淡()}而不是 D ) 批处理 = 输入.暗淡() == 2 如果 not 批处理: 输入 = 输入.展平(0) 如果 h5 : 零值 = 火炬.( 输入.尺寸(0), self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备 ) hx = (, ) 否则: hx = (hx[0].展平(0), hx[1].展平(0)) 如果 not 批处理 否则 h5 返回 = _VF.LSTM 单元( 输入, hx, self.输入层权重, self.隐藏层权重, self.输入层偏置, self.隐藏层偏置, ) 如果 not 批处理: 返回 = (返回[0].挤压(0), 返回[1].挤压(0)) 返回 返回
[文档] GRU 单元(RNNCellBase): r"""门控循环单元(GRU)单元。""" .. math:: \begin{array}{ll} r = σ(W_{ir} x + b_{ir} + W_{hr} h + b_{hr}) z = σ(W_{iz} x + b_{iz} + W_{hz} h + b_{hz}) n = tanh(W_{in} x + b_{in} + r ⊙ (W_{hn} h + b_{hn})) h' = (1 - z) ⊙ n + z ⊙ h \end{array} 其中 :math:`σ` 是 sigmoid 函数,:math:`⊙` 是 Hadamard 积。 Args: 输入大小:输入 `x` 预期特征的数量 隐藏大小:隐藏状态 `h` 中的特征数量 偏置:如果为 ``False``,则该层不使用偏置权重 `b_ih` `b_hh`. 默认:``True`` 输入:input, 隐藏 - **input**:包含输入特征的张量 - **hidden**:包含初始隐藏状态的张量 批量中每个元素的当前状态。 如果未提供,则默认为零。 输出:h' - **h'**:包含下一个隐藏状态的张量 批量中的每个元素 形状: - 输入::math:`(N, H_{in})` 或 :math:`(H_{in})` 张量,包含输入特征 math:`H_{in}` = 输入大小。 - 隐藏层::math:`(N, H_{out})` 或 :math:`(H_{out})` 张量,包含初始隐藏状态 状态,其中 :math:`H_{out}` = `hidden_size`。如果未提供,则默认为零。 输出::math:`(N, H_{out})` 或 :math:`(H_{out})` 张量,包含下一个隐藏状态。 属性: weight_ih:可学习的输入-隐藏权重,形状为 `(3*hidden_size, input_size)` weight_hh:可学习的隐藏-隐藏权重,形状为 `(3*hidden_size, hidden_size)` bias_ih:可学习的输入-隐藏偏置,形状为`(3*hidden_size)` bias_hh:可学习的隐藏-隐藏偏置,形状为`(3*hidden_size)` .. 注意:: 所有权重和偏置都初始化为 :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` 其中 :math:`k = \frac{1}{\text{hidden\_size}}` 在某些 ROCm 设备上,当使用 float16 输入时,此模块将使用:ref:`不同精度`进行反向操作。 示例: >>> rnn = nn.GRUCell(10, 20) >>> input = torch.randn(6, 3, 10) >>> hx = torch.randn(3, 20) >>> output = [] >>> for i in range(6): ... hx = rnn(input[i], hx) ... output.append(hx) "源代码" def 初始化( self, 输入大小: int, 隐藏层大小: int, 偏差: 布尔类型 = True, 设备=, 数据类型=, ) -> : 工厂参数 = {"设备": 设备, "dtype": 数据类型} 超级().初始化(输入大小, 隐藏层大小, 偏差, num_chunks=3, **工厂参数) def 前向(self, 输入: 张量, hx: 可选[张量] = ) -> 张量: 如果 输入.暗淡() not (1, 2): 提升 ValueError( fGRUCell:期望输入为 1D 或 2D,实际得到{输入.暗淡()}而不是 D ) 如果 hx not hx.暗淡() not (1, 2): 提升 ValueError( fGRUCell:期望隐藏状态为 1D 或 2D,实际得到{hx.暗淡()}而不是 D ) 批处理 = 输入.暗淡() == 2 如果 not 批处理: 输入 = 输入.展平(0) 如果 hx : hx = 火炬.( 输入.尺寸(0), self.隐藏层大小, 数据类型=输入.数据类型, 设备=输入.设备 ) 否则: 水平方向 = hx.展平(0) 如果 not 批处理 否则 水平方向 返回 = _VF.gru 单元( 输入, hx, self.weight_ih, self.weight_hh, self.偏差_ih, self.偏差_hh, ) 如果 not 批处理: 返回 = 返回.挤压(0) 返回 返回

© 版权所有 PyTorch 贡献者。

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

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源