Scaled dot product attention 計算の q と k の内積を q と k のユークリッド距離の逆数にしても学習します。

## はじめに

Transformer のことを勉強していたら、Scaled dot product attention の q と k の内積は、q と k の類似度を見ているという説明がありました。類似度なら、内積以外にも計算方法があるぞと思い、コサイン類似度とユークリッド距離を試してみました。コサイン類似度は距離の情報がなくなるということで学習には使えないようです。ユークリッド距離の逆数を使うと学習することが分かったので、ご報告させていただきます。


## Scaled Euclid Distance Attention クラス

```python
import torch
import torch.nn as nn

class MultiHeadAttention(nn.Module):
    def __init__(self, dim_hidden: int, n_head: int, dropout: float=0.1, qkv_bias: bool=False):
        super().__init__()
        self.n_head = n_head

        self.proj_q = nn.Linear( dim_hidden, dim_hidden, bias=qkv_bias)
        self.proj_k = nn.Linear( dim_hidden, dim_hidden, bias=qkv_bias)
        self.proj_v = nn.Linear( dim_hidden, dim_hidden, bias=qkv_bias)
        self.proj_out = nn.Linear(dim_hidden, dim_hidden)

        self.qkv_attention = ScaledEuclidDistanceAttention( dim_hidden, n_head, dropout )
        
    def forward( self,query,key,value, attn_mask = None ):

        q = self.proj_q( query )
        k = self.proj_k( key )
        v = self.proj_v( value )
        
        output = self.qkv_attention(q, k, v, attn_mask)

        output = self.proj_out( output )
        
        return output 

    
class ScaledEuclidDistanceAttention(nn.Module):
    def __init__(self, dim_hidden: int, num_heads: int, dropout: float=0.1):
        super().__init__()

        assert dim_hidden % num_heads == 0

        self.num_heads = num_heads

        dim_head = dim_hidden // num_heads

        # Scale Value of Softmax
        self.scale = dim_head ** -0.5
        
        self.dropout = nn.Dropout(dropout)

    def forward(self, q, k, v, mask=None ):

        q = q.view( q.size(0), q.size(1), self.num_heads, -1 ).permute( 0,2,1,3 )
        k = k.view( k.size(0), k.size(1), self.num_heads, -1 ).permute( 0,2,1,3 )
        v = v.view( v.size(0), v.size(1), self.num_heads, -1 ).permute( 0,2,1,3 )

        qk_dis = torch.cdist( q, k, p = 2 ) * self.scale # cdist is distance function of pytorch
        attn =  1 / ( qk_dis + 1e-9 )
        # Check of learning was carried out with mask = None
        if mask is not None:
            attn = attn + torch.unsqueeze( torch.unsqueeze( mask, dim = 0 ), dim = 0 ).to(torch.float16) * -1e9
        attn = ( attn ).softmax(dim=-1)  

        attn = self.dropout( attn )
        
        x = attn.matmul(v)

        x = x.permute(0, 2, 1, 3).flatten(2)

        return x    
if __name__ == "__main__":

    num_batch = 8
    q_seq = 300
    k_seq = 100
    dim_hidden = 512
    num_heads = 8

    func2 = MultiHeadAttention( dim_hidden, num_heads )

    q = torch.randn( ( num_batch, q_seq, dim_hidden))
    k = torch.randn( ( num_batch, k_seq, dim_hidden))
    v = k
    mask = torch.randint(low=0, high=2, size=(q_seq, k_seq)).to( torch.bool )

    x = func2( q,k,v,mask)

    print( x.size() )
```

## Vision Transformer での確認。

こちらでの確認を報告します。画像分類のプログラムのTransformer Encoder の Self Attention にユークリッド距離の attention を使って試したのですが、学習がすすみました。内積だと1エポック12分程度(cpu)で、ユークリッド距離だと14分程度(cpu)です。この確認のための学習だけでモデルの良さの結論は出せません。「Python で学ぶ画像認識」という本のプログラムで、q と k の類似度に通常の内積を使った場合、ある画像分類の問題のテストデータの正解率が 63.8% であったと本に書いてあります。本のプログラムで内積の代わりにユークリッド距離の逆数を使った確認のための学習では、同じ問題について、正解率が 66.7 %になりました。

画像分類プログラムで学習確認したときの Loss の推移

![Loss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/11248569-d73d-0995-9dd3-e238b12cf414.png)

Accuracy の推移

![Accuracy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/cf29b430-d6c7-ecd7-21c2-0102063e70c4.png)

## 機械翻訳プログラムでの確認

機械翻訳の Transformer ですが、プログラム的にはTransformer Decoder の Self Attention でも Cross Attention でも通ります。また、機械翻訳のプログラムで、Transformer Encoder と Transformer Decoder にユークリッド距離による attention を使って学習が進むことを確認しました。

## Github

この案件は、英語でも報告したほうが良さそうなので、Github でつたない英語ですが報告しておきます。

https://github.com/toshiouchi/ScaledEuclideanDistanceAttention/tree/main

## 2024年3月8日追記、image captioning の Transforemer Decdoer で動作確認

時間がとれたので、既出の本「Python で学ぶ画像認識」の p. 331 で述べられている Transformer を使った image captioning のプログラムの MultiHeadAttention モジュールをこのページで提案しているモジュールに修正して学習を行いました。キャプショニングの結果を示します。

![adorable-1849992_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/c4f57cc4-09a0-8550-5ea0-1d78a109c889.jpeg)
&lt;start&gt; a dog is playing with a frisbee in its mouth &lt;end&gt;

![africa-1170179_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/eec1e925-1c6d-20e8-fe69-97d247ceaf4a.jpeg)
&lt;start&gt; a herd of giraffes are standing in a field &lt;end&gt;

![airplane-3702676_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/4c38813f-065c-8cfb-bd9c-e5b2186d50a4.jpeg)
&lt;start&gt; a plane flying over a plane flying over a plane &lt;end&gt;

![automotive-1846910_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/e1845d8a-66dd-8803-8902-be583ca32d56.jpeg)
&lt;start&gt; a car is parked on a car on the street &lt;end&gt;

![beach-1837030_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/91647999-eea1-75bd-99d9-1fecef6b16d8.jpeg)
&lt;start&gt; a man is surfing on a wave on a wave &lt;end&gt;

![caravan-339564_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/47c21849-d7fe-8a60-ab2b-8fbd2db44a9a.jpeg)
&lt;start&gt; a group of people riding on a beach &lt;end&gt;

![cat-4467818_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/2c7bceb6-8813-82c6-3115-982eccf0f57b.jpeg)
&lt;start&gt; a cat is sitting on a colorful rug &lt;end&gt;

![cherry-1468933_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/7b883716-5729-34d2-3f7d-855294bbe62a.jpeg)
&lt;start&gt; a bowl of fruit and a bowl of fruit &lt;end&gt;

![couple-955926_1280.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/484e9120-d784-22fa-bb89-886be7d7b6c3.jpeg)
&lt;start&gt; a woman is riding a beach with a beach &lt;end&gt;

![dog-7367949_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/271a5bef-6e52-8ce5-dfd7-e0e92faeaa30.jpeg)
&lt;start&gt; a man is playing with a frisbee in the water &lt;end&gt;

![hit-1407826_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/a909d4ad-dfd8-795e-e992-9663a2b57cbe.jpeg)
&lt;start&gt; a baseball player is swinging a baseball game &lt;end&gt;

![man-498473_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/cf84f7f8-2472-6f56-02db-c9c1a2f5c98b.jpeg)
&lt;start&gt; a man riding skis down a snow covered slope &lt;end&gt;

![musician-743973_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/9c7a3f0d-b279-4cc0-df4d-0bdf9077b78e.jpeg)
&lt;start&gt; three men are standing on a beach with surfboards &lt;end&gt;

![port-5788261_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/9eadc539-5586-9277-a31e-c31bedd66e03.jpeg)
&lt;start&gt; a large clock tower towering over a city street &lt;end&gt;

![profile-7579739_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/ba7388af-773c-ff0d-6707-dfff0eb3bd01.jpeg)
&lt;start&gt; a man riding a skateboard on a skateboard &lt;end&gt;

![ural-owl-4808774_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/8febc6c7-e584-ffe4-646e-19f227cc57e4.jpeg)
&lt;start&gt; a bird perched on a branch in a tree branch &lt;end&gt;

![wine-bar-2139973_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/0155972d-5666-72f0-b66b-bf6cadd81698.jpeg)
&lt;start&gt; a man in a man in a bar &lt;end&gt;

![woman-3432069_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/929897a5-b54c-2a8b-1c50-b0d7ef541f63.jpeg)
&lt;start&gt; a horse is standing in the grass field &lt;end&gt;

![zebras-1883654_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958180/4cf3e2b7-999a-b640-3bde-be5b7421a599.jpeg)
&lt;start&gt; a zebra standing in a field with a field &lt;end&gt;