1674 lines
75 KiB
Python
1674 lines
75 KiB
Python
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, overload
|
|
|
|
import numpy as np
|
|
|
|
import paddle
|
|
from paddle.base import core
|
|
from paddle.base.dygraph import no_grad
|
|
from paddle.base.framework import convert_nptype_to_datatype_or_vartype
|
|
from paddle.framework import in_dynamic_mode
|
|
from paddle.incubate.nn import functional as incubate_f
|
|
from paddle.nn import Layer
|
|
from paddle.nn.initializer import Constant
|
|
from paddle.nn.layer.transformer import (
|
|
MultiHeadAttention,
|
|
_convert_attention_mask,
|
|
_convert_param_attr_to_list,
|
|
)
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Sequence
|
|
|
|
from paddle import Tensor
|
|
from paddle._typing import ParamAttrLike
|
|
|
|
|
|
# for distributed tensor model parallel
|
|
def _set_var_distributed(var):
|
|
if var is None:
|
|
return
|
|
|
|
var.is_distributed = True
|
|
|
|
if not in_dynamic_mode():
|
|
# NOTE: use current_block and find_var_recursive to support while_loop
|
|
startup_block = paddle.static.default_startup_program().current_block()
|
|
main_block = paddle.static.default_main_program().current_block()
|
|
startup_block._find_var_recursive(var.name).is_distributed = True
|
|
main_block._find_var_recursive(var.name).is_distributed = True
|
|
|
|
|
|
def _to_dtype(t, dtype):
|
|
# this function is a prune of Layer._transform function to fix fused op under amp.decorator(O2)
|
|
if not paddle.is_floating_point(t):
|
|
return t
|
|
|
|
if not isinstance(dtype, (core.VarDesc.VarType, core.DataType)):
|
|
dtype = convert_nptype_to_datatype_or_vartype(dtype)
|
|
|
|
if t.place.is_gpu_place():
|
|
var_dtype = paddle.base.framework.convert_to_vartype(dtype)
|
|
size_dtype = core.size_of_dtype(var_dtype)
|
|
waiting_alloc_memory = (
|
|
((np.prod(t.shape) * size_dtype) / 256 + 1) * 256 * 1.2
|
|
)
|
|
gpu_memory_available = core.gpu_memory_available()
|
|
if gpu_memory_available < waiting_alloc_memory:
|
|
t_used = t._copy_to(paddle.CPUPlace(), False)
|
|
t.value().get_tensor()._clear()
|
|
else:
|
|
t_used = t
|
|
else:
|
|
t_used = t
|
|
|
|
if dtype is not None and dtype != t_used.dtype:
|
|
with paddle.base.framework._dygraph_place_guard(place=t_used.place):
|
|
t_casted = t_used.cast(dtype=dtype)
|
|
else:
|
|
t_casted = t_used
|
|
|
|
new_t = t_casted
|
|
|
|
dst_tensor = t.value().get_tensor()
|
|
src_tensor = new_t.value().get_tensor()
|
|
dst_tensor._share_data_with(src_tensor)
|
|
|
|
return t
|
|
|
|
|
|
class FusedBiasDropoutResidualLayerNorm(Layer):
|
|
"""
|
|
Applies fused_bias_dropout_residual_layer_norm operation.
|
|
|
|
Parameters:
|
|
embed_dim (int): The expected feature size in the input and output.
|
|
dropout_rate (float, optional): The dropout probability used on attention
|
|
weights to drop some attention targets for the dropout after attention.
|
|
0 for no dropout. Default 0.5.
|
|
weight_attr (ParamAttr|None, optional): The attribute for the learnable
|
|
weight of this layer. The default value is None and the weight will be
|
|
initialized to zero. For detailed information, please refer to
|
|
paddle.ParamAttr.
|
|
bias_attr (ParamAttr|bool|None, optional): To specify the bias parameter property.
|
|
Default: None, which means the default bias parameter property is used.
|
|
If it is set to False, this layer will not have trainable bias parameter.
|
|
See usage for details in :code:`ParamAttr`.
|
|
epsilon (float, optional): The small value added to the variance to prevent
|
|
division by zero. Default: 1e-05.
|
|
name (str|None, optional): Normally there is no need for user to set this parameter.
|
|
For detailed information, please refer to :ref:`api_guide_Name` .
|
|
|
|
Examples:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> # doctest: +REQUIRES(env:GPU)
|
|
>>> import paddle
|
|
>>> paddle.device.set_device('gpu')
|
|
>>> # input: [batch_size, seq_len, embed_dim]
|
|
>>> x = paddle.rand((2, 4, 128))
|
|
>>> # residual: [batch_size, seq_len, embed_dim]
|
|
>>> residual = paddle.rand((2, 4, 128))
|
|
>>> fused_bias_dropout_residual_ln = paddle.incubate.nn.FusedBiasDropoutResidualLayerNorm(128)
|
|
>>> output = fused_bias_dropout_residual_ln(x, residual)
|
|
>>> print(output.shape)
|
|
paddle.Size([2, 4, 128])
|
|
"""
|
|
|
|
embed_dim: int
|
|
linear_bias: Tensor
|
|
ln_scale: Tensor
|
|
ln_bias: Tensor
|
|
dropout_rate: float
|
|
name: str | None
|
|
|
|
def __init__(
|
|
self,
|
|
embed_dim: int,
|
|
dropout_rate: float = 0.5,
|
|
weight_attr: ParamAttrLike | None = None,
|
|
bias_attr: ParamAttrLike | None = None,
|
|
epsilon: float = 1e-5,
|
|
name: str | None = None,
|
|
) -> None:
|
|
super().__init__()
|
|
assert embed_dim > 0, (
|
|
f"Expected embed_dim to be greater than 0, but received {embed_dim}"
|
|
)
|
|
self._dtype = self._helper.get_default_dtype()
|
|
self._bias_attr = bias_attr
|
|
self._weight_attr = weight_attr
|
|
self.embed_dim = embed_dim
|
|
self.linear_bias = self.create_parameter(
|
|
shape=[embed_dim],
|
|
attr=self._bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
self.ln_scale = self.create_parameter(
|
|
attr=self._weight_attr,
|
|
shape=[embed_dim],
|
|
default_initializer=Constant(value=1.0),
|
|
)
|
|
self.ln_bias = self.create_parameter(
|
|
attr=self._bias_attr, shape=[embed_dim], is_bias=True
|
|
)
|
|
self.dropout_rate = dropout_rate
|
|
self._epsilon = epsilon
|
|
|
|
self.name = name
|
|
|
|
def forward(self, x: Tensor, residual: Tensor) -> Tensor:
|
|
"""
|
|
Applies fused_bias_dropout_residual_layer_norm operation.
|
|
|
|
Parameters:
|
|
x (Tensor): The input tensor. It is a tensor with shape
|
|
`[batch_size, seq_len, embed_dim]`. The data type should be
|
|
float32 or float64.
|
|
residual (Tensor, optional): The residual tensor. It is a tensor
|
|
with shape `[batch_size, value_length, vdim]`. The data type
|
|
should be float32 or float64.
|
|
|
|
Returns:
|
|
Tensor|tuple: It is a tensor that has the same shape and data type \
|
|
as `x`.
|
|
"""
|
|
|
|
out = incubate_f.fused_bias_dropout_residual_layer_norm(
|
|
x=x,
|
|
residual=residual,
|
|
bias=self.linear_bias,
|
|
ln_scale=self.ln_scale,
|
|
ln_bias=self.ln_bias,
|
|
dropout_rate=self.dropout_rate,
|
|
ln_epsilon=self._epsilon,
|
|
training=self.training,
|
|
mode='upscale_in_train',
|
|
name=self.name,
|
|
)
|
|
return out
|
|
|
|
def extra_repr(self):
|
|
name_str = f', name={self.name}' if self.name else ''
|
|
return f'embed_dim={self.embed_dim}, seq_len={self.seq_len}, dropout_rate={self.dropout_rate}, epsilon={self._epsilon}, dtype={self._dtype}{name_str}'
|
|
|
|
|
|
class FusedMultiHeadAttention(Layer):
|
|
"""
|
|
Attention maps queries and a set of key-value pairs to outputs, and
|
|
Multi-Head Attention performs multiple parallel attention to jointly attending
|
|
to information from different representation subspaces.
|
|
Please refer to `Attention Is All You Need <https://arxiv.org/pdf/1706.03762.pdf>`_
|
|
for more details.
|
|
|
|
Parameters:
|
|
embed_dim (int): The expected feature size in the input and output.
|
|
num_heads (int): The number of heads in multi-head attention.
|
|
dropout_rate (float, optional): The dropout probability used on attention
|
|
weights to drop some attention targets for the dropout after attention.
|
|
0 for no dropout. Default 0.5.
|
|
attn_dropout_rate (float, optional): The dropout probability used on attention
|
|
weights to drop some attention targets for the dropout in attention.
|
|
0 for no dropout. Default 0.5.
|
|
kdim (int, optional): The feature size in key. If None, assumed equal to
|
|
`embed_dim`. Default None.
|
|
vdim (int, optional): The feature size in value. If None, assumed equal to
|
|
`embed_dim`. Default None.
|
|
normalize_before (bool, optional): Indicate whether it is pre_layer_norm
|
|
(True) or post_layer_norm architecture (False). Default False.
|
|
need_weights (bool, optional): Indicate whether to return the attention
|
|
weights. Now, only False is supported. Default False.
|
|
qkv_weight_attr(ParamAttr|None, optional): To specify the weight parameter property
|
|
for QKV projection computation. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
qkv_bias_attr(ParamAttr|bool|None, optional): To specify the bias parameter property
|
|
for QKV projection computation. The `False` value means the corresponding layer
|
|
would not have trainable bias parameter. Default: None, which means the
|
|
default bias parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
linear_weight_attr(ParamAttr|None, optional): To specify the weight parameter property
|
|
for linear projection computation. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
linear_bias_attr(ParamAttr|bool|None, optional): To specify the bias parameter property
|
|
for linear projection computation. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
pre_ln_scale_attr(ParamAttr|None, optional): To specify the weight parameter property
|
|
for pre_layer_norm computation. Otherwise, all layers both use it as
|
|
`attr` to create parameters. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
pre_ln_bias_attr(ParamAttr|bool|None, optional): To specify the bias parameter property
|
|
for pre_layer_norm computation. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ln_scale_attr(ParamAttr|None, optional): To specify the weight parameter property
|
|
for post_layer_norm computation. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ln_bias_attr(ParamAttr|bool|None, optional): To specify the bias parameter property
|
|
for post_layer_norm computation. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
epsilon (float, optional): The small value added to the variance to prevent
|
|
division by zero. Default: 1e-05.
|
|
nranks (int, optional): Distributed tensor model parallel nranks. Default is 1, means not using tensor parallel.
|
|
ring_id (int, optional): For distributed tensor model parallel. Default is -1, means not using tensor parallel.
|
|
transpose_qkv_wb (bool, optional): Support input qkv matmul weight shape as
|
|
[hidden_size, 3 * hidden_size] and qkv matmul bias shape as [3 * hidden_size].
|
|
Will transpose the weight to [3, num_head, head_dim, hidden_size] and transpose bias to
|
|
[3, num_head, hidden_size] in the fused_attention_op. Only support for GPU for now.
|
|
The default value is False, which is not do transpose to qkv_w and qkv_b.
|
|
name (str|None, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
|
|
|
|
Examples:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> # doctest: +REQUIRES(env:GPU)
|
|
>>> import paddle
|
|
>>> paddle.device.set_device('gpu')
|
|
>>> # input: [batch_size, sequence_length, embed_dim]
|
|
>>> query = paddle.rand((2, 4, 128))
|
|
>>> # self attention mask: [batch_size, num_heads, query_len, query_len]
|
|
>>> attn_mask = paddle.rand((2, 2, 4, 4))
|
|
>>> multi_head_attn = paddle.incubate.nn.FusedMultiHeadAttention(128, 2)
|
|
>>> output = multi_head_attn(query, None, None, attn_mask=attn_mask)
|
|
>>> print(output.shape)
|
|
paddle.Size([2, 4, 128])
|
|
"""
|
|
|
|
normalize_before: bool
|
|
embed_dim: int
|
|
num_heads: int
|
|
head_dim: int
|
|
kdim: int | None
|
|
vdim: int | None
|
|
need_weights: bool
|
|
transpose_qkv_wb: bool
|
|
qkv_weight: Tensor
|
|
qkv_bias: Tensor
|
|
linear_weight: Tensor
|
|
linear_bias: Tensor
|
|
pre_ln_scale: Tensor
|
|
pre_ln_bias: Tensor
|
|
ln_bias: Tensor
|
|
ln_scale: Tensor
|
|
dropout_rate: float
|
|
attn_dropout_rate: float
|
|
name: str | None
|
|
|
|
def __init__(
|
|
self,
|
|
embed_dim: int,
|
|
num_heads: int,
|
|
dropout_rate: float = 0.5,
|
|
attn_dropout_rate: float = 0.5,
|
|
kdim: int | None = None,
|
|
vdim: int | None = None,
|
|
normalize_before: bool = False,
|
|
need_weights: bool = False,
|
|
qkv_weight_attr: ParamAttrLike | None = None,
|
|
qkv_bias_attr: ParamAttrLike | None = None,
|
|
linear_weight_attr: ParamAttrLike | None = None,
|
|
linear_bias_attr: ParamAttrLike | None = None,
|
|
pre_ln_scale_attr: ParamAttrLike | None = None,
|
|
pre_ln_bias_attr: ParamAttrLike | None = None,
|
|
ln_scale_attr: ParamAttrLike | None = None,
|
|
ln_bias_attr: ParamAttrLike | None = None,
|
|
epsilon: float = 1e-5,
|
|
nranks: int = 1,
|
|
ring_id: int = -1,
|
|
transpose_qkv_wb: bool = False,
|
|
name: str | None = None,
|
|
) -> None:
|
|
super().__init__()
|
|
|
|
assert embed_dim > 0, (
|
|
f"Expected embed_dim to be greater than 0, but received {embed_dim}"
|
|
)
|
|
assert num_heads > 0, (
|
|
f"Expected nhead to be greater than 0, but received {num_heads}"
|
|
)
|
|
|
|
self.normalize_before = normalize_before
|
|
self._dtype = self._helper.get_default_dtype()
|
|
self._epsilon = epsilon
|
|
self._ring_id = ring_id
|
|
|
|
self.embed_dim = embed_dim
|
|
self.num_heads = num_heads
|
|
self.head_dim = embed_dim // num_heads
|
|
self.kdim = kdim
|
|
self.vdim = vdim
|
|
self.need_weights = need_weights
|
|
assert self.head_dim * num_heads == embed_dim, (
|
|
"embed_dim must be divisible by num_heads"
|
|
)
|
|
assert need_weights is False, "Only support need_weight is False now."
|
|
|
|
# tensor model parallel
|
|
assert num_heads % nranks == 0
|
|
self.num_heads = num_heads // nranks
|
|
|
|
self.transpose_qkv_wb = transpose_qkv_wb
|
|
if self.transpose_qkv_wb:
|
|
# For tensor model parallel, use num_head * head_dim to compute the real shape.
|
|
qkv_wight_shape = [embed_dim, 3 * self.num_heads * self.head_dim]
|
|
qkv_bias_shape = [3 * self.num_heads * self.head_dim]
|
|
else:
|
|
qkv_wight_shape = [3, self.num_heads, self.head_dim, embed_dim]
|
|
qkv_bias_shape = [3, self.num_heads, self.head_dim]
|
|
|
|
self.qkv_weight = self.create_parameter(
|
|
shape=qkv_wight_shape,
|
|
attr=qkv_weight_attr,
|
|
dtype=self._dtype,
|
|
is_bias=False,
|
|
)
|
|
self.qkv_bias = self.create_parameter(
|
|
shape=qkv_bias_shape,
|
|
attr=qkv_bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
self.linear_weight = self.create_parameter(
|
|
shape=[self.num_heads * self.head_dim, embed_dim],
|
|
attr=linear_weight_attr,
|
|
dtype=self._dtype,
|
|
is_bias=False,
|
|
)
|
|
self.linear_bias = self.create_parameter(
|
|
shape=[embed_dim],
|
|
attr=linear_bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
|
|
# tensor model parallel
|
|
if nranks > 1:
|
|
assert ring_id != -1
|
|
# column parallel
|
|
_set_var_distributed(self.qkv_weight)
|
|
_set_var_distributed(self.qkv_bias)
|
|
# row parallel
|
|
_set_var_distributed(self.linear_weight)
|
|
|
|
if normalize_before:
|
|
self.pre_ln_scale = self.create_parameter(
|
|
attr=pre_ln_scale_attr,
|
|
shape=[embed_dim],
|
|
default_initializer=Constant(value=1.0),
|
|
)
|
|
self.pre_ln_bias = self.create_parameter(
|
|
attr=pre_ln_bias_attr, shape=[embed_dim], is_bias=True
|
|
)
|
|
self.ln_scale = None
|
|
self.ln_bias = None
|
|
else:
|
|
self.pre_ln_scale = None
|
|
self.pre_ln_bias = None
|
|
self.ln_scale = self.create_parameter(
|
|
attr=ln_scale_attr,
|
|
shape=[embed_dim],
|
|
default_initializer=Constant(value=1.0),
|
|
)
|
|
self.ln_bias = self.create_parameter(
|
|
attr=ln_bias_attr, shape=[embed_dim], is_bias=True
|
|
)
|
|
|
|
self.dropout_rate = dropout_rate
|
|
self.attn_dropout_rate = attn_dropout_rate
|
|
|
|
self.name = name
|
|
|
|
def forward(
|
|
self,
|
|
query: Tensor,
|
|
key: Tensor | None = None,
|
|
value: Tensor | None = None,
|
|
attn_mask: Tensor | None = None,
|
|
cache: None = None,
|
|
) -> Tensor:
|
|
"""
|
|
Applies multi-head attention to map queries and a set of key-value pairs
|
|
to outputs.
|
|
|
|
Parameters:
|
|
query (Tensor): The queries for multi-head attention. It is a
|
|
tensor with shape `[batch_size, query_length, embed_dim]`. The
|
|
data type should be float32 or float64.
|
|
key (Tensor, optional): The keys for multi-head attention. It is
|
|
a tensor with shape `[batch_size, key_length, kdim]`. The
|
|
data type should be float32 or float64. If None, use `query` as
|
|
`key`. Default None.
|
|
value (Tensor, optional): The values for multi-head attention. It
|
|
is a tensor with shape `[batch_size, value_length, vdim]`.
|
|
The data type should be float32 or float64. If None, use `query` as
|
|
`value`. Default None.
|
|
attn_mask (Tensor, optional): A tensor used in multi-head attention
|
|
to prevents attention to some unwanted positions, usually the
|
|
paddings or the subsequent positions. It is a tensor with shape
|
|
broadcasted to `[batch_size, n_head, sequence_length, sequence_length]`.
|
|
When the data type is bool, the unwanted positions have `False`
|
|
values and the others have `True` values. When the data type is
|
|
int, the unwanted positions have 0 values and the others have 1
|
|
values. When the data type is float, the unwanted positions have
|
|
`-INF` values and the others have 0 values. It can be None when
|
|
nothing wanted or needed to be prevented attention to. Default None.
|
|
cache (MultiHeadAttention.Cache|MultiHeadAttention.StaticCache, optional):
|
|
Now, only None is supported. Default None.
|
|
|
|
Returns:
|
|
Tensor|tuple: It is a tensor that has the same shape and data type \
|
|
as `query`, representing attention output.
|
|
"""
|
|
if attn_mask is not None:
|
|
# Support bool or int mask
|
|
attn_mask = _convert_attention_mask(attn_mask, query.dtype)
|
|
|
|
out = incubate_f.fused_multi_head_attention(
|
|
x=query,
|
|
qkv_weight=self.qkv_weight,
|
|
linear_weight=self.linear_weight,
|
|
pre_layer_norm=self.normalize_before,
|
|
pre_ln_scale=self.pre_ln_scale,
|
|
pre_ln_bias=self.pre_ln_bias,
|
|
ln_scale=self.ln_scale,
|
|
ln_bias=self.ln_bias,
|
|
pre_ln_epsilon=self._epsilon,
|
|
qkv_bias=self.qkv_bias,
|
|
linear_bias=self.linear_bias,
|
|
cache_kv=cache,
|
|
attn_mask=attn_mask,
|
|
dropout_rate=self.dropout_rate,
|
|
attn_dropout_rate=self.attn_dropout_rate,
|
|
ln_epsilon=self._epsilon,
|
|
training=self.training,
|
|
ring_id=self._ring_id,
|
|
num_heads=self.num_heads,
|
|
transpose_qkv_wb=self.transpose_qkv_wb,
|
|
name=self.name,
|
|
)
|
|
return out
|
|
|
|
def extra_repr(self) -> str:
|
|
name_str = f', name={self.name}' if self.name else ''
|
|
return f'embed_dim={self.embed_dim}, num_heads={self.num_heads}, dropout_rate={self.dropout_rate}, attn_dropout_rate={self.attn_dropout_rate}, epsilon={self._epsilon}, kdim={self.kdim}, vdim={self.vdim}, normalize_before={self.normalize_before}, need_weights={self.need_weights}, dtype={self._dtype}{name_str}'
|
|
|
|
def _amp_decorate(self, dtype):
|
|
# tmp fix for amp.decorator(O2)
|
|
layer_norm_params_id = []
|
|
if self.normalize_before:
|
|
layer_norm_params_id.append(id(self.pre_ln_scale))
|
|
layer_norm_params_id.append(id(self.pre_ln_bias))
|
|
else:
|
|
layer_norm_params_id.append(id(self.ln_scale))
|
|
layer_norm_params_id.append(id(self.ln_bias))
|
|
|
|
for key, param in self._parameters.items():
|
|
if id(param) in layer_norm_params_id:
|
|
continue
|
|
if param is not None:
|
|
with no_grad():
|
|
param_applied = _to_dtype(param, dtype)
|
|
|
|
self._dtype = dtype
|
|
|
|
|
|
class FusedFeedForward(Layer):
|
|
"""
|
|
Parameters:
|
|
d_model (int): The expected feature size in the input and output.
|
|
dim_feedforward (int): The hidden layer size.
|
|
dropout_rate (float, optional): The dropout probability used in pre-process
|
|
and post-process. Default 0.1
|
|
epsilon (float, optional): he small value added to the variance to prevent
|
|
division by zero. Default: 1e-05.
|
|
activation (str, optional): The activation function. Default relu.
|
|
act_dropout_rate (float, optional): The dropout probability after activation.
|
|
If None, use the value of `dropout_rate`. Default None
|
|
normalize_before (bool, optional): Indicate whether to put layer normalization
|
|
into, preprocessing or postprocessing. Default False
|
|
linear1_weight_attr(ParamAttr, optional): To specify the weight parameter property
|
|
for FFN first linear. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
linear1_bias_attr(ParamAttr|bool, optional): To specify the bias parameter property
|
|
for FFN first linear. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
linear2_weight_attr(ParamAttr, optional): To specify the weight parameter property
|
|
for FFN second linear. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
linear2_bias_attr(ParamAttr|bool, optional): To specify the bias parameter property
|
|
for FFN second linear. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ln1_scale_attr(ParamAttr, optional): To specify the weight parameter property
|
|
for FFN pre_layer_norm. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ln1_bias_attr(ParamAttr|bool, optional): To specify the bias parameter property
|
|
for FFN pre_layer_norm. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ln2_scale_attr(ParamAttr, optional): To specify the weight parameter property
|
|
for FFN post_layer_norm. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ln2_bias_attr(ParamAttr|bool, optional): To specify the bias parameter property
|
|
for FFN layer_norm. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
nranks (int, optional): Distributed tensor model parallel nranks. Default is 1, means not using tensor parallel.
|
|
ring_id (int, optional): For distributed tensor model parallel. Default is -1, means not using tensor parallel.
|
|
name (str, optional): The default value is None. Normally there is no need for user to set
|
|
this property. For more information, please refer to :ref:`api_guide_Name`.
|
|
|
|
Examples:
|
|
.. code-block:: pycon
|
|
|
|
>>> # doctest: +REQUIRES(env:GPU)
|
|
>>> import paddle
|
|
>>> from paddle.incubate.nn import FusedFeedForward
|
|
>>> paddle.device.set_device('gpu')
|
|
|
|
>>> fused_feedforward_layer = FusedFeedForward(8, 8)
|
|
>>> x = paddle.rand((1, 8, 8))
|
|
>>> out = fused_feedforward_layer(x)
|
|
>>> print(out.shape)
|
|
paddle.Size([1, 8, 8])
|
|
"""
|
|
|
|
name: str | None
|
|
|
|
def __init__(
|
|
self,
|
|
d_model: int,
|
|
dim_feedforward: int,
|
|
dropout_rate: float = 0.1,
|
|
epsilon: float = 1e-05,
|
|
activation: str = "relu",
|
|
act_dropout_rate: float | None = None,
|
|
normalize_before: bool = False,
|
|
linear1_weight_attr: ParamAttrLike | None = None,
|
|
linear1_bias_attr: ParamAttrLike | None = None,
|
|
linear2_weight_attr: ParamAttrLike | None = None,
|
|
linear2_bias_attr: ParamAttrLike | None = None,
|
|
ln1_scale_attr: ParamAttrLike | None = None,
|
|
ln1_bias_attr: ParamAttrLike | None = None,
|
|
ln2_scale_attr: ParamAttrLike | None = None,
|
|
ln2_bias_attr: ParamAttrLike | None = None,
|
|
nranks: int = 1,
|
|
ring_id: int = -1,
|
|
name: str | None = None,
|
|
) -> None:
|
|
super().__init__()
|
|
assert d_model > 0, (
|
|
f"Expected d_model to be greater than 0, but received {d_model}"
|
|
)
|
|
assert dim_feedforward > 0, (
|
|
f"Expected dim_feedforward to be greater than 0, but received {dim_feedforward}"
|
|
)
|
|
|
|
self._dtype = self._helper.get_default_dtype()
|
|
self._d_model = d_model
|
|
|
|
assert dim_feedforward % nranks == 0
|
|
dim_feedforward = dim_feedforward // nranks
|
|
self._dim_feedforward = dim_feedforward
|
|
self._dropout_rate = dropout_rate
|
|
self._act_dropout_rate = (
|
|
dropout_rate if act_dropout_rate is None else act_dropout_rate
|
|
)
|
|
self._act_method = activation
|
|
self._normalize_before = normalize_before
|
|
self._epsilon = epsilon
|
|
self._ring_id = ring_id
|
|
|
|
self._linear1_weight = self.create_parameter(
|
|
shape=[d_model, dim_feedforward],
|
|
attr=linear1_weight_attr,
|
|
dtype=self._dtype,
|
|
is_bias=False,
|
|
)
|
|
self._linear1_bias = self.create_parameter(
|
|
shape=[dim_feedforward],
|
|
attr=linear1_bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
|
|
self._linear2_weight = self.create_parameter(
|
|
shape=[dim_feedforward, d_model],
|
|
attr=linear2_weight_attr,
|
|
dtype=self._dtype,
|
|
is_bias=False,
|
|
)
|
|
|
|
self._linear2_bias = self.create_parameter(
|
|
shape=[d_model],
|
|
attr=linear2_bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
|
|
if nranks > 1:
|
|
assert ring_id != -1
|
|
# column parallel
|
|
_set_var_distributed(self._linear1_weight)
|
|
_set_var_distributed(self._linear1_bias)
|
|
_set_var_distributed(self._linear2_weight)
|
|
|
|
if normalize_before:
|
|
self._ln1_scale = self.create_parameter(
|
|
shape=[d_model],
|
|
attr=ln1_scale_attr,
|
|
is_bias=False,
|
|
default_initializer=Constant(1.0),
|
|
)
|
|
self._ln1_bias = self.create_parameter(
|
|
shape=[d_model], attr=ln1_bias_attr, is_bias=True
|
|
)
|
|
self._ln2_scale = None
|
|
self._ln2_bias = None
|
|
else:
|
|
self._ln1_scale = None
|
|
self._ln1_bias = None
|
|
self._ln2_scale = self.create_parameter(
|
|
shape=[d_model],
|
|
attr=ln2_scale_attr,
|
|
is_bias=False,
|
|
default_initializer=Constant(1.0),
|
|
)
|
|
self._ln2_bias = self.create_parameter(
|
|
shape=[d_model], attr=ln2_bias_attr, is_bias=True
|
|
)
|
|
|
|
self.name = name
|
|
|
|
def forward(self, src: Tensor, cache: Tensor | None = None) -> Tensor:
|
|
out = incubate_f.fused_feedforward(
|
|
src,
|
|
self._linear1_weight,
|
|
self._linear2_weight,
|
|
self._linear1_bias,
|
|
self._linear2_bias,
|
|
self._ln1_scale,
|
|
self._ln1_bias,
|
|
self._ln2_scale,
|
|
self._ln2_bias,
|
|
dropout1_rate=self._act_dropout_rate,
|
|
dropout2_rate=self._dropout_rate,
|
|
activation=self._act_method,
|
|
ln1_epsilon=self._epsilon,
|
|
ln2_epsilon=self._epsilon,
|
|
pre_layer_norm=self._normalize_before,
|
|
training=self.training,
|
|
ring_id=self._ring_id,
|
|
name=self.name,
|
|
)
|
|
return out
|
|
|
|
def extra_repr(self) -> str:
|
|
name_str = f', name={self.name}' if self.name else ''
|
|
return f'd_model={self._d_model}, dim_feedforward={self._dim_feedforward}, dropout_rate={self._dropout_rate}, epsilon={self._epsilon}, activation={self._act_method}, act_dropout_rate={self._act_dropout_rate}, normalize_before={self._normalize_before}, dtype={self._dtype}{name_str}'
|
|
|
|
def _amp_decorate(self, dtype):
|
|
# tmp fix for amp.decorator(O2)
|
|
layer_norm_params_id = []
|
|
if self._normalize_before:
|
|
layer_norm_params_id.append(id(self._ln1_scale))
|
|
layer_norm_params_id.append(id(self._ln1_bias))
|
|
else:
|
|
layer_norm_params_id.append(id(self._ln2_scale))
|
|
layer_norm_params_id.append(id(self._ln2_bias))
|
|
|
|
for key, param in self._parameters.items():
|
|
if id(param) in layer_norm_params_id:
|
|
continue
|
|
if param is not None:
|
|
with no_grad():
|
|
param_applied = _to_dtype(param, dtype)
|
|
|
|
self._dtype = dtype
|
|
|
|
|
|
class FusedTransformerEncoderLayer(Layer):
|
|
"""
|
|
|
|
FusedTransformerEncoderLayer is composed of two sub-layers which are self (multi-head)
|
|
attention and feedforward network. Before and after each sub-layer, pre-process
|
|
and post-process would be applied on the input and output accordingly. If
|
|
`normalize_before` is True, pre-process is layer normalization and post-process
|
|
includes dropout, residual connection. Otherwise, no pre-process and post-process
|
|
includes dropout, residual connection, layer normalization.
|
|
|
|
Parameters:
|
|
d_model (int): The expected feature size in the input and output.
|
|
nhead (int): The number of heads in multi-head attention(MHA).
|
|
dim_feedforward (int): The hidden layer size in the feedforward network(FFN).
|
|
dropout_rate (float, optional): The dropout probability used in pre-process
|
|
and post-process of MHA and FFN sub-layer. Default 0.1
|
|
activation (str, optional): The activation function in the feedforward
|
|
network. Default relu.
|
|
attn_dropout_rate (float, optional): The dropout probability used
|
|
in MHA to drop some attention target. If None, use the value of
|
|
`dropout`. Default None
|
|
act_dropout_rate (float, optional): The dropout probability used after FFN
|
|
activation. If None, use the value of `dropout`. Default None
|
|
normalize_before (bool, optional): Indicate whether to put layer normalization
|
|
into preprocessing of MHA and FFN sub-layers. If True, pre-process is layer
|
|
normalization and post-process includes dropout, residual connection.
|
|
Otherwise, no pre-process and post-process includes dropout, residual
|
|
connection, layer normalization. Default False
|
|
weight_attr(ParamAttr|list|tuple, optional): To specify the weight parameter property.
|
|
If it is a list/tuple, `weight_attr[0]` would be used as `weight_attr` for
|
|
MHA, and `weight_attr[1]` would be used as `weight_attr` for linear in FFN.
|
|
Otherwise, MHA and FFN both use it as `weight_attr` to create parameters.
|
|
Default: None, which means the default weight parameter property is used.
|
|
See usage for details in :code:`ParamAttr` .
|
|
bias_attr (ParamAttr|list|tuple|bool, optional): To specify the bias parameter property.
|
|
If it is a list/tuple, `bias_attr[0]` would be used as `bias_attr` for
|
|
MHA, and `bias_attr[1]` would be used as `bias_attr` for linear in FFN.
|
|
Otherwise, MHA and FFN both use it as `bias_attr` to create parameters.
|
|
The `False` value means the corresponding layer would not have trainable
|
|
bias parameter. See usage for details in :code:`ParamAttr` . Default: None,
|
|
which means the default bias parameter property is used.
|
|
|
|
|
|
Examples:
|
|
.. code-block:: pycon
|
|
|
|
>>> # doctest: +REQUIRES(env:GPU)
|
|
>>> import paddle
|
|
>>> from paddle.incubate.nn import FusedTransformerEncoderLayer
|
|
>>> paddle.device.set_device('gpu')
|
|
|
|
>>> # encoder input: [batch_size, src_len, d_model]
|
|
>>> enc_input = paddle.rand((2, 4, 128))
|
|
>>> # self attention mask: [batch_size, n_head, src_len, src_len]
|
|
>>> attn_mask = paddle.rand((2, 2, 4, 4))
|
|
>>> encoder_layer = FusedTransformerEncoderLayer(128, 2, 512)
|
|
>>> enc_output = encoder_layer(enc_input, attn_mask)
|
|
>>> print(enc_output.shape)
|
|
paddle.Size([2, 4, 128])
|
|
|
|
"""
|
|
|
|
fused_attn: FusedMultiHeadAttention
|
|
ffn: FusedFeedForward
|
|
|
|
def __init__(
|
|
self,
|
|
d_model: int,
|
|
nhead: int,
|
|
dim_feedforward: int,
|
|
dropout_rate: float = 0.1,
|
|
activation: str = "relu",
|
|
attn_dropout_rate: float | None = None,
|
|
act_dropout_rate: float | None = None,
|
|
normalize_before: bool = False,
|
|
weight_attr: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
bias_attr: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
) -> None:
|
|
self._config = locals()
|
|
self._config.pop("self")
|
|
self._config.pop("__class__", None) # py3
|
|
|
|
super().__init__()
|
|
assert d_model > 0, (
|
|
f"Expected d_model to be greater than 0, but received {d_model}"
|
|
)
|
|
assert nhead > 0, (
|
|
f"Expected nhead to be greater than 0, but received {nhead}"
|
|
)
|
|
assert dim_feedforward > 0, (
|
|
"Expected dim_feedforward to be greater than 0, "
|
|
f"but received {dim_feedforward}"
|
|
)
|
|
attn_dropout_rate = (
|
|
dropout_rate if attn_dropout_rate is None else attn_dropout_rate
|
|
)
|
|
act_dropout_rate = (
|
|
dropout_rate if act_dropout_rate is None else act_dropout_rate
|
|
)
|
|
self.normalize_before = normalize_before
|
|
|
|
weight_attrs = _convert_param_attr_to_list(weight_attr, 2)
|
|
bias_attrs = _convert_param_attr_to_list(bias_attr, 2)
|
|
|
|
self.fused_attn = FusedMultiHeadAttention(
|
|
d_model,
|
|
nhead,
|
|
dropout_rate=dropout_rate,
|
|
attn_dropout_rate=attn_dropout_rate,
|
|
normalize_before=self.normalize_before,
|
|
qkv_weight_attr=weight_attrs[0],
|
|
qkv_bias_attr=bias_attrs[0],
|
|
linear_weight_attr=weight_attrs[0],
|
|
linear_bias_attr=bias_attrs[0],
|
|
pre_ln_scale_attr=weight_attrs[0],
|
|
pre_ln_bias_attr=bias_attrs[0],
|
|
ln_scale_attr=weight_attrs[0],
|
|
ln_bias_attr=bias_attrs[0],
|
|
)
|
|
|
|
self.ffn = FusedFeedForward(
|
|
d_model,
|
|
dim_feedforward,
|
|
dropout_rate=dropout_rate,
|
|
activation=activation,
|
|
act_dropout_rate=act_dropout_rate,
|
|
normalize_before=self.normalize_before,
|
|
linear1_weight_attr=weight_attrs[1],
|
|
linear1_bias_attr=bias_attrs[1],
|
|
linear2_weight_attr=weight_attrs[1],
|
|
linear2_bias_attr=bias_attrs[1],
|
|
)
|
|
|
|
@overload
|
|
def forward(
|
|
self,
|
|
src: Tensor,
|
|
src_mask: Tensor | None = ...,
|
|
cache: None = ...,
|
|
) -> Tensor: ...
|
|
|
|
@overload
|
|
def forward(
|
|
self,
|
|
src: Tensor,
|
|
src_mask: Tensor | None = ...,
|
|
cache: MultiHeadAttention.Cache = ...,
|
|
) -> tuple[Tensor, MultiHeadAttention.Cache]: ...
|
|
|
|
def forward(
|
|
self,
|
|
src,
|
|
src_mask=None,
|
|
cache=None,
|
|
):
|
|
"""
|
|
|
|
Applies a Transformer encoder layer on the input.
|
|
|
|
Parameters:
|
|
src (Tensor): The input of Transformer encoder layer. It is
|
|
a tensor with shape `[batch_size, sequence_length, d_model]`.
|
|
The data type should be float32 or float64.
|
|
src_mask (Tensor, optional): A tensor used in multi-head attention
|
|
to prevents attention to some unwanted positions, usually the
|
|
paddings or the subsequent positions. It is a tensor with shape
|
|
broadcasted to `[batch_size, n_head, sequence_length, sequence_length]`.
|
|
When the data type is bool, the unwanted positions have `False`
|
|
values and the others have `True` values. When the data type is
|
|
int, the unwanted positions have 0 values and the others have 1
|
|
values. When the data type is float, the unwanted positions have
|
|
`-INF` values and the others have 0 values. It can be None when
|
|
nothing wanted or needed to be prevented attention to. Default None.
|
|
cache (Tensor, optional): It is an instance of `MultiHeadAttention.Cache`.
|
|
See :ref:`api_paddle_nn_TransformerEncoderLayer`.gen_cache for more details. It is
|
|
only used for inference and should be None for training. Default
|
|
None.
|
|
|
|
Returns:
|
|
Tensor|tuple, It is a tensor that has the same shape and data type \
|
|
as `enc_input`, representing the output of Transformer encoder \
|
|
layer. Or a tuple if `cache` is not None, except for encoder \
|
|
layer output, the tuple includes the new cache which is same \
|
|
as input `cache` argument but `incremental_cache` has an \
|
|
incremental length. See `MultiHeadAttention.gen_cache` and \
|
|
`MultiHeadAttention.forward` for more details.
|
|
|
|
"""
|
|
src_mask = _convert_attention_mask(src_mask, src.dtype)
|
|
if cache is None:
|
|
attn_out = self.fused_attn(src, attn_mask=src_mask)
|
|
else:
|
|
attn_out, incremental_cache = self.fused_attn(
|
|
src, attn_mask=src_mask, cache=cache
|
|
)
|
|
|
|
ffn_out = self.ffn(attn_out)
|
|
|
|
return ffn_out if cache is None else (ffn_out, incremental_cache)
|
|
|
|
|
|
class FusedTransformer(Layer):
|
|
"""
|
|
A Transformer model composed of an instance of `TransformerEncoder` and an
|
|
instance of `TransformerDecoder`. While the embedding layer and output layer
|
|
are not included.
|
|
|
|
Please refer to `Attention is all you need <http://papers.nips.cc/paper/7181-attention-is-all-you-need.pdf>`_ ,
|
|
and see `TransformerEncoder` and `TransformerDecoder` for more details.
|
|
|
|
Users can configure the model architecture with corresponding parameters.
|
|
Note the usage of `normalize_before` representing where to apply layer
|
|
normalization (in pre-process or post-process of multi-head attention or FFN),
|
|
and some transformer like models are different on this, such as
|
|
`BERT <https://arxiv.org/abs/1810.04805>`_ and `GPT2 <https://d4mucfpksywv.cloudfront.net/better-language-models/language-models.pdf>`_ .
|
|
The default architecture here places layer normalization in post-process and
|
|
applies another layer normalization on the output of last encoder/decoder layer.
|
|
|
|
Parameters:
|
|
d_model (int, optional): The expected feature size in the encoder/decoder input
|
|
and output. Default 512
|
|
nhead (int, optional): The number of heads in multi-head attention(MHA). Default 8
|
|
num_encoder_layers (int, optional): The number of layers in encoder. Default 6
|
|
num_decoder_layers (int, optional): The number of layers in decoder. Default 6
|
|
dim_feedforward (int, optional): The hidden layer size in the feedforward network(FFN). Default 2048
|
|
dropout (float, optional): The dropout probability used in pre-process
|
|
and post-process of MHA and FFN sub-layer. Default 0.1
|
|
activation (str, optional): The activation function in the feedforward
|
|
network. Default relu.
|
|
attn_dropout (float, optional): The dropout probability used
|
|
in MHA to drop some attention target. If None, use the value of
|
|
`dropout`. Default None
|
|
act_dropout (float, optional): The dropout probability used after FFN
|
|
activation. If None, use the value of `dropout`. Default None
|
|
normalize_before (bool, optional): Indicate whether to put layer normalization
|
|
into preprocessing of MHA and FFN sub-layers. If True, pre-process is layer
|
|
normalization and post-process includes dropout, residual connection.
|
|
Otherwise, no pre-process and post-process includes dropout, residual
|
|
connection, layer normalization. Default False
|
|
weight_attr(ParamAttr|list|tuple, optional): To specify the weight parameter property.
|
|
If it is a list/tuple, the length of `weight_attr` could be 1, 2 or 3. If it is 3,
|
|
`weight_attr[0]` would be used as `weight_attr` for self attention, `weight_attr[1]`
|
|
would be used as `weight_attr` for cross attention of `TransformerDecoder`,
|
|
and `weight_attr[2]` would be used as `weight_attr` for linear in FFN.
|
|
If it is 2, `weight_attr[0]` would be used as `weight_attr` both for self attention
|
|
and cross attention and `weight_attr[1]` would be used as `weight_attr` for
|
|
linear in FFN. If it is 1, `weight_attr[0]` would be used as `weight_attr`
|
|
for self attention, cross attention and linear in FFN. Otherwise,
|
|
the three sub-layers all uses it as `weight_attr` to create parameters.
|
|
Default: None, which means the default weight parameter property is used.
|
|
See usage for details
|
|
in :code:`ParamAttr` .
|
|
bias_attr (ParamAttr|list|tuple|bool, optional): To specify the bias parameter property.
|
|
If it is a list/tuple, the length of `bias_attr` could be 1, 2 or 3. If it is 3,
|
|
`bias_attr[0]` would be used as `bias_attr` for self attention, `bias_attr[1]`
|
|
would be used as `bias_attr` for cross attention of `TransformerDecoder`,
|
|
and `bias_attr[2]` would be used as `bias_attr` for linear in FFN.
|
|
If it is 2, `bias_attr[0]` would be used as `bias_attr` both for self attention
|
|
and cross attention and `bias_attr[1]` would be used as `bias_attr` for
|
|
linear in FFN. If it is 1, `bias_attr[0]` would be used as `bias_attr`
|
|
for self attention, cross attention and linear in FFN. Otherwise,
|
|
the three sub-layers all uses it as `bias_attr` to create parameters.
|
|
The `False` value means the corresponding layer would not have trainable
|
|
bias parameter. See usage for details in :code:`ParamAttr` .
|
|
Default: None,which means the default bias parameter property is used.
|
|
custom_encoder (Layer, optional): If custom encoder is provided, use it as the encoder.
|
|
Default None
|
|
custom_decoder (Layer, optional): If custom decoder is provided, use it as the decoder.
|
|
Default None
|
|
|
|
Examples:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> import paddle
|
|
>>> from paddle.nn import Transformer
|
|
|
|
>>> # src: [batch_size, tgt_len, d_model]
|
|
>>> enc_input = paddle.rand((2, 4, 128))
|
|
>>> # tgt: [batch_size, src_len, d_model]
|
|
>>> dec_input = paddle.rand((2, 6, 128))
|
|
>>> # src_mask: [batch_size, n_head, src_len, src_len]
|
|
>>> enc_self_attn_mask = paddle.rand((2, 2, 4, 4))
|
|
>>> # tgt_mask: [batch_size, n_head, tgt_len, tgt_len]
|
|
>>> dec_self_attn_mask = paddle.rand((2, 2, 6, 6))
|
|
>>> # memory_mask: [batch_size, n_head, tgt_len, src_len]
|
|
>>> cross_attn_mask = paddle.rand((2, 2, 6, 4))
|
|
>>> transformer = Transformer(128, 2, 4, 4, 512)
|
|
>>> output = transformer(
|
|
... enc_input,
|
|
... dec_input,
|
|
... enc_self_attn_mask,
|
|
... dec_self_attn_mask,
|
|
... cross_attn_mask,
|
|
... )
|
|
>>> print(output.shape)
|
|
paddle.Size([2, 6, 128])
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
d_model: int = 512,
|
|
nhead: int = 8,
|
|
num_encoder_layers: int = 6,
|
|
num_decoder_layers: int = 6,
|
|
dim_feedforward: int = 2048,
|
|
dropout: float = 0.1,
|
|
activation: str = "relu",
|
|
attn_dropout: str | None = None,
|
|
act_dropout: float | None = None,
|
|
normalize_before: bool = False,
|
|
weight_attr: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
bias_attr: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
custom_encoder: Layer | None = None,
|
|
custom_decoder: Layer | None = None,
|
|
) -> None:
|
|
super().__init__()
|
|
raise NotImplementedError
|
|
|
|
def forward(self, src, tgt, src_mask=None, tgt_mask=None, memory_mask=None):
|
|
raise NotImplementedError
|
|
|
|
|
|
class FusedMultiTransformer(Layer):
|
|
"""
|
|
FusedMultiTransformer is composed of multi transformer layers which contains two
|
|
sub-layers which are self (multi-head) attention and feedforward network. The
|
|
function of one transformer layer is consistent with the following pseudo code:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> # doctest: +SKIP('This is not an example')
|
|
>>> if pre_layer_norm:
|
|
... out = layer_norm(x)
|
|
... out = qkv_linear(out) + qkv_bias
|
|
... else:
|
|
... out = qkv_linear(x) + qkv_bias
|
|
>>> out = transpose(out, perm=[2, 0, 3, 1, 4])
|
|
>>> # extract q, k and v from out.
|
|
>>> q = out[0:1, ::]
|
|
>>> k = out[1:2, ::]
|
|
>>> v = out[2:3, ::]
|
|
>>> out = q * k ^ t
|
|
>>> out = attn_mask + out
|
|
>>> out = softmax(out)
|
|
>>> out = dropout(out)
|
|
>>> out = out * v
|
|
>>> out = transpose(out, perm=[0, 2, 1, 3])
|
|
>>> out = linear(out)
|
|
>>> if pre_layer_norm:
|
|
... out = x + dropout(out + bias)
|
|
... else:
|
|
... out = layer_norm(x + dropout(out + bias))
|
|
|
|
>>> residual = out
|
|
>>> if pre_layer_norm:
|
|
... out = ffn_layer_norm(out)
|
|
>>> out = ffn1_linear(out)
|
|
>>> out = dropout(activation(out + ffn1_bias))
|
|
>>> out = ffn2_linear(out)
|
|
>>> out = residual + dropout(out + ffn2_bias)
|
|
>>> if not pre_layer_norm:
|
|
... out = ffn_layer_norm(out)
|
|
|
|
Parameters:
|
|
embed_dim (int): The expected feature size in the input and output.
|
|
num_heads (int): The number of heads in multi-head attention(MHA).
|
|
dim_feedforward (int): The hidden layer size in the feedforward network(FFN).
|
|
dropout_rate (float, optional): The dropout probability used in pre-process
|
|
and post-process of MHA and FFN sub-layer. Default 0.0
|
|
activation (str, optional): The activation function in the feedforward
|
|
network. Default "gelu".
|
|
normalize_before (bool, optional): Indicate whether to put layer normalization
|
|
into preprocessing of MHA and FFN sub-layers. If True, pre-process is layer
|
|
normalization and post-process includes dropout, residual connection.
|
|
Otherwise, no pre-process and post-process includes dropout, residual
|
|
connection, layer normalization. Default True
|
|
ln_scale_attrs(ParamAttr|list|tuple, optional): To specify the weight parameter property
|
|
for Attention layer_norm. For Attention layer_norm weight, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ln_bias_attrs(ParamAttr|list|tuple|bool, optional): To specify the bias parameter property
|
|
for Attention layer_norm. For Attention layer_norm bias, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
qkv_weight_attrs(ParamAttr|list|tuple, optional): To specify the weight parameter property
|
|
for Attention qkv computation. For Attention qkv weight, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
qkv_bias_attrs(ParamAttr|list|tuple|bool, optional): To specify the bias parameter property
|
|
for Attention qkv computation. For Attention qkv bias, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
linear_weight_attrs(ParamAttr|list|tuple, optional): To specify the weight parameter property
|
|
for Attention linear. For Attention linear weight, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
linear_bias_attrs(ParamAttr|list|tuple|bool, optional): To specify the bias parameter property
|
|
for Attention linear computation. For Attention linear bias, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ffn_ln_scale_attrs(ParamAttr|list|tuple, optional): To specify the weight parameter property
|
|
for FFN layer_norm. For FFN layer_norm weight, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ffn_ln_bias_attrs(ParamAttr|list|tuple|bool, optional): To specify the bias parameter property
|
|
for FFN layer_norm. For FFN layer_norm bias, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ffn1_weight_attrs(ParamAttr|list|tuple, optional): To specify the weight parameter property
|
|
for FFN first linear. For FFN first linear weight, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ffn1_bias_attrs(ParamAttr|list|tuple|bool, optional): To specify the bias parameter property
|
|
for FFN first linear. For FFN first linear bias, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ffn2_weight_attrs(ParamAttr|list|tuple, optional): To specify the weight parameter property
|
|
for FFN second linear. For FFN second linear weight, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. Default: None, which means the default weight
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
ffn2_bias_attrs(ParamAttr|list|tuple|bool, optional): To specify the bias parameter property
|
|
for FFN second linear. For FFN second linear bias, if it is a list/tuple, `attrs[0]`
|
|
would be used as `attr` for transformer layer 0, and `attrs[1]` would be used as
|
|
`attr` for transformer layer 1, etc. Otherwise, all layers both use it as
|
|
`attr` to create parameters. The `False` value means the corresponding layer would
|
|
not have trainable bias parameter. Default: None, which means the default bias
|
|
parameter property is used. See usage for details in :code:`ParamAttr`.
|
|
epsilon (float, optional): Small float value added to denominator of the layer_norm to
|
|
avoid dividing by zero. Default: 1e-05.
|
|
residual_alpha (float, optional): a scale factor for residual. default is 1.0.
|
|
num_layers (int, optional): The number of layers of the transformer. If `qkv_weight_attrs`
|
|
is a list or tuple, the number of layers is obtained from `qkv_weight_attrs`. num_layers
|
|
only takes effect when `qkv_weight_attrs` is not a list or tuple. Default: -1.
|
|
nranks (int, optional): Distributed tensor model parallel nranks. Default is 1, means not using mp.
|
|
trans_qkvw (bool, optional): Whether to transpose for weights of qkv.
|
|
If true, the shape eights of qkv should be [3, num_head, dim_head, dim_embed].
|
|
Otherwise the shape of weights of qkv should be [dim_embed, 3, num_head, dim_head]. Default: True.
|
|
ring_id (int, optional): For distributed tensor model parallel. Default is -1, means not using mp.
|
|
use_neox_rotary_style(bool, optional): When the use_neox_rotary_style is True, every two adjacent numbers
|
|
are calculated. When the use_neox_rotary_style is False, the numbers corresponding to the positions of
|
|
the front half and back half segments are calculated. Default False.
|
|
name (str, optional): The default value is None. Normally there is no need for user to set
|
|
this property. For more information, please refer to :ref:`api_guide_Name`.
|
|
|
|
Examples:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> # doctest: +SKIP('Need compile flash attention')
|
|
>>> # doctest: +REQUIRES(env:GPU)
|
|
>>> import paddle
|
|
>>> from paddle.incubate.nn import FusedMultiTransformer
|
|
>>> paddle.device.set_device('gpu')
|
|
|
|
>>> # encoder input: [batch_size, src_len, d_model]
|
|
>>> enc_input = paddle.rand((2, 4, 128))
|
|
>>> # self attention mask: [batch_size, 1, src_len, src_len]
|
|
>>> attn_mask = paddle.rand((2, 1, 4, 4))
|
|
>>> encoder_layers = FusedMultiTransformer(128, 2, 512, num_layers=1)
|
|
>>> enc_output = encoder_layers(enc_input, attn_mask)
|
|
>>> print(enc_output.shape)
|
|
paddle.Size([2, 4, 128])
|
|
"""
|
|
|
|
normalize_before: bool
|
|
embed_dim: int
|
|
num_heads: int
|
|
head_dim: int
|
|
ln_biases: list[Tensor]
|
|
ln_scales: list[Tensor]
|
|
qkv_biases: list[Tensor]
|
|
qkv_weights: list[Tensor]
|
|
linear_biases: list[Tensor]
|
|
linear_weights: list[Tensor]
|
|
ffn_ln_biases: list[Tensor]
|
|
ffn_ln_scales: list[Tensor]
|
|
ffn1_biases: list[Tensor]
|
|
ffn1_weights: list[Tensor]
|
|
ffn2_biases: list[Tensor]
|
|
ffn2_weights: list[Tensor]
|
|
qkv_weights_scales: list[Tensor]
|
|
linear_weights_scales: list[Tensor]
|
|
ffn1_weights_scales: list[Tensor]
|
|
ffn2_weights_scales: list[Tensor]
|
|
dropout_rate: float
|
|
activation: str
|
|
name: str | None
|
|
|
|
def __init__(
|
|
self,
|
|
embed_dim: int,
|
|
num_heads: int,
|
|
dim_feedforward: int,
|
|
dropout_rate: float = 0.0,
|
|
activation: str = "gelu",
|
|
normalize_before: bool = True,
|
|
ln_scale_attrs: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
ln_bias_attrs: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
qkv_weight_attrs: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
qkv_bias_attrs: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
linear_weight_attrs: (
|
|
ParamAttrLike | Sequence[ParamAttrLike] | None
|
|
) = None,
|
|
linear_bias_attrs: (
|
|
ParamAttrLike | Sequence[ParamAttrLike] | None
|
|
) = None,
|
|
ffn_ln_scale_attrs: (
|
|
ParamAttrLike | Sequence[ParamAttrLike] | None
|
|
) = None,
|
|
ffn_ln_bias_attrs: (
|
|
ParamAttrLike | Sequence[ParamAttrLike] | None
|
|
) = None,
|
|
ffn1_weight_attrs: (
|
|
ParamAttrLike | Sequence[ParamAttrLike] | None
|
|
) = None,
|
|
ffn1_bias_attrs: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
ffn2_weight_attrs: (
|
|
ParamAttrLike | Sequence[ParamAttrLike] | None
|
|
) = None,
|
|
ffn2_bias_attrs: ParamAttrLike | Sequence[ParamAttrLike] | None = None,
|
|
epsilon: float = 1e-5,
|
|
residual_alpha: float = 1.0,
|
|
num_layers: int = -1,
|
|
nranks: int = 1,
|
|
trans_qkvw=True,
|
|
ring_id: int = -1,
|
|
norm_type: str = "layernorm",
|
|
use_neox_rotary_style=False,
|
|
gqa_group_size: int = -1,
|
|
name: str | None = None,
|
|
) -> None:
|
|
super().__init__()
|
|
|
|
assert embed_dim > 0, (
|
|
f"Expected embed_dim to be greater than 0, but received {embed_dim}"
|
|
)
|
|
assert num_heads > 0, (
|
|
f"Expected nhead to be greater than 0, but received {num_heads}"
|
|
)
|
|
assert dim_feedforward > 0, (
|
|
f"Expected dim_feedforward to be greater than 0, but received {dim_feedforward}"
|
|
)
|
|
|
|
self.normalize_before = normalize_before
|
|
self._dtype = self._helper.get_default_dtype()
|
|
self._epsilon = epsilon
|
|
self._residual_alpha = residual_alpha
|
|
self._trans_qkvw = trans_qkvw
|
|
self._ring_id = ring_id
|
|
self._norm_type = norm_type
|
|
self._use_neox_rotary_style = use_neox_rotary_style
|
|
self._gqa_group_size = gqa_group_size
|
|
self._norm_weight_dtype = (
|
|
"float32" if self._norm_type == "layernorm" else self._dtype
|
|
)
|
|
|
|
self.embed_dim = embed_dim
|
|
self.num_heads = num_heads
|
|
self.head_dim = embed_dim // num_heads
|
|
assert self.head_dim * num_heads == embed_dim, (
|
|
"embed_dim must be divisible by num_heads"
|
|
)
|
|
|
|
# tensor model parallel
|
|
if nranks > 1:
|
|
assert ring_id != -1
|
|
assert num_heads % nranks == 0
|
|
assert dim_feedforward % nranks == 0
|
|
num_heads = num_heads // nranks
|
|
dim_feedforward = dim_feedforward // nranks
|
|
self._dim_feedforward = dim_feedforward
|
|
|
|
if isinstance(qkv_weight_attrs, (list, tuple)):
|
|
num_layers = len(qkv_weight_attrs)
|
|
assert num_layers > 0
|
|
|
|
self.ln_scales, self.ln_biases = [], []
|
|
self.qkv_weights, self.qkv_biases = [], []
|
|
self.linear_weights, self.linear_biases = [], []
|
|
self.ffn_ln_scales, self.ffn_ln_biases = [], []
|
|
self.ffn1_weights, self.ffn1_biases = [], []
|
|
self.ffn2_weights, self.ffn2_biases = [], []
|
|
self.qkv_weights_scales = []
|
|
self.linear_weights_scales = []
|
|
self.ffn1_weights_scales = []
|
|
self.ffn2_weights_scales = []
|
|
|
|
def get_attr(attrs, idx):
|
|
if isinstance(attrs, (list, tuple)):
|
|
assert len(attrs) == num_layers
|
|
return attrs[idx]
|
|
return attrs
|
|
|
|
def _add_parameter(param):
|
|
if param is None:
|
|
return
|
|
assert param.name not in self._parameters
|
|
self._parameters[param.name] = param
|
|
|
|
for i in range(num_layers):
|
|
ln_scale_attr = get_attr(ln_scale_attrs, i)
|
|
ln_bias_attr = get_attr(ln_bias_attrs, i)
|
|
qkv_weight_attr = get_attr(qkv_weight_attrs, i)
|
|
qkv_bias_attr = get_attr(qkv_bias_attrs, i)
|
|
linear_weight_attr = get_attr(linear_weight_attrs, i)
|
|
linear_bias_attr = get_attr(linear_bias_attrs, i)
|
|
|
|
ffn_ln_scale_attr = get_attr(ffn_ln_scale_attrs, i)
|
|
ffn_ln_bias_attr = get_attr(ffn_ln_bias_attrs, i)
|
|
ffn1_weight_attr = get_attr(ffn1_weight_attrs, i)
|
|
ffn1_bias_attr = get_attr(ffn1_bias_attrs, i)
|
|
ffn2_weight_attr = get_attr(ffn2_weight_attrs, i)
|
|
ffn2_bias_attr = get_attr(ffn2_bias_attrs, i)
|
|
|
|
ln_scale = self.create_parameter(
|
|
attr=ln_scale_attr,
|
|
shape=[embed_dim],
|
|
default_initializer=Constant(value=1.0),
|
|
dtype=self._norm_weight_dtype,
|
|
)
|
|
ln_bias = None
|
|
if ln_bias_attr:
|
|
ln_bias = self.create_parameter(
|
|
attr=ln_bias_attr,
|
|
shape=[embed_dim],
|
|
is_bias=True,
|
|
dtype=self._norm_weight_dtype,
|
|
)
|
|
qkv_head_shape = (
|
|
[3, num_heads]
|
|
if self._gqa_group_size <= 0
|
|
else [num_heads + 2 * self._gqa_group_size]
|
|
)
|
|
qkv_weight = self.create_parameter(
|
|
shape=(
|
|
[*qkv_head_shape, self.head_dim, embed_dim]
|
|
if trans_qkvw
|
|
else [embed_dim, *qkv_head_shape, self.head_dim]
|
|
),
|
|
attr=qkv_weight_attr,
|
|
dtype=self._dtype,
|
|
is_bias=False,
|
|
)
|
|
qkv_bias = None
|
|
if qkv_bias_attr:
|
|
qkv_bias = self.create_parameter(
|
|
shape=[*qkv_head_shape, self.head_dim],
|
|
attr=qkv_bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
linear_weight = self.create_parameter(
|
|
shape=[num_heads * self.head_dim, embed_dim],
|
|
attr=linear_weight_attr,
|
|
dtype=self._dtype,
|
|
is_bias=False,
|
|
)
|
|
linear_bias = None
|
|
if linear_bias_attr:
|
|
linear_bias = self.create_parameter(
|
|
shape=[embed_dim],
|
|
attr=linear_bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
|
|
ffn_ln_scale = self.create_parameter(
|
|
shape=[embed_dim],
|
|
attr=ffn_ln_scale_attr,
|
|
is_bias=False,
|
|
default_initializer=Constant(1.0),
|
|
dtype=self._norm_weight_dtype,
|
|
)
|
|
ffn_ln_bias = None
|
|
if ffn_ln_bias_attr:
|
|
ffn_ln_bias = self.create_parameter(
|
|
shape=[embed_dim],
|
|
attr=ffn_ln_bias_attr,
|
|
is_bias=True,
|
|
dtype=self._norm_weight_dtype,
|
|
)
|
|
ffn1_weight = self.create_parameter(
|
|
shape=(
|
|
[embed_dim, dim_feedforward * 2]
|
|
if activation.endswith("glu")
|
|
else [embed_dim, dim_feedforward]
|
|
),
|
|
attr=ffn1_weight_attr,
|
|
dtype=self._dtype,
|
|
is_bias=False,
|
|
)
|
|
ffn1_bias = None
|
|
if ffn1_bias_attr:
|
|
ffn1_bias = self.create_parameter(
|
|
shape=(
|
|
[dim_feedforward * 2]
|
|
if activation.endswith("glu")
|
|
else [dim_feedforward]
|
|
),
|
|
attr=ffn1_bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
ffn2_weight = self.create_parameter(
|
|
shape=[dim_feedforward, embed_dim],
|
|
attr=ffn2_weight_attr,
|
|
dtype=self._dtype,
|
|
is_bias=False,
|
|
)
|
|
ffn2_bias = None
|
|
if ffn2_bias_attr:
|
|
ffn2_bias = self.create_parameter(
|
|
shape=[embed_dim],
|
|
attr=ffn2_bias_attr,
|
|
dtype=self._dtype,
|
|
is_bias=True,
|
|
)
|
|
|
|
# tensor model parallel
|
|
if nranks > 1:
|
|
# column parallel
|
|
_set_var_distributed(qkv_weight)
|
|
_set_var_distributed(qkv_bias)
|
|
_set_var_distributed(ffn1_weight)
|
|
_set_var_distributed(ffn1_bias)
|
|
# row parallel
|
|
_set_var_distributed(linear_weight)
|
|
_set_var_distributed(ffn2_weight)
|
|
|
|
self.ln_scales.append(ln_scale)
|
|
self.ln_biases.append(ln_bias)
|
|
self.qkv_weights.append(qkv_weight)
|
|
self.qkv_biases.append(qkv_bias)
|
|
self.linear_weights.append(linear_weight)
|
|
self.linear_biases.append(linear_bias)
|
|
|
|
self.ffn_ln_scales.append(ffn_ln_scale)
|
|
self.ffn_ln_biases.append(ffn_ln_bias)
|
|
self.ffn1_weights.append(ffn1_weight)
|
|
self.ffn1_biases.append(ffn1_bias)
|
|
self.ffn2_weights.append(ffn2_weight)
|
|
self.ffn2_biases.append(ffn2_bias)
|
|
_add_parameter(ln_scale)
|
|
_add_parameter(ln_bias)
|
|
_add_parameter(qkv_weight)
|
|
_add_parameter(qkv_bias)
|
|
_add_parameter(linear_weight)
|
|
_add_parameter(linear_bias)
|
|
|
|
_add_parameter(ffn_ln_scale)
|
|
_add_parameter(ffn_ln_bias)
|
|
_add_parameter(ffn1_weight)
|
|
_add_parameter(ffn1_bias)
|
|
_add_parameter(ffn2_weight)
|
|
_add_parameter(ffn2_bias)
|
|
|
|
if self.ln_biases[0] is None:
|
|
self.ln_biases = None
|
|
|
|
if self.qkv_biases[0] is None:
|
|
self.qkv_biases = None
|
|
|
|
if self.linear_biases[0] is None:
|
|
self.linear_biases = None
|
|
|
|
if self.ffn_ln_biases[0] is None:
|
|
self.ffn_ln_biases = None
|
|
|
|
if self.ffn1_biases[0] is None:
|
|
self.ffn1_biases = None
|
|
|
|
if self.ffn2_biases[0] is None:
|
|
self.ffn2_biases = None
|
|
|
|
self.dropout_rate = dropout_rate
|
|
self.activation = activation
|
|
self.name = name
|
|
|
|
@overload
|
|
def forward(
|
|
self,
|
|
src: Tensor,
|
|
attn_mask: Tensor | None = ...,
|
|
caches: None = ...,
|
|
pre_caches: Sequence[Tensor] | None = ...,
|
|
rotary_embs: Tensor | None = ...,
|
|
rotary_emb_dims: int = ...,
|
|
beam_offset: Tensor | None = ...,
|
|
seq_lens: Tensor | None = ...,
|
|
time_step: Tensor | None = ...,
|
|
) -> Tensor: ...
|
|
|
|
@overload
|
|
def forward(
|
|
self,
|
|
src: Tensor,
|
|
attn_mask: Tensor | None = ...,
|
|
caches: Sequence[Tensor] = ...,
|
|
pre_caches: Sequence[Tensor] | None = ...,
|
|
rotary_embs: Tensor | None = ...,
|
|
rotary_emb_dims: int = ...,
|
|
beam_offset: Tensor | None = ...,
|
|
seq_lens: Tensor | None = ...,
|
|
time_step: Tensor | None = ...,
|
|
) -> tuple[Tensor, Sequence[Tensor]]: ...
|
|
|
|
def forward(
|
|
self,
|
|
src,
|
|
attn_mask=None,
|
|
caches=None,
|
|
pre_caches=None,
|
|
rotary_embs=None,
|
|
rotary_emb_dims=0,
|
|
beam_offset=None,
|
|
seq_lens=None,
|
|
time_step=None,
|
|
):
|
|
r"""
|
|
Applies multi transformer layers on the input.
|
|
|
|
Parameters:
|
|
src (Tensor): The input of Transformer layers. It is
|
|
a tensor with shape `[batch_size, sequence_length, d_model]`.
|
|
The data type should be float16 or float32.
|
|
attn_mask (Tensor, optional): A tensor used in multi-head attention
|
|
to prevents attention to some unwanted positions, usually the
|
|
paddings or the subsequent positions. It is a tensor with shape
|
|
`[batch_size, 1, sequence_length, sequence_length]`. It can be
|
|
None when nothing wanted or needed to be prevented attention to.
|
|
Default None.
|
|
caches (list(Tensor)|tuple(Tensor), optional): The cache structure
|
|
tensors for the inference generation model. It is only used for
|
|
inference and should be None for training. The shape is
|
|
`[2, batch_size, num_head, max_seq_len, head_dim]`. Default None.
|
|
pre_caches (list(Tensor)|tuple(Tensor), optional): The prefix caches
|
|
for the generation model. The shape is
|
|
`[2, bsz, num\_head, cache\_len, head\_dim]`. Default None.
|
|
rotary_embs (Tensor optional): The RoPE embs for the rotary computation.
|
|
The shape is `[2, bsz, 1, seq\_len, head\_dim]`. Default None.
|
|
rotary_emb_dims (int, optional): The rotary_emb_dims of rotary computation,
|
|
and it is 0 when rotary_embs is None,
|
|
1 when rotary_embs is not None and pos_extra_ids is None,
|
|
2 when rotary_embs and pos_extra_ids are both not None. Default 0.
|
|
seq_lens (Tensor optional): The sequence lengths of this batch.
|
|
The shape is `[bsz]`. Default None.
|
|
time_step (Tensor, optional): The time step tensor for the generation
|
|
model. Which used in decode stage, to represent the time step,
|
|
that is, the real seq_len of CacheKV. The shape is `[1]`, must be
|
|
in CPUPlace. Default None.
|
|
|
|
Returns:
|
|
Tensor|tuple: If `caches` is None, return a tensor that has
|
|
the same shape and data type with `src`, representing the output
|
|
of Transformer layers. If `caches` is not None, return the
|
|
tuple (output, caches), which output is the output of
|
|
Transformer layers, caches is inplace with input `caches`.
|
|
"""
|
|
|
|
if caches is not None:
|
|
assert len(caches) == len(self.qkv_weights)
|
|
out = incubate_f.fused_multi_transformer(
|
|
src,
|
|
self.ln_scales,
|
|
self.ln_biases,
|
|
self.qkv_weights,
|
|
self.qkv_biases,
|
|
self.linear_weights,
|
|
self.linear_biases,
|
|
self.ffn_ln_scales,
|
|
self.ffn_ln_biases,
|
|
self.ffn1_weights,
|
|
self.ffn1_biases,
|
|
self.ffn2_weights,
|
|
self.ffn2_biases,
|
|
pre_layer_norm=self.normalize_before,
|
|
epsilon=self._epsilon,
|
|
residual_alpha=self._residual_alpha,
|
|
cache_kvs=caches,
|
|
beam_offset=beam_offset,
|
|
pre_caches=pre_caches,
|
|
rotary_embs=rotary_embs,
|
|
time_step=time_step,
|
|
seq_lens=seq_lens,
|
|
attn_mask=attn_mask,
|
|
dropout_rate=self.dropout_rate,
|
|
rotary_emb_dims=rotary_emb_dims,
|
|
activation=self.activation,
|
|
training=self.training,
|
|
mode='upscale_in_train',
|
|
trans_qkvw=self._trans_qkvw,
|
|
ring_id=self._ring_id,
|
|
norm_type=self._norm_type,
|
|
use_neox_rotary_style=self._use_neox_rotary_style,
|
|
gqa_group_size=self._gqa_group_size,
|
|
name=self.name,
|
|
)
|
|
return out
|