From 6db20debb4c882cfde8a1759aa56e4fc295f0713 Mon Sep 17 00:00:00 2001 From: Phil Wang Date: Tue, 1 Mar 2022 16:50:17 -0800 Subject: [PATCH] add patch merger --- README.md | 62 +++++++++++- images/patch_merger.png | Bin 0 -> 55266 bytes setup.py | 2 +- vit_pytorch/vit_with_patch_merger.py | 144 +++++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 images/patch_merger.png create mode 100644 vit_pytorch/vit_with_patch_merger.py diff --git a/README.md b/README.md index 1eb3abb..edb97ee 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ - [Simple Masked Image Modeling](#simple-masked-image-modeling) - [Masked Patch Prediction](#masked-patch-prediction) - [Adaptive Token Sampling](#adaptive-token-sampling) +- [Patch Merger](#patch-merger) - [Vision Transformer for Small Datasets](#vision-transformer-for-small-datasets) - [Dino](#dino) - [Accessing Attention](#accessing-attention) @@ -732,12 +733,58 @@ v = ViT( img = torch.randn(4, 3, 256, 256) -preds = v(img) # (1, 1000) +preds = v(img) # (4, 1000) # you can also get a list of the final sampled patch ids # a value of -1 denotes padding -preds, token_ids = v(img, return_sampled_token_ids = True) # (1, 1000), (1, <=8) +preds, token_ids = v(img, return_sampled_token_ids = True) # (4, 1000), (4, <=8) +``` + +## Patch Merger + + + + +This paper proposes a simple module (Patch Merger) for reducing the number of tokens at any layer of a vision transformer without sacrificing performance. + +```python +import torch +from vit_pytorch.vit_with_patch_merger import ViT + +v = ViT( + image_size = 256, + patch_size = 16, + num_classes = 1000, + dim = 1024, + depth = 12, + heads = 8, + patch_merge_layer = 6, # at which transformer layer to do patch merging + patch_merge_num_tokens = 8, # the output number of tokens from the patch merge + mlp_dim = 2048, + dropout = 0.1, + emb_dropout = 0.1 +) + +img = torch.randn(4, 3, 256, 256) + +preds = v(img) # (4, 1000) +``` + +One can also use the `PatchMerger` module by itself + +```python +import torch +from vit_pytorch.vit_with_patch_merger import PatchMerger + +merger = PatchMerger( + dim = 1024, + num_tokens_out = 8 # output number of tokens +) + +features = torch.randn(4, 256, 1024) # (batch, num tokens, dimension) + +out = merger(features) # (4, 8, 1024) ``` ## Vision Transformer for Small Datasets @@ -1294,6 +1341,17 @@ Coming from computer vision and new to transformers? Here are some resources tha } ``` +```bibtex +@misc{renggli2022learning, + title = {Learning to Merge Tokens in Vision Transformers}, + author = {Cedric Renggli and André Susano Pinto and Neil Houlsby and Basil Mustafa and Joan Puigcerver and Carlos Riquelme}, + year = {2022}, + eprint = {2202.12015}, + archivePrefix = {arXiv}, + primaryClass = {cs.CV} +} +``` + ```bibtex @misc{vaswani2017attention, title = {Attention Is All You Need}, diff --git a/images/patch_merger.png b/images/patch_merger.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a537c7923e6e4e05d9f1a0a0d1ee7729f58fd3 GIT binary patch literal 55266 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 Z{tsS1!E92_biV)q002ovPDHLkV1lE638w%6 literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index 122e5b0..9f50a6d 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages setup( name = 'vit-pytorch', packages = find_packages(exclude=['examples']), - version = '0.26.7', + version = '0.27.0', license='MIT', description = 'Vision Transformer (ViT) - Pytorch', author = 'Phil Wang', diff --git a/vit_pytorch/vit_with_patch_merger.py b/vit_pytorch/vit_with_patch_merger.py new file mode 100644 index 0000000..3106bb3 --- /dev/null +++ b/vit_pytorch/vit_with_patch_merger.py @@ -0,0 +1,144 @@ +import torch +from torch import nn + +from einops import rearrange, repeat +from einops.layers.torch import Rearrange, Reduce + +# helpers + +def exists(val): + return val is not None + +def default(val ,d): + return val if exists(val) else d + +def pair(t): + return t if isinstance(t, tuple) else (t, t) + +# patch merger class + +class PatchMerger(nn.Module): + def __init__(self, dim, num_tokens_out): + super().__init__() + self.scale = dim ** -0.5 + self.norm = nn.LayerNorm(dim) + self.queries = nn.Parameter(torch.randn(num_tokens_out, dim)) + + def forward(self, x): + x = self.norm(x) + sim = torch.matmul(self.queries, x.transpose(-1, -2)) * self.scale + attn = sim.softmax(dim = -1) + return torch.matmul(attn, x) + +# classes + +class PreNorm(nn.Module): + def __init__(self, dim, fn): + super().__init__() + self.norm = nn.LayerNorm(dim) + self.fn = fn + def forward(self, x, **kwargs): + return self.fn(self.norm(x), **kwargs) + +class FeedForward(nn.Module): + def __init__(self, dim, hidden_dim, dropout = 0.): + super().__init__() + self.net = nn.Sequential( + nn.Linear(dim, hidden_dim), + nn.GELU(), + nn.Dropout(dropout), + nn.Linear(hidden_dim, dim), + nn.Dropout(dropout) + ) + def forward(self, x): + return self.net(x) + +class Attention(nn.Module): + def __init__(self, dim, heads = 8, dim_head = 64, dropout = 0.): + super().__init__() + inner_dim = dim_head * heads + project_out = not (heads == 1 and dim_head == dim) + + self.heads = heads + self.scale = dim_head ** -0.5 + + self.attend = nn.Softmax(dim = -1) + self.to_qkv = nn.Linear(dim, inner_dim * 3, bias = False) + + self.to_out = nn.Sequential( + nn.Linear(inner_dim, dim), + nn.Dropout(dropout) + ) if project_out else nn.Identity() + + def forward(self, x): + qkv = self.to_qkv(x).chunk(3, dim = -1) + q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.heads), qkv) + + dots = torch.matmul(q, k.transpose(-1, -2)) * self.scale + + attn = self.attend(dots) + + out = torch.matmul(attn, v) + out = rearrange(out, 'b h n d -> b n (h d)') + return self.to_out(out) + +class Transformer(nn.Module): + def __init__(self, dim, depth, heads, dim_head, mlp_dim, dropout = 0., patch_merge_layer = None, patch_merge_num_tokens = 8): + super().__init__() + self.layers = nn.ModuleList([]) + + self.patch_merge_layer_index = default(patch_merge_layer, depth // 2) - 1 # default to mid-way through transformer, as shown in paper + self.patch_merger = PatchMerger(dim = dim, num_tokens_out = patch_merge_num_tokens) + + for _ in range(depth): + self.layers.append(nn.ModuleList([ + PreNorm(dim, Attention(dim, heads = heads, dim_head = dim_head, dropout = dropout)), + PreNorm(dim, FeedForward(dim, mlp_dim, dropout = dropout)) + ])) + def forward(self, x): + for index, (attn, ff) in enumerate(self.layers): + x = attn(x) + x + x = ff(x) + x + + if index == self.patch_merge_layer_index: + x = self.patch_merger(x) + + return x + +class ViT(nn.Module): + def __init__(self, *, image_size, patch_size, num_classes, dim, depth, heads, mlp_dim, patch_merge_layer = None, patch_merge_num_tokens = 8, channels = 3, dim_head = 64, dropout = 0., emb_dropout = 0.): + super().__init__() + image_height, image_width = pair(image_size) + patch_height, patch_width = pair(patch_size) + + assert image_height % patch_height == 0 and image_width % patch_width == 0, 'Image dimensions must be divisible by the patch size.' + + num_patches = (image_height // patch_height) * (image_width // patch_width) + patch_dim = channels * patch_height * patch_width + + self.to_patch_embedding = nn.Sequential( + Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = patch_height, p2 = patch_width), + nn.Linear(patch_dim, dim), + ) + + self.pos_embedding = nn.Parameter(torch.randn(1, num_patches + 1, dim)) + self.dropout = nn.Dropout(emb_dropout) + + self.transformer = Transformer(dim, depth, heads, dim_head, mlp_dim, dropout, patch_merge_layer, patch_merge_num_tokens) + + self.mlp_head = nn.Sequential( + Reduce('b n d -> b d', 'mean'), + nn.LayerNorm(dim), + nn.Linear(dim, num_classes) + ) + + def forward(self, img): + x = self.to_patch_embedding(img) + b, n, _ = x.shape + + x += self.pos_embedding[:, :n] + x = self.dropout(x) + + x = self.transformer(x) + + return self.mlp_head(x)