From cdbe1952c6ee4c3f33b3b1df01e37befa820830d Mon Sep 17 00:00:00 2001 From: Benjamin Lefaudeux Date: Wed, 19 Jan 2022 23:32:29 -0500 Subject: [PATCH] [feat] Compositional attention (#178) * Initial implementation * adding the graphs * doc + removing seemingly niche options * minor fixes to the LRA setup * Refactor the projection, align args on other attentions * code review, thanks @dianaml0 * adding some more explanations --- BENCHMARKS.md | 2 +- CHANGELOG.md | 3 + README.md | 3 + docs/plots/memory_vs_attention.png | Bin 34360 -> 35471 bytes docs/plots/runtime_vs_attention.png | Bin 31679 -> 35099 bytes examples/microGPT.py | 1 + requirements-lra.txt | 1 + tests/test_attentions.py | 4 +- tests/test_block_factory.py | 8 +- tests/test_compositional_attention.py | 113 ++++++ xformers/benchmarks/LRA/code/config.json | 4 +- xformers/components/__init__.py | 5 + .../components/attention/attention_mask.py | 6 +- xformers/components/attention/base.py | 8 +- .../components/attention/compositional.py | 337 ++++++++++++++++++ xformers/components/attention/favor.py | 6 +- xformers/components/multi_head_dispatch.py | 10 +- 17 files changed, 496 insertions(+), 15 deletions(-) create mode 100644 tests/test_compositional_attention.py create mode 100644 xformers/components/attention/compositional.py diff --git a/BENCHMARKS.md b/BENCHMARKS.md index eb443ffe6..87d809dc2 100644 --- a/BENCHMARKS.md +++ b/BENCHMARKS.md @@ -11,7 +11,7 @@ Please note that: - These numbers are dependent of hyperparameters (dimensions chosen for Linformer, sparsity of the pattern), they are mostly an illustration - The sparse attention patterns tested here are just presets, as explained in the linked notebook generating any new sparse attention pattern should be relatively easy, while keeping the benefits of optimized computations. -Some examples, generated with `python3 xformers/benchmarks/benchmark_encoder.py --activations gelu --plot -emb 256 -bs 32 -heads 16` +Some examples, generated with `python3 xformers/benchmarks/benchmark_encoder.py --activations gelu --plot -emb 256 -bs 8 -heads 4` ![Memory use for different attentions](docs/plots/memory_vs_attention.png) ![Runtime for different attentions](docs/plots/runtime_vs_attention.png) diff --git a/CHANGELOG.md b/CHANGELOG.md index f01c4704b..6f0361333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## TBD +### Added +- Compositional Attention [#41] + ### Fixed - bugfix Favor, single feature map [#183] diff --git a/README.md b/README.md index 32b991b68..b2aa27174 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,9 @@ Patrick et al., 2021](https://arxiv.org/abs/2106.05392)* - See BigBird, Longformers,.. - [FourierMix](xformers/components/attention/fourier_mix.py) - *[FNet: Mixing Tokens with Fourier Transforms, Lee-Thorp et al.](https://arxiv.org/abs/2105.03824v1)* +- [CompositionalAttention](xformers/components/attention/compositional.py) + - *[Compositional Attention: Disentangling search and retrieval, S. Mittal et al.](https://arxiv.org/pdf/2110.09419v1.pdf)* + - ... add a new one [see Contribution.md](CONTRIBUTING.md)

diff --git a/docs/plots/memory_vs_attention.png b/docs/plots/memory_vs_attention.png index 35652a36851b82f997d2f2a0c5b02a90301a1a7e..da43c9501e9c84a3b5c21d40d00f4df221c41211 100644 GIT binary patch literal 35471 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 literal 34360 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 Ub9Byg1^*j4Y^=@UA=3l?52nP`H2?qr diff --git a/docs/plots/runtime_vs_attention.png b/docs/plots/runtime_vs_attention.png index 0b32e683f51bc8c273a69d1ed333c42aae9069be..bc379e9ed8e1da529e47d7a2ea4f44619fde4881 100644 GIT binary patch literal 35099 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 literal 31679 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 diff --git a/examples/microGPT.py b/examples/microGPT.py index fe664d1c1..2a9d9b38a 100644 --- a/examples/microGPT.py +++ b/examples/microGPT.py @@ -68,6 +68,7 @@ def __init__( "dropout": self.hparams.attn_pdrop, "causal": True, "seq_len": self.hparams.block_size, + "num_rules": self.hparams.n_head, }, }, "feedforward_config": { diff --git a/requirements-lra.txt b/requirements-lra.txt index 35e257777..bfe69c2d4 100644 --- a/requirements-lra.txt +++ b/requirements-lra.txt @@ -4,5 +4,6 @@ tensorboard>=2.3.0 tensorflow>=2.3.1 tensorflow-datasets>=4.0.1 +tensorflow-text>=2.7.3 submitit fvcore diff --git a/tests/test_attentions.py b/tests/test_attentions.py index ffa8bee78..3b0fe8632 100644 --- a/tests/test_attentions.py +++ b/tests/test_attentions.py @@ -43,10 +43,12 @@ def _get_multihead( "dropout": attn_dropout, "causal": causal, "seq_len": SEQ, - "window_size": SEQ // 8 + 1, + "window_size": SEQ // 8 + 1, # local attention "attention_query_mask": torch.rand((SEQ, 1)) < GLOBAL_ATTENTION_RATIO, + "dim_model": MODEL, "num_heads": heads, "dim_head": MODEL / heads, + "num_rules": 2, # Compositional Attention } if skip_output_projection: diff --git a/tests/test_block_factory.py b/tests/test_block_factory.py index 24fa0bd7b..bbe22f94a 100644 --- a/tests/test_block_factory.py +++ b/tests/test_block_factory.py @@ -58,10 +58,12 @@ def test_xformer_encoder_block( "window_size": SEQ // 8 + 1, "seq_len": SEQ, "attention_query_mask": torch.rand((SEQ, 1)) < GLOBAL_ATTENTION_RATIO, + "dim_model": MODEL, "num_heads": heads, - "dim_head": MODEL / heads, + "dim_head": MODEL // heads, "layout": torch.eye(SEQ // block_size, SEQ // block_size, dtype=torch.long), "block_size": block_size, + "num_rules": 2, # Compositional Attention } multi_head_config = { @@ -146,11 +148,11 @@ def test_xformer_decoder_block( "causal": causal, "window_size": SEQ // 8 + 1, "seq_len": SEQ, + "dim_head": MODEL // heads, "attention_query_mask": torch.rand((SEQ, 1)) < GLOBAL_ATTENTION_RATIO, - "num_heads": heads, - "dim_head": MODEL / heads, "layout": torch.eye(SEQ // block_size, SEQ // block_size, dtype=torch.long), "block_size": block_size, + "num_rules": 2, # Compositional Attention } multi_head_config = { diff --git a/tests/test_compositional_attention.py b/tests/test_compositional_attention.py new file mode 100644 index 000000000..99484d20b --- /dev/null +++ b/tests/test_compositional_attention.py @@ -0,0 +1,113 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +# +# This source code is licensed under the BSD license found in the +# LICENSE file in the root directory of this source tree. + +import pytest +import torch + +from xformers.components import MultiHeadDispatch + +# Automatically test all the registered attentions +from xformers.components.attention import ( + _DENSITY_THRESHOLD, + ATTENTION_REGISTRY, + build_attention, +) + +DEVICES = ( + [torch.device("cpu")] if not torch.cuda.is_available() else [torch.device("cuda")] +) + +BATCH = 2 +SEQ = 128 if torch.cuda.is_available() else 32 +MODEL = 128 if torch.cuda.is_available() else 64 +GLOBAL_ATTENTION_RATIO = ( + _DENSITY_THRESHOLD * 0.9 +) # Make sure that we test the sparse implementation, no matter the threshold + +assert ATTENTION_REGISTRY.keys(), "Attention layers should have been registered" + + +@pytest.mark.parametrize("attn_dropout", [0.0, 0.3]) +@pytest.mark.parametrize("causal", [True, False]) +@pytest.mark.parametrize("heads", [1, 4]) +@pytest.mark.parametrize("rules", [1, 4]) +@pytest.mark.parametrize("q_compose", [False, True]) +@pytest.mark.parametrize("dim_selection", [MODEL // 2, None]) +@pytest.mark.parametrize("bias", [True, False]) +@pytest.mark.parametrize("qk_rule", [True, False]) +@pytest.mark.parametrize("nonlinear", [True, False]) +@pytest.mark.parametrize("device", DEVICES) +def test_build_and_run( + heads: int, + attn_dropout: float, + causal: bool, + rules: int, + q_compose: bool, + dim_selection: int, + bias: bool, + qk_rule: bool, + nonlinear: bool, + device: torch.device, +): + + torch.manual_seed(42) + + test_config = { + "name": "compositional", + "dropout": attn_dropout, + "causal": causal, + "seq_len": SEQ, + "window_size": SEQ // 8 + 1, # local attention + "attention_query_mask": torch.rand((SEQ, 1)) < GLOBAL_ATTENTION_RATIO, + "dim_model": MODEL, + "num_heads": heads, + "num_rules": 2, # Compositional Attention + "q_compose": q_compose, + "rules": rules, + "dim_selection": dim_selection, + "bias": bias, + "qk_rule": qk_rule, + "nonlinear": nonlinear, + } + + # Add some blocksparse layout to test the corresponding attention + block_size = 16 + test_config["layout"] = torch.eye( + SEQ // block_size, SEQ // block_size, dtype=torch.long + ) + test_config["block_size"] = block_size + + attention = build_attention(test_config) + + # build a multi head dispatch to test this attention mechanism + multi_head = MultiHeadDispatch( + seq_len=SEQ, + dim_model=MODEL, + num_heads=heads, + attention=attention, + residual_dropout=0.0, + ).to(device) + + # Check that a shuffled input produces the same results + seqs = [SEQ, SEQ - 16] + + for seq in seqs: + # Check that we can pass a smaller sequence + inputs = torch.rand(BATCH, seq, MODEL, device=device) + shuffle = torch.randperm(inputs.shape[1]) + inputs_shuffled = inputs[:, shuffle, :].clone() + + results = multi_head(inputs, inputs, inputs) + results_shuffled = multi_head(inputs_shuffled, inputs_shuffled, inputs_shuffled) + + torch.allclose(results[:, shuffle, :], results_shuffled) + + # Test the non-self-attention codepath + att = multi_head(inputs, inputs_shuffled, inputs) + + # Check that dropout actually drops some values + if attn_dropout > 0: + att_2 = multi_head(inputs, inputs_shuffled, inputs) + assert (att != att_2).any() diff --git a/xformers/benchmarks/LRA/code/config.json b/xformers/benchmarks/LRA/code/config.json index d240907e3..c3bfb5830 100644 --- a/xformers/benchmarks/LRA/code/config.json +++ b/xformers/benchmarks/LRA/code/config.json @@ -80,7 +80,7 @@ "eval_frequency": 50, "num_train_steps": 10000, "num_eval_steps": 62, - "gradient_accumulation": 1 + "gradient_accumulation": 2 }, "model": { "pooling_mode": "mean", @@ -94,7 +94,7 @@ }, "xformer": [ { - "reversible": true, + "reversible": false, "block_type": "encoder", "num_layers": 2, "layer_norm_style": "pre", diff --git a/xformers/components/__init__.py b/xformers/components/__init__.py index 2bf470714..bfe4e1281 100644 --- a/xformers/components/__init__.py +++ b/xformers/components/__init__.py @@ -48,6 +48,11 @@ def build_multi_head_attention( "num_heads" ] + if "dim_model" not in multi_head_config["attention"]: + multi_head_config["attention"]["dim_model"] = multi_head_config[ + "dim_model" + ] + if ( "dim_features" not in multi_head_config["attention"] or multi_head_config["attention"]["dim_features"] is None diff --git a/xformers/components/attention/attention_mask.py b/xformers/components/attention/attention_mask.py index 93e1f30ef..526411844 100644 --- a/xformers/components/attention/attention_mask.py +++ b/xformers/components/attention/attention_mask.py @@ -24,7 +24,7 @@ class AttentionMask: """ def __init__(self, additive_mask: torch.Tensor, is_causal: bool = False): - assert additive_mask.is_floating_point() + assert additive_mask.is_floating_point(), additive_mask.dtype assert not additive_mask.requires_grad if additive_mask.ndim == 2: @@ -49,7 +49,7 @@ def from_bool(cls: Type[Self], x: torch.Tensor) -> Self: """ assert x.dtype == torch.bool - additive_mask = torch.empty_like(x, dtype=torch.float) + additive_mask = torch.empty_like(x, dtype=torch.float, device=x.device) additive_mask.masked_fill_(x, 0.0) additive_mask.masked_fill_(~x, float("-inf")) @@ -62,7 +62,7 @@ def from_multiplicative(cls: Type[Self], x: torch.Tensor) -> Self: """ assert not x.dtype == torch.bool - additive_mask = torch.empty_like(x, dtype=torch.float) + additive_mask = torch.empty_like(x, dtype=torch.float, device=x.device) x = x.bool() additive_mask.masked_fill_(x, 0.0) diff --git a/xformers/components/attention/base.py b/xformers/components/attention/base.py index 4728a0db2..511dcd04f 100644 --- a/xformers/components/attention/base.py +++ b/xformers/components/attention/base.py @@ -11,6 +11,8 @@ import torch import torch.nn as nn +from xformers.components.attention import AttentionMask + @dataclass class AttentionConfig: @@ -29,7 +31,7 @@ class AttentionConfig: class Attention(nn.Module, metaclass=ABCMeta): r"""The base Attention mechanism, which is typically a sub-part of the multi-head attention""" - _causal_mask: Optional[torch.Tensor] = None + _causal_mask: Optional[AttentionMask] = None @abstractmethod def __init__(self, dropout: Optional[float] = None, *args, **kwargs): @@ -47,6 +49,10 @@ def __init__(self, dropout: Optional[float] = None, *args, **kwargs): # Requires that K and Q have the same sequence length self.requires_same_k_q_dimensions = False + # Whether the attention owns the single head/multihead mechanism + # so that the MHA wrapper should skip it + self.requires_skip_multi_head = False + @classmethod def from_config(cls: Type[Self], config: AttentionConfig) -> Self: # Generate the class inputs from the config diff --git a/xformers/components/attention/compositional.py b/xformers/components/attention/compositional.py new file mode 100644 index 000000000..8d9276f4e --- /dev/null +++ b/xformers/components/attention/compositional.py @@ -0,0 +1,337 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +# +# This source code is licensed under the BSD license found in the +# LICENSE file in the root directory of this source tree. + + +# Credits: this is heavily inspired by the official implementation, present in +# https://github.com/sarthmit/Compositional-Attention +# Original author: Sarthak Mittal + +# This is a simplified version, for the sake of clarity, and because some features could be exposed later +# via the library directly. +# In particular, code paths for TPUs, quantization and gumbel softmax have been removed +# We're also following the same dimension ordering as in the rest of the xformers library +# which is to say [Batch, Sequence, Embedding] wherever possible + +import math +from dataclasses import dataclass +from typing import Optional + +import torch +import torch.nn.functional as F +from torch import Tensor, nn + +from xformers.components.attention import ( + Attention, + AttentionConfig, + AttentionMask, + register_attention, +) +from xformers.components.attention.core import _softmax +from xformers.components.in_proj_container import InProjContainer, InProjParams + + +def _either_or(a: Optional[int], b: int) -> int: + return a if a is not None else b + + +@dataclass +class CompositionalAttentionConfig(AttentionConfig): + dim_model: int + num_heads: int + dim_attn: Optional[int] = None + num_rules: Optional[int] = None + dim_key: Optional[int] = None + dim_value: Optional[int] = None + dim_selection: Optional[int] = None + dropout: float + qk_rule: bool = False + nonlinear: bool = False + q_compose: bool = False + bias: bool = True + causal: Optional[bool] = False + in_proj_container: Optional[InProjContainer] = None + use_separate_proj_weight: Optional[bool] = False + + +@register_attention("compositional", CompositionalAttentionConfig) +class CompositionalAttention(Attention): + """Compositional Attention, as proposed in + "Compositional Attention: Disentangling search and retrieval"_, S. Mittal et al. + + A key insight from this proposal is that the attention mechanism can be conceived as two steps: + a search and a retrieval operation. When queried, the model can search for the most relevant information + (Softmax(QKt)), then retrieve information given the Value. + + Contrary to the original attention proposal, which does not consider interactions in between heads, + the comppositional attention will consider all possible interactions and softmax over that dimension, + so that the information retrieved covers the most relevant dimensions. The number of heads and rules to + use is thus typically smaller than for a comparable traditional Transformer, and asking for the same number of heads + may not fit in memory. + + Args: + dim_model: dimension of the incoming latent space + num_heads: number of heads *for the search operation* + dim_attn: dimension (embedding) of the attention + num_rules: number of rules to consider *for the retrieval operation* + dim_selection: dimension of the scoring/selection space for the retrievals + dim_key, dim_value: dimensions of K and V, if different from Q + dropout: attention dropout probability + qk_rule: QK product will drive the retrieval process + nonlinear: use a non linear method to score the retrievals + bias: use bias in the initial projection step + causal: causal computations (attend to the past only) + + _"Compositional Attention: Disentangling search and retrieval": https://arxiv.org/pdf/2110.09419v1.pdf + """ + + def __init__( + self, + dim_model: int, + num_heads: int, + dim_attn: Optional[int] = None, + num_rules: Optional[int] = None, + dim_selection: Optional[int] = None, + dim_key: Optional[int] = None, + dim_value: Optional[int] = None, + dropout=0.0, + qk_rule=False, + nonlinear=False, + q_compose=False, + in_proj_container: Optional[InProjContainer] = None, + use_separate_proj_weight: Optional[bool] = False, + bias=True, + causal=False, + *_, + **__, + ): + super().__init__() + + # Define the inherited flags + self.requires_skip_multi_head = ( + True # This attention owns the multi-head mechanism + ) + + # Handle defaults / undefined values + self.dim_model = dim_model + num_rules = _either_or(num_rules, num_heads) + dim_selection = _either_or(dim_selection, dim_model // num_heads) + + # All the initial definition plumbing + dim_attn = _either_or(dim_attn, dim_model) + dim_key = _either_or(dim_key, dim_model) + dim_value = _either_or(dim_value, dim_model) + + self.in_proj_container = ( + in_proj_container + if in_proj_container is not None + else InProjContainer( + query_proj_params=InProjParams(dim_model, dim_key, bias=bias), + key_proj_params=InProjParams(dim_model, dim_key, bias=bias) + if use_separate_proj_weight + else None, + value_proj_params=InProjParams(dim_model, dim_value, bias=bias) + if use_separate_proj_weight + else None, + ) + ) + + self.num_heads = num_heads + self.num_rules = num_rules + self.qk_rule = qk_rule + self.dim_selection = dim_selection + self.nonlinear = nonlinear + self.q_compose = q_compose + + self.dropout_module = nn.Dropout(dropout) + self.dim_head = dim_model // num_heads + self.value_dim = dim_attn // num_rules + + assert ( + self.value_dim * num_rules == dim_attn + ), "value_dim must be divisible by num_rules" + + self.scaling = self.dim_head ** -0.5 + self.scaling_values = self.dim_selection ** -0.5 + + self.out_proj = nn.Linear(self.num_heads * self.value_dim, dim_model, bias=bias) + + if self.qk_rule: + self.value_k = nn.Linear(self.value_dim, self.dim_selection, bias=bias) + if self.q_compose: + self.value_q = nn.Linear(self.dim_head, self.dim_selection, bias=bias) + else: + self.value_q = nn.Linear( + dim_model, self.dim_selection * self.num_heads, bias=bias + ) + else: + if self.q_compose: + self.value_q = nn.Linear(self.dim_head, self.dim_selection, bias=bias) + else: + self.value_q = nn.Linear( + dim_model, self.dim_selection * self.num_heads, bias=bias + ) + if self.nonlinear: + self.score_network: nn.Module = nn.Sequential( + nn.Linear( + self.dim_selection + self.value_dim, + self.dim_selection, + bias=bias, + ), + nn.ReLU(), + nn.Linear(self.dim_selection, 1, bias=bias), + ) + else: + self.score_network = nn.Linear( + self.dim_selection + self.value_dim, 1, bias=bias + ) + + self.causal = causal + + self._reset_parameters() + + def _reset_parameters(self): + # NOTE: in_proj_container is already initialized + + if self.qk_rule: + nn.init.xavier_uniform_(self.value_k.weight, gain=1 / math.sqrt(2)) + nn.init.xavier_uniform_(self.value_q.weight, gain=1 / math.sqrt(2)) + else: + nn.init.xavier_uniform_(self.value_q.weight) + if self.nonlinear: + nn.init.xavier_uniform_(self.score_network[0].weight) + nn.init.xavier_uniform_(self.score_network[2].weight) + else: + nn.init.xavier_uniform_(self.score_network.weight) + + nn.init.xavier_uniform_(self.out_proj.weight) + if self.out_proj.bias is not None: + nn.init.constant_(self.out_proj.bias, 0.0) + + def forward( + self, + q: Tensor, + k: Tensor, + v: Tensor, + att_mask: Optional[Tensor] = None, + *args, + **kwargs, + ) -> Tensor: + """ + Input shape: Time x Batch x Channel + + Args: + attn_mask (ByteTensor, optional): typically used to + implement causal attention, where the mask prevents the + attention from looking forward in time (default: None). + """ + + B, Sq, E = q.shape + _, Sk, _ = k.shape + + assert E == self.dim_model + + # First define projected query/key/values + # We keep the projected and original tensors in flight, + # depending on the options the original values could be reused + q_unprojected = q + q, k, v = self.in_proj_container(query=q, key=k, value=v) + q *= self.scaling + + # Init causal mask if needed, now that we know the context length + if self.causal and ( + self._causal_mask is None or self._causal_mask.shape[0] != Sk + ): + self._causal_mask = AttentionMask.make_causal(Sq, Sq, device=q.device) + + # Convenience, create an attention mask if a tensor was passed + # This sanitizes different mask types being passed, from now on it's additive + if isinstance(att_mask, torch.Tensor): + # By default we don't know of the causality, and a check would be expensive + att_mask_additive: Optional[AttentionMask] = ( + AttentionMask.from_bool(att_mask) + if att_mask.dtype == torch.bool + else AttentionMask(att_mask, is_causal=False) + ) + else: + att_mask_additive = None + + # Handle the attention and key padding masks + if self._causal_mask is not None: + # Optionally add the causal mask + if att_mask_additive is not None: + att_mask_additive += self._causal_mask + else: + att_mask_additive = self._causal_mask + + # Flatten the heads or the rules + q = ( + q.view(B, Sq, self.num_heads, self.dim_head) + .movedim(2, 1) + .flatten(0, 1) # [B * num_heads, Sq, dim_head] + ) + k = ( + k.view(B, Sk, self.num_heads, self.dim_head).movedim(2, 1).flatten(0, 1) + ) # [B * num_heads, Sk, dim_head] + v = v.view(B, -1, self.num_rules, self.value_dim).movedim(2, 1).flatten(0, 1) + + # Compute the search: Softmax(QKt) + attn_weights = torch.bmm(q, k.transpose(1, 2)) # [B * self.num_heads, Sq, Sk] + + if att_mask_additive is not None: + attn_weights += att_mask_additive.values + + attn_weights = _softmax(attn_weights, causal=self.causal) + + attn_weights = attn_weights.view(B, self.num_heads, Sq, Sk) + attn_probs = self.dropout_module(attn_weights) + + # Now compute the information retrieval + # keep all the heads in flight, we'll score the different possibilities + # - compute all the possible retrievals + v = v.view(B, 1, self.num_rules, Sk, self.value_dim) + attn_probs = attn_probs.unsqueeze(2) + attn = torch.matmul(attn_probs, v).view( + B, self.num_heads, self.num_rules, Sq, self.value_dim + ) + + attn = attn.movedim(3, 1) # [B, Sq, H, Rules, Values] + + # - search the most appropriate retrieval among all the values + if self.q_compose: + v_q = self.value_q(q.transpose(0, 1)).view( + B, Sq, self.num_heads, 1, self.dim_selection + ) + else: + v_q = self.value_q(q_unprojected).view( + B, Sq, self.num_heads, 1, self.dim_selection + ) + + if self.qk_rule: + v_q *= self.scaling_values + v_k = ( + self.value_k(attn) + .view(B, Sq, self.num_heads, self.num_rules, self.dim_selection) + .transpose(4, 3) + .contiguous() + ) + v_score = torch.matmul(v_q, v_k).view( + B, Sq, self.num_heads, self.num_rules, 1 + ) + else: + v_q = v_q.expand(-1, -1, -1, self.num_rules, -1) + v_in = torch.cat([attn, v_q], dim=-1) + v_score = self.score_network(v_in).view( + B, Sq, self.num_heads, self.num_rules, 1 + ) + + v_score = F.softmax(v_score, dim=3) + + # - extracted values are the original attention (inc. all the values) weighted by value score + attn = (attn * v_score).sum(dim=3).view(B, Sq, self.num_heads * self.value_dim) + + # Final attention projection, same as other mechanisms + attn = self.out_proj(attn) + + return attn diff --git a/xformers/components/attention/favor.py b/xformers/components/attention/favor.py index 3f80a8065..340da110e 100644 --- a/xformers/components/attention/favor.py +++ b/xformers/components/attention/favor.py @@ -50,7 +50,8 @@ def __init__( **__, ): r""" - Kernelized attention, as proposed in Performers_. + Kernelized attention, as proposed in Performers_ + ("Rethinking attention with performers." K. Choromanski et al. (2020).). FAVOR stands for "Fast Attention Via positive Orthogonal Random features" @@ -61,8 +62,7 @@ def __init__( feature_map_type (FeatureMapType): the type of feature map being used, for instance orthogonal random features. - .. _Performers: "Rethinking attention with performers." K. Choromanski et al. (2020). - https://arxiv.org/pdf/2009.14794v1.pdf + .. _Performers: https://arxiv.org/pdf/2009.14794v1.pdf """ super().__init__() diff --git a/xformers/components/multi_head_dispatch.py b/xformers/components/multi_head_dispatch.py index 8e83dd629..104062e8b 100644 --- a/xformers/components/multi_head_dispatch.py +++ b/xformers/components/multi_head_dispatch.py @@ -127,6 +127,7 @@ def forward( key: Optional[torch.Tensor] = None, value: Optional[torch.Tensor] = None, att_mask: Optional[torch.Tensor] = None, + key_padding_mask: Optional[torch.Tensor] = None, ) -> torch.Tensor: """ Expected input dimensions are [batch size, sequence length, embed dim] @@ -158,6 +159,11 @@ def forward( + "In that case causality is ill-determined. Please pad your sequences accordingly" ) + if self.attention.requires_skip_multi_head: + return self.attention( + query, key, value, att_mask=att_mask, key_padding_mask=key_padding_mask + ) + # Calculate query, key, values for all heads in batch if self.attention.requires_input_projection: q, k, v = self.in_proj_container(query=query, key=key, value=value) @@ -187,7 +193,9 @@ def forward( v = reshape_fn(v, B, S_K, self.num_heads, self.dim_k) # Self-attend - y = self.attention(q=q, k=k, v=v, att_mask=att_mask) + y = self.attention( + q=q, k=k, v=v, att_mask=att_mask, key_padding_mask=key_padding_mask + ) # Re-assemble all head outputs side by side y = (