2次元空間の特徴を高次元空間に写像した後に，活性化関数に通し2次元空間の特徴がどれくらい残るのか確認してみる

# やり方
1. 2次元ベクトルの特徴の代わりを用意する

![origin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478008/034fa637-8531-0290-659c-acbfb9984571.jpeg)

2. 2次元ベクトルから高次元ベクトルに飛ばす行列と高次元ベクトルから2次元ベクトルに戻す疑似逆行列を用意する

```math
y = Tx \\
x' = T^{-1}x
```

3. 高次元ベクトルに対して使う活性化関数を用意する

4. 2次元空間の特徴を高次元空間に写像した後に，活性化関数に通し2次元空間の特徴がどれくらい残るのか確認してみる

# 結果
## ReLU
![relu.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478008/0371d894-c199-1cb7-0d4d-57d7f497a022.jpeg)
低次元だとバッサリ切れている感じがする．
高次元になるにつれて丸っぽさがでてくるような気がする．

## Leaky-ReLU
![leaky_relu.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478008/87257569-1326-7fe3-fa2d-e00db9843f8c.jpeg)
結果をわかりやすくするため，negative_slop = 0.05とした．
原点の近くでぴょこっと出ているのが特徴のようだ．

## ReLU6
![relu6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478008/cbceb73f-84d3-8424-1b0f-6a73492ef176.jpeg)
ReLUを圧縮したような印象がある．
高次元に行けば行くほど原型の面影を感じる．
実際はnormalizationをするだろうから，こんなに圧縮されることも少ないと思われる．

## Mish
![mish.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478008/74b9fba3-8b0b-0e8e-3d33-2bac6e35af8c.jpeg)
原点の近くはReLUよりもバッサリいってないように見える．
Leaky-ReLUよりもスタイリッシュな感じがある．

# コード
```python
import time
import numpy as np
import matplotlib.pyplot as plt

def get_eddy():
    theta = np.arange(0.0, 4 * 2 * np.pi, 0.01)
    r = 0.5 * theta
    return theta, r

def get_xy(theta, r):
    x = r * np.cos(theta)
    y = r * np.sin(theta)
    return np.vstack((x, y))

def get_mat(dim):
    mat = np.random.rand(dim, 2)
    return mat

def relu(high_dim_xy):
    return np.maximum(high_dim_xy, 0)

def lrelu(high_dim_xy):
    return np.where(high_dim_xy > 0, high_dim_xy, 0.05 * high_dim_xy)

def relu6(high_dim_xy):
    return np.minimum(np.maximum(high_dim_xy, 0), 6)

def mish(high_dim_xy):
    def softplus(i):
        return np.log(1 + np.exp(i))
    def tanh(i):
        return (np.exp(i) - np.exp(-i)) / (np.exp(i) + np.exp(-i))
    return high_dim_xy * tanh(softplus(high_dim_xy))

if __name__=="__main__":
    theta, r = get_eddy()
    xy = get_xy(theta, r)
    high_dims = [2, 4, 8, 16, 32, 64, 128]
    mats = []
    for high_dim in high_dims:
        time.sleep(0.2)
        mats.append(get_mat(high_dim))
    
    acts = {"relu" : relu, "leaky_relu" : lrelu, "relu6" : relu6, "mish" : mish}

    plt.figure(figsize = (10, 10))
    plt.plot(xy[0], xy[1])
    plt.xlim([-15, 15])
    plt.ylim([-15, 15])
    plt.savefig(f"origin.jpg")
    plt.clf()
    plt.close()

    for filename, func in acts.items():
        processed = []
        processed.append(xy.copy())

        for mat in mats:
            high_dim_xy = mat @ xy
            high_dim_xy = func(high_dim_xy)
            new_xy = np.linalg.pinv(mat) @ high_dim_xy
            processed.append(new_xy.copy())
        
        fig = plt.figure(figsize=(10 * len(processed) // 2, 10 * 2))
        for count, p in enumerate(processed):
            ax = fig.add_subplot(2, len(processed) // 2, count + 1)
            ax.plot(p[0], p[1])
            ax.set_xlim([-15, 15])
            ax.set_ylim([-15, 15])
            title = "input" if count == 0 else f"output/dim={high_dims[count-1]}"
            ax.set_title(title, fontsize = 24)

        plt.savefig(f"{filename}.jpg")
        plt.clf()
        plt.close()
```

## 参考にした論文
MobileNetV2: Inverted Residuals and Linear Bottlenecks

https://openaccess.thecvf.com/content_cvpr_2018/papers/Sandler_MobileNetV2_Inverted_Residuals_CVPR_2018_paper.pdf