U
    ¯Ê¹jï  ã                   @   s˜   d Z ddlmZ ddlZddlmZ ddlm  mZ ddl	m
Z
mZ ddlmZ ddlmZ ee dœd	d
„ZG dd„ dejƒZG dd„ dejƒZdS )aP   Bottleneck Self Attention (Bottleneck Transformers)

Paper: `Bottleneck Transformers for Visual Recognition` - https://arxiv.org/abs/2101.11605

@misc{2101.11605,
Author = {Aravind Srinivas and Tsung-Yi Lin and Niki Parmar and Jonathon Shlens and Pieter Abbeel and Ashish Vaswani},
Title = {Bottleneck Transformers for Visual Recognition},
Year = {2021},
}

Based on ref gist at: https://gist.github.com/aravindsrinivas/56359b79f0ce4449bcb04ab4b56a57a2

This impl is a WIP but given that it is based on the ref gist likely not too far off.

Hacked together by / Copyright 2021 Ross Wightman
é    )ÚListNé   )Ú	to_2tupleÚmake_divisible)Útrunc_normal_)Ú_assert©Úpermute_maskc           	      C   sÀ   | j \}}}}| | dd¡ }| d|d| d ¡}t |ddg¡ d¡}t |d|d g¡}| d|d d| d ¡}|dd…d|…|d d…f }| ||d||¡ dd|dd¡}| |¡S )a„   Compute relative logits along one dimension

    As per: https://gist.github.com/aravindsrinivas/56359b79f0ce4449bcb04ab4b56a57a2
    Originally from: `Attention Augmented Convolutional Networks` - https://arxiv.org/abs/1904.09925

    Args:
        q: (batch, heads, height, width, dim)
        rel_k: (2 * width - 1, dim)
        permute_mask: permute output dim according to this
    éÿÿÿÿéþÿÿÿé   r   r   N)ÚshapeÚ	transposeÚreshapeÚFÚpadÚflattenÚexpandZpermute)	ÚqZrel_kr	   ÚBÚHÚWÚdimÚxZx_pad© r   úZ/var/www/html/bwave/python/venv/lib/python3.8/site-packages/timm/layers/bottleneck_attn.pyÚrel_logits_1d   s     r   c                       s(   e Zd ZdZ‡ fdd„Zdd„ Z‡  ZS )ÚPosEmbedRelzÛ Relative Position Embedding
    As per: https://gist.github.com/aravindsrinivas/56359b79f0ce4449bcb04ab4b56a57a2
    Originally from: `Attention Augmented Convolutional Networks` - https://arxiv.org/abs/1904.09925
    c                    sh   t ƒ  ¡  t|ƒ\| _| _|| _t t 	| jd d |¡| ¡| _
t t 	| jd d |¡| ¡| _d S )Nr   r   )ÚsuperÚ__init__r   ÚheightÚwidthÚdim_headÚnnÚ	ParameterÚtorchZrandnÚ
height_relÚ	width_rel)ÚselfÚ	feat_sizer"   Úscale©Ú	__class__r   r   r   =   s
    
"zPosEmbedRel.__init__c                 C   sf   |j \}}}| || j| jd¡}t|| jdd�}| dd¡}t|| jdd�}|| }| |||¡}|S )Nr
   )r   r   é   r   é   r   r   r   )r   r-   r   r.   r   )r   r   r    r!   r   r'   r   r&   )r(   r   r   ZHWÚ_Zrel_logits_wZrel_logits_hZ
rel_logitsr   r   r   ÚforwardD   s    zPosEmbedRel.forward)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r0   Ú__classcell__r   r   r+   r   r   8   s   r   c                       s2   e Zd ZdZd‡ fdd„	Zd	d
„ Zdd„ Z‡  ZS )ÚBottleneckAttna†   Bottleneck Attention
    Paper: `Bottleneck Transformers for Visual Recognition` - https://arxiv.org/abs/2101.11605

    The internal dimensions of the attention module are controlled by the interaction of several arguments.
      * the output dimension of the module is specified by dim_out, which falls back to input dim if not set
      * the value (v) dimension is set to dim_out // num_heads, the v projection determines the output dim
      * the query and key (qk) dimensions are determined by
        * num_heads * dim_head if dim_head is not None
        * num_heads * (dim_out * attn_ratio // num_heads) if dim_head is None
      * as seen above, attn_ratio determines the ratio of q and k relative to the output if dim_head not used

    Args:
        dim (int): input dimension to the module
        dim_out (int): output dimension of the module, same as dim if not set
        stride (int): output stride of the module, avg pool used if stride == 2 (default: 1).
        num_heads (int): parallel attention heads (default: 4)
        dim_head (int): dimension of query and key heads, calculated from dim_out * attn_ratio // num_heads if not set
        qk_ratio (float): ratio of q and k dimensions to output dimension when dim_head not set. (default: 1.0)
        qkv_bias (bool): add bias to q, k, and v projections
        scale_pos_embed (bool): scale the position embedding as well as Q @ K
    Nr   r.   ç      ð?Fc
           
         sæ   t ƒ  ¡  |d k	stdƒ‚|p |}|| dks2t‚|| _|pNt|| dd�| | _|| j | _|| j | _|| j | _| jd | _	|	| _
tj|| jd | j d|d�| _t|| j| j	d	�| _|dkrÐt dd¡nt ¡ | _|  ¡  d S )
NzBA concrete feature size matching expected input (H, W) is requiredr   é   )Zdivisorç      à¿r   r   )Zbias)r"   r*   )r   r   ÚAssertionErrorÚ	num_headsr   Údim_head_qkÚ
dim_head_vÚ
dim_out_qkÚ	dim_out_vr*   Úscale_pos_embedr#   ZConv2dÚqkvr   Ú	pos_embedZ	AvgPool2dZIdentityÚpoolÚreset_parameters)
r(   r   Zdim_outr)   Zstrider;   r"   Zqk_ratioZqkv_biasr@   r+   r   r   r   j   s    
 zBottleneckAttn.__init__c                 C   sF   t | jj| jjjd d d� t | jj| jd� t | jj| jd� d S )Nr   r9   )Zstd)r   rA   Úweightr   rB   r&   r*   r'   )r(   r   r   r   rD   ‚   s    zBottleneckAttn.reset_parametersc                 C   s   |j \}}}}t|| jjkdƒ t|| jjkdƒ |  |¡}tj|| j| j| j	gdd�\}}}| 
|| j | jd¡ dd¡}| 
|| j | jd¡}| 
|| j | jd¡ dd¡}| jrÐ|| |  |¡ | j }	n|| | j |  |¡ }	|	jdd�}	|	|  dd¡ 
|| j	||¡}
|  |
¡}
|
S )NÚ r   )r   r
   r   )r   r   rB   r    r!   rA   r%   Úsplitr>   r?   r   r;   r<   r   r=   r@   r*   ZsoftmaxrC   )r(   r   r   ÚCr   r   r   ÚkÚvZattnÚoutr   r   r   r0   ‡   s    
"
zBottleneckAttn.forward)NNr   r.   Nr7   FF)r1   r2   r3   r4   r   rD   r0   r5   r   r   r+   r   r6   T   s                 þr6   )r4   Útypingr   r%   Ztorch.nnr#   Ztorch.nn.functionalZ
functionalr   Zhelpersr   r   Zweight_initr   Ztrace_utilsr   Úintr   ÚModuler   r6   r   r   r   r   Ú<module>   s   