umap-learn は何をしますか?
概要
UMAP(一様多様体近似と射影)は、可視化と一般的な非線形次元削減のための手法です。このスキルを使用して、局所的および大域的な構造を保持した高速でスケーラブルな埋め込み、教師あり学習、クラスタリング前処理を実行できます。
クイックスタート
インストール
現在の安定版リリース: umap-learn 0.5.12(2026年4月リリース)。Python 3.9以上が必要で、scikit-learn>=1.6、numba、pynndescent、numpy、scipyに依存します。検証済みのリリースに固定するには:
uv pip install umap-learn==0.5.12
基本的な使い方
UMAPはscikit-learnの慣例に従い、t-SNEやPCAのドロップイン代替として使用できます。
import umap
from sklearn.preprocessing import StandardScaler
# データの準備(標準化は必須)
scaled_data = StandardScaler().fit_transform(data)
# 方法1: 単一ステップ(適合と変換を同時に)
embedding = umap.UMAP().fit_transform(scaled_data)
# 方法2: 別々のステップ(学習済みモデルを再利用する場合)
reducer = umap.UMAP(random_state=42)
reducer.fit(scaled_data)
embedding = reducer.embedding_ # 学習済み埋め込みにアクセス
前処理の要件: 距離メトリックに合わせて前処理を行います。数値ユークリッド系メトリックの場合は、特徴量をスケーリングして分散の大きい列が支配的にならないようにします。コサイン、バイナリ、事前計算距離、または混合特徴量のワークフローの場合は、すべての列を無条件に標準化するのではなく、メトリックに合った前処理を選択します。
典型的なワークフロー
import umap
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
# 1. データの前処理
scaler = StandardScaler()
scaled_data = scaler.fit_transform(raw_data)
# 2. UMAPの作成と適合
reducer = umap.UMAP(
n_neighbors=15,
min_dist=0.1,
n_components=2,
metric='euclidean',
random_state=42
)
embedding = reducer.fit_transform(scaled_data)
# 3. 可視化
plt.scatter(embedding[:, 0], embedding[:, 1], c=labels, cmap='Spectral', s=5)
plt.colorbar()
plt.title('UMAP埋め込み')
plt.show()
パラメータ調整ガイド
UMAPには埋め込みの動作を制御する4つの主要パラメータがあります。これらを理解することは効果的な使用のために重要です。
n_neighbors(デフォルト: 15)
目的: 埋め込みにおける局所構造と大域構造のバランスを調整します。
仕組み: UMAPが多様体構造を学習する際に考慮する近傍のサイズを制御します。
値による効果:
- 低い値(2-5): 細かい局所的詳細を重視しますが、データが複数の連結成分に断片化する可能性があります。
- 中程度の値(15-20): 局所構造と大域的な関係のバランスが取れています(推奨される開始点)。
- 高い値(50-200): 細かい詳細を犠牲にして、広範なトポロジー構造を優先します。
推奨: 15から始めて、結果に応じて調整します。より大域的な構造が必要な場合は増やし、より局所的な詳細が必要な場合は減らします。
min_dist(デフォルト: 0.1)
目的: 低次元空間での点の凝集度を制御します。
仕組み: 出力表現において、点が互いに近づける最小距離を設定します。
値による効果:
- 低い値(0.0-0.1): クラスタリングに役立つ凝集した埋め込みを作成し、細かいトポロジー的詳細を明らかにします。
- 高い値(0.5-0.99): 密なパッキングを防ぎ、局所構造よりも広範なトポロジー保存を重視します。
推奨: クラスタリング用途では0.0、可視化では0.1-0.3、疎な構造が必要な場合は0.5以上を使用します。
n_components(デフォルト: 2)
目的: 埋め込み出力空間の次元数を決定します。
主な特徴: t-SNEとは異なり、UMAPは埋め込み次元に対してスケーラブルであり、可視化以外の用途でも使用できます。
一般的な用途:
- 2-3次元: 可視化
- 5-10次元: クラスタリング前処理(2次元よりも密度を適切に保存)
- 10-50次元: 下流のMLモデルのための特徴量エンジニアリング
推奨: 可視化には2、クラスタリングには5-10、MLパイプラインにはより高い次元を使用します。
metric(デフォルト: 'euclidean')
目的: 入力データポイント間の距離の計算方法を指定します。
サポートされるメトリック:
- ミンコフスキー変種: euclidean, manhattan, chebyshev
- 空間メトリック: canberra, braycurtis, haversine
- 相関メトリック: cosine, correlation(テキスト/文書埋め込みに適しています)
- バイナリデータメトリック: hamming, jaccard, dice, russellrao, kulsinski, rogerstanimoto, sokalmichener, sokalsneath, yule
- カスタムメトリック: Numbaを介したユーザー定義の距離関数
推奨: 数値データにはeuclidean、テキスト/文書ベクトルにはcosine、バイナリデータにはhammingを使用します。
パラメータ調整の例
# 局所構造を重視した可視化
umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, metric='euclidean')
# クラスタリング前処理
umap.UMAP(n_neighbors=30, min_dist=0.0, n_components=10, metric='euclidean')
# 文書埋め込み
umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, metric='cosine')
# 大域構造を保持
umap.UMAP(n_neighbors=100, min_dist=0.5, n_components=2, metric='euclidean')
教師ありおよび半教師あり次元削減
UMAPはラベル情報を組み込んで埋め込みプロセスをガイドし、クラス分離を実現しながら内部構造を保持できます。
教師ありUMAP
適合時にyパラメータでターゲットラベルを渡します:
# 教師あり次元削減
embedding = umap.UMAP().fit_transform(data, y=labels)
主な利点:
- クラスが明確に分離されます
- 各クラス内の内部構造を保持します
- クラス間の大域的な関係を維持します
半教師ありUMAP
部分的なラベルの場合、scikit-learnの慣例に従い、ラベルなしの点を-1でマークします:
# 半教師ありラベルの作成
semi_labels = labels.copy()
semi_labels[unlabeled_indices] = -1
# 部分ラベルで適合
embedding = umap.UMAP().fit_transform(data, y=semi_labels)
使用すべき場合: ラベル付けにコストがかかる場合や、利用可能なラベルよりも多くのデータがある場合。
クラスタリングのためのUMAP
UMAPは、HDBSCANなどの密度ベースのクラスタリングアルゴリズムの効果的な前処理として機能し、次元の呪いを克服します。
クラスタリングのベストプラクティス
主要な原則: クラスタリング用と可視化用でUMAPの設定を変えます。
推奨パラメータ:
- n_neighbors: 約30に増やします(デフォルトの15は局所的すぎて、人為的な細かいクラスタを作成する可能性があります)
- min_dist: 0.0に設定します(クラスタ内の点を密に詰めて、境界を明確にします)
- n_components: 5-10次元を使用します(2次元と比較して密度の保存を改善しながら、パフォーマンスを維持します)
クラスタリングワークフロー
密度ベースクラスタリングのためにHDBSCANを別途インストールします:
uv pip install hdbscan
import umap
import hdbscan
from sklearn.preprocessing import StandardScaler
# 1. データの前処理
scaled_data = StandardScaler().fit_transform(data)
# 2. クラスタリング最適化パラメータでUMAP
reducer = umap.UMAP(
n_neighbors=30,
min_dist=0.0,
n_components=10, # 密度保存を向上させるため2より大きい値
metric='euclidean',
random_state=42
)
embedding = reducer.fit_transform(scaled_data)
# 3. HDBSCANクラスタリングの適用
clusterer = hdbscan.HDBSCAN(
min_cluster_size=15,
min_samples=5,
metric='euclidean'
)
labels = clusterer.fit_predict(embedding)
# 4. 評価
from sklearn.metrics import adjusted_rand_score
score = adjusted_rand_score(true_labels, labels)
print(f"調整ランド指数: {score:.3f}")
print(f"クラスタ数: {len(set(labels)) - (1 if -1 in labels else 0)}")
print(f"ノイズ点: {sum(labels == -1)}")
クラスタリング後の可視化
# 可視化用の2次元埋め込みを作成(クラスタリングとは別に)
vis_reducer = umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, random_state=42)
vis_embedding = vis_reducer.fit_transform(scaled_data)
# クラスタラベルでプロット
import matplotlib.pyplot as plt
plt.scatter(vis_embedding[:, 0], vis_embedding[:, 1], c=labels, cmap='Spectral', s=5)
plt.colorbar()
plt.title('HDBSCANクラスタによるUMAP可視化')
plt.show()
重要な注意点: UMAPは密度を完全には保持せず、人為的なクラスタ分割を作成する可能性があります。常に結果のクラスタを検証し、探索してください。
新しいデータの変換
UMAPはtransform()メソッドを介して新しいデータの前処理を可能にし、学習済みモデルが未知のデータを学習済みの埋め込み空間に射影できるようにします。
基本的な変換の使用法
# 訓練データで学習
trans = umap.UMAP(n_neighbors=15, random_state=42).fit(X_train)
# テストデータを変換
test_embedding = trans.transform(X_test)
機械学習パイプラインとの統合
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import umap
# データ分割
X_train, X_test, y_train, y_test = train_test_split(data, labels, test_size=0.2)
# 前処理
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# UMAPの学習
reducer = umap.UMAP(n_components=10, random_state=42)
X_train_embedded = reducer.fit_transform(X_train_scaled)
X_test_embedded = reducer.transform(X_test_scaled)
# 埋め込み上で分類器を学習
clf = SVC()
clf.fit(X_train_embedded, y_train)
accuracy = clf.score(X_test_embedded, y_test)
print(f"テスト精度: {accuracy:.3f}")
重要な考慮事項
データの一貫性: transformメソッドは、訓練データとテストデータ間で高次元空間における全体分布が一貫していることを前提とします。この前提が成り立たない場合は、代わりにParametric UMAPの使用を検討してください。
パフォーマンス: transform操作は効率的ですが(通常1秒未満)、初回の呼び出しはNumba JITコンパイルのために遅くなる可能性があります。
scikit-learn互換性: UMAPは標準的なsklearnの慣例に従い、パイプラインで動作します。最近の0.5.xリリースでは、特徴量名のサポートと現在のscikit-learn検証APIとの互換性も向上しています:
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
('scaler', StandardScaler()),
('umap', umap.UMAP(n_components=10)),
('classifier', SVC())
])
pipeline.fit(X_train, y_train)
predictions = pipeline.predict(X_test)
feature_names = pipeline.named_steps['umap'].get_feature_names_out()
高度な機能
パラメトリックUMAP
パラメトリックUMAPは、直接的な埋め込み最適化を学習済みニューラルネットワークマッピング関数に置き換えます。
標準UMAPとの主な違い:
- TensorFlow/Kerasを使用してエンコーダネットワークを訓練します
- 新しいデータの効率的な変換を可能にします
- デコーダネットワークによる再構築(逆変換)をサポートします
- カスタムアーキテクチャを許可します(画像用CNN、シーケンス用RNN)
インストール:
uv pip install "umap-learn[parametric-umap]==0.5.12"
# TensorFlowベースのParametric UMAPエクストラをインストールします。
基本的な使用法:
from umap.parametric_umap import ParametricUMAP
# デフォルトアーキテクチャ(3層100ニューロン全結合ネットワーク)
embedder = ParametricUMAP()
embedding = embedder.fit_transform(data)
# 新しいデータを効率的に変換
new_embedding = embedder.transform(new_data)
カスタムアーキテクチャ:
import tensorflow as tf
# カスタムエンコーダの定義
encoder = tf.keras.Sequential([
tf.keras.layers.InputLayer(shape=(input_dim,)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(2) # 出力次元
])
embedder = ParametricUMAP(encoder=encoder, dims=(input_dim,))
embedding = embedder.fit_transform(data)
永続化: Parametric UMAPは、プレーンなpickleではなく、組み込みのKeras対応メソッドを使用して保存します:
embedder.save("parametric_umap_model", exclude_raw_data=True)
from umap.parametric_umap import load_ParametricUMAP
loaded = load_ParametricUMAP("parametric_umap_model")
new_embedding = loaded.transform(new_data)
最近の0.5.12修正には、パラメトリックUMAPの再学習の安定性向上とメトリック勾配の修正が含まれているため、ニューラルネットワークワークフローでは現在のピン留めされたリリースを推奨します。
パラメトリックUMAPを使用すべき場合:
- 学習後に新しいデータを効率的に変換する必要がある場合
- 再構築機能(逆変換)が必要な場合
- UMAPをオートエンコーダと組み合わせたい場合
- 特殊なアーキテクチャの恩恵を受ける複雑なデータタイプ(画像、シーケンス)を扱う場合
逆変換
逆変換により、低次元埋め込みから高次元データを再構築できます。
基本的な使用法:
reducer = umap.UMAP()
embedding = reducer.fit_transform(data)
# 埋め込み座標から高次元データを再構築
reconstructed = reducer.inverse_transform(embedding)
重要な制限:
- 計算コストが高い操作です
- 埋め込みの凸包の外側ではうまく機能しません
- クラスタ間のギャップがある領域では精度が低下します
例: 埋め込み空間の探索:
import numpy as np
# 埋め込み空間にグリッド点を作成
x = np.linspace(embedding[:, 0].min(), embedding[:, 0].max(), 10)
y = np.linspace(embedding[:, 1].min(), embedding[:, 1].max(), 10)
xx, yy = np.meshgrid(x, y)
grid_points = np.c_[xx.ravel(), yy.ravel()]
# グリッドからサンプルを再構築
reconstructed_samples = reducer.inverse_transform(grid_points)
AlignedUMAP
時間的または関連するデータセットで共有座標系が必要な場合(時系列実験、バッチ)、umap.AlignedUMAP().fit(datasets, relations=relations)を使用します。ここでrelationsは連続するデータセット間のサンプルインデックスをマッピングし、意味のあるアライメントに必要です。パラメータ、メソッド、および具体的な例は、references/api_reference.mdの「AlignedUMAPクラス」と「使用例」にあります。
再現性
再現可能な結果を確保するために、常にrandom_stateパラメータを設定してください:
reducer = umap.UMAP(random_state=42)
引用
UMAPを使用する場合は、以下の論文を引用してください:
McInnes, L, Healy, J, UMAP: Uniform Manifold Approximation and Projection for Dimension Reduction, ArXiv e-prints 1802.03426, 2018