Install colt5-attention
mainInstall the package via pip:
$ pip install colt5-attentionrepository·main·Indexed 42 days ago
https://github.com/lucidrains/colt5-attentionA PyTorch implementation of conditionally routed efficient attention and feedforward blocks based on the CoLT5 architecture. Version 0.11.2 features coordinate descent to route tokens to high-capacity branches, supporting long sequences and high-resolution images via ConditionalRoutedAttention, ConditionalRoutedFeedForward, and ConditionalRoutedViT.
Install the package via pip:
$ pip install colt5-attentionThe ConditionalRoutedAttention implements conditionally routed efficient attention. It uses a light branch with a local attention receptive field (light_window_size) and a heavy branch that receives a specific number of routed tokens for both queries and key-values.
import torch
from colt5_attention import ConditionalRoutedAttention
tokens = torch.randn(2, 32768, 512)
mask = torch.ones(2, 32768).bool()
attn = ConditionalRoutedAttention(
dim = 512,
light_dim_head = 64,
light_heads = 8,
light_window_size = 128,
heavy_dim_head = 64,
heavy_heads = 8,
num_heavy_tokens_q = 1024,
num_heavy_tokens_kv = 1024
)
attn_out = attn(tokens, mask = mask) # (2, 32768, 512)The ConditionalRoutedTransformerBlock combines both routed attention and routed feedforward with residual connections. A stack of these blocks constitutes a CoLT5 encoder.
import torch
from colt5_attention import ConditionalRoutedTransformerBlock
tokens = torch.randn(2, 32768, 512)
mask = torch.ones(2, 32768).bool()
block = ConditionalRoutedTransformerBlock(
dim = 512,
light_dim_head = 64,
light_heads = 8,
light_window_size = 128,
heavy_dim_head = 64,
heavy_heads = 8,
light_ff_mult = 0.5,
heavy_ff_mult = 4,
num_heavy_ff_tokens = 1024,
num_heavy_attn_tokens_q = 1024,
num_heavy_attn_tokens_kv = 1024
)
block_out = block(tokens, mask = mask) # (2, 32768, 512)The ConditionalRoutedImageAttention is designed for high-resolution image feature maps. It uses a local window patch for the light branch and routed attention for the heavy branch.
Key parameters:
channel_first: Set to True if the input has channels before spatial dimensions.import torch
from colt5_attention import ConditionalRoutedImageAttention
attn = ConditionalRoutedImageAttention(
dim = 32,
light_dim_head = 64,
light_heads = 8,
light_window_size = 32,
channel_first = True,
heavy_dim_head = 64,
heavy_heads = 8,
num_heavy_tokens_q = 1024,
num_heavy_tokens_kv = 1024
).cuda()
fmap = torch.randn(1, 32, 256, 256).cuda()
out = attn(fmap)The ConditionalRoutedAutoregressiveAttention is an improvised version for autoregressive generation. It views the sequence in windows where each window attends to past windows. The light branch handles intra-window attention.
Key parameters:
heavy_window_size: The windowing for the routed heavy attention. If this is greater than light_window_size, some tokens might be missed.num_routed_kv: Splits attention heads so groups attend to different sets of key-values.use_triton: Highly recommended for viability.use_flash_attn: Enables flash attention in the heavy branch.import torch
from colt5_attention import ConditionalRoutedAutoregressiveAttention
tokens = torch.randn(2, 8192, 512).cuda()
attn = ConditionalRoutedAutoregressiveAttention(
dim = 512,
light_dim_head = 64,
light_heads = 8,
light_window_size = 128,
heavy_window_size = 128,
heavy_dim_head = 64,
heavy_heads = 8,
num_heavy_tokens_q = 32,
num_heavy_tokens_kv = 1024,
num_routed_kv = 2,
use_triton = True,
use_flash_attn = True
).cuda()
attn_out = attn(tokens) + tokensThe ConditionalRoutedViT is a Vision Transformer implementation using coordinate descent routed attention and feedforward.
import torch
from colt5_attention.vit import ConditionalRoutedViT
vit = ConditionalRoutedViT(
image_size = 256,
patch_size = 32,
num_classes = 1000,
dim = 1024,
depth = 6,
attn_num_heavy_tokens_q = 16,
attn_num_heavy_tokens_kv = 16,
attn_heavy_dim_head = 64,
attn_heavy_heads = 8,
attn_light_window_size = 4,
attn_light_dim_head = 32,
attn_light_heads = 4,
ff_num_heavy_tokens = 16,
ff_heavy_mult = 4,
ff_light_mult = 2
)
images = torch.randn(1, 3, 256, 256)
logits = vit(images)The topk function provides a differentiable version of topk using a small wrapper around coordinate descent.
Returns:
values: The values, which have already been multiplied by the gates.indices: The topk indices.coor_descent_values: The coordinate descent values.gates: The routing gates.import torch
from colt5_attention import topk
x = torch.randn(1024, 512)
values, indices, coor_descent_values, gates = topk(x, k = 10, fused = True)The ConditionalRoutedFeedForward implements a routed feedforward block where a subset of tokens is routed to a 'heavy' branch with a larger hidden dimension, while the rest use a 'light' branch. The outputs are summed.
import torch
from colt5_attention import ConditionalRoutedFeedForward
tokens = torch.randn(2, 32768, 512)
mask = torch.ones(2, 32768).bool()
ff = ConditionalRoutedFeedForward(
dim = 512,
light_ff_mult = 0.5, # hidden dimension ratio of light branch
heavy_ff_mult = 4, # hidden dimension ratio of heavy branch
num_heavy_tokens = 1024 # heavy branch receives only 1024 routed tokens of 32768
)
ff_out = ff(tokens, mask = mask) # (2, 32768, 512)The ConditionalRoutedCrossAttention is designed for attending to very long context memories (e.g., in Transformer-XL). It allows routing a subset of queries and a subset of key-values from the memory.
Key parameters:
kv_routing_tokens: Specifies how many routing tokens to use to split attention heads into groups that attend to different sets of key/values.use_triton: Set to True to use the optimized CUDA kernel.route_block_size: The size of blocks used for routing.import torch
from colt5_attention import ConditionalRoutedCrossAttention
tokens = torch.randn(1, 1024, 512).cuda()
tokens_mask = torch.ones(1, 1024).bool().cuda()
memories = torch.randn(1, 1_048_576, 512).cuda()
memories_mask = torch.ones(1, 1_048_576).bool().cuda()
cross_attn = ConditionalRoutedCrossAttention(
dim = 512,
dim_head = 64,
heads = 8,
num_tokens_q = 512,
num_tokens_kv = 1024,
kv_routing_tokens = 2,
use_triton = True,
route_block_size = 131072
).cuda()
cross_attn_out = cross_attn(
tokens,
context = memories,
mask = tokens_mask,
context_mask = memories_mask
)