次元削減の手法まとめ


# 次元削減

次元削減とは高次元のデータ集合 を低次元のデータ集合に変換することを意味します．
大量で複雑なデータを扱う際に、データの本質的な構造を保ちつつ、次元を減らすことで計算コストを下げ、データの可視化や分析を容易にすることを目的としています。

高次元のデータ集合の特徴をできる限り保持できるようにします。

## 次元削減の手法の歴史

| 年代 | 手法 | 
|------|------|
| 1901 | 主成分分析（PCA） | Pearson |
| 1933 | 主成分分析（PCA）の発展 | Hotelling |
| 1952 | 多次元尺度構成法（MDS） | Torgerson |
| 1969 | Sammon写像（Sammon Mapping） | Sammon |
| 2000 | Isomap（アイソマップ） | Tenenbaum et al. |
| 2000 | LLE（Locally Linear Embedding） | Roweis and Saul |
| 2006 | Autoencoders（オートエンコーダ）のスタック型 | Hinton and Salakhutdinov |
| 2008 | t-SNE（t-Distributed Stochastic Neighbor Embedding） | van der Maaten and Hinton |
| 2018 | UMAP（Uniform Manifold Approximation and Projection） | McInnes et al. |


これらの手法は、それぞれの時代のデータの特性や計算リソースに合わせて開発されてきました。現在では、これらの手法を組み合わせたり、改良したりすることで、さらに高度で効率的な次元削減が可能となっています。次元削減は、データの可視化、特徴抽出、ノイズ除去など、様々な応用分野で重要な役割を果たしています。



## 次元削減の主な手法

| 手法 | 説明 |
|------|------|
| 主成分分析（PCA） | データの次元を削減し、データの特徴を少数の主成分で表現する手法。データの分散を最大限に保持するように主成分を選択する。 |
| 多次元尺度構成法(MDS) | 高次元のデータ間の距離関係を保持しつつ、低次元空間にデータを埋め込む手法。データ間の類似度や非類似度を距離として扱う。 |
| Sammon写像 | MDSの一種で、高次元データ間の距離関係を低次元空間で可能な限り保持するように埋め込む手法。非線形な写像が可能。 |
| Isomap | 多様体学習の一種で、データ間の測地距離を用いて低次元空間にデータを埋め込む手法。非線形な構造を保持できる。 |
| LLE（Locally Linear Embedding） | 多様体学習の一種で、データ間の局所的な線形構造を保持しつつ、低次元空間にデータを埋め込む手法。 |
| Autoencoders| ニューラルネットワークを用いた次元削減手法。入力データを低次元の潜在表現に圧縮し、再構成する。複数のオートエンコーダを積み重ねることで、より高度な特徴抽出が可能。 |
| t-SNE | 高次元データの局所的な構造を保持しつつ、低次元空間にデータを埋め込む手法。データ間の類似度を確率的に扱い、t分布を用いる。 |
| UMAP| 多様体学習と次元削減を組み合わせた手法。データの局所的な構造を保持しつつ、低次元空間にデータを埋め込む。t-SNEと比較して高速で、大規模データにも適用可能。 |

各手法には長所と短所があり、データの性質やタスクの目的に応じて適切な手法を選択することが重要です。また、次元削減の結果は、元のデータの構造や特徴をどの程度保持できているかによって評価されます。

## 実装例

```python
import numpy as np
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
from sklearn.manifold import MDS, Isomap, LocallyLinearEmbedding, TSNE
import torch
import torch.nn as nn
import torch.optim as optim
import umap.umap_ as umap
import matplotlib.pyplot as plt

def perform_dimensionality_reduction(X, method, n_components=2, **kwargs):
    # 次元削減手法を選択し、適用する関数
    if method == 'PCA':
        reducer = PCA(n_components=n_components)  # 主成分分析(PCA)
    elif method == 'MDS':
        reducer = MDS(n_components=n_components)  # 多次元尺度構成法(MDS)
    elif method == 'Isomap':
        reducer = Isomap(n_components=n_components)  # Isomap
    elif method == 'LLE':
        reducer = LocallyLinearEmbedding(n_components=n_components)  # 局所線形埋め込み(LLE)
    elif method == 't-SNE':
        reducer = TSNE(n_components=n_components)  # t-SNE
    elif method == 'UMAP':
        reducer = umap.UMAP(n_components=n_components)  # UMAP
    else:
        raise ValueError(f"Unknown dimensionality reduction method: {method}")
    
    return reducer.fit_transform(X)

class Autoencoder(nn.Module):
    def __init__(self):
        super(Autoencoder, self).__init__()
        self.encoder = nn.Sequential(
            nn.Linear(4, 8),  # 入力層から隠れ層へ
            nn.ReLU(),        # ReLU活性化関数
            nn.Linear(8, 2)   # 隠れ層からコード層へ
        )
        self.decoder = nn.Sequential(
            nn.Linear(2, 8),  # コード層から隠れ層へ
            nn.ReLU(),        # ReLU活性化関数
            nn.Linear(8, 4)   # 隠れ層から出力層へ
        )

    def forward(self, x):
        x = self.encoder(x)  # エンコード処理
        x = self.decoder(x)  # デコード処理
        return x

def train_autoencoder(X, model, epochs=50, batch_size=32):
    dataset = torch.tensor(X, dtype=torch.float32)  # データセットをテンソルに変換
    dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)  # データローダの設定
    criterion = nn.MSELoss()  # 損失関数としてMSEを使用
    optimizer = optim.Adam(model.parameters(), lr=0.01)  # 最適化アルゴリズムとしてAdamを使用
    
    # 訓練ループ
    for epoch in range(epochs):
        for data in dataloader:
            optimizer.zero_grad()  # 勾配を0で初期化
            reconstruction = model(data)  # データを通じて再構成
            loss = criterion(reconstruction, data)  # 損失の計算
            loss.backward()  # 勾配の計算
            optimizer.step()  # パラメータの更新

    encoded_data = model.encoder(dataset).detach().numpy()  # エンコーダの出力を取得し、Numpy配列に変換
    return encoded_data

def plot_results(X_reduced_list, y, methods):
    plt.figure(figsize=(12, 8))  # 図のサイズを指定
    
    # 結果を一つずつプロット
    for i, (method, X_reduced) in enumerate(zip(methods, X_reduced_list), 1):
        plt.subplot(2, 4, i)
        for label in np.unique(y):
            plt.scatter(X_reduced[y == label, 0], X_reduced[y == label, 1], label=f'Class {label}')  # ラベルごとに色を変えてプロット
        plt.title(f'{method}')  # サブプロットのタイトル
        plt.xlabel('Component 1')  # X軸ラベル
        plt.ylabel('Component 2')  # Y軸ラベル
        plt.legend()  # 凡例の表示
    
    plt.tight_layout()  # レイアウトの調整
    plt.show()

def main():
    iris = load_iris()  # Irisデータセットの読み込み
    X = iris.data
    y = iris.target
    
    methods = ['PCA', 'MDS', 'Isomap', 'LLE', 't-SNE', 'UMAP']
    X_reduced_list = [perform_dimensionality_reduction(X, method) for method in methods]  # 様々な次元削減手法を適用
    
    autoencoder = Autoencoder()  # オートエンコーダモデルのインスタンス化
    X_autoencoder = train_autoencoder(X, autoencoder)  # オートエンコーダでの学習
    X_reduced_list.insert(4, X_autoencoder)
    methods.insert(4, 'Autoencoder')
    
    plot_results(X_reduced_list, y, methods)  # 結果のプロット

if __name__ == '__main__':
    main()

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348593/47fd2c0d-de3e-ca26-68ee-bc8d4599b9b3.png)

# 教師あり次元削減

教師あり次元削減は、教師情報（ラベルやクラス情報）を利用して、高次元データを低次元空間に埋め込む手法です。教師情報を考慮することで、同じクラスに属するデータポイントが低次元空間で近くに配置され、異なるクラスに属するデータポイントが遠くに配置されるように次元削減を行います。

## 従来手法と何が違うのか？
従来の次元削減手法（PCA、t-SNEなど）は、教師情報を考慮せずに、データの構造を捉えるように設計されています。しかし、教師情報を活用することで、より効果的に次元削減を行うことができます。教師あり次元削減は、教師情報を用いてデータの構造を学習し、同じクラスに属するデータポイントを近くに、異なるクラスに属するデータポイントを遠くに配置するように低次元空間を構築します。これにより、クラス分離性が向上し、分類タスクの性能が改善されます。

## 教師あり次元削減手法

| 年代 | 手法 | 説明 |
|-----|------|------|
| 1990年代 | Partial Least Squares (PLS) | 教師情報を考慮しながら、データの共分散構造を捉えるように次元削減を行う手法。高次元で多重共線性のあるデータに対して有効。 |
| 1996年 | Kernel Fisher Discriminant Analysis (KFD) | カーネル法を用いてLDAを非線形に拡張した手法。非線形の判別境界を学習することができる。 |
| 2002年 | Locality Preserving Projections (LPP) | グラフ埋め込みの概念を用いて、データの局所的な構造を保持するように次元削減を行う手法。教師情報を組み込むことで教師あり次元削減に拡張可能。 |
| 2005年 | Marginal Fisher Analysis (MFA) | LDAとLPPの概念を組み合わせた教師あり次元削減手法。クラス間の分離を最大化しつつ、クラス内の局所的な構造を保持するように次元削減を行う。 |
| 2005年 | Neighborhood Components Analysis (NCA) | 最近傍法による分類性能を最大化するように、マハラノビス距離を学習する手法。教師情報を用いて、同じクラスに属するデータポイントを近くに、異なるクラスに属するデータポイントを遠くに配置。 |
| 2018年 | Supervised UMAP | UMAPに教師情報を組み込んだ拡張版。教師情報を用いて、同じクラスに属するデータポイント間の類似性を強調し、異なるクラスに属するデータポイント間の類似性を減らすように埋め込みを学習。 |

## 実装例