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

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

# mypy: 允许未类型化定义
导入 警告
来自 打字 导入 可选

导入 火炬
导入 torch.jit  # 需要避免循环导入
导入 torch.nn.functional 作为 F
来自 火炬 导入 nn, 张量


__all__ = ["MultiheadAttention"]


[文档] 多头注意力(nn.多头注意力): 浮点模块 = nn.多头注意力 r可量化的 MultiheadAttention 实现。 注意:: 请参阅::class:`~torch.nn.MultiheadAttention` 了解更多 信息 允许模型联合关注来自不同表示子空间的信息。 代表子空间。 参考文献:《Attention Is All You Need》 原始的 MHA 模块是不可量化的。 通过显式实例化线性层来实现它。 .. math:: \text{MultiHead}(Q, K, V) = \text{Concat}(head_1,\dots,head_h)W^O \text{其中} head_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V) 参数: embed_dim: 模型的总维度。 num_heads: 并行注意力头。 dropout: 在 attn_output_weights 上添加 Dropout 层。默认:0.0。 bias: 将偏置作为模块参数添加。默认:True。 add_bias_kv: 在 dim=0 维度上向 key 和 value 序列添加偏置。 add_zero_attn: 向 key 添加一个新的全零批次。 dim=1 的值序列。 kdim:键中特征的总数。默认:None。 vdim:值中特征的总数。默认:None。 batch_first:如果为 ``True``,则输入和输出张量以(batch,seq,feature)的形式提供。 默认:``False``(seq,batch,feature)。 注意,如果:attr:`kdim` 和:attr:`vdim` 为 None,它们将被设置为 attr:`embed_dim`,以便查询、键和值具有相同的 特征数量。 示例: >>> 导入 torch.ao.nn.quantizable 作为 nnqa >>> multihead_attn = nnqa.MultiheadAttention(embed_dim, num_heads) >>> attn_output, attn_output_weights = multihead_attn(query, key, value) 注意:: 请遵循量化流程以转换可量化的 MHA。 ```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) ``` 常量 = ["batch_first"] def 初始化( 自身, 嵌入维度: int, 头数: int, dropout: 浮点数 = 0.0, 偏差: 布尔类型 = True, 添加偏置 kv: 布尔类型 = 错误, 添加零注意力: 布尔类型 = 错误, kdim: 可选[int] = , vdim: 可选[int] = , 批量优先: 布尔类型 = 错误, 设备=, 数据类型=, ) -> : 工厂参数 = {"设备": 设备, "dtype": 数据类型} 超级().初始化( 嵌入维度, 头数, dropout, 偏差, 添加偏置 kv, 添加零注意力, kdim, vdim, 批量优先, **工厂参数, ) 自身.线性_Q = nn.线性( 自身.嵌入维度, 自身.嵌入维度, 偏差=偏差, **工厂参数 ) 自身.线性_K = nn.线性( 自身.kdim, 自身.嵌入维度, 偏差=偏差, **工厂参数 ) 自身.线性_V = nn.线性( 自身.vdim, 自身.嵌入维度, 偏差=偏差, **工厂参数 ) # 对于类型:忽略,请参阅 https://github.com/pytorch/pytorch/issues/58969 自身.out_proj = nn.线性(自身.嵌入维度, 自身.嵌入维度, 偏差=偏差, **工厂参数) # 类型:忽略[赋值] 功能性 自身.q_scaling_product = 火炬.ao.nn.量化.浮点功能() # 注意:在顶部导入 torch.ao.nn.quantized 会导致循环导入 # 量化/反量化 自身.量化注意力输出 = 火炬.ao.量化.量化占位符() 自身.量化注意力输出权重 = 火炬.ao.量化.量化占位符() 自身.dequant_q = 火炬.ao.量化.DeQuantStub() 自身.dequant_k = 火炬.ao.量化.DeQuantStub() 自身.dequant_v = 火炬.ao.量化.DeQuantStub() def _获取名称(自身): 返回 可量化的多头注意力 @classmethod def 从浮点数(, 其他): 断言 类型(其他) == .浮点模块 断言 有属性(其他, qconfig), "浮点模块必须包含 'qconfig'" # 将 dropout 设置为 0.0! 观察到 = ( 其他.嵌入维度, 其他.头数, 其他.dropout, (其他.in_proj_bias not ), (其他.偏差_k not ), 其他.添加零注意力, 其他.kdim, 其他.vdim, 其他.批量优先, ) 观察到.偏差_k = 其他.偏差_k 观察.偏置_v = 其他.偏置_v 观察.qconfig = 其他.qconfig 设置线性权重 关于类型:忽略,请参阅 https://github.com/pytorch/pytorch/issues/58969 观察.out_proj.权重 = 其他.out_proj.权重 观察.out_proj.bias = 其他.out_proj.bias 如果 其他._qkv_same_embed_dim: # 使用单独的参数 bias = 其他.in_proj_bias _start = 0 _end = _start + 其他.嵌入维度 权重 = 其他.输入投影权重[_start:结束, ] 如果 bias not : bias = 火炬.nn.参数(偏差[_start:结束] 偏差.需要梯度) 观察.线性_Q.权重 = 火炬.nn.参数(重量, 重量.需要梯度) 观察.线性_Q.bias = bias bias = 其他.in_proj_bias _start = _end _end = _start + 其他.嵌入维度 权重 = 其他.输入投影权重[_start:结束, ] 如果 bias not : bias = 火炬.nn.参数(偏差[_start:结束] 偏差.需要梯度) 观察.线性_K.权重 = 火炬.nn.参数(重量, 重量.需要梯度) 观察.线性_K.bias = bias bias = 其他.in_proj_bias _start = _end 权重 = 其他.输入投影权重[_start:, ] 如果 bias not : bias = 火炬.nn.参数(偏差[_start 偏差.需要梯度) 观察.线性_V.权重 = 火炬.nn.参数(重量, 重量.需要梯度) 观察.线性_V.bias = bias 否则: 观察.线性_Q.权重 = nn.参数(其他.q_proj_weight) 观察.线性_K.权重 = nn.参数(其他.k_proj_weight) 观察.线性_V.权重 = nn.参数(其他.v_项目权重) 如果 其他.in_proj_bias : 观察.线性_Q.bias = None 观察.线性_K.bias = None 观察.线性_V.bias = None 否则: 观察.线性_Q.bias = nn.参数( 其他.输入投影偏置[0 : 其他.嵌入维度] ) 观察.线性_K.bias = nn.参数( 其他.输入投影偏置[其他.嵌入维度 : (其他.嵌入维度 * 2] ) 观察.线性_V.bias = nn.参数( 其他.输入投影偏置[其他.嵌入维度 * 2) ] ) 观察.评估() 明确准备 观察 = 火炬.ao.量化.prepare(观察, 内置=True) 返回 观察
[文档] @torch.算子.未使用 def 反量化(自身): r将量化 MHA 转换回浮点数的工具。 做这件事的动机在于,将量化版本中使用的格式转换回权重并不简单。 将量化版本中使用的格式转换回权重的操作并不简单。 浮点数. ```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) ``` 文件指针 = 自身.浮点模块( 自身.嵌入维度, 自身.头数, 自身.dropout, (自身.线性_Q._权重偏置()[1] not ), # type: ignore[operator] (自身.偏差_k not ), 自身.添加零注意力, 自身.kdim, 自身.vdim, 自身.批量优先, ) 断言 fp._qkv_same_embed_dim == 自身._qkv_same_embed_dim 如果 自身.偏差_k not : fp.偏差_k = nn.参数(自身.偏置_k.反量化()) 如果 自身.偏置_v not : fp.偏置_v = nn.参数(自身.偏置_v.反量化()) # 设置线性权重 因为线性层被量化,mypy 不知道如何处理它们——可能需要忽略类型检查。 可能需要忽略类型检查。 关于 type: ignore[has-type],请参阅 https://github.com/pytorch/pytorch/issues/58969。 w, b = 自身.out_proj._weight_bias() # type: ignore[operator, has-type] fp.out_proj.权重 = nn.参数(w.反量化()) 如果 b not : fp.out_proj.bias = nn.参数(b) wQ, bQ = 自身.线性_Q.权重偏置() # type: ignore[operator] wQ = wQ.反量化() wK, bK = 自身.线性_K._权重偏置() # type: ignore[operator] wK = wK.反量化() wV, bV = 自身.线性_V.权重偏置() # type: ignore[operator] wV = wV.反量化() 如果 fp._qkv_same_embed_dim: 使用单独的参数 _开始 = 0 _结束 = _开始 + fp.嵌入维度 fp.输入投影权重[_start:结束, ] = wQ 如果 fp.in_proj_bias not : 断言 所有(bQ == 0) fp.输入投影偏置[_start:结束] = bQ _start = _end _end = _开始 + fp.嵌入维度 fp.输入投影权重[_start:_结束, ] = wK 如果 fp.in_proj_bias not : 断言 所有(bK == 0) fp.输入投影偏置[_start:结束] = bK 开始 = 结束 fp.输入投影权重[_start:, ] = wV 如果 fp.in_proj_bias not : 断言 所有(bV == 0) fp.输入投影偏置[_start] = bV 否则: fp.q_proj_weight = nn.参数(wQ) fp.k_proj_weight = nn.参数(wK) fp.v_proj_weight = nn.参数(wV) 如果 fp.in_proj_bias : 自身.线性_Q.bias = None 自身.线性_K.bias = None 自身.线性_V.bias = None 否则: fp.输入投影偏置[0 : fp.嵌入维度] = bQ fp.输入投影偏置[fp.嵌入维度 : (fp.嵌入维度 * 2] = bK fp.输入投影偏置[fp.嵌入维度 * 2) ] = bV 返回 fp
@classmethod def 来自观察(, 其他): 整个流程是浮点数 -> 观察到 -> 量化 这个类只做浮点数 -> 观察到 请参阅 nn.quantized.MultiheadAttention 抛出异常 不支持的操作异常( 看起来您正在尝试准备一个 "MHA 模块。请参阅" "可量化的 MHA 示例。" )
[文档] def 前向( 自身, 查询: 张量, : 张量, : 张量, key_padding_mask: 可选[张量] = , 需要的权重: 布尔类型 = True, attn_mask: 可选[张量] = , 平均注意力权重: 布尔类型 = True, 因果: 布尔类型 = 错误, ) -> 元组[张量, 可选[张量]] r"" 注意:: 请参阅 :func:`~torch.nn.MultiheadAttention.forward` 获取更多信息 信息 参数: 查询、键、值:将查询和一组键值对映射到输出。 请参阅“Attention Is All You Need”以获取更多详细信息。 key_padding_mask:如果提供,指定键中的填充元素 当给定一个二进制掩码且值为 True 时,将被注意力忽略。 对应的注意力层上的值将被忽略。 需要权重:输出注意力输出权重。 attn_mask:2D 或 3D 掩码,用于阻止对某些位置的注意力。2D 掩码将广播到所有 批处理时,3D 掩码允许为每个批次的条目指定不同的掩码。 形状: - 输入: - 查询::math:`(L, N, E)` 其中 L 是目标序列长度,N 是批大小,E 是 嵌入维度。:math:`(N, L, E)` 如果 ``batch_first`` 为 ``True``。 - key: (S, N, E),其中 S 是源序列长度,N 是批量大小,E 是嵌入维度。如果 batch_first 为 True,则为(N, S, E)。 嵌入维度。如果 batch_first 为 True,则为(N, S, E)。 - value: (S, N, E)其中 S 是源序列长度,N 是批量大小,E 是嵌入维度。如果 batch_first 为 True,则为(N, S, E)。 嵌入维度。如果 batch_first 为 True,则为(N, S, E)。 key_padding_mask: :math:`(N, S)` 其中 N 是批大小,S 是源序列长度。 如果提供一个 BoolTensor,则值为 ``True`` 的位置将被忽略,而值为 ``False`` 的位置将保持不变。 值为 ``True`` 的位置将被忽略,而值为 ``False`` 的位置将保持不变。 - attn_mask:2D 掩码:math:`(L, S)`,其中 L 为目标序列长度,S 为源序列长度。 3D 掩码:math:`(N*num_heads, L, S)`,其中 N 为批大小,L 为目标序列长度, S 是源序列长度。attn_mask 确保位置 i 可以关注未掩码的 如果提供 BoolTensor,则位置与``True``相关。 不允许关注,而 ``False`` 值将保持不变。如果是一个 FloatTensor 它将被添加到注意力权重中。 - is_causal: 如果指定,则应用因果掩码作为注意力掩码。与提供 attn_mask 互斥。 默认:``False``。 - average_attn_weights: 如果为真,表示返回的 `attn_weights` 应该在所有注意力权重上进行平均 heads. 否则,每个 heads 分别提供 ``attn_weights``。请注意,此标志仅具有 当 `need_weights=True` 时的效果。默认:True(即平均头权重) 输出: - attn_output: :math:`(L, N, E)` 其中 L 是目标序列长度,N 是批大小, E 是嵌入维度。:math:`(N, L, E)` 如果 `batch_first` 为 `True`。 - attn_output_weights: 如果 ``average_attn_weights=True``,则返回平均的注意力权重 形状的头部::math:`(N, L, S)`,其中 N 是批量大小,L 是目标序列长度 S 是源序列长度。如果 `average_attn_weights=False`,则返回每个注意力权重。 形状的头部::math:`(N, num_heads, L, S)`。 ```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) ``` 返回 自身._forward_impl( 查询, , , key_padding_mask, 需要的权重, attn_mask, 平均注意力权重, 因果, )
def _forward_impl( 自身, 查询: 张量, : 张量, : 张量, key_padding_mask: 可选[张量] = , 需要的权重: 布尔类型 = True, attn_mask: 可选[张量] = , 平均注意力权重: 布尔类型 = True, 因果: 布尔类型 = 错误, ) -> 元组[张量, 可选[张量]] 此版本将不会处理静态键/值对。 保留此处以供将来更改。 # TODO:此方法有一些重复的行, `torch.nn.functional.multi_head_attention`。需要重构。 静态键 = None static_v = None 如果 注意力掩码 not None 因果: 抛出异常 断言错误(仅允许因果掩码或 attn_mask) 如果 因果: 抛出异常 断言错误("AO MHA 模块不支持因果掩码") 如果 自身.批量优先: 查询, , value = (x.转置(0, 1) x (查询, , )) tgt_len, bsz, 嵌入维度检查 = 查询.尺寸() 断言 自身.嵌入维度 == 嵌入维度检查 允许 MHA 具有不同大小的特征维度 断言 .尺寸(0) == .尺寸(0) .尺寸(1) == .尺寸(1) 头维度 = 自身.嵌入维度 // 自身.头数 断言 ( 头维度 * 自身.头数 == 自身.嵌入维度 ), "embed_dim 必须能被 num_heads 整除" 缩放 = float(头维度) ** -0.5 q = 自身.线性_Q(查询) k = 自身.线性_K() v = 自身.线性_V() q = 自身.q 缩放乘积.多标量(q, 扩展) 如果 注意力掩码 not : 如果 attn_mask.dtype == 火炬.uint8: warnings.警告( "在 `nn.MultiheadAttention` 中的 `attn_mask` 的 `Byte tensor` 已弃用。" "请使用布尔 tensor 代替。", 栈级别=3, ) 注意力掩码 = attn_mask.(火炬.布尔) 断言 ( attn_mask.is_floating_point() attn_mask.dtype == 火炬.布尔类型 ), f仅支持 float 和 bool 类型用于 attn_mask,不支持{attn_mask.数据类型}" 如果 attn_mask.暗淡() == 2: 注意力掩码 = attn_mask.展平(0) 如果 列表(attn_mask.尺寸()) != [1, 查询.尺寸(0), .尺寸(0) 抛出异常 运行时错误("2D 注意力掩码的大小不正确。") elif attn_mask.暗淡() == 3: 如果 列表(attn_mask.尺寸()) != [ 批大小 * 自身.头数, 查询.尺寸(0), .尺寸(0), ]: 抛出异常 运行时错误("3D 注意力掩码的大小不正确。") 否则: 抛出异常 运行时错误( f注意力掩码的维度{attn_mask.暗淡()}不受支持" ) # 现在注意力掩码的维度是 3。 将 ByteTensor 的 key_padding_mask 转换为布尔值 如果 key_padding_mask not None key_padding_mask.dtype == 火炬.uint8: warnings.警告( "在`nn.MultiheadAttention`中,`key_padding_mask`的 Byte tensor 已被弃用。" "请使用布尔 tensor 代替。", 栈级别=3, ) key_padding_mask = key_padding_mask.(火炬.布尔) 如果 自身.偏差_k not None 自身.偏置_v not : 如果 静态键 None static_v : 明确断言 bias_k 和 bias_v 不为 None 以 TorchScript 可以理解的方式 偏差_k = 自身.偏差_k 断言 偏差_k not None 偏置_v = 自身.偏置_v 断言 偏置_v not None k = 火炬.([k, 偏置_k.重复(1, bsz, 1)]]) v = 火炬.([v, 偏置_v.重复(1, bsz, 1)]]) 如果 注意力掩码 not : 注意力掩码 = F.填充(attn_mask, (0, 1)) 如果 key_padding_mask not : key_padding_mask = F.填充(key_padding_mask, (0, 1)) 否则: 断言 静态键 , "偏差不能添加到静态键。" 断言 static_v , 偏差不能添加到静态值。 否则: 断言 自身.偏差_k None 断言 自身.偏置_v None q = q.连续().视图(tgt_len, 批大小 * 自身.头数, 头维度).转置(0, 1) 如果 k not : k = k.连续().视图(-1, 批大小 * 自身.头数, 头维度).转置(0, 1) 如果 v not : v = v.连续().视图(-1, 批大小 * 自身.头数, 头维度).转置(0, 1) 如果 静态键 not : 断言 静态_k.尺寸(0) == 批大小 * 自身.头数 断言 静态_k.尺寸(2) == 头维度 k = 静态键 如果 static_v not : 断言 静态_v.尺寸(0) == 批大小 * 自身.头数 断言 静态_v.尺寸(2) == 头维度 v = static_v 源长度 = k.尺寸(1) 如果 key_padding_mask not : 断言 key_padding_mask.尺寸(0) == 批大小 断言 key_padding_mask.尺寸(1) == 源长度 如果 自身.添加零注意力: 源长度 += 1 = 火炬.((k.尺寸(0), 1) + k.尺寸()[2]) 如果 k.是否量化: = 火炬.按张量量化( , k.q_scale(), k.q_zero_point(), k.dtype ) k = 火炬.([k, 零的个数] 暗淡=1) 零的个数 = 火炬.((v.尺寸(0), 1) + k.尺寸()[2]) 如果 v.是否量化: 零的个数 = 火炬.按张量量化( 零的个数, v.q_scale(), v.q_zero_point(), v.dtype ) v = 火炬.([v, v_zeros] 暗淡=1) 如果 注意力掩码 not : 注意力掩码 = F.填充(attn_mask, (0, 1)) 如果 key_padding_mask not : key_padding_mask = F.填充(key_padding_mask, (0, 1)) 这里留下量化区域 q = 自身.解量化_q(q) k = 自身.解量化_k(k) v = 自身.dequant_v(v) attn_output_weights = 火炬.bmm(q, k.转置(1, 2)) 断言 列表(注意力输出权重.尺寸()) == [ 批大小 * 自身.头数, tgt_len, 源长度, ] 如果 注意力掩码 not : 如果 attn_mask.dtype == 火炬.布尔: 注意力输出权重.遮蔽填充(attn_mask, float(-无穷大)) 否则: attn_output_weights += 注意力掩码 如果 key_padding_mask not : attn_output_weights = 注意力输出权重.视图( bsz, 自身.头数, tgt_len, 源长度 ) attn_output_weights = 注意力输出权重.遮蔽填充( key_padding_mask.展平(1).展平(2), float(-无穷大), ) attn_output_weights = 注意力输出权重.视图( 批大小 * 自身.头数, tgt_len, 源长度 ) attn_output_weights = F.软式最大化(注意力输出权重, 暗淡=-1) attn_output_weights = F.dropout( 注意力输出权重, p=自身.dropout, 训练=自身.训练 ) attn_output = 火炬.bmm(注意力输出权重, v) 断言 列表(attn_output.尺寸()) == [批大小 * 自身.头数, tgt_len, 头维度] 如果 自身.批量优先: attn_output = attn_output.视图(bsz, tgt_len, 自身.嵌入维度) 否则: attn_output = ( attn_output.转置(0, 1) .连续() .视图(tgt_len, bsz, 自身.嵌入维度) ) 重新进入量化区域 attn_output = 自身.quant_attn_output(attn_output) 关于类型:忽略[has-type],请参阅 https://github.com/pytorch/pytorch/issues/58969 attn_output = 自身.out_proj(attn_output) # 类型:忽略[has-type] attn_output_weights = 自身.量化注意力输出权重(注意力输出权重) 如果 需要的权重: 头部平均注意力权重 attn_output_weights = 注意力输出权重.视图( bsz, 自身.头数, tgt_len, 源长度 ) 如果 平均注意力权重: attn_output_weights = 注意力输出权重.均值(暗淡=1) 返回 attn_output, attn_output_weights 否则: 返回 attn_output,

© 版权所有 PyTorch 贡献者。

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

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源