@@ -458,6 +458,10 @@ class TransformerBlock(torch.nn.Module):
458458 attention.
459459 post_attn_norm: Normalization applied to the attention output before
460460 its residual addition.
461+ attn_residual_norm: Normalization applied after the attention residual
462+ addition.
463+ mlp_residual_norm: Normalization applied after the feedforward
464+ residual addition. Requires ``mlp``.
461465 query_transform: Transformation applied to projected query heads before
462466 scaled dot-product attention.
463467 key_transform: Transformation applied to projected key heads before
@@ -468,7 +472,8 @@ class TransformerBlock(torch.nn.Module):
468472 scale: Scaling factor passed to
469473 :func:`torch.nn.functional.scaled_dot_product_attention`.
470474 ``None`` uses ``1 / sqrt(channels_per_head)``.
471- dropout: Attention dropout probability.
475+ dropout: Dropout probability applied to attention weights and to the
476+ attention output before its residual addition.
472477 bias: If set to ``False``, the module will not learn an additive bias.
473478 device: The device.
474479 dtype: The dtype.
@@ -483,6 +488,8 @@ def __init__(
483488 query_norm : torch .nn .Module | None = None ,
484489 key_value_norm : torch .nn .Module | None = None ,
485490 post_attn_norm : torch .nn .Module | None = None ,
491+ attn_residual_norm : torch .nn .Module | None = None ,
492+ mlp_residual_norm : torch .nn .Module | None = None ,
486493 query_transform : torch .nn .Module | None = None ,
487494 key_transform : torch .nn .Module | None = None ,
488495 query_scaling : QueryScaling | None = None ,
@@ -494,12 +501,18 @@ def __init__(
494501 dtype : torch .dtype | None = None ,
495502 ) -> None :
496503 super ().__init__ ()
504+ if mlp is None and mlp_residual_norm is not None :
505+ raise ValueError ("'mlp_residual_norm' requires 'mlp'" )
506+
497507 factory_kwargs : dict [str , Any ] = {"device" : device , "dtype" : dtype }
498508
499509 self .mlp = mlp
500510 self .query_norm = query_norm
501511 self .key_value_norm = key_value_norm
502512 self .post_attn_norm = post_attn_norm
513+ self .attn_residual_norm = attn_residual_norm
514+ self .mlp_residual_norm = mlp_residual_norm
515+ self .dropout = dropout
503516
504517 self .attn = Attention (
505518 channels = channels ,
@@ -811,20 +824,33 @@ def _forward(
811824
812825 if self .post_attn_norm is not None :
813826 attn_out = self .post_attn_norm (attn_out )
827+ if self .training and self .dropout > 0.0 :
828+ attn_out = F .dropout (attn_out , p = self .dropout )
814829
815830 if (
816831 out is not None
817832 and torch .compiler .is_compiling ()
818833 and not out .is_contiguous ()
819834 ):
820835 tmp = (attn_out + query ).to (out .dtype )
836+ if self .attn_residual_norm is not None :
837+ tmp = self .attn_residual_norm (tmp )
821838 if self .mlp is not None :
822- tmp += self .mlp (tmp )
839+ tmp = (tmp + self .mlp (tmp )).to (out .dtype )
840+ if self .mlp_residual_norm is not None :
841+ tmp = self .mlp_residual_norm (tmp )
823842 out .copy_ (tmp )
824843 else :
825844 tmp = torch .add (attn_out , query , out = out )
845+ if self .attn_residual_norm is not None :
846+ tmp = self .attn_residual_norm (tmp )
826847 if self .mlp is not None :
827848 tmp = torch .add (tmp , self .mlp (tmp ), out = out )
849+ if self .mlp_residual_norm is not None :
850+ tmp = self .mlp_residual_norm (tmp )
851+ # Normalization allocates, so copy its result into `out`.
852+ if out is not None and tmp is not out :
853+ tmp = out .copy_ (tmp )
828854 out = tmp
829855
830856 return (out , kv ) if return_key_value else out
0 commit comments