alterlab-umap について
alterlab-umapは、高次元の特徴量や埋め込みを扱う研究者や機械学習実務者向けに、UMAPによる次元削減を解説するスキルです。可視化、クラスタリング前処理、教師あり埋め込み、パラメーター調整、新規データの変換を扱います。
主な機能
- 01高次元データを低次元空間へ射影
- 02教師あり・半教師あり埋め込みに対応
- 03近傍数や距離パラメーターの調整
- 04新規データの変換とsklearnパイプライン利用
- 05Parametric UMAPと逆変換の解説
活用シーン
- 01特徴量や埋め込みの2D・3D可視化
- 02HDBSCANクラスタリング前の次元削減
- 03ラベルによるクラス分離の誘導
- 04学習済みモデルのテストデータへの適用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ alterlab-ieu/ alterlab-academic-skills --skill alterlab-umapインストール後、Claude Code で/alterlab-umapを入力して読み込まれたか確認します。
同梱ファイルevals/evals.jsonreferences/api_reference.md
詳細
UMAP-Learn
概要
UMAP(Uniform Manifold Approximation and Projection)は、可視化および一般的な非線形次元削減に用いられる手法です。局所構造と大域構造を保持する高速でスケーラブルな埋め込み、教師あり学習、クラスタリングの前処理には、このスキルを使用してください。
このスキルを使用する場面
次のような場合に、このスキルを使用してください。
- 高次元の特徴量や埋め込みを 2D/3D に射影して可視化する。
- 密度ベースのクラスタリング(HDBSCAN)の前に次元を削減する。
- 教師あり、半教師あり、パラメトリック、または整列 UMAP モデルを適合させる、あるいは適合済みモデルで新しいデータを変換する。
n_neighbors、min_dist、n_components、metricを調整する、または再現可能な埋め込みを作成する。
対象外
| シナリオ | 代わりに使用 |
|---|---|
単一細胞のワークフロー(AnnData 上での sc.pp.neighbors → sc.tl.umap) | alterlab-scanpy |
| 線形次元削減(PCA/TruncatedSVD)、または一般的な ML パイプラインとモデル選択 | alterlab-scikit-learn |
| BERTopic を使った文書のトピックモデリング(内部で UMAP を使用)を測定設計として行う | alterlab-text-as-data |
クイックスタート
インストール
uv pip install "umap-learn>=0.5,<0.6" # examples target the 0.5.x API
基本的な使い方
UMAP は scikit-learn の規約に準拠しており、t-SNE や PCA のドロップイン置換として使用できます。
import umap
from sklearn.preprocessing import StandardScaler
# Prepare data (put features on comparable scales)
scaled_data = StandardScaler().fit_transform(data)
# Method 1: Single step (fit and transform)
embedding = umap.UMAP().fit_transform(scaled_data)
# Method 2: Separate steps (for reusing trained model)
reducer = umap.UMAP(random_state=42)
reducer.fit(scaled_data)
embedding = reducer.embedding_ # Access the trained embedding
前処理: UMAP を適用する前に、単位の異なる特徴量を標準化してください。そうしないと、距離メトリックによって各次元が元のスケールに応じて重み付けされます。選択したメトリックにとって元のスケールに意味がある場合(例:テキストやモデルの埋め込みに対するコサイン距離、バイナリデータに対するジャカード距離)は、標準化を省略してください。
一般的なワークフロー
import umap
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
# 1. Preprocess data
scaler = StandardScaler()
scaled_data = scaler.fit_transform(raw_data)
# 2. Create and fit 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. Visualize
plt.scatter(embedding[:, 0], embedding[:, 1], c=labels, cmap='Spectral', s=5)
plt.colorbar()
plt.title('UMAP Embedding')
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 次元: クラスタリングの前処理(2D よりも密度をよく保持します)
- 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 を使用してください。
パラメーター調整の例
# For visualization with emphasis on local structure
umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, metric='euclidean')
# For clustering preprocessing
umap.UMAP(n_neighbors=30, min_dist=0.0, n_components=10, metric='euclidean')
# For document embeddings
umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, metric='cosine')
# For preserving global structure
umap.UMAP(n_neighbors=100, min_dist=0.5, n_components=2, metric='euclidean')
教師ありおよび半教師ありの次元削減
UMAP ではラベル情報を取り入れて埋め込み処理を導き、内部構造を保ちながらクラスを分離できます。
教師あり UMAP
フィッティング時に y パラメーターを通じてターゲットラベルを渡します。
# Supervised dimension reduction
embedding = umap.UMAP().fit_transform(data, y=labels)
主な利点:
- クラスを明確に分離できます
- 各クラス内の内部構造を保ちます
- クラス間の全体的な関係を維持します
使用する場面: ラベル付きデータがあり、意味のあるポイントの埋め込みを維持しながら既知のクラスを分離したい場合です。
半教師あり UMAP
ラベルが一部のみの場合、scikit-learn の規約に従い、ラベルのないポイントに -1 を指定します。
# Create semi-supervised labels
semi_labels = labels.copy()
semi_labels[unlabeled_indices] = -1
# Fit with partial labels
embedding = umap.UMAP().fit_transform(data, y=semi_labels)
使用する場面: ラベリングにコストがかかる場合や、利用可能なラベル数よりもデータ数が多い場合です。
UMAP によるメトリック学習
ラベル付きデータで教師あり埋め込みを学習し、新しいラベルなしデータに適用します。
# Train on labeled data
mapper = umap.UMAP().fit(train_data, train_labels)
# Transform unlabeled test data
test_embedding = mapper.transform(test_data)
# Use as feature engineering for downstream classifier
from sklearn.svm import SVC
clf = SVC().fit(mapper.embedding_, train_labels)
predictions = clf.predict(test_embedding)
使用する場面: 機械学習パイプラインで教師あり特徴量エンジニアリングを行う場合です。
クラスタリングのための UMAP
UMAP は、次元の呪いを克服するうえで、HDBSCAN などの密度ベースのクラスタリングアルゴリズムに効果的な前処理として機能します。
クラスタリングのベストプラクティス
重要な原則: クラスタリングでは、可視化の場合とは異なる方法で UMAP を設定します。
推奨パラメーター:
- n_neighbors: 約 30 に増やします(デフォルトの 15 では局所的すぎるため、人工的な細分化クラスタが生じることがあります)
- min_dist: 0.0 に設定します(境界を明確にするため、クラスタ内のポイントを密に配置します)
- n_components: 5~10 次元を使用します(2D と比べて密度の保持を向上させながら、パフォーマンスを維持します)
クラスタリングのワークフロー
import umap
import hdbscan
from sklearn.preprocessing import StandardScaler
# 1. Preprocess data
scaled_data = StandardScaler().fit_transform(data)
# 2. UMAP with clustering-optimized parameters
reducer = umap.UMAP(
n_neighbors=30,
min_dist=0.0,
n_components=10, # Higher than 2 for better density preservation
metric='euclidean',
random_state=42
)
embedding = reducer.fit_transform(scaled_data)
# 3. Apply HDBSCAN clustering (standalone `hdbscan` package; scikit-learn >= 1.3
# also ships sklearn.cluster.HDBSCAN with a similar interface)
clusterer = hdbscan.HDBSCAN(
min_cluster_size=15,
min_samples=5,
metric='euclidean'
)
labels = clusterer.fit_predict(embedding)
# 4. Evaluate
from sklearn.metrics import adjusted_rand_score
score = adjusted_rand_score(true_labels, labels)
print(f"Adjusted Rand Score: {score:.3f}")
print(f"Number of clusters: {len(set(labels)) - (1 if -1 in labels else 0)}")
print(f"Noise points: {sum(labels == -1)}")
クラスタリング後の可視化
# Create 2D embedding for visualization (separate from clustering)
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)
# Plot with cluster labels
import matplotlib.pyplot as plt
plt.scatter(vis_embedding[:, 0], vis_embedding[:, 1], c=labels, cmap='Spectral', s=5)
plt.colorbar()
plt.title('UMAP Visualization with HDBSCAN Clusters')
plt.show()
重要な注意点: UMAP は密度を完全には保持せず、人工的なクラスタ分割を生じさせることがあります。結果として得られたクラスタは、必ず検証して調べてください。
新しいデータの変換
UMAP では transform() メソッドを使って新しいデータを前処理し、学習済みモデルで未知のデータを学習済みの埋め込み空間に射影できます。
基本的な transform の使い方
# Train on training data
trans = umap.UMAP(n_neighbors=15, random_state=42).fit(X_train)
# Transform test data
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
# Split data
X_train, X_test, y_train, y_test = train_test_split(data, labels, test_size=0.2)
# Preprocess
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Train 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)
# Train classifier on embeddings
clf = SVC()
clf.fit(X_train_embedded, y_train)
accuracy = clf.score(X_test_embedded, y_test)
print(f"Test accuracy: {accuracy:.3f}")
重要な考慮事項
データの一貫性: transform メソッドは、高次元空間における全体的な分布が学習データとテストデータの間で一貫していることを前提とします。この前提が満たされない場合は、代わりに Parametric UMAP の使用を検討してください。
パフォーマンス: 変換処理は効率的です(通常は 1 秒未満)。ただし、Numba の JIT コンパイルにより、初回の呼び出しは遅くなる場合があります。
Scikit-learn との互換性: UMAP は標準的な sklearn の規約に従っており、パイプラインでシームレスに動作します。
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)
高度な機能
Parametric UMAP
Parametric UMAP は、埋め込みを直接最適化する代わりに、学習済みのニューラルネットワークによる写像関数を使用します。
標準の UMAP との主な違い:
- TensorFlow/Keras を使用してエンコーダーネットワークを学習します
- 新しいデータを効率よく変換できます
- デコーダーネットワークによる再構成(逆変換)をサポートします
- カスタムアーキテクチャ(画像用の CNN、系列用の RNN など)を使用できます
インストール:
uv pip install "umap-learn[parametric_umap]"
# Requires TensorFlow 2.x; import as `from umap.parametric_umap import ParametricUMAP`
# (also re-exported as `umap.ParametricUMAP`)
基本的な使い方:
from umap.parametric_umap import ParametricUMAP
# Default architecture (3-layer 100-neuron fully-connected network)
embedder = ParametricUMAP()
embedding = embedder.fit_transform(data)
# Transform new data efficiently
new_embedding = embedder.transform(new_data)
カスタムアーキテクチャ:
import tensorflow as tf
# Define custom encoder
encoder = tf.keras.Sequential([
tf.keras.layers.InputLayer(input_shape=(input_dim,)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(2) # Output dimension
])
embedder = ParametricUMAP(encoder=encoder, dims=(input_dim,))
embedding = embedder.fit_transform(data)
Parametric UMAP を使用する場合:
- 学習後に新しいデータを効率よく変換する必要がある
- 再構成機能(逆変換)が必要である
- UMAP とオートエンコーダーを組み合わせたい
- 特殊なアーキテクチャの利点を活かせる複雑なデータ型(画像、系列)を扱う
標準の UMAP を使用する場合:
- シンプルさと迅速なプロトタイピングを重視する
- データセットが小さく、計算効率が重要ではない
- 将来のデータに対する学習済み変換が不要である
逆変換
逆変換を使用すると、低次元の埋め込みから高次元データを再構成できます。
基本的な使い方:
reducer = umap.UMAP()
embedding = reducer.fit_transform(data)
# Reconstruct high-dimensional data from embedding coordinates
reconstructed = reducer.inverse_transform(embedding)
重要な制約:
- 計算コストの高い処理です
- 埋め込みの凸包の外側では、うまく機能しません
- クラスター間にギャップがある領域では、精度が低下します
使用例:
- 埋め込まれたデータの構造を理解する
- クラスター間の滑らかな遷移を可視化する
- データポイント間の補間を調べる
- 埋め込み空間で合成サンプルを生成する
例:埋め込み空間を調べる:
import numpy as np
# Create grid of points in embedding space
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()]
# Reconstruct samples from grid
reconstructed_samples = reducer.inverse_transform(grid_points)
AlignedUMAP
時間的または関連性のあるデータセット(例:時系列実験、バッチデータ)を分析する場合:
from umap import AlignedUMAP
# List of related datasets
datasets = [day1_data, day2_data, day3_data]
# Create aligned embeddings
mapper = AlignedUMAP().fit(datasets)
aligned_embeddings = mapper.embeddings_ # List of embeddings
**使用する場合:**一貫した座標系を維持しながら、関連するデータセット間で埋め込みを比較します。
再現性
UMAP は確率的最適化を使用するため、ランダム状態を固定しない限り、実行するたびに結果が変わります。
reducer = umap.UMAP(random_state=42)
注意点(umap-learn 0.5.x で確認済み):random_state を設定すると、実行が単一スレッドに固定されます。UMAP は n_jobs を 1 に上書きし、"n_jobs value ... overridden to 1 by setting random_state. Use no seed for parallelism." を出力します。つまり、固定シードで完全な再現性を得る代わりに、デフォルトのマルチコア並列処理(n_jobs=-1)が使えなくなるというトレードオフがあります。大規模なデータセットを調べる際は、処理速度を優先して random_state=None のままにし、最終的な記録用の実行時にのみシードを設定してください。完全な再現性を確保するには、埋め込みの安定性はバージョン間で保証されていないため、umap-learn のバージョンも記録してください。
よくある問題と解決策
**問題:**連結成分が分断される、またはクラスターが断片化する
- 解決策:
n_neighborsを増やして、より大域的な構造を重視します
**問題:**クラスターが広がりすぎる、または十分に分離されない
- 解決策:
min_distを小さくして、より密に配置できるようにします
**問題:**クラスタリングの結果が良くない
- **解決策:**クラスタリングに特化したパラメーターを使用します(n_neighbors=30、min_dist=0.0、n_components=5-10)
**問題:**変換結果が学習時の結果と大きく異なる
- **解決策:**テストデータの分布が学習データと一致していることを確認するか、Parametric UMAP を使用します
**問題:**大規模なデータセットで処理が遅い
- 解決策:
low_memory=True(デフォルト)を設定するか、まず PCA による次元削減を検討します
**問題:**すべてのポイントが単一のクラスターにまとまる
- **解決策:**データの前処理(適切なスケーリングが行われていること)を確認し、
min_distを大きくします
リソース
references/
詳細な API ドキュメントが含まれています:
api_reference.md:UMAP クラスの全パラメーターとメソッド
詳細なパラメーター情報や高度なメソッドの使い方が必要な場合は、これらのリファレンスを読み込んでください。
AlterLab Academic Skills スイートの一部です。