2022-12-23 09:19:45 +08:00
|
|
|
""" Position Embedding Utilities
|
|
|
|
|
|
|
|
Hacked together by / Copyright 2022 Ross Wightman
|
|
|
|
"""
|
|
|
|
import logging
|
2022-03-01 05:56:23 +08:00
|
|
|
import math
|
|
|
|
from typing import List, Tuple, Optional, Union
|
|
|
|
|
|
|
|
import torch
|
2022-12-23 09:19:45 +08:00
|
|
|
import torch.nn.functional as F
|
2022-03-01 05:56:23 +08:00
|
|
|
|
2022-12-23 09:19:45 +08:00
|
|
|
from .helpers import to_2tuple
|
2022-03-01 05:56:23 +08:00
|
|
|
|
2022-12-23 09:19:45 +08:00
|
|
|
_logger = logging.getLogger(__name__)
|
2022-03-01 05:56:23 +08:00
|
|
|
|
|
|
|
|
2022-12-23 09:19:45 +08:00
|
|
|
def resample_abs_pos_embed(
|
|
|
|
posemb,
|
|
|
|
new_size: List[int],
|
|
|
|
old_size: Optional[List[int]] = None,
|
|
|
|
num_prefix_tokens: int = 1,
|
|
|
|
interpolation: str = 'bicubic',
|
|
|
|
antialias: bool = True,
|
|
|
|
verbose: bool = False,
|
2022-03-01 05:56:23 +08:00
|
|
|
):
|
2022-12-23 09:19:45 +08:00
|
|
|
# sort out sizes, assume square if old size not provided
|
2023-05-10 08:59:22 +08:00
|
|
|
num_pos_tokens = posemb.shape[1]
|
|
|
|
num_new_tokens = new_size[0] * new_size[1] + num_prefix_tokens
|
|
|
|
if num_new_tokens == num_pos_tokens and new_size[0] == new_size[1]:
|
2022-12-23 09:19:45 +08:00
|
|
|
return posemb
|
|
|
|
|
2023-05-10 08:59:22 +08:00
|
|
|
if not old_size:
|
|
|
|
hw = int(math.sqrt(num_pos_tokens - num_prefix_tokens))
|
|
|
|
old_size = hw, hw
|
|
|
|
|
2022-12-23 09:19:45 +08:00
|
|
|
if num_prefix_tokens:
|
|
|
|
posemb_prefix, posemb = posemb[:, :num_prefix_tokens], posemb[:, num_prefix_tokens:]
|
|
|
|
else:
|
|
|
|
posemb_prefix, posemb = None, posemb
|
2022-03-01 05:56:23 +08:00
|
|
|
|
2022-12-23 09:19:45 +08:00
|
|
|
# do the interpolation
|
2023-05-10 08:59:22 +08:00
|
|
|
embed_dim = posemb.shape[-1]
|
2022-12-23 09:19:45 +08:00
|
|
|
posemb = posemb.reshape(1, old_size[0], old_size[1], -1).permute(0, 3, 1, 2)
|
|
|
|
posemb = F.interpolate(posemb, size=new_size, mode=interpolation, antialias=antialias)
|
2023-05-10 08:59:22 +08:00
|
|
|
posemb = posemb.permute(0, 2, 3, 1).reshape(1, -1, embed_dim)
|
2022-03-01 05:56:23 +08:00
|
|
|
|
2022-12-23 09:19:45 +08:00
|
|
|
# add back extra (class, etc) prefix tokens
|
|
|
|
if posemb_prefix is not None:
|
|
|
|
posemb = torch.cat([posemb_prefix, posemb], dim=1)
|
2023-05-10 08:59:22 +08:00
|
|
|
|
|
|
|
if not torch.jit.is_scripting() and verbose:
|
|
|
|
_logger.info(f'Resized position embedding: {old_size} to {new_size}.')
|
|
|
|
|
2022-12-23 09:19:45 +08:00
|
|
|
return posemb
|
2023-05-19 07:43:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
def resample_abs_pos_embed_nhwc(
|
|
|
|
posemb,
|
|
|
|
new_size: List[int],
|
|
|
|
interpolation: str = 'bicubic',
|
|
|
|
antialias: bool = True,
|
|
|
|
verbose: bool = False,
|
|
|
|
):
|
|
|
|
if new_size[0] == posemb.shape[-3] and new_size[1] == posemb.shape[-2]:
|
|
|
|
return posemb
|
|
|
|
|
|
|
|
# do the interpolation
|
|
|
|
posemb = posemb.reshape(1, posemb.shape[-3], posemb.shape[-2], posemb.shape[-1]).permute(0, 3, 1, 2)
|
|
|
|
posemb = F.interpolate(posemb, size=new_size, mode=interpolation, antialias=antialias)
|
|
|
|
posemb = posemb.permute(0, 2, 3, 1)
|
|
|
|
|
|
|
|
if not torch.jit.is_scripting() and verbose:
|
|
|
|
_logger.info(f'Resized position embedding: {posemb.shape[-3:-1]} to {new_size}.')
|
|
|
|
|
|
|
|
return posemb
|