torch.nn.modules.transformer 的源代码
# mypy: 允许未类型化定义
导入
复制
导入
警告
来自
打字
导入
任意,
可调用,
可选,
联合
导入
火炬
导入 torch.nn.functional
作为 F
来自
火炬
导入
张量
来自 torch.nn.init
导入 xavier_uniform_
来自
.激活
导入
多头注意力
来自
.容器
导入
模块列表
来自 .dropout
导入 Dropout
来自 .linear
导入
线性
来自
.模块
导入
模块
来自
.归一化
导入
层归一化
__all__ = [
变换器,
"Transformer 编码器",
"Transformer 解码器",
"Transformer 编码器层",
"Transformer 解码器层",
]
def _生成正方形后续掩码(
大小: int,
设备:
可选[
火炬.
设备] =
无,
数据类型:
可选[
火炬.
数据类型] =
无,
) -> 张量:
r"生成序列的正方形因果掩码。"
遮蔽的位置用 float('-inf') 填充。未遮蔽的位置用 float(0.0) 填充。
"源代码"
返回
火炬.
三角形(
火炬.full((
大小,
大小), float(
-无穷大),
数据类型=
数据类型,
设备=
设备),
对角线=1,
)
def _get_seq_len(源:
张量,
批量优先:
布尔) ->
可选[int
]:
如果
源.
是嵌套的:
返回
无
否则:
src_size = 源.
尺寸()
如果
长度(src_size) == 2:
# 未分批: S, E
返回
源大小[0]
否则:
# 分批: B, S, E 如果 batch_first 则为 S, B, E
序列长度位置 = 1
如果
批量优先
否则 0
返回
源大小[
序列长度位置]
[文档]
类 Transformer(
模块):
r“一个 Transformer 模型。”
.. 注意::
请参阅此教程 了解 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块深入讨论。
有关 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块的深入讨论,请参阅。
Transformer 层。
用户能够根据需要修改属性。架构
基于论文《Attention Is All You Need 》。
Args:
d_model:编码器/解码器输入中期望的特征数量(默认=512)。
nhead:多头注意力模型中的头数(默认=8)。
num_encoder_layers: 编码器中子编码层的数量(默认=6)。
num_decoder_layers: 解码器中子解码层的数量(默认=6)。
dim_feedforward: 前馈网络模型的维度(默认=2048)。
dropout: dropout 值(默认=0.1)。
激活函数:编码器/解码器中间层的激活函数,可以是字符串
("relu" 或 "gelu") 或一元可调用函数。默认:relu
custom_encoder:自定义编码器(默认=None)。
custom_decoder:自定义解码器(默认=None)。
layer_norm_eps:层归一化组件中的 eps 值(默认=1e-5)。
batch_first:如果为 ``True``,则输入和输出张量以(batch,seq,feature)的形式提供。
默认:``False``(seq,batch,feature)。
norm_first:如果为 True,编码器和解码器层将在其他注意力和前馈操作之前执行 LayerNorms,否则之后。默认:False(之后)。
bias:如果设置为 False,`Linear`和`LayerNorm`层将不会学习一个加性偏置。
bias:如果设置为 False,`Linear`和`LayerNorm`层将不会学习一个加性偏置。
偏置。默认:``True``。
示例:
>>> transformer_model = nn.Transformer(nhead=16, num_encoder_layers=12)
>>> src = torch.rand((10, 32, 512))
>>> tgt = torch.rand((20, 32, 512))
>>> out = transformer_model(src, tgt)
注意:有关应用 nn.Transformer 模块进行词语言模型的完整示例
https://github.com/pytorch/examples/tree/master/word_language_model
"源代码"
def 初始化(
self,
d_model: 整型 = 512,
nhead: 整型 = 8,
编码器层数:
整型 = 6,
解码器层数:
整型 = 6,
前馈维度:
整型 = 2048,
dropout: 浮点数 = 0.1,
激活:
联盟[
字符串,
可调用[[
张量
]
张量]] = F.relu,
自定义编码器:
可选[
任意] =
无,
自定义解码器:
可选[
任意] =
无,
层归一化 epsilon:
浮点数 =
0.00001,
批量优先:
布尔类型 =
错误,
归一化优先:
布尔类型 =
错误,
偏差:
布尔类型 = True,
设备=
无,
数据类型=
无,
) -> 无:
工厂参数 = {
"设备":
设备, "dtype":
数据类型}
超级().
初始化()
火炬._C._log_api_usage_once(f
torch.nn.modules.{self.
类.__name__}")
如果
自定义编码器
是 not
无:
self.编码器 =
自定义编码器
否则:
编码层 =
Transformer 编码器层(
d_model,
nhead,
dim_feedforward,
dropout,
激活,
层归一化 epsilon,
批量优先,
首先归一化,
偏差,
**工厂参数,
)
编码器归一化 =
层归一化(
d 模型, eps=
层归一化 epsilon,
偏差=
偏差, **
工厂参数
)
self.编码器 =
Transformer 编码器(
编码层,
编码层数,
编码器归一化
)
如果
自定义解码器
是 not
无:
self.解码器 =
自定义解码器
否则:
解码层 =
Transformer 解码层(
d 模型,
n 头,
dim_feedforward,
dropout,
激活,
层归一化 eps,
批量优先,
标准第一,
偏差,
**工厂参数,
)
解码器标准 =
层归一化(
d 模型, eps=
层归一化 epsilon,
偏差=
偏差, **
工厂参数
)
self.解码器 =
Transformer 解码器(
解码器层,
解码器层数量,
解码器归一化
)
self._重置参数()
self.模型维度 =
模型维度
self.头数 = nhead
self.批量优先 =
批量优先
[文档] def
前向(
self,
源:
张量,
目标:
张量,
src_mask: 可选[
张量] =
无,
tgt_mask: 可选[
张量] =
无,
memory_mask: 可选[
张量] =
无,
源_key_padding_mask:
可选[
张量] =
无,
目标_key_padding_mask:
可选[
张量] =
无,
内存_key_padding_mask:
可选[
张量] =
无,
源是否因果:
可选[
布尔] =
无,
tgt_is_causal: 可选[
布尔] =
无,
memory_is_causal: 布尔类型 =
错误,
) -> 张量:
r"接收并处理掩码的源/目标序列。"
.. 注意::
如果提供了任何[src/tgt/memory]_mask 参数的布尔张量,则位置值为``True``的位置
不允许参与注意力机制,
这与 :attr:`attn_mask` 的定义相反。
在 :func:`torch.nn.functional.scaled_dot_product_attention` 中。
Args:
src: 发送到编码器的序列(必需)。
解码器序列(必需)。
源序列的加性掩码(可选)。
目标序列的加性掩码(可选)。
编码器输出的加性掩码(可选)。
src_key_padding_mask:每个批次的 src 键的 Tensor 掩码(可选)。
tgt_key_padding_mask:每个批次的 tgt 键的 Tensor 掩码(可选)。
memory_key_padding_mask:每个批次的 memory 键的 Tensor 掩码(可选)。
src_is_causal:如果指定,则将因果掩码应用于 src_mask。
默认:``None``;尝试检测因果掩码。
警告:
``src_is_causal`` 提供了 ``src_mask`` 是的提示。
因果掩码。提供错误的提示可能导致结果不正确。
包括前向和反向传播在内的执行错误。
兼容性。
tgt_is_causal:如果指定,则将因果掩码应用于 ``tgt_mask``。
默认:``None``;尝试检测因果掩码。
警告:
``tgt_is_causal`` 提供了 ``tgt_mask`` 是的提示。
因果掩码。提供错误的提示可能会导致。
包括前向和反向传播在内的执行错误。
兼容性。
memory_is_causal:如果指定,则应用因果掩码。
``memory_mask``.
默认:``False``。
警告:
``memory_is_causal`` 提供了一个提示,
``memory_mask`` 是因果掩码。提供错误的提示
可能会导致执行错误,包括
前向和后向兼容性。
形状:
- src: :math:`(S, E)` 对于非批处理输入,如果 `batch_first=False` 则为 :math:`(S, N, E)`
`(N, S, E)` 如果 `batch_first=True`。
- tgt: :math:`(T, E)` 对于非批处理输入,如果 `batch_first=False` 则为 :math:`(T, N, E)`
`(N, T, E)` 如果 `batch_first=True`。
- 源掩码::math:`(S, S)` 或 :math:`(N·text{num\_heads}, S, S)`。
- 目标掩码::math:`(T, T)` 或 :math:`(N·text{num\_heads}, T, T)`。
- 内存掩码::math:`(T, S)`。
- src_key_padding_mask: 对于未批处理的输入为 :math:`(S)`,否则为 :math:`(N, S)`。
- tgt_key_padding_mask: 对于未批处理的输入为 :math:`(T)`,否则为 :math:`(N, T)`。
- memory_key_padding_mask: 对于未批处理的输入为 :math:`(S)`,否则为 :math:`(N, S)`。
注意:[src/tgt/memory]_mask 确保位置 :math:`i` 可以访问未掩码的
如果提供 BoolTensor,则位置与``True``相关。
在此情况下不允许参加,而 ``False`` 值将保持不变。如果提供一个浮点张量,
它将被添加到注意力权重中。
[src/tgt/memory]_key_padding_mask 提供指定元素在键中要忽略
注意。如果提供了一个 BoolTensor,则保留原文不变。
值为 ``True`` 的位置将被忽略,而值为 ``False`` 的位置将保持不变。
输出:对于非批处理输入,输出为::math:`(T, E)`;如果 `batch_first=False`,则输出为::math:`(T, N, E)`
`(N, T, E)` 如果 `batch_first=True`。
注意:由于 Transformer 模型中的多头注意力架构,
Transformer 的输出序列长度与输入序列长度相同
(即目标)解码器的长度。
源序列长度,T 为目标序列长度,N 是
批处理大小,:math:`E` 是特征数量
示例:
>>> # xdoctest: +SKIP
>>> 输出 = transformer_model(src, tgt, src_mask=src_mask, tgt_mask=tgt_mask)
"源代码"
批处理 =
源.
暗淡() == 3
如果 not self.
批量优先
和
源.
尺寸(1) !=
目标.
尺寸(1)
和
批处理:
提升
运行时错误(
"源和目标的批处理数量必须相等")
elif self.批量优先
和
源.
尺寸(0) !=
目标.
尺寸(0)
和
批处理:
提升
运行时错误(
源和目标的批次号必须相等)
如果
源.
尺寸(-1) != self.d_model
或
目标.
尺寸(-1) != self.d_model:
提升
运行时错误(
"源和目标的特征数必须等于 d_model"
)
内存 = self.
编码器(
源,
遮罩=
源掩码,
源键控掩码=
源关键填充掩码,
因果=
源是否因果,
)
输出 = self.
解码器(
目标,
内存,
目标掩码=
目标掩码,
内存掩码=
内存掩码,
tgt_key_padding_mask=tgt_key_padding_mask,
memory_key_padding_mask=memory_key_padding_mask,
目标是因果的=
目标是因果的,
内存是因果的=
内存是因果的,
)
返回
输出
[文档] @staticmethod
def 生成平方后续掩码(
sz: int,
device: Optional[torch.device] = None,
dtype: Optional[torch.dtype] = None,
) -> Tensor:
r"""生成序列的平方因果掩码。
掩码位置填充为 float('-inf')。未掩码位置填充为 float(0.0)。
"""
返回 _generate_square_subsequent_mask(sz, dtype=dtype, device=device)
def _重置参数(self):
r"""在 Transformer 模型中初始化参数。"""
为 p
在 self.
参数():
如果 p.
暗淡() > 1:
xavier_uniform_(p)
[文档]
类
Transformer 编码器(
模块):
r"""Transformer 编码器是由 N 个编码层堆叠而成的。"""
.. 注意::
请参阅此教程 了解 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块深入讨论。
有关 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块的深入讨论,请参阅。
Transformer 层。
用户可以使用相应的参数构建 BERT(https://arxiv.org/abs/1810.04805)模型。
Args:
encoder_layer: TransformerEncoderLayer() 类的一个实例(必需)。
num_layers: 编码器中子编码器层的数量(必需)。
norm: 层归一化组件(可选)。
enable_nested_tensor: 如果为 True,输入将自动转换为嵌套张量
(并在输出时转换回来)。这将提高整体性能。
当填充率较高时,TransformerEncoder 的性能。默认:``True``(启用)。
示例:
>>> 编码器层 = nn.TransformerEncoderLayer(d_model=512, nhead=8)
>>> transformer_encoder = nn.TransformerEncoder(编码器层, num_layers=6)
>>> src = torch.rand(10, 32, 512)
>>> out = transformer_encoder(src)
"源代码"
常量 = ["norm"]
def 初始化(
self,
编码器层:
"Transformer 编码器层",
层数: int,
归一化:
可选[
模块] =
无,
启用嵌套张量:
布尔类型 = True,
遮罩检查:
布尔类型 = True,
) -> 无:
超级().
初始化()
火炬._C._log_api_usage_once(f
torch.nn.modules.{self.
类.__name__}")
self.层 =
获取副本(
编码器层,
层数)
self.层数 =
层数
self.标准 =
标准
# 此属性保存对象构造时提供的值
self.启用嵌套张量 =
启用嵌套张量
# 此属性控制是否使用嵌套张量
self.使用嵌套张量 =
启用嵌套张量
self.面具检查 =
面具检查
编码层 =
编码层
为什么不使用稀疏快速路径 =
请提供需要翻译的文本
如果 not isinstance(
编码层,
火炬.nn.
Transformer 编码层):
为什么不使用稀疏性快速路径 = f"{
编码层}
不是 TransformerEncoderLayer
elif 编码器层.
首先归一化:
为什么不使用稀疏快速路径 = f"{
编码层}
.norm_first 为 True
elif not 编码器层.
自注意力机制.
批量优先:
为什么不使用稀疏性快速路径 = (
f"{编码层}
.self_attn.batch_first" 不为 True
+ "(使用 batch_first 以获得更好的推理性能)"
)
elif not 编码层.
自注意力机制._qkv_same_embed_dim:
为什么不使用稀疏性快速路径 = (
f"{编码层}
.self_attn._qkv_same_embed_dim 不为 True
)
elif 编码器层.self_attn.in_proj_bias
是
无:
为什么不使用稀疏性快速路径 = f"{
编码层}
.self_attn"传递了 bias=False
elif not 编码器层.
激活函数 relu 或 geLU:
为什么不使用稀疏快速路径 = (
f"{编码层}
.激活函数 relu 或 geLU" 不为 True
)
elif not (编码器层.norm1.eps ==
编码器层.norm2.eps):
为什么不使用稀疏快速路径 = (
f"{编码层}
.norm1.eps 不等于{
编码层}.norm2.eps"
)
elif 编码层.
自注意力机制.
头数 % 2 == 1:
为什么不使用稀疏性快速路径 = f"{
编码层}
.self_attn.num_heads 是奇数
如果
启用嵌套张量
和
为什么不使用稀疏快速路径:
warnings.警告(
f"enable_nested_tensor 为 True,但 self.use_nested_tensor 为 False 因为"{
为什么不使用稀疏快速路径}"
)
self.使用嵌套张量 =
假
[文档] def
前向(
self,
源:
张量,
遮罩:
可选[
张量] =
无,
源键填充掩码:
可选[
张量] =
无,
因果:
可选[
布尔] =
无,
) -> 张量:
r依次将输入通过编码器层。
Args:
src:编码器的序列(必需)。
mask:源序列的掩码(可选)。
src_key_padding_mask:每个批次的源键掩码(可选)。
如果指定,则应用因果掩码作为“mask”。
默认:`None`;尝试检测因果掩码。
警告:
`is_causal` 提供了一个提示,表明“mask”是
因果掩码。提供错误的提示可能会导致
包括前向和反向传播在内的执行错误。
兼容性。
形状:
请参阅 `torch.nn.Transformer` 的文档。
"源代码"
src_key_padding_mask = F._规范掩码(
遮罩=src_key_padding_mask,
面具名称="src_key_padding_mask",
其他类型=F.
_无或数据类型(
遮罩),
其他名称="mask",
目标类型=
源.
数据类型,
)
遮罩 = F.
_规范掩码(
遮罩=
遮罩,
面具名称=
面具,
其他类型=
无,
其他名称="",
目标类型=
源.
数据类型,
检查其他=
错误,
)
输出 =
源
转换为嵌套 =
假
第一层 = self.
层[0]
层级源键填充掩码 =
源键填充掩码
为什么不使用稀疏性快速路径 =
请提供需要翻译的文本
第一层字符串 = "self.layers[0]"
批量优先 =
第一层.self_attn.
批量优先
是否启用快速路径 =
火炬.
后端.mha.get_fastpath_enabled()
如果 not is_fastpath_enabled:
为什么不使用稀疏路径快速路径 = (
"torch.backends.mha.get_fastpath_enabled() 不是 True"
)
elif not 有属性(self,
使用嵌套张量):
为什么不使用稀疏快速路径 =
"使用嵌套张量" 属性不存在
elif not self.使用嵌套张量:
为什么不使用稀疏快速路径 = (
"self.use_nested_tensor(在初始化中设置)不为 True"
)
elif 第一层.
训练:
为什么不使用稀疏快速路径 = f"{
第一层}
处于训练模式"
elif not 源.
暗淡() == 3:
为什么不使用稀疏快速路径 = (
f输入未分批;期望 src.dim()为 3,但得到{
源.
暗淡()}"
)
elif src_key_padding_mask 是
无:
why_not_sparsity_fast_path = "src_key_padding_mask 为 None"
elif (
(not 有属性(self,
"掩码检查"))
或 self.
面具检查
) 和 not
火炬.
从面具左对齐构建嵌套张量(
源, src_key_padding_mask.
逻辑非()
):
why_not_sparsity_fast_path = "mask_check 已启用,且 src 和 src_key_padding_mask 未左对齐"
elif 输出.
是嵌套的:
why_not_sparsity_fast_path = "嵌套张量输入不受支持"
elif 遮罩
是 not
无:
为什么不支持稀疏快速路径 = (
"同时提供了 src_key_padding_mask 和 mask"
)
elif 火炬.is_autocast_enabled():
为什么不支持稀疏快速路径 =
自动转换已启用
如果 not
为什么不使用稀疏快速路径:
张量参数 = (
源,
第一层.
自注意力.
输入投影权重,
第一层.
自注意力机制.
输入投影偏置,
第一层.
自注意力机制.out_proj.
重量,
第一层.
自注意力.out_proj.
偏差,
第一层.
规范 1.
重量,
第一层.
标准化 1.
偏差,
第一层.
标准化 2.
重量,
第一层.norm2.
偏差,
第一层.
线性 1.
重量,
第一层.
线性 1.
偏差,
第一层.
线性 2.
重量,
第一层.
线性 2.
偏差,
)
支持的设备类型 = [
"cpu",
cuda,
火炬.
工具.
后端注册.
_私有用途 1 后端名称,
]
如果
火炬.
覆盖.
有 torch 功能(tensor_args):
为什么不使用稀疏快速路径 =
"某些张量参数有 torch_function 函数"
elif 源.
设备.
类型 not
在
支持的设备类型:
为什么不使用稀疏性快速路径 = (
f"源设备既不是以下支持的设备类型之一"{
_支持的设备类型}"
)
elif 火炬.
梯度是否启用()
和
任何(x.requires_grad
为 x
在 tensor_args):
为什么不使用稀疏快速路径 = (
梯度已启用,且查询或其中至少一个已启用
输入/输出投影权重或偏置需要梯度
)
如果 (not
为什么不使用稀疏快速路径)
和 (
源键填充掩码
是 not
无):
转换为嵌套结构 =
真实
输出 =
火炬.
从掩码中获取嵌套张量(
输出,
源键填充掩码.
逻辑非(),
掩码检查=
假
)
层的源键填充掩码 =
无
序列长度 =
获取序列长度(
源,
批量优先)
是因果的 =
检测因果掩码(
遮罩,
因果,
序列长度)
为
修饰
在 self.
层:
输出 =
模块(
输出,
源掩码=
遮罩,
因果=
因果,
src_key_padding_mask=src_key_padding_mask_for_layers,
)
如果 convert_to_nested:
输出 =
输出.
转换为填充张量(0.0,
源.
尺寸())
如果 self.
标准
是 not
无:
输出 = self.
归一化(
输出)
返回
输出
[文档]
类 TransformerDecoder(
模块):
rTransformerDecoder 是由 N 个解码器层堆叠而成的。
.. 注意::
请参阅此教程 了解 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块深入讨论。
有关 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块的深入讨论,请参阅。
Transformer 层。
Args:
decoder_layer:TransformerDecoderLayer() 类的实例(必需)。
num_layers:解码器中子解码器层的数量(必需)。
norm:层归一化组件(可选)。
示例:
>>> decoder_layer = nn.TransformerDecoderLayer(d_model=512, nhead=8)
>>> transformer_decoder = nn.TransformerDecoder(decoder_layer, num_layers=6)
>>> memory = torch.rand(10, 32, 512)
>>> tgt = torch.rand(20, 32, 512)
>>> out = transformer_decoder(tgt, memory)
"源代码"
常量 = ["norm"]
def 初始化(
self,
解码器层:
"Transformer 解码器层",
层数: int,
归一化:
可选[
模块] =
无,
) -> 无:
超级().
初始化()
火炬._C._log_api_usage_once(f
"torch.nn.modules."{self.
类.__name__}")
self.层 =
_获取副本(
解码层,
层数)
self.层数 =
层数
self.标准 =
标准
[文档] def
前向(
self,
目标:
张量,
内存:
张量,
目标掩码:
可选[
张量] =
无,
内存掩码:
可选[
张量] =
无,
目标键填充掩码:
可选[
张量] =
无,
内存键填充掩码:
可选[
张量] =
无,
tgt_is_causal: 可选[
布尔] =
无,
memory_is_causal: 布尔类型 =
错误,
) -> 张量:
r依次将输入(和掩码)通过解码器层传递。
Args:
tgt: 传递给解码器的序列(必需)。
内存:编码器最后一层的序列(必需)。
tgt_mask:目标序列的掩码(可选)。
memory_mask:内存序列的掩码(可选)。
tgt_key_padding_mask:每个批次的 tgt 键的掩码(可选)。
memory_key_padding_mask:每个批次的内存键的掩码(可选)。
tgt_is_causal:如果指定,则将因果掩码应用于 tgt 掩码。
默认:`None`;尝试检测因果掩码。
警告:
``tgt_is_causal`` 提供了一个提示,表明 ``tgt_mask`` 是
因果掩码。提供错误的提示可能会导致
包括前向和反向传播在内的执行错误。
兼容性。
memory_is_causal: 如果指定,则应用因果掩码作为
``内存掩码``。
默认:``False``。
警告:
``memory_is_causal`` 提供了一个提示,
``memory_mask`` 是因果掩码。提供错误提示可能导致执行错误,包括
前向和后向兼容性。
。
形状:
请参阅 :class:`~torch.nn.Transformer` 中的文档。
"源代码"
输出 =
目标
序列长度 = _get_seq_len(
目标, self.
层[0].self_attn.
批量优先)
目标是因果 =
检测是否因果掩码(
目标掩码,
目标是因果,
序列长度)
为
修饰
在 self.
层:
输出 =
模块(
输出,
内存,
目标掩码=
目标掩码,
内存掩码=
内存掩码,
目标键填充掩码=
目标键填充掩码,
memory_key_padding_mask=memory_key_padding_mask,
tgt_is_causal=tgt_is_causal,
记忆是因果的=
记忆是因果的,
)
如果 self.
标准
是 not
无:
输出 = self.
归一化(
输出)
返回
输出
[文档]
类
Transformer 编码器层(
模块):
rTransformer 编码器层由自注意力机制和前馈网络组成。
.. 注意::
请参阅此教程 了解 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块深入讨论。
有关 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块的深入讨论,请参阅。
Transformer 层。
该标准编码层基于论文《Attention Is All You Need 》。
用户可以在应用中对其进行修改或以不同的方式实现。
TransformerEncoderLayer 可以处理传统的 torch.tensor 输入,
或者嵌套张量输入。派生类应类似地接受
两种输入格式。(目前并非所有输入组合都由 TransformerEncoderLayer 支持,而嵌套张量仍在原型阶段。)
如果您正在实现自定义层,您可以从中派生它。
(状态。)
如果您正在实现自定义层,您可以从中派生它。
模块或 TransformerEncoderLayer 类。如果您自定义的层
支持 torch.Tensors 和嵌套张量输入,使其
实现一个 TransformerEncoderLayer 的派生类。如果您自定义
层只支持 torch.Tensor 输入,从其实现中派生
模块。
Args:
d_model:输入中期望的特征数量(必需)。
nhead:多头注意力模型中的头数(必需)。
dim_feedforward:前馈网络模型的维度(默认=2048)。
dropout:丢弃率(默认=0.1)。
activation:中间层的激活函数,可以是字符串
("relu" 或 "gelu")或一元可调用对象。默认:relu
layer_norm_eps:层归一化组件中的 eps 值(默认=1e-5)。
batch_first:如果为 ``True``,则输入和输出张量以(batch,seq,feature)的形式提供。
默认:``False``(seq,batch,feature)。
norm_first: 如果为 ``True``,则先进行层归一化,然后再进行注意力和前馈
操作,分别。否则在之后完成。默认:``False``(之后)。
偏差:如果设置为“False”,则“线性”和“层归一化”层将不会学习加性
偏差。默认:``True``。
示例:
>>> 编码器层 = nn.TransformerEncoderLayer(d_model=512, nhead=8)
>>> src = torch.rand(10, 32, 512)
>>> out = encoder_layer(src)
或者,当 ``batch_first`` 为 ``True`` 时:
>>> 编码器层 = nn.TransformerEncoderLayer(d_model=512, nhead=8, batch_first=True)
>>> src = torch.rand(32, 10, 512)
>>> out = encoder_layer(src)
快速路径:
forward()将使用一种特殊的优化实现
如果满足以下所有条件:`FlashAttention:具有 IO 感知的快速和内存高效的精确注意力`_
条件:
- 要么禁用了 autograd(使用`torch.inference_mode`或`torch.no_grad`)或者没有 tensor
argument `requires_grad`
训练被禁用(使用 `.eval()`)
- batch_first 为 `True` 且输入已分批(即 `src.dim() == 3`)
- 激活函数为以下之一:`"relu"`、`"gelu"`、`torch.functional.relu` 或 `torch.functional.gelu`
最多只能传递 ``src_mask`` 和 ``src_key_padding_mask`` 中的一个
如果 src 是 `NestedTensor `_,则不传递 ``src_mask``
也不传递 ``src_key_padding_mask``
两个 ``LayerNorm`` 实例具有一致的 ``eps`` 值(这将是自然的情况
除非调用者手动修改了其中一个而没有修改另一个)
如果正在使用优化后的实现,
`嵌套张量 `_ 可以传递给 ``src`` 以比使用填充更有效地表示填充
传递给 ``src`` 以比使用填充更有效地表示填充
mask. 在这种情况下,将使用 `NestedTensor `_
返回,并且额外加速与输入分数成比例
是填充可以预期。
.. _`FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness`:
https://arxiv.org/abs/2205.14135
"源代码"
常量 = ["norm_first"]
def 初始化(
self,
d 模型: int,
n 头: int,
dim_feedforward: 整型 = 2048,
dropout: 浮点数 = 0.1,
激活:
联盟[
字符串,
可调用[[
张量
]
张量]] = F.relu,
层归一化 eps:
浮点数 =
0.00001,
批量优先:
布尔类型 =
错误,
标准第一:
布尔类型 =
错误,
偏差:
布尔类型 = True,
设备=
无,
数据类型=
无,
) -> 无:
工厂参数 = {
"设备":
设备, "dtype":
数据类型}
超级().
初始化()
self.自注意力 =
多头注意力(
模型维度,
头数,
dropout=dropout,
偏差=
偏差,
批量优先=
批量优先,
**工厂参数,
)
前馈模型的实现
self.线性 1 =
线性(d_model, dim_feedforward,
偏差=
偏差, **
工厂参数)
self.dropout = Dropout(dropout)
self.线性 2 =
线性(
深度前馈,
模型维度,
偏差=
偏差, **
工厂参数)
self.首先归一化 =
标准首次
self.标准 1 =
层归一化(
模型深度, eps=
层归一化 epsilon,
偏差=
偏差, **
工厂参数)
self.归一化 2 =
层归一化(
模型深度, eps=
层归一化 epsilon,
偏差=
偏差, **
工厂参数)
self.dropout1 = Dropout(dropout)
self.dropout2 = Dropout(dropout)
# 对激活函数的旧字符串支持。
如果 isinstance(
激活,
字符串):
激活 =
_获取激活函数(
激活)
在 TorchScript 中无法测试 forward()中的 self.activation,
因此保存一些关于它的信息。
如果
激活
是 F.relu
或 isinstance(
激活,
火炬.nn.
ReLU 激活函数):
self.激活_relu_or_gelu = 1
elif 激活
是 F.gelu
或 isinstance(
激活,
火炬.nn.GELU):
self.激活函数:ReLU 或 GELU = 2
否则:
self.激活函数:ReLU 或 GELU = 0
self.激活 =
激活
def __setstate__(self, 状态):
超级().__setstate__(
状态)
如果 not
有属性(self,
激活):
self.激活 = F.relu
[文档] def
前向(
self,
源:
张量,
src_mask: 可选[
张量] =
无,
src_key_padding_mask: 可选[
张量] =
无,
因果:
布尔类型 =
错误,
) -> 张量:
r将输入通过编码器层。
Args:
src: 传递给编码器层的序列(必需)。
src_mask:源序列的掩码(可选)。
src_key_padding_mask:每个批次的源键掩码(可选)。
is_causal:如果指定,则将因果掩码应用于“src_mask”。
默认:``False``。
警告:
``is_causal`` 提供了一个提示,即“src_mask”是
因果掩码。提供错误的提示可能会导致
包括前向和反向传播在内的执行错误。
兼容性。
形状:
查看文档::class:`~torch.nn.Transformer` 中的说明。
"源代码"
src_key_padding_mask = F._规范掩码(
遮罩=src_key_padding_mask,
面具名称="src_key_padding_mask",
其他类型=F.
_无或数据类型(
源掩码),
其他名称=
"源掩码",
目标类型=
源.
数据类型,
)
源掩码 = F.
_规范掩码(
遮罩=
源掩码,
面具名称=
src_mask,
其他类型=
无,
其他名称="",
目标类型=
源.
数据类型,
检查其他=
错误,
)
是否启用快速路径 =
火炬.
后端.mha.get_fastpath_enabled()
为什么不使用稀疏快速路径 =
请提供需要翻译的文本
如果 not is_fastpath_enabled:
为什么不使用稀疏快速路径 = (
"torch.backends.mha.get_fastpath_enabled() 不是 True"
)
elif not 源.
暗淡() == 3:
为什么不使用稀疏快速路径 = (
f输入未分批;期望 src.dim()为 3,但得到{
源.
暗淡()}"
)
elif self.训练:
为什么不使用稀疏性快速路径 =
"训练已启用"
elif not self.自注意力机制.
批量优先:
为什么不使用稀疏性快速路径 =
"self_attn.batch_first 不为 True"
elif self.自注意力.in_proj_bias
是
无:
为什么不使用稀疏性快速路径 =
"自注意力传递时设置 bias=False"
elif not self.自注意力._qkv_same_embed_dim:
为什么不使用稀疏性快速路径 =
"self_attn._qkv_same_embed_dim 不为 True"
elif not self.激活函数为 ReLU 或 GeLU:
为什么不使用稀疏快速路径 =
"激活函数 relu 或 geLU 不是 True"
elif not (self.规范 1.eps == self.
规范 2.eps):
为什么不使用稀疏快速路径 =
"norm1.eps 不等于 norm2.eps"
elif 源.
是嵌套的
和 (
src_key_padding_mask 是 not
无
或 src_mask
是 not
无
):
为什么不使用稀疏快速路径 =
"既不支持使用 NestedTensor 输入的 src_key_padding_mask,也不支持 src_mask"
elif self.self_attn.头数 % 2 == 1:
为什么不使用稀疏快速路径 =
"num_head 的值是奇数"
elif 火炬.is_autocast_enabled():
为什么不使用稀疏性快速路径 =
自动转换已启用
elif 任何(
长度(getattr(m, "_forward_hooks", {}))
+ 长度(getattr(m, "_forward_pre_hooks", {}))
为 m
在 self.
模块()
):
为什么不使用稀疏性快速路径 =
"前向预-/钩子被附加到模块上"
如果 not
为什么不使用稀疏快速路径:
张量参数 = (
源,
self.自注意力机制.
输入投影权重,
self.自注意力.
输入投影偏置,
self.自注意力.out_proj.
重量,
self.自注意力.out_proj.
偏差,
self.规范 1.
重量,
self.标准一.
偏差,
self.标准二.
重量,
self.标准二.
偏差,
self.线性一.
重量,
self.线性 1.
偏差,
self.线性 2.
重量,
self.线性 2.
偏差,
)
我们必须使用列表推导,因为 TorchScript 不支持
生成器表达式。
支持的设备类型 = [
"cpu",
cuda,
火炬.
工具.
后端注册.
_私有用途 1 后端名称,
]
如果
火炬.
覆盖.
有 torch 功能(tensor_args):
为什么不使用稀疏快速路径 =
"某些张量参数有 torch_function 函数"
elif not 所有(
(x.设备.
类型
在
支持的设备类型)
为 x
在
张量参数
):
为什么不使用稀疏快速路径 = (
"某些张量参数的设备既不是 CPU、也不是 CUDA"
f"{支持的设备类型}"
)
elif 火炬.
梯度是否启用()
和
任何(x.requires_grad
为 x
在 tensor_args):
为什么不使用稀疏快速路径 = (
梯度已启用,且查询或其中至少一个已启用
输入/输出投影权重或偏置需要梯度
)
如果 not
为什么不使用稀疏快速路径:
合并掩码,
掩码类型 = self.
自注意力.
合并掩码(
源掩码,
源键控掩码,
源
)
返回
火炬.
_Transformer 编码器层前向(
源,
self.自注意力.
嵌入维度,
self.自注意力.
头数,
self.自注意力.
输入投影权重,
self.自注意力.
输入投影偏置,
self.self_attn.out_proj.重量,
self.self_attn.out_proj.偏差,
self.activation_relu_or_gelu == 2,
self.norm_first,
self.标准一.eps,
self.标准一.
重量,
self.标准一.
偏差,
self.标准化 2.
重量,
self.标准化 2.
偏差,
self.线性 1.
重量,
self.线性 1.
偏差,
self.linear2.重量,
self.linear2.偏差,
合并掩码,
掩码类型,
)
# 请参阅 https://arxiv.org/pdf/2002.04745v1.pdf 中的图 1
x = 源
如果 self.
标准第一:
x = x + self._sa 块(
self.标准 1(x),
源掩码, src_key_padding_mask,
因果=
是因果的
)
x = x + self._ff_block(self.norm2(x))
否则:
x = self.norm1(
x
+ self._sa_block(x, src_mask, src_key_padding_mask, 因果=
因果)
)
x = self.norm2(x + self._ff_block(x))
返回 x
# 自注意力块
def _sa_block(
self,
x: 张量,
attn_mask: 可选[
张量
]
key_padding_mask: 可选[
张量
]
因果:
布尔类型 =
错误,
) -> 张量:
x = self.self_attn(
x,
x,
x,
attn_mask=attn_mask,
key_padding_mask=key_padding_mask,
需要的权重=
错误,
因果=
因果,
)0]
返回 self.dropout1(x)
# 前馈块
def _ff_block(self, x: 张量) ->
张量:
x = self.线性 2(self.dropout(self.
激活(self.
线性 1(x))))
返回 self.dropout2(x)
[文档]
类 TransformerDecoderLayer(
模块):
rTransformerDecoderLayer 由自注意力、多头注意力和前馈网络组成。
.. 注意::
请参阅此教程 了解 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块深入讨论。
有关 PyTorch 提供的用于构建自己的 Transformer 层的高效构建块的深入讨论,请参阅。
Transformer 层。
该标准解码器层基于论文《Attention Is All You Need 》。
用户可以在应用中对其进行修改或以不同的方式进行实现。
Args:
d_model:输入中预期的特征数量(必需)。
nhead:多头注意力模型中的头数(必需)。
前馈网络模型的维度(默认=2048)。
dropout 值(默认=0.1)。
中间层的激活函数,可以是字符串("relu"或"gelu")或一元可调用对象。默认:relu
("relu"或"gelu")或一元可调用对象。默认:relu
layer_norm_eps:层归一化组件中的 eps 值(默认=1e-5)。
batch_first:如果为 ``True``,则输入和输出张量以(batch,seq,feature)的形式提供。
默认:``False``(seq,batch,feature)。
norm_first:如果为 True,则层归一化在自注意力、多头注意力和前馈操作之前执行。否则在之后执行。
attention 和 feedforward 操作,分别。否则它是在之后执行的。
默认:False(之后)。
如果设置为 ``False``,则 ``Linear`` 和 ``LayerNorm`` 层不会学习加性
偏置。默认值:``True``。
示例:
>>> decoder_layer = nn.TransformerDecoderLayer(d_model=512, nhead=8)
>>> memory = torch.rand(10, 32, 512)
>>> tgt = torch.rand(20, 32, 512)
>>> out = decoder_layer(tgt, memory)
或者当 ``batch_first`` 为 ``True`` 时:
>>> decoder_layer = nn.TransformerDecoderLayer(d_model=512, nhead=8, batch_first=True)
>>> memory = torch.rand(32, 10, 512)
>>> tgt = torch.rand(32, 20, 512)
>>> out = decoder_layer(tgt, memory)
"源代码"
常量 = [
规范优先]
def 初始化(
self,
d 模型: int,
n 头: int,
dim_feedforward: 整型 = 2048,
dropout: 浮点数 = 0.1,
激活:
联盟[
字符串,
可调用[[
张量
]
张量]] = F.relu,
层归一化 eps:
浮点数 =
0.00001,
批量优先:
布尔类型 =
错误,
norm_first: 布尔类型 =
错误,
偏差:
布尔类型 = True,
设备=
无,
数据类型=
无,
) -> 无:
工厂参数 = {
"设备":
设备, "dtype":
数据类型}
超级().
初始化()
self.自注意力 =
多头注意力(
模型维度,
头数,
dropout=dropout,
批量优先=
批量优先,
偏差=
偏差,
**工厂参数,
)
self.多头注意力 =
多头注意力(
d 模型,
n 头,
dropout=dropout,
批量优先=
批量优先,
偏差=
偏差,
**工厂参数,
)
# 前馈模型的实现
self.线性 1 =
线性(
d 模型, dim_feedforward,
偏差=
偏差, **
工厂参数)
self.dropout = Dropout(dropout)
self.linear2 = 线性(dim_feedforward,
d 模型,
偏差=
偏差, **
工厂参数)
self.首先归一化 =
首先归一化
self.norm1 = 层归一化(d_model, eps=layer_norm_eps,
偏差=
偏差, **
工厂参数)
self.norm2 = 层归一化(d_model, eps=
层归一化 epsilon,
偏差=
偏差, **
工厂参数)
self.规范 3 =
层归一化(
模型深度, eps=
层归一化 epsilon,
偏差=
偏差, **
工厂参数)
self.dropout1 = Dropout(dropout)
self.dropout2 = Dropout(dropout)
self.dropout3 = Dropout(dropout)
# 对激活函数的旧版字符串支持。
如果 isinstance(
激活,
字符串):
self.激活 =
获取激活函数(
激活)
否则:
self.激活 =
激活
def __setstate__(self, 状态):
如果
激活 not
在
状态:
状态[
激活] = F.relu
超级().__setstate__(
状态)
[文档] def
前向(
self,
目标:
张量,
内存:
张量,
目标掩码:
可选[
张量] =
无,
内存掩码:
可选[
张量] =
无,
目标填充掩码:
可选[
张量] =
无,
内存填充掩码:
可选[
张量] =
无,
目标是否因果:
布尔类型 =
错误,
内存是否因果:
布尔类型 =
错误,
) -> 张量:
r将输入(和掩码)通过解码器层。
Args:
tgt:发送到解码器层的序列(必需)。
memory:来自编码器最后一层的序列(必需)。
tgt_mask:tgt 序列的掩码(可选)。
memory_mask: 内存序列的掩码(可选)。
tgt_key_padding_mask: 每批次的 tgt 键的掩码(可选)。
memory_key_padding_mask: 每批次的内存键的掩码(可选)。
tgt_is_causal: 如果指定,则将因果掩码应用于 tgt 掩码。
默认:``False``。
警告:
``tgt_is_causal`` 提供了一个提示,表明 ``tgt_mask`` 是
因果掩码。提供错误的提示可能会导致
包括前向和反向传播在内的执行错误。
兼容性。
memory_is_causal:如果指定,则应用因果掩码作为
``内存掩码``。
默认:``False``。
警告:
``memory_is_causal`` 提供了一个提示,
``memory_mask`` 是因果掩码。提供错误提示可能导致执行错误,包括
前向和后向兼容性。
。
形状:
请参阅 :class:`~torch.nn.Transformer` 中的文档。
"源代码"
# 请参阅 https://arxiv.org/pdf/2002.04745v1.pdf 中的图 1。
x = 目标
如果 self.
首先归一化:
x = x + self._sa_block(
self.norm1(x), 目标掩码,
目标键填充掩码,
目标是否因果
)
x = x + self._mha_block(
self.norm2(x),
memory,
memory_mask,
内存填充掩码键,
内存是否因果,
)
x = x + self._ff 块(self.
规范 3(x))
否则:
x = self.norm1(
x + self._sa_block(x, tgt_mask, tgt_key_padding_mask, tgt_is_causal)
)
x = self.norm2(
x
+ self._mha_block(
x, memory, 内存掩码,
内存填充掩码键,
内存是否因果
)
)
x = self.规范 3(x + self.
_ff 块(x))
返回 x
自注意力块
def _sa_block(
self,
x: 张量,
attn_mask: 可选[
张量
]
key_padding_mask: 可选[
张量
]
因果:
布尔类型 =
错误,
) -> 张量:
x = self.self_attn(
x,
x,
x,
attn_mask=attn_mask,
key_padding_mask=key_padding_mask,
因果=
因果,
需要的权重=
错误,
)0]
返回 self.dropout1(x)
多头注意力块
def _mha_block(
self,
x: 张量,
内存:
张量,
attn_mask: 可选[
张量
]
key_padding_mask: 可选[
张量
]
因果:
布尔类型 =
错误,
) -> 张量:
x = self.multihead_attn(
x,
内存,
内存,
attn_mask=attn_mask,
key_padding_mask=key_padding_mask,
因果=
因果,
需要的权重=
错误,
)0]
返回 self.dropout2(x)
前馈块
def _ff_block(self, x: 张量) ->
张量:
x = self.线性 2(self.dropout(self.
激活(self.
线性 1(x))))
返回 self.dropout3(x)
def _get_clones(模块, N):
# FIXME: 在 nn.module 上未定义 copy.deepcopy()
返回
模块列表([
复制.
深拷贝(
模块)
为 i
在
范围(N
)]])
def _获取激活函数(
激活:
字符串) ->
可调用[[
张量
]
张量
]:
如果
激活 ==
ReLU:
返回 F.relu
elif 激活 == "gelu":
返回 F.gelu
提升
运行时错误(f
"激活函数应为 relu/gelu,而不是"{
激活}")
def 检测因果掩码(
遮罩:
可选[
张量
]
因果:
可选[
布尔] =
无,
尺寸:
可选[int] =
无,
) -> 布尔:
返回给定的注意力掩码是否为因果的。
警告:
如果 `is_causal` 不是 `None`,则其值将按原样返回。如果 a
用户提供了一个错误的 `is_causal` 提示
当掩码实际上是一个因果注意力掩码时,使用 `is_causal=False`
可能相对于使用 `is_causal=True` 时的性能有所降低
使用 `is_causal=True`;当掩码实际上并不是因果注意力掩码时
``is_causal=True`` 当掩码实际上并不是因果注意力掩码
可能导致执行不正确和不可预测 - 在某些场景中,
基于提示,可能应用因果掩码,在其他执行中
场景中可能使用指定掩码的情况。选择可能不会出现。
确保确定性,因为在对齐等因素方面存在许多因素
硬件 SKU 等会影响是否使用口罩的决定
依赖提示
如果`size`不为空,检查提供的口罩是否为该大小的因果掩码
否则,检查是否存在任何因果掩码
"源代码"
防止类型细化
make_causal = 是因果的
是
真实
如果
是因果的
是
无
和
遮罩
是 not
无:
sz = 大小
如果
大小
是 not
无
否则
遮罩.
尺寸(-2)
因果比较 = _generate_square_subsequent_mask(
大小,
设备=
遮罩.
设备,
数据类型=
遮罩.dtype
)
不要使用 `torch.equal`,因为我们通过广播比较来处理批处理的掩码。
避免使用广播比较。
如果
遮罩.
尺寸() ==
因果比较.
尺寸():
make_causal = 布尔((
遮罩 ==
因果比较).
所有())
否则:
构建因果关系 =
假
返回
构建因果关系