次元削減手法の比較検証:定量的・定性的評価によるPCA、t-SNE、UMAPの特徴分析

はじめに

この記事では、機械学習や統計分析において重要な、高次元データの可視化および分析のための次元削減手法について解説します。特に、PCA(主成分分析)、t-SNE、UMAPという代表的な3つの手法に焦点を当て、それぞれの理論的背景、性能評価、そして実践的な使い分けについて、詳細な比較と具体例を交えながら説明します。

この記事を書いたひと

デジタルリアクタ合同会社 代表
機械学習・統計、数値計算などの領域を軸としたソフトウェアエンジニアリングを専門としています。スタートアップからグローバル企業まで、さまざまなスケールの企業にて、事業価値に直結する計算システムを設計・構築してきました。主に機械学習の応用分野において、出版・発表、特許取得等の実績があり、また、IT戦略やデータベース技術等の情報処理に関する専門領域の国家資格を複数保有しています。九州大学理学部卒業。日本ITストラテジスト協会正会員。

対象読者:

  • 機械学習エンジニアやデータサイエンティスト
  • 次元削減の手法選択に悩んでいる方
  • 高次元データの可視化や分析に関心のある方

記事のポイント:

  • PCA、t-SNE、UMAPの理論的な違いを理解できる
  • 各手法の長所と短所を把握し、適切な使い分けができるようになる
  • 定量的な評価指標(トラストワーシネス、再構成誤差)と定性的な評価を比較できる

次元削減手法の理論的背景

PCA(主成分分析)

PCAは、最も基本的かつ広く利用されている次元削減手法です。

  • 仕組み: データの分散が最大となる方向(主成分)を順次見つけ出し、それらの主成分にデータを射影します。
  • 特徴:
    • 線形変換であり、変換後の空間から元の空間へ戻すこと(逆変換)が可能です。
    • 計算が高速で、大規模なデータセットにも適用可能です。
  • 最適化問題: 以下の最適化問題を解くことで主成分を求めます。
\max_{w} w^T X^T X w \quad \text{subject to} \quad \|w\| = 1

ここで、X はデータ行列、w は主成分ベクトルを表します。

t-SNE

t-SNEは、非線形な次元削減手法であり、特にデータの局所的な構造を保持することに優れています。

  • 仕組み: 高次元空間と低次元空間におけるデータ点間の類似度を確率分布で表現し、それらの分布が近づくように低次元空間でのデータ点配置を最適化します。
  • 特徴:
    • データの局所的な構造(クラスターなど)を可視化するのに適しています。
    • 計算コストが高く、大規模データセットへの適用には工夫が必要です。
  • 最適化問題: 以下のKLダイバージェンスを最小化します。
KL(P||Q) = \sum_{i}\sum_{j} p_{ij} \log\frac{p_{ij}}{q_{ij}}

ここで、P は高次元空間での確率分布、Q は低次元空間での確率分布、p_{ij}q_{ij} はそれぞれデータ点 ij 間の類似度を表します。

UMAP

UMAPは、比較的新しい非線形次元削減手法で、t-SNEの改良版とも言えます。

  • 仕組み: リーマン幾何学とトポロジーの概念を応用し、高次元空間と低次元空間におけるデータ点間の関係性を保持するように低次元空間でのデータ点配置を最適化します。
  • 特徴:
    • t-SNEよりも高速で、グローバルな構造もある程度保持できます。
    • 新しいデータ点を既存の低次元空間に射影する機能(transform)を持っています。

評価指標

次元削減の性能を評価するため、以下の指標を用います。

トラストワーシネス(Trustworthiness)

トラストワーシネスは、局所的な構造の保持度を評価する指標です。

  • 定義: 元の高次元空間での近傍関係が、低次元空間でもどの程度保持されているかを測定します。
  • 値域: 0から1の値をとり、1に近いほど良好な保持度を示します。
  • 計算方法: 以下のPythonコードで計算できます。
from sklearn.manifold import trustworthiness
trust_score = trustworthiness(X_original, X_reduced)

再構成誤差(Reconstruction Error)

再構成誤差は、PCAに特有の評価指標で、情報の保持度を表します。

  • 定義: 低次元空間に射影したデータを元の高次元空間に戻した際に、元のデータとどの程度の差(二乗平均平方根誤差、RMSE)が生じるかを測定します。
  • : 値が小さいほど、元の情報が保持されていることを示します。
  • 計算方法: 以下のPythonコードで計算できます。
def compute_reconstruction_error(X, X_transformed, pca):
    X_reconstructed = pca.inverse_transform(X_transformed)
    return np.mean(np.square(X - X_reconstructed))

実験:3つのデータセットでの比較

実験設定

以下の3つのデータセットを用いて、PCA、t-SNE、UMAPの比較実験を行いました。

  1. Swiss Roll: 3次元の非線形多様体(人工データ)
  2. S-curve: 3次元の滑らかな曲面(人工データ)
  3. アヤメデータセット: 4次元の特徴量を持つ分類データ(実データ)
import numpy as np
from sklearn.datasets import make_swiss_roll, make_s_curve, load_iris
from sklearn.preprocessing import StandardScaler

# データセットの生成と前処理
X_swiss, color_swiss = make_swiss_roll(n_samples=1000, random_state=42)
X_s_curve, color_s_curve = make_s_curve(n_samples=1000, random_state=42)
iris = load_iris()
X_iris = StandardScaler().fit_transform(iris.data)

実験結果

定量的評価の比較

評価指標 データセット PCA t-SNE UMAP
トラストワーシネス Swiss Roll 0.982 1.000 0.999
S-curve 0.978 1.000 0.999
Iris 0.974 0.991 0.982
計算時間 (秒) Swiss Roll 0.01 2.45 0.32
S-curve 0.01 2.38 0.30
Iris 0.01 1.12 0.15
再構成誤差 Swiss Roll 12.390 - -
S-curve 0.113 - -
Iris 0.042 - -

定性的特徴の比較

特徴 PCA t-SNE UMAP
非線形性の扱い 線形のみ 優れている 優れている
局所構造の保持 中程度 非常に優れている 優れている
グローバル構造の保持 良好 弱い 中程度
スケーラビリティ 優れている 低い 良好
新規データの射影 可能 不可能 可能
解釈のしやすさ 容易 難しい やや難しい

実践的な使い分け

用途別の推奨手法

用途 推奨手法 理由
次元の意味理解 PCA 主成分の解釈が容易で、データの変動の方向性が明確
クラスタリング可視化 t-SNE/UMAP 局所構造の保持に優れ、クラスター間の分離が明確
大規模データ処理 UMAP 計算効率が良く、比較的高品質な結果が得られる
リアルタイム処理 PCA 計算が非常に高速で、新規データの射影も容易
教師なし異常検知 UMAP 局所構造を保持しつつ、計算効率も比較的良好で、外れ値の検出に適している

データサイズによる選択指針

データサイズ 推奨手法 注意点
小規模(<1000) 全て使用可 まずPCAで試し、必要に応じてt-SNEやUMAPを使用
中規模(1000-10000) PCA/UMAP t-SNEは計算時間に注意
大規模(>10000) UMAP PCAも可能だが、非線形性の表現が限定的になる可能性がある。

まとめ

本記事では、PCA、t-SNE、UMAPという3つの代表的な次元削減手法について、理論的背景、定量的・定性的な評価、そして実践的な使い分けについて解説しました。

以下に重要なポイントをまとめます。

  • PCAは線形変換で高速だが、非線形なデータの構造を捉えられない場合がある。
  • t-SNEはデータの局所構造の保持に優れるが、計算コストが高く、大規模データには不向き。
  • UMAPはt-SNEの利点を持ちつつ、高速でグローバルな構造もある程度保持でき、新規データの射影も可能。

次元削減手法の選択は、データの性質や分析の目的に大きく依存します。本記事で紹介した情報を参考に、最適な手法を選択し、効果的なデータ分析を実現してください。

コード

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_swiss_roll, make_s_curve, load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE, trustworthiness
from sklearn.metrics.pairwise import euclidean_distances
import umap
import japanize_matplotlib
from time import time

def compute_reconstruction_error(X, X_transformed, pca):
    """PCAの再構成誤差を計算"""
    if not isinstance(pca, PCA):
        return None
    X_reconstructed = pca.inverse_transform(X_transformed)
    return np.mean(np.square(X - X_reconstructed))

def compute_metrics(X, X_transformed, method_name, pca=None):
    """各種評価指標を計算"""
    metrics = {}

    # トラストワーシネス(局所構造の保持度)
    metrics['trustworthiness'] = trustworthiness(X, X_transformed)

    # 再構成誤差(PCAのみ)
    if isinstance(pca, PCA):
        metrics['reconstruction_error'] = compute_reconstruction_error(X, X_transformed, pca)

    return metrics

def generate_datasets():
    # スイスロールデータセット
    X_swiss, color_swiss = make_swiss_roll(n_samples=1000, random_state=42)

    # S字カーブデータセット
    X_s_curve, color_s_curve = make_s_curve(n_samples=1000, random_state=42)

    # IRISデータセット
    iris = load_iris()
    X_iris = StandardScaler().fit_transform(iris.data)
    color_iris = iris.target

    return (X_swiss, color_swiss, "Swiss_Roll"), (X_s_curve, color_s_curve, "S_Curve"), (X_iris, color_iris, "Iris")

def apply_dimension_reduction(X, methods):
    results = {}
    times = {}
    metrics = {}

    for name, method in methods.items():
        start_time = time()
        results[name] = method.fit_transform(X)
        times[name] = time() - start_time

        # 評価指標の計算
        pca = method if isinstance(method, PCA) else None
        metrics[name] = compute_metrics(X, results[name], name, pca)

    return results, times, metrics

def plot_results(results, colors, dataset_name, times, metrics):
    fig = plt.figure(figsize=(15, 5))

    for idx, (name, embedding) in enumerate(results.items()):
        ax = fig.add_subplot(1, 3, idx + 1)
        scatter = ax.scatter(embedding[:, 0], embedding[:, 1], c=colors, cmap='viridis')

        # タイトルに評価指標を追加
        title = f'{name}\nTime: {times[name]:.2f}s\n'
        title += f'Trust: {metrics[name]["trustworthiness"]:.3f}'
        if "reconstruction_error" in metrics[name]:
            title += f'\nRecon Error: {metrics[name]["reconstruction_error"]:.3f}'
        ax.set_title(title)

        if dataset_name == "Iris":
            plt.colorbar(scatter, ticks=[0, 1, 2], label='Species')
        else:
            plt.colorbar(scatter)

    plt.suptitle(f'{dataset_name}の次元削減結果比較')
    plt.tight_layout()
    plt.savefig(f'{dataset_name}_comparison.png')
    plt.close()

def main():
    # 次元削減手法の定義
    methods = {
        'PCA': PCA(n_components=2),
        't-SNE': TSNE(n_components=2, random_state=42),
        'UMAP': umap.UMAP(random_state=42)
    }

    # データセットの生成
    datasets = generate_datasets()

    # 各データセットに対して次元削減を適用
    for X, colors, name in datasets:
        results, times, metrics = apply_dimension_reduction(X, methods)
        plot_results(results, colors, name, times, metrics)

        # 評価指標の詳細を出力
        print(f"\n{name}データセットの評価指標:")
        for method_name, method_metrics in metrics.items():
            print(f"\n{method_name}:")
            for metric_name, value in method_metrics.items():
                print(f"  {metric_name}: {value:.3f}")

if __name__ == '__main__':
    main() 

お気軽にご相談ください!

弊社のデジタル技術を活用し、貴社のDXをサポートします。

基本的な設計や実装支援はもちろん、機械学習・データ分析・3D計算などの高度な技術が求められる場面でも、最適なソリューションをご提案します。

初回相談は無料で受け付けております。困っていること、是非お聞かせください。