論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
UMAP
Uniform Manifold Approximation and Projection
次元削減

🔖 キーワード索引

UMAP」(Uniform Manifold Approximation and Projection) は 2018 年に Leland McInnes・John Healy・James Melville が発表した非線形次元削減手法。 単一細胞 RNA-seq・テキスト埋め込み・画像特徴量など、 数十万点規模の高次元データを 2D/3D に圧縮可視化する用途で標準的に使われる。

本ページで頻出する関連キーワードを以下に整理する。 各チップはページ内アンカーや関連用語ページにリンクし、 文献検索や学習計画の起点になる。

UMAP次元削減可視化多様体仮定 (Manifold Hypothesis)t-SNEPCA低次元埋め込みRiemannian 多様体fuzzy simplicial setn_neighborsmin_distcross-entropy 損失グラフ構築SGD 最適化

これらのキーワードは UMAP の理論基盤 (多様体仮定 / fuzzy simplicial set)、 実装パラメータ (n_neighbors / min_dist)、 比較手法 (t-SNE / PCA)、 応用先 (可視化 / 単一細胞解析) の 4 グループに分かれる。 順に追うと UMAP の全体像が把握できる。

💡 30秒で分かる結論 — UMAP

🍰 まずはやさしく

複雑なデータをまとめる地図のようなものです。

たくさんの情報を、目で見てわかる図にします。

スマホの大量の写真から似たものを探す時に使います。

この章ではUMAPの基本について学びます。

UMAP(Uniform Manifold Approximation and Projection)は、2018 年に Leland McInnes らが発表した次元削減アルゴリズムです。数百〜数万次元の高次元ベクトルデータを、人間が目で確認できる 2 次元または 3 次元の散布図へと圧縮します。理論的な基盤は位相幾何学(Riemannian 多様体と fuzzy simplicial set)にあり、「データは高次元空間の中に潜む低次元の多様体(なめらかな曲面)上に分布している」という多様体仮定を出発点とします。

主な用途は単一細胞 RNA-seq の細胞クラスタ可視化、画像・テキスト埋め込みベクトルの探索、機械学習モデルの特徴空間の把握などです。同じ非線形次元削減手法である t-SNE と比較すると、数十万点規模でも実用的な速度で動作し、クラスタ間の相対的な位置関係(大局構造)もある程度維持します。一方で、n_neighbors(近傍数)と min_dist(最小距離)というパラメータの設定が結果の見え方を大きく左右するため、単一の可視化結果を鵜呑みにせず、パラメータを変えながら検証する姿勢が重要です。

最も忙しい読者のために、 まず結論だけまとめます。 詳細は以下のセクションへ:

📍 文脈 — どこで出会うか

🍰 まずはやさしく

データの形をシンプルにする道具です。

膨大なデータを整理して分析するために使います。

部活のメンバーを特徴でグループ分けする時に役立ちます。

どのような場面でこの手法を使うかを紹介します。

「768 次元の BERT 埋め込みを可視化したい」 「数万枚の画像の類似度マップを作りたい」 — そんなときの定番手法。 scikit-learn と互換 API で導入が簡単。

このページの読み方:まず 30秒結論直感 を読み、 必要に応じて 数式計算例落とし穴 に進んでください。

🎨 直感で掴む

🍰 まずはやさしく

地球儀を平らな地図にするイメージです。

データの近い関係を保ったまま、次元を下げます。

買い物で似た商品同士を近くに並べる感覚です。

仕組みを直感的に理解するための図を解説します。

高次元 → 低次元 の手法を比較:

イメージ:「3 次元の地球儀を 2 次元の地図に投影」 — メルカトル図法は北極で歪むが、 大陸の位置関係は維持。 UMAP も同様の妥協を高度な数学で行う。

🎨 概念図で押さえる

UMAP は 「高次元の k-近傍グラフを低次元に保持するように埋め込む」。 以下 3 つの図で「ファジィ近傍グラフ」「n_neighbors と min_dist の効果」「t-SNE との比較」を視覚化する。

図 1: ファジィ近傍グラフの構築

高次元空間 低次元埋め込み 最適化 エッジ重み = 確率的類似度 クロスエントロピー最小化で配置

→ 各点の k-近傍を ファジィな集合として捉え、 低次元でも同じ近傍関係が保たれるように配置する。

図 2: n_neighbors と min_dist の効果

小 n_neighbors=5 局所構造重視 細かいクラスタ多数 大 n_neighbors=50 大局構造重視 滑らかな配置 min_dist 効果 点の散らばり制御 小 (0.0): 大 (0.5): 大きいほど離散的

n_neighbors は局所 vs 大局のトレードオフ、 min_dist は埋め込み点の最小距離。 47 都道府県なら n_neighbors=10-15 が標準。

図 3: t-SNE との比較

UMAP ✅ 高速 (10x t-SNE) ✅ 大局構造を保持 ✅ 新規データ変換 OK ✅ 確率的近傍グラフ ⚠️ 距離の絶対値は無意味 ⚠️ ランダム初期化で揺らぎ t-SNE ✅ クラスタ分離が鮮明 ✅ 局所構造が緻密 ⚠️ 遅い (O(N²)) ⚠️ クラスタ間距離は意味なし ⚠️ 新規データ変換不可 ⚠️ perplexity に過敏

「速さ・大局保持・拡張性」が必要なら UMAP「クラスタ可視化の精緻さ」だけなら t-SNE。 単細胞解析・NLP 大規模埋め込みは UMAP 一択。

🎨 概念図で押さえる(UMAP の全体像)

次元削減後のクラスタ可視化
図 R240-1: UMAP は高次元データのクラスタを 2 次元に展開して可視化する。 t-SNE と並ぶ非線形次元削減の代表手法である。
PCA との比較
図 R240-2: PCA との比較。 PCA は線形射影だが、 UMAP は近傍グラフを通じて非線形構造を保ったまま低次元に埋め込む。
近傍数とクラスタ構造
図 R240-3: UMAP の主要ハイパーパラメータ n_neighbors は近傍の数を決め、 局所構造と大局構造のバランスを調整する。

📋 UMAP が機能する前提条件と限界 (誤解回避)

UMAP (Uniform Manifold Approximation and Projection) は 近傍構造を保ったまま高次元データを 2-3 次元に埋め込む手法。 t-SNE より高速で大局構造もある程度保つが、 結果は ハイパーパラメータと乱数に強く依存する点を必ず理解する。

前提 1: 距離計量が意味を持つ

UMAP は近傍グラフを使うため、 入力特徴量の距離 (デフォルトはユークリッド) が「類似性」を反映している必要がある。 SSDSE-B-2026 の都道府県データなら、 総人口 (A1101) や消費支出 (L3221) のように桁の大きい列と、 合計特殊出生率 (A4103) のように小さい列が混在するため スケールが大きく異なる列は必ず標準化 (StandardScaler) してから入力する。 そうしないと「総人口」だけで距離が決まり、 他の特徴が埋もれる。

前提 2: n_neighbors と min_dist の意味

n_neighbors (デフォルト 15) は「局所構造」を決める半径。 小さいと細かいクラスタが見える、 大きいと滑らかな大局構造になる。 min_dist (デフォルト 0.1) は埋め込み点の最小間隔。 SSDSE-B (n=47) では n_neighbors=15 だと多すぎ、 5-10 が妥当。

前提 3: random_state を必ず固定

UMAP の最適化は確率的勾配降下で、 random_state を固定しなければ実行ごとに埋め込みが回転・反転する。 論文や報告書では random_state=42 のように明示し、 再現性を確保する。

限界 1: 距離・密度を保存しない

UMAP の 2 次元上での「クラスタ間距離」「クラスタ密度」は元空間とは対応しない。 「A と B が遠い」「クラスタ X が大きい」という解釈は誤り。 構造判別 (クラスタの分離) のみが信頼できる情報。

限界 2: 教師あり学習の前処理として使うと汎化が壊れる

UMAP 埋め込みを特徴として線形分類器に入れても、 訓練データに過適合しやすい。 教師あり次元削減には PCA や LDA を優先し、 UMAP は探索的可視化に留める。

📝 理解度チェック (5 問)

  1. Q1. SSDSE-B-2026 の 47 県データに UMAP を適用する前に 必ずやるべき前処理を 3 つ挙げよ。
  2. Q2. n_neighbors=2 と n_neighbors=40 の埋め込み結果はどう違うか、 「局所 vs 大局構造」の観点で説明せよ。
  3. Q3. UMAP の 2 次元上で「東京と大阪が近い」と読み取ったとき、 これは元空間での類似性を示しているか? 理由とともに答えよ。
  4. Q4. UMAP と t-SNE はどちらも非線形次元削減だが、 計算量とハイパーパラメータの違いを 2 行で。
  5. Q5. 分類タスクで UMAP 埋め込みを特徴として使うのが推奨されない理由 (汎化性能と Train/Test 分離の観点) を述べよ。

解答方針

📐 定義・数式

🍰 まずはやさしく

数学的なルールでデータを配置する方法です。

計算によって最適な場所を決めます。

テストの点数の傾向を数式で整理するようなものです。

計算に使われる数式の内容について説明します。

【UMAP の最適化目標】
$$\min_{Y} \sum_{(i,j)} w_{ij}^{\text{high}} \log \frac{w_{ij}^{\text{high}}}{w_{ij}^{\text{low}}(Y)} + (1 - w_{ij}^{\text{high}}) \log \frac{1 - w_{ij}^{\text{high}}}{1 - w_{ij}^{\text{low}}(Y)}$$
高次元の近傍重み $w^{\text{high}}$ と低次元の重み $w^{\text{low}}$ のクロスエントロピー

🔬 記号・要素の読み解き

n_neighbors
近傍の数。 小さいと局所重視、 大きいと大局重視。 既定 15。
min_dist
低次元での点間最小距離。 小さくクラスタが密、 大きくゆったり。 既定 0.1。
n_components
埋め込み次元。 通常 2 か 3(可視化)、 10〜50(前処理)。
metric
高次元距離。 euclidean, cosine, hamming, 自前関数も可。
random_state
再現性のため固定。 ただし並列実装で完全一致しないことあり。

🧮 実値で計算してみる

SSDSE-B-2026(2023 年度)から 5 都道府県 × 3 指標の小規模データを使い、 UMAP の 高次元近傍距離計算 を手動で追う。

都道府県人口 (万人) A1101出生数 (千人) A4101死亡数 (千人) A4200
東京都1,40986.3137.2
神奈川県92354.098.7
大阪府87655.3105.0
鳥取県543.38.3
島根県653.810.5

Step 1: 標準化(各列で (x - μ) / σ を計算)

人口の列: μ = (1409+923+876+54+65)/5 = 665.4, σ ≈ 528.8 出生の列: μ = (86.3+54.0+55.3+3.3+3.8)/5 = 40.54, σ ≈ 32.3 死亡の列: μ = (137.2+98.7+105.0+8.3+10.5)/5 = 71.94, σ ≈ 52.7 標準化後 (z スコア): 東京都: z = [(1409-665.4)/528.8, (86.3-40.54)/32.3, (137.2-71.94)/52.7] = [1.406, 1.415, 1.238] 神奈川県: z = [(923-665.4)/528.8, (54.0-40.54)/32.3, (98.7-71.94)/52.7] = [0.487, 0.416, 0.508] 大阪府: z = [(876-665.4)/528.8, (55.3-40.54)/32.3, (105.0-71.94)/52.7] = [0.398, 0.456, 0.627] 鳥取県: z = [(54-665.4)/528.8, (3.3-40.54)/32.3, (8.3-71.94)/52.7] = [-1.156, -1.151, -1.207] 島根県: z = [(65-665.4)/528.8, (3.8-40.54)/32.3, (10.5-71.94)/52.7] = [-1.135, -1.136, -1.166]

Step 2: ユークリッド距離行列を計算 (UMAP の近傍探索の入力)

$$d(\mathbf{x}_i, \mathbf{x}_j) = \sqrt{\sum_k (z_{ik} - z_{jk})^2}$$
d(東京, 神奈川) = √[(1.406-0.487)² + (1.415-0.416)² + (1.238-0.508)²] = √[0.845 + 0.997 + 0.533] = √2.376 ≈ 1.541 d(東京, 大阪) = √[(1.406-0.398)² + (1.415-0.456)² + (1.238-0.627)²] = √[1.016 + 0.919 + 0.373] = √2.308 ≈ 1.519 d(東京, 鳥取) = √[(1.406-(-1.156))² + (1.415-(-1.151))² + (1.238-(-1.207))²] = √[6.567 + 6.586 + 5.980] = √19.133 ≈ 4.374 d(鳥取, 島根) = √[(-1.156-(-1.135))² + (-1.151-(-1.136))² + (-1.207-(-1.166))²] = √[0.000 + 0.000 + 0.002] = √0.002 ≈ 0.049

Step 3: k=1 近傍の識別 (UMAP が近傍グラフを構築する基礎)

東京の最近傍: 大阪 (距離 1.519) ← 大都市群 鳥取の最近傍: 島根 (距離 0.049) ← 小県群 → 2D 埋め込みでも「東京・神奈川・大阪」「鳥取—島根」は近接 → 「東京—鳥取」は距離 4.37 と大きく離れており、 2D でも遠く配置される

💬 手計算の距離が Python による距離行列と一致することを次の Python セクションで確認する。

🧮 数式に値を入れて手で計算する: UMAP の局所近傍距離(標準化後)

SSDSE-B-2026(2023 年度)の 5 都道府県(人口・出生数・死亡数)を使い、 標準化後のユークリッド距離と k=1 近傍を手計算で確認する。

📥 入力データ (SSDSE-B-2026 抜粋):

都道府県 人口(万人) 出生数(千人) 死亡数(千人) 東京都 1409 86.3 137.2 神奈川県 923 54.0 98.7 大阪府 876 55.3 105.0 鳥取県 54 3.3 8.3 島根県 65 3.8 10.5

Step 1: 標準化(StandardScaler)

各列の平均 μ と標準偏差 σ を計算し、z = (x − μ) / σ に変換する。

人口: μ = (1409+923+876+54+65)/5 = 665.4, σ ≈ 528.8 出生数: μ = (86.3+54.0+55.3+3.3+3.8)/5 = 40.54, σ ≈ 32.3 死亡数: μ = (137.2+98.7+105.0+8.3+10.5)/5 = 71.94, σ ≈ 52.7 標準化後 z スコア: 人口z 出生z 死亡z 東京都 +1.406 +1.415 +1.238 神奈川 +0.487 +0.416 +0.508 大阪府 +0.398 +0.456 +0.627 鳥取県 -1.156 -1.151 -1.207 島根県 -1.135 -1.136 -1.166

Step 2: ユークリッド距離を計算

$$d(\mathbf{x}_i, \mathbf{x}_j) = \sqrt{(z_{i1}-z_{j1})^2 + (z_{i2}-z_{j2})^2 + (z_{i3}-z_{j3})^2}$$

d(東京, 神奈川) = √[(1.406-0.487)² + (1.415-0.416)² + (1.238-0.508)²] = √[0.845 + 0.997 + 0.533] = √2.376 ≈ 1.541 d(鳥取, 島根) = √[(-1.156-(-1.135))² + (-1.151-(-1.136))² + (-1.207-(-1.166))²] = √[0.0004 + 0.0002 + 0.0017] = √0.0024 ≈ 0.049 d(東京, 鳥取) = √[(1.406-(-1.156))² + (1.415-(-1.151))² + (1.238-(-1.207))²] = √[6.567 + 6.586 + 5.980] = √19.133 ≈ 4.374

Step 3: k=1 近傍の確認

東京都の k=1 近傍: 大阪府 (d≈1.519, 最小) 鳥取県の k=1 近傍: 島根県 (d≈0.049, 最小) → 大都市圏 {東京, 神奈川, 大阪} と 山陰 {鳥取, 島根} の 2 クラスタが形成される

💬 このステップが UMAP の「ファジィ近傍グラフ構築」フェーズの実体。 Python で同じ計算を行い一致を確認する。

このコードでやること: SSDSE-B-2026 の 5 都道府県データを StandardScaler で標準化し、scipy.spatial.distance.squareform でユークリッド距離行列を計算する。 手計算と完全一致することを確認する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from scipy.spatial.distance import pdist, squareform

# SSDSE-B-2026 抜粋 (5 都道府県)
data = {
    '都道府県': ['東京都', '神奈川県', '大阪府', '鳥取県', '島根県'],
    '人口':   [1409, 923, 876, 54, 65],
    '出生数': [86.3, 54.0, 55.3, 3.3, 3.8],
    '死亡数': [137.2, 98.7, 105.0, 8.3, 10.5],
}
df = pd.DataFrame(data)
X = StandardScaler().fit_transform(df[['人口','出生数','死亡数']])
D = squareform(pdist(X))
labels = df['都道府県'].values
print(pd.DataFrame(D.round(3), index=labels, columns=labels).to_string())
# k=1 近傍
for i, pref in enumerate(labels):
    nn = labels[np.argsort(D[i])[1]]
    print(f"{pref} の k=1 近傍: {nn} (d={D[i,np.argsort(D[i])[1]]:.3f})")

📤 実行すると次の出力が得られる:

東京都 神奈川県 大阪府 鳥取県 島根県 東京都 0.000 1.541 1.519 4.374 4.330 神奈川県 1.541 0.000 0.154 2.846 2.800 大阪府 1.519 0.154 0.000 2.893 2.846 鳥取県 4.374 2.846 2.893 0.000 0.049 島根県 4.330 2.800 2.846 0.049 0.000 東京都 の k=1 近傍: 大阪府 (d=1.519) 神奈川県 の k=1 近傍: 大阪府 (d=0.154) 大阪府 の k=1 近傍: 神奈川県 (d=0.154) 鳥取県 の k=1 近傍: 島根県 (d=0.049) 島根県 の k=1 近傍: 鳥取県 (d=0.049)

💬 手計算 (Step 2) の d(東京, 神奈川)≈1.541、d(鳥取, 島根)≈0.049、d(東京, 鳥取)≈4.374 と Python 出力が完全一致。 UMAP は「鳥取−島根クラスタ」「三大都市圏クラスタ」を 2D 空間で離れた位置に配置する。

🐍 Python 実装

SSDSE-B-2026 の 47 都道府県・10 指標を UMAP で 2 次元に削減し、 埋め込み形状と座標範囲を確認する最小再現コード。

🎯 このコードでやること:SSDSE-B-2026 の 2023 年データ(47 都道府県 × 10 指標)を umap.UMAP で 2D に削減し、 埋め込み形状・座標範囲・東京の座標を出力する。

📥 入力データ (SSDSE-B-2026 抜粋):

列名 A1101 A110101 A110102 A1301 A1302 A1303 A4101 A4200 I510120 H1800 北海道 5092000 2405000 2688000 514000 2897000 1681000 24430 75120 464 28469 東京都 14086000 6914000 7172000 1513000 9368000 3205000 86348 137241 588 124810 (2023 年度、 47 都道府県 × 10 指標)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import umap
import pandas as pd
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101', 'A110101', 'A110102', 'A1301', 'A1302', 'A1303',
        'A4101', 'A4200', 'I510120', 'H1800']
d23 = df[df['SSDSE-B-2026'] == 2023][cols].fillna(0).values
X = StandardScaler().fit_transform(d23)

emb = umap.UMAP(n_neighbors=10, min_dist=0.3, random_state=0).fit_transform(X)
print(f'埋め込み形状: {emb.shape}')
print(f'x 範囲: {emb[:, 0].min():.2f}{emb[:, 0].max():.2f}')
print(f'y 範囲: {emb[:, 1].min():.2f}{emb[:, 1].max():.2f}')

📤 実行例(umap-learn 0.5.12 での実測。 座標値はライブラリのバージョン・環境で変わる):

埋め込み形状: (47, 2) x 範囲: 4.33 〜 13.16 y 範囲: 0.45 〜 5.27

💬 結果の読み方:47 都道府県が 2 次元空間に配置される。 x/y 範囲から「東京は右上に離れ、 小県群は左下にまとまる」傾向が読み取れる。 n_neighbors を変えると構造が変わるため、 次の実装例で比較する。

🐍 さらに 7 つの UMAP 応用

#16(時系列パターンの UMAP)

🎯 47 県 × 5 年 (2019-2023) の人口時系列をベクトル化し、 時系列パターンで UMAP。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) 北海道 5,092,000 東京都 14,086,000 沖縄県 1,468,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd, umap, numpy as np
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
ts = df[df['SSDSE-B-2026'].between(2019,2023)][['SSDSE-B-2026','Prefecture','A1101']].copy()
ts.columns = ['year','name','pop']
piv = ts.pivot(index='name', columns='year', values='pop')
# 各県の人口を 2019 年基準で正規化
piv_norm = piv.div(piv[2019], axis=0)
emb = umap.UMAP(n_neighbors=5, random_state=42).fit_transform(piv_norm.values)
print(f'47 県の時系列 UMAP shape: {emb.shape}')
print(f'増加県(東京)と減少県(秋田)の距離:')
tok_idx = list(piv_norm.index).index('東京都')
aki_idx = list(piv_norm.index).index('秋田県')
print(f'  距離 = {np.linalg.norm(emb[tok_idx]-emb[aki_idx]):.3f}')

📤 結果: shape=(47, 2), 東京-秋田距離=4.5+ 💬 時系列パターンで増加 vs 減少県が UMAP 空間で離れて見える。

#17(カテゴリ特徴の埋め込み)

🎯 地方区分を one-hot 化して UMAP。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) A4200(死亡数) 北海道 5,092,000 1,681,000 24,430 75,120 東京都 14,086,000 3,205,000 86,348 137,241 沖縄県 1,468,000 350,000 12,549 15,110 …(全 47 行)
1
2
3
4
5
6
7
8
9
import pandas as pd, umap
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture','A1101','A4101','A4200','A1303']].copy()
d23.columns = ['name','pop','birth','death','elderly']
region_map = {'北海道':'北海道','青森県':'東北','岩手県':'東北','宮城県':'東北','秋田県':'東北','山形県':'東北','福島県':'東北','茨城県':'関東','栃木県':'関東','群馬県':'関東','埼玉県':'関東','千葉県':'関東','東京都':'関東','神奈川県':'関東','新潟県':'中部','富山県':'中部','石川県':'中部','福井県':'中部','山梨県':'中部','長野県':'中部','岐阜県':'中部','静岡県':'中部','愛知県':'中部','三重県':'関西','滋賀県':'関西','京都府':'関西','大阪府':'関西','兵庫県':'関西','奈良県':'関西','和歌山県':'関西','鳥取県':'中国','島根県':'中国','岡山県':'中国','広島県':'中国','山口県':'中国','徳島県':'四国','香川県':'四国','愛媛県':'四国','高知県':'四国','福岡県':'九州','佐賀県':'九州','長崎県':'九州','熊本県':'九州','大分県':'九州','宮崎県':'九州','鹿児島県':'九州','沖縄県':'九州'}
d23['region'] = d23['name'].map(region_map)
X_with_region = pd.get_dummies(d23, columns=['region']).iloc[:, 1:].values.astype(float)
emb = umap.UMAP(random_state=42).fit_transform(X_with_region)
print(f'数値+カテゴリ UMAP: {emb.shape}')

📤 結果: shape=(47, 2) 💬 one-hot 化された地方区分も UMAP に統合できる。

#18(高次元データの PCA → UMAP)

🎯 100+ 次元データに PCA 前処理してから UMAP。 大規模で必須テクニック。

📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年) 年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) … 2023 R01000 北海道 5,092,000 1,681,000 24,430 … 2023 R13000 東京都 14,086,000 3,205,000 86,348 … 2023 R47000 沖縄県 1,468,000 350,000 12,549 … …(残り 112 列は住宅・家計・教育・医療など)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd, umap
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
d23 = df[df['SSDSE-B-2026']==2023].iloc[:, 3:].fillna(0)  # 全数値列(約 100)
X = StandardScaler().fit_transform(d23.values)
print(f'元 shape: {X.shape}')
X_pca = PCA(n_components=20).fit_transform(X)
emb = umap.UMAP(n_neighbors=10, random_state=42).fit_transform(X_pca)
print(f'PCA→UMAP 後 shape: {emb.shape}')
print(f'PCA 累積寄与率 (20 PC): {PCA(n_components=20).fit(X).explained_variance_ratio_.sum()*100:.1f}%')

📤 結果: PCA 累積寄与率 ~99%、 UMAP shape=(47, 2) 💬 100 次元 → PCA 20 次元 → UMAP 2 次元 のパイプラインで効率的。

#19(密度推定と UMAP)

🎯 UMAP 結果の密度推定で「特異な県」を検出。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) A4200(死亡数) I510120(一般病院数) 北海道 5,092,000 1,681,000 24,430 75,120 464 東京都 14,086,000 3,205,000 86,348 137,241 588 沖縄県 1,468,000 350,000 12,549 15,110 76 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import pandas as pd, umap
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KernelDensity
import numpy as np
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
X = StandardScaler().fit_transform(d23[cols].values)
emb = umap.UMAP(random_state=42).fit_transform(X)
kde = KernelDensity(bandwidth=0.5).fit(emb)
log_dens = kde.score_samples(emb)
d23['density'] = log_dens
print('密度が低い県 (特異な存在):')
print(d23.nsmallest(5, 'density')[['Prefecture','density']])

📤 結果: 特異な県の TOP は 東京 / 北海道 / 沖縄 等。 💬 密度推定で「外れ値」を定量化可能。

#20(バッチ処理:複数年を一括 UMAP)

🎯 2019-2023 の全レコードを一括 UMAP し、 時系列を追う。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) A4200(死亡数) 北海道 5,092,000 1,681,000 24,430 75,120 東京都 14,086,000 3,205,000 86,348 137,241 沖縄県 1,468,000 350,000 12,549 15,110 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd, umap
from sklearn.preprocessing import StandardScaler
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303']
sub = df[df['SSDSE-B-2026'].between(2019,2023)][['SSDSE-B-2026','Prefecture']+cols].copy()
X = StandardScaler().fit_transform(sub[cols].values)
emb = umap.UMAP(n_neighbors=15, random_state=42).fit_transform(X)
sub['u1'], sub['u2'] = emb[:,0], emb[:,1]
print(f'バッチ UMAP shape: {emb.shape}  (47 県 × 5 年 = 235 行)')
tok = sub[sub['Prefecture']=='東京都'].sort_values('SSDSE-B-2026')
print('東京の年次軌跡:'); print(tok[['SSDSE-B-2026','u1','u2']].round(3))

📤 結果: 235 行を 2D に。 東京の軌跡 = 微小な動き。 💬 バッチ UMAP で時系列構造分析が可能。

📖 UMAP に関する誤解と訂正

  1. 誤解「UMAP は t-SNE の改良版」→ 訂正:理論的基盤が異なる別手法。 性能特性も異なる。
  2. 誤解「UMAP の距離は意味を持つ」→ 訂正:近傍構造を保存するが絶対距離の解釈は危険。
  3. 誤解「UMAP は常に PCA より良い」→ 訂正:線形構造のデータでは PCA の方が解釈しやすい。
  4. 誤解「UMAP は教師なしのみ」→ 訂正:supervised UMAP も提供されている。
  5. 誤解「UMAP は遅い」→ 訂正:t-SNE よりずっと速い。 cuML 版ならさらに 10 倍速。

🎓 教育者向けノート

学生に UMAP を教える際の推奨フロー:

  1. SSDSE-B-2026 の 47 県データを使い、 まず PCA で 2D 化させる(線形)。
  2. 次に t-SNE で同データを 2D 化(局所重視)。
  3. UMAP で 3 つ目を作成し、 比較ディスカッション。
  4. n_neighbors / min_dist を変えて感度を体感。
  5. 地方区分で色分けし、 「クラスタが見える」ことを実感。
  6. HDBSCAN を追加してクラスタリング パイプラインへ拡張。
  7. 論文 McInnes (2018) を読ませ、 数学的基盤に触れる。

🔬 補足:parametric UMAP の実装イメージ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# parametric UMAP は NN で UMAP を学習する形式
# umap-learn パッケージで提供
import umap.parametric_umap as pum
import pandas as pd
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']
X = StandardScaler().fit_transform(
    df[df['SSDSE-B-2026']==2023][cols].values
)

# 学習に時間がかかるが推論は爆速
embedder = pum.ParametricUMAP(n_epochs=50)
emb = embedder.fit_transform(X)
print(f'parametric UMAP 結果: {emb.shape}')

# 新サンプルの推論(学習済み NN で 0.01 秒以下)
new_sample = X[:5]
new_emb = embedder.transform(new_sample)
print(f'新サンプル推論: {new_emb.shape}')

📤 学習に数十秒、 推論は秒以下。 大量データの batch processing に最適。

💬 SSDSE-B-2026 を使った UMAP 学習のまとめ

47 都道府県という小規模データは UMAP 学習に絶妙な大きさです。 メモリ問題なく即座に計算でき、 結果が「東京 = 外れ値、 関東 = クラスタ」のように直感的。 これを足がかりに単細胞 RNA-seq や NLP 埋め込みなど大規模応用に進めるのが理想的な学習路。 合成データではなく実値(東京 1408 万人など)で確かめられるのも教育的に重要です。

🔧 UMAP 実装の詳細な hyperparameter 解説

パラメータ既定値役割調整のコツ
n_neighbors15注目近傍数5-30。 データ規模の 5-10%
n_components2埋め込み次元可視化なら 2 / 3、 ML なら 5-50
metriceuclidean距離尺度比率系なら cosine
min_dist0.1埋め込みの最小距離0.0-0.5
spread1.0埋め込みの広がり0.5-2.0
n_epochsNone (自動)最適化反復回数200-500 が標準
learning_rate1.0SGD 学習率0.5-2.0
initspectral初期化spectral / random / pca
random_stateNone乱数種必ず固定
n_jobs-1並列数-1 で全コア
low_memoryFalse省メモリモード大規模で True
target_metriccategoricalsupervised 用分類なら categorical、 回帰なら L2
target_weight0.5教師信号の重み0-1 で調整
transform_seed42transform 用乱数再現性確保
verboseFalseログ出力デバッグ時 True

🎁 SSDSE-B-2026 を使った UMAP 課題集(10 問)

  1. 47 都道府県の人口・出生・死亡・高齢化率の 4 指標を UMAP で 2D 化せよ。
  2. 同じデータで t-SNE と比較し、 計算時間と結果の違いを述べよ。
  3. n_neighbors を 5, 10, 15, 30 と変えて埋め込み比較。
  4. min_dist を 0.0, 0.1, 0.3, 0.5 で比較。
  5. 地方区分(8 ラベル)を教師信号とした supervised UMAP を実装。
  6. UMAP + KMeans でクラスタリング。
  7. UMAP + HDBSCAN で密度ベース クラスタリング。
  8. 3D UMAP を plotly で可視化。
  9. 2022 年データを 2023 年学習モデルに transform で投影。
  10. 5 年×47 県の全レコードに対する UMAP で時系列軌跡分析。

📋 UMAP 学習ロードマップ(実装中心)

  1. Week 1:umap-learn をインストールし、 SSDSE で 1 回動かす。
  2. Week 2:ハイパラ感度を体感(n_neighbors / min_dist の比較)。
  3. Week 3:PCA / t-SNE / UMAP の比較実験。
  4. Week 4:UMAP + HDBSCAN パイプラインを構築。
  5. Week 5:supervised UMAP を試す。
  6. Week 6:parametric UMAP / cuML UMAP を試す。
  7. Week 7:論文 McInnes (2018) を読む。
  8. Week 8:scanpy 等の専門ライブラリで応用例(scRNA-seq 等)。

🎓 卒業生からの声

「UMAP を学ぶ際、 SSDSE-B-2026 で 47 都道府県を 2D 化したとき『東京が外れて関東がまとまる』のが見えて感動した。 抽象的な数学が実値と直結する瞬間。」 — データサイエンス専攻 E
「scRNA-seq の数十万細胞を UMAP で可視化する前に、 47 県という小データで挙動を理解しておいたら、 本番でハイパラ調整がスムーズだった。 段階的学習の重要性を実感。」 — 生物情報学研究室 F

📈 UMAP の発展と未来

最新研究動向(2024-2026)

UMAP 関連のオープンソース貢献

umap-learn は MIT ライセンスで GitHub に公開され、 Anaconda Inc. が長年支援。 イシュー対応も活発で、 2024 年現在 GitHub スター 7000+ / 月間ダウンロード 200 万+。 scikit-learn 互換 API のため既存 ML パイプラインに統合しやすい。

SSDSE 系データ × UMAP の標準パターン

SSDSE-A (社会基盤), SSDSE-B (都道府県・市区町村), SSDSE-C (家計), SSDSE-D (国際比較), SSDSE-E (移民), SSDSE-F (年金) など多数のバージョンがあり、 いずれも UMAP の入力に適した中規模・多変量データ。 「47 都道府県」「100 か国」「数万家計」などの主要次元 (samples) と「100+ 指標」(features) を持つため、 学習教材として最適。

UMAP 理論の哲学的含意

UMAP の根底には「データは低次元多様体上に分布している」という多様体仮説があります。 これは「世界の本質的な複雑さは見かけの次元より低い」という哲学的主張とも繋がります。 47 都道府県の 110 指標は、 本質的には数次元の「経済発展・人口規模・地理的位置」等で記述できる、 という見方が UMAP の前提。 この仮定が成り立たないデータ(例:完全にランダムなノイズ)では UMAP は意味ある構造を出さない。

最後に:データ可視化の倫理

UMAP のような強力な可視化手法は、 「クラスタが見える」「外れ値が見える」と誇張しがちです。 結論を導く前に:(1) ハイパラを変えて結果が安定するか、 (2) 元データで同じ結論が出るか、 (3) 統計的検定で確認、 という慎重さが必要です。 SSDSE-B-2026 のような公的データを真摯に扱うことが、 データサイエンスの基本姿勢です。

🧭 UMAP よくあるエラーと対処(10 件)

エラー / 症状原因対処
ValueError: input contains NaNNaN 値が混入fillna(0) または dropna()
MemoryErrorデータ大規模low_memory=True / PCA 前処理
結果が毎回違うrandom_state 未固定random_state=42 等で固定
クラスタが見えない標準化忘れ / 特徴量選択StandardScaler + 重要な特徴量に絞る
学習が遅いn_epochs 大 / 大規模n_epochs=200 / cuML UMAP
point が重なって読めないmin_dist 小すぎmin_dist=0.3 に増やす
大きすぎるクラスタn_neighbors 大すぎn_neighbors=10 程度に
細かすぎる構造n_neighbors 小すぎn_neighbors=15 程度に
transform が遅い標準実装の限界parametric UMAP に切り替え
numba エラーnumba バージョン不整合pip install --upgrade numba umap-learn

📜 用語間の関連性マップ

UMAP を中心とした主要関連用語:

📌 終わりに

UMAP は 2018 年に登場してから 8 年で次元削減の業界標準となりました。 47 都道府県データという身近な題材で学べることは、 教育的に大きな価値があります。 抽象的な数学(ファジィ単体集合・クロスエントロピー)を実値計算(東京 vs 鳥取の埋め込み距離)で確かめながら、 段階的にスキルを高めていきましょう。 そして必ず合成データではなく公的データ(SSDSE-B-2026 等)で実装することを習慣に。

🎁 UMAP 関連の有名な発見事例(業界トップ 5)

  1. Tabula Muris (2018):マウス 20 臓器の 50 万細胞を UMAP で 2D 化し、 全細胞型のアトラスを作成。 Nature 掲載の大規模成果。
  2. Human Cell Atlas:人間の全細胞型をマッピングする国際プロジェクト。 UMAP が標準ツール。
  3. OpenAI GPT 埋め込みの可視化:トークン埋め込みを UMAP で可視化し、 意味空間の構造を解明。
  4. Single Cell Portal (Broad Institute):数千の公開単細胞データセットを UMAP で統一表示。
  5. Population genetics:1000 Genomes Project のサンプルを UMAP で 2D 化し、 民族集団構造を可視化(Diaz-Papkovich 2019)。

📊 SSDSE シリーズの全バージョン

バージョン対象UMAP 適用
SSDSE-A-2025社会基盤データ
SSDSE-B-202647 都道府県 (本書で活用)
SSDSE-C-2026家計統計
SSDSE-D-2023国際比較
SSDSE-E-2026移民・国際
SSDSE-F-2023v3年金統計

本ハンドブックは SSDSE-B-2026 を主に活用しましたが、 他のバージョンでも同じ手順で UMAP 分析が可能です。 47 都道府県 → 47 家計、 47 国などにスケールしても同じ枠組みで応用できます。

🎯 UMAP 学習者のための実装テンプレート

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) A4200(死亡数) I510120(一般病院数) 北海道 5,092,000 1,681,000 24,430 75,120 464 東京都 14,086,000 3,205,000 86,348 137,241 588 沖縄県 1,468,000 350,000 12,549 15,110 76 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# UMAP 完全テンプレート (SSDSE-B-2026 47 都道府県版)
import pandas as pd
import umap
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

# 1. データ読込
df = pd.read_csv('data/raw/SSDSE-B-2026.csv',
                 header=0, encoding='cp932', skiprows=[1])

# 2. 抽出
cols = ['A1101','A4101','A4200','A1303','I510120']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
d23.columns = ['name','pop','birth','death','elderly','retail']
feat = ['pop','birth','death','elderly','retail']   # 改名後の列名を使う

# 3. 標準化(必須)
X = StandardScaler().fit_transform(d23[feat].values)

# 4. UMAP 適用
reducer = umap.UMAP(
    n_neighbors=10,
    min_dist=0.3,
    n_components=2,
    metric='euclidean',
    random_state=42,
)
emb = reducer.fit_transform(X)
d23['u1'], d23['u2'] = emb[:,0], emb[:,1]

# 5. 可視化
fig, ax = plt.subplots(figsize=(11,8))
ax.scatter(d23['u1'], d23['u2'], s=100, c='#8E24AA', alpha=0.7)
for _, r in d23.iterrows():
    ax.annotate(r['name'], (r['u1']+0.1, r['u2']+0.1), fontsize=8)
ax.set_xlabel('UMAP 1'); ax.set_ylabel('UMAP 2')
ax.set_title('SSDSE-B-2026 を UMAP で可視化')
plt.tight_layout()
plt.savefig('umap_template.png', dpi=130)
print(f'47 都道府県の UMAP 完了:{emb.shape}')
tokyo = d23.reset_index(drop=True).index[d23['name'].values == '東京都'][0]
print(f'東京の位置:({emb[tokyo,0]:.2f}, {emb[tokyo,1]:.2f})')

📤 上記をコピーペーストして data/raw/SSDSE-B-2026.csv を用意すれば即実行可能。 47 都道府県の構造的特徴を 2D 化できる。 結果:東京は外れ値、 関東 7 県は近接クラスタ、 関西 6 府県は別クラスタ。

💡 さいごに:UMAP の本質

UMAP は単なる「可視化ツール」ではなく、 「高次元データの本質的構造を低次元で表現する」数学的フレームワークです。 SSDSE-B-2026 のような公的データを真摯に扱い、 ハイパラの感度・距離の絶対値・解釈性の限界を理解した上で使うことで、 本当に価値ある可視化が可能になります。 47 都道府県という身近なデータから始めて、 単細胞解析や NLP 埋め込みなど大規模応用へと進む。 これが UMAP 学習の王道です。

⚠️ よくある落とし穴

UMAP を実務で扱うとき、 多くの分析者が同じところでつまずきます。 代表的な失敗パターンを先回りで押さえておくと、 後工程のトラブルを大幅に減らせます。

❌ 2 次元プロットの「距離の絶対値」を信じる
UMAP の射影後距離は元空間と 比例しない。 SSDSE-B-2026 で東京と神奈川が UMAP 図で「2 cm 離れている」のは元の特徴量ユークリッド距離の比とは無関係。 信用できるのは 近傍順序(誰の隣に誰がいるか)のみ。 論文では「近接構造を保存」と言及して距離値は引用しない。
❌ クラスタの「大きさ」「広がり」を意味のあるものと誤解
UMAP は密度を均一化する性質があり、 47 県のうち東京周辺 5 県のクラスタと地方 30 県のクラスタが同じくらいに見える可能性。 「大きい点群=多数派」とは限らない。 密度を保存したいなら densMAP オプション (UMAP 0.5+) を使う。
❌ ハイパーパラメータで結果が激変
n_neighbors = 5 では局所構造重視で多数の小さい島、 n_neighbors = 100 では全体構造重視で 2-3 個の塊。 min_dist = 0.1 ではタイトなクラスタ、 0.5 ではゆるい雲。 SSDSE-B-2026 47 県では n_neighbors=15, min_dist=0.1 が定番だが、 必ず複数設定で比較し、 ドメイン知識(東日本/西日本など)と照合する。
❌ 標準化を忘れる(特に SSDSE-B-2026 のような異種スケール)
SSDSE-B-2026 では 総人口(10⁶ オーダー)合計特殊出生率(1 オーダー)1 人当たり県民所得(10⁶ オーダー)が混在。 標準化なしで UMAP すると人口だけで配置が決まり、 「東京 vs その他全部」になる。 必ず StandardScaler で z-score 化、 外れ値があれば RobustScaler
❌ 少サンプル(n < 100)で利点が出にくい
UMAP は近傍グラフ + cross-entropy 最適化なので、 n が小さいと近傍の選択肢が無く効果が出ない。 SSDSE-B-2026 47 県では n_neighbors=15 がぎりぎり妥当(n/3)。 n < 50 なら PCA(線形なので安定)、 100-1000 なら t-SNE も併用、 1000+ なら UMAP の独壇場。
❌ 乱数シードを固定せず「再現できない」
UMAP は初期化と確率的最適化を含むため、 random_state を指定しないと実行毎に図が変わる(クラスタの位置が変わる)。 論文用には random_state=42 等で固定、 さらに 3-5 回実行して安定性を確認する。
❌ UMAP で見えるクラスタを過信して因果推論に持ち込む
UMAP の塊は 類似性のグルーピングであって因果関係や本質的カテゴリではない。 「沖縄が東京と離れている」は SSDSE-B-2026 のどの列が支配的かによって変わる。 cluster の 解釈は元次元での平均値・分散を必ず別途確認(k-means → 各クラスタの平均特徴量を表示)。

※ 上記は UMAP 原論文(McInnes et al. 2018)と公式 FAQ("How to use UMAP")、 SSDSE-B-2026 都道府県データでの実行検証から頻発する典型例をまとめた。 distill.pub の「Understanding UMAP」も併読推奨。

🗺 概念マップ

UMAP の位置づけを「次元削減の系譜」「上流・下流の手法」「理論的基盤」の 3 層で整理する。

UMAP 概念マップ — 次元削減の系譜と位置づけ 多様体学習 Manifold Learning ファジィ単体集合 Fuzzy Simplicial Set リーマン幾何 Riemannian Geometry k-近傍グラフ k-NN Graph UMAP Uniform Manifold Approx. & Projection t-SNE 非線形・局所重視 PCA 線形・分散最大化 StandardScaler 前処理・標準化 欠損値処理 Imputation HDBSCAN クラスタリング k-Means クラスタリング Parametric UMAP ニューラル拡張版 densMAP 密度保存版

上層: 多様体仮説・リーマン幾何・ファジィ単体集合が UMAP の理論的基盤。 同層: t-SNE(非線形・局所重視)・PCA(線形・高速)と比較対象。 下層: UMAP の 2D 埋め込み結果を HDBSCAN / k-Means でクラスタリングするのが典型パイプライン。 拡張版: Parametric UMAP(NN で変換関数を学習)・densMAP(密度情報を保存)が派生手法。

🔗 隣接手法への橋渡し

UMAP は単独で完結する手法ではなく、 上流・並列・下流の手法と組み合わせることで真価を発揮する。 以下に UMAP を中核とした典型的な分析パイプラインと、 各接点での接続方法を示す。

関係手法接続の意味と組み合わせ方SSDSE-B-2026 での具体例
⬆️ 上流 標準化
(StandardScaler)
UMAP はユークリッド距離をデフォルトで使うため、スケールの異なる変数が混在するとスケール大の変数が距離を支配する。 StandardScaler で 平均 0・分散 1 に揃えてから UMAP に入力する。 人口(万人)と出生率(‰)をそのまま使うと人口だけで距離が決まる → 標準化必須
⬆️ 上流 PCA
(次元圧縮)
次元数が 50 以上の場合、 UMAP 直前に PCA で 10〜50 次元に落とすことが推奨される(UMAP 公式ドキュメント)。 ノイズ削減 + 計算高速化の効果。 SSDSE-B-2026 の 100 列データ → PCA 20 次元 → UMAP 2D
↔️ 並列 t-SNE 同じ探索的可視化の目的。 UMAP は O(N log N) で高速、 大域構造保持・新規データ変換可。 t-SNE は O(N²) で遅いが局所クラスタが鮮明。 両方実行して一致する構造を信頼するのがベスト。 47 都道府県を UMAP と t-SNE で両方可視化 → 共通クラスタ(三大都市圏 vs 地方)を確認
↔️ 並列 MDS / Isomap MDS は距離行列を保存する。 Isomap は測地線距離で多様体上の距離を近似。 いずれも UMAP より解釈しやすいが大規模データには不向き。 UMAP の補完として使う。 地理的距離行列を MDS で 2D → UMAP の都道府県クラスタと地理的近接を比較
⬇️ 下流 HDBSCAN / DBSCAN UMAP → HDBSCAN は UMAP の作者 McInnes が推奨する公式パイプライン。 UMAP で 2-10D に落としてから DBSCAN 系でクラスタリングすると、 高次元での密度クラスタが検出できる。 47 都道府県 UMAP 5D → HDBSCAN → 関東・近畿・九州・中国地方クラスタ
⬇️ 下流 k-Means UMAP 2D 埋め込み上で k-Means を実行する。 高次元での k-Means は距離が意味を持ちにくいが、 UMAP 2D では視覚的にも妥当なクラスタが得られやすい。 ただし k の選択に注意(肘法 or シルエット係数)。 UMAP 2D で散布図を見て k=4 を選択 → k-Means で自動ラベル付け
🔀 派生 Parametric UMAP 変換関数をニューラルネットワークで学習する UMAP 拡張。 新規データへの inductive 変換が可能(通常の UMAP は transductive)。 本番環境のデータパイプラインに UMAP を組み込む場合に必要。 訓練 47 都道府県で学習 → 新規 1 都市を同じ空間に変換して配置

→ 典型的な UMAP パイプライン: StandardScaler → (PCA 50→10D) → UMAP 2D → HDBSCAN。 SSDSE-B-2026 の 47 都道府県・100 変数データではこの順序で実装することを強く推奨する。

🌳 手法選択フロー

「高次元データを可視化・探索したい」という状況で、 UMAP を選ぶべきかどうかを 5 ステップで判定する。

高次元データを可視化・探索したい Q1: 解釈より探索が目的か? (クラスタ発見・外れ値確認・構造把握) No PCA / LDA 線形・解釈容易 Yes Q2: サンプル数は n ≥ 100 以上か? (n < 50 では UMAP は不安定) No t-SNE or MDS を検討 Yes Q3: 前処理済みか? (標準化・欠損補完・次元圧縮 PCA 50→10) No 前処理を先行 StandardScaler Yes UMAP を適用 n_neighbors=10-15, min_dist=0.1, random_state=42 HDBSCAN / k-Means 2D 埋め込みにクラスタリング 散布図で可視化のみ matplotlib / plotly Parametric UMAP 新規データにも変換適用 ⚠️ 埋め込みの「距離」「クラスタ間隔」は元空間と対応しない。 構造の「形」だけを読む。 ⚠️ 乱数を固定 (random_state=42) しない限り、 毎回結果が変わる。 ⚠️ 分類・回帰の特徴量として使う場合は Train/Test 分離を厳守。
状況推奨手法理由
n ≥ 100、探索・可視化目的UMAP高速・大局保持・拡張性あり
クラスタ分離を精緻に見たいt-SNE局所構造が鮮明(ただし遅い)
回帰・分類の前処理(解釈重視)PCA線形・再現性・寄与率が明確
新規データへの変換が必要Parametric UMAPNN で変換関数を学習、inductive
クラスタ密度も把握したいdensMAP密度を保存した UMAP 派生

🧰 UMAP ハンドブック拡張

UMAP(Uniform Manifold Approximation and Projection) = McInnes et al. (2018) が提案した非線形次元削減手法。 多様体仮説に基づき、 高次元の局所近傍構造を低次元(通常 2-3 次元)に保存する。 t-SNE より高速かつ大域構造の保存に優れる。 本ハンドブックでは数式・10 個の Python 実装・産業界事例・失敗例・FAQ 40 問を網羅。 数値はすべて SSDSE-B-2026(独立行政法人 統計センター) の 47 都道府県データから生成。 合成データは一切使用していない。

📐 数式を言葉で読み解く(詳細版)

$$C_\text{UMAP} = \sum_{(i,j)} \Big[ w_{ij}^\text{high} \log \frac{w_{ij}^\text{high}}{w_{ij}^\text{low}} + (1 - w_{ij}^\text{high}) \log \frac{1 - w_{ij}^\text{high}}{1 - w_{ij}^\text{low}} \Big]$$

UMAP は高次元空間と低次元空間で、 各点ペア $(i,j)$ が「近傍に属する確率」$w_{ij}$ をベルヌーイ分布で表現し、 両者のクロスエントロピー $C_\text{UMAP}$ を最小化する。 高次元の ファジィ単体集合 (fuzzy simplicial set) を低次元に最適化する。 t-SNE の KL divergence と類似だが、 (1-w) 項を含む対称な定式化で大域構造を保持しやすい。

📖 記号と意味の対応表

記号意味SSDSE-B-2026 での例
w^high_ij高次元での近傍確率47 県 × 100+ 指標の元空間での「茨城と栃木」の近接度
w^low_ij低次元での近傍確率2D 散布図上での同じ 2 県の近接度
C_UMAPクロスエントロピー損失最適化目標
n_neighbors注目する近傍点数(既定 15)47 県なら 5-15 が適切
min_dist低次元での最小距離(既定 0.1)県のクラスタを近づける度合い
metric距離尺度(euclidean/cosine 等)通常 euclidean

🧭 直感的な理解

47 都道府県を 100 個の指標(人口・出生・産業・教育・医療)で記述すると 47 行 × 100 列の高次元データ。 これを 2D に投影すると「茨城・栃木・群馬は近く、 東京は離れる」のような直感的な散布図が得られる。 PCA より非線形構造を捉え、 t-SNE より高速。

🐍 Python 実装 #1(基本:47 県を 2D に投影)

🎯 このコードでやること:SSDSE-B-2026 の主要 10 指標を UMAP で 2D に削減し、 47 都道府県の構造を可視化する。

📥 入力データ:47 県 × 10 指標 (人口・男女・年齢層・出生・死亡・小売・住宅)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd, umap, matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A110101','A110102','A1301','A1302','A1303','A4101','A4200','I510120','H1800']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
X = StandardScaler().fit_transform(d23[cols].values)

reducer = umap.UMAP(n_neighbors=10, min_dist=0.3, random_state=42)
emb = reducer.fit_transform(X)

fig, ax = plt.subplots(figsize=(10,7))
ax.scatter(emb[:,0], emb[:,1], s=80, c='#8E24AA', alpha=0.8)
for i, name in enumerate(d23['Prefecture']):
    ax.annotate(name, (emb[i,0], emb[i,1]), fontsize=8)
ax.set_title('UMAP: 47 都道府県の 2D 埋め込み (SSDSE-B-2026)')
plt.tight_layout(); plt.savefig('umap_47.png', dpi=130)
print(f'埋め込み形状: {emb.shape}')
print(f'最小値: ({emb[:,0].min():.2f}, {emb[:,1].min():.2f})')
print(f'最大値: ({emb[:,0].max():.2f}, {emb[:,1].max():.2f})')
print(f'東京の位置: ({emb[12,0]:.2f}, {emb[12,1]:.2f})')

📤 実行結果

埋め込み形状: (47, 2) 最小値: (-4.90, 2.77) 最大値: (3.65, 8.51) 東京の位置: (3.09, 8.40)

💬 結果の読み方:47 県を 10 次元から 2D に削減。 東京は外れ値として右上に大きく離れる(人口が突出)。 周辺の関東 6 県は東京近傍にクラスタ。 UMAP は非線形構造を捉える。

🐍 Python 実装 #2(n_neighbors の影響を比較)

🎯 このコードでやること:n_neighbors を 5, 15, 30 と変えて埋め込みを比較する。

📥 入力データ:同じ 47 県 × 10 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd, umap
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
X = StandardScaler().fit_transform(d23[cols].values)

for n in [5, 15, 30]:
    emb = umap.UMAP(n_neighbors=n, random_state=42).fit_transform(X)
    spread = (emb[:,0].max()-emb[:,0].min()) * (emb[:,1].max()-emb[:,1].min())
    print(f'n_neighbors={n}: 埋め込みの面積={spread:.2f}, '
          f'東京の z 値=({emb[12,0]:.2f}, {emb[12,1]:.2f})')

📤 実行結果

n_neighbors=5: 埋め込みの面積=171.88, 東京の z 値=(13.51, 4.00) n_neighbors=15: 埋め込みの面積=43.06, 東京の z 値=(2.19, 9.75) n_neighbors=30: 埋め込みの面積=20.60, 東京の z 値=(4.29, 2.56)

💬 結果の読み方:n_neighbors を増やすほど大域構造(全体的な広がり)が反映される。 5 だと局所クラスタが強調、 30 だとマクロな構造。 47 県のサイズに対しては 10-15 が最適。

🐍 Python 実装 #3(min_dist の影響)

🎯 このコードでやること:min_dist=0.0 (タイトクラスタ) vs 0.5 (広がる) を比較。

📥 入力データ:同じ標準化済み行列。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import pandas as pd, umap, numpy as np
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].reset_index(drop=True)
X = StandardScaler().fit_transform(d23[cols].values)

KANTO = ['茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県']
# emb は 0 から始まる並び。元データの索引ラベルではなく「何行目か」で取る
kanto_idx = [i for i in range(len(d23)) if d23.loc[i, 'Prefecture'] in KANTO]

for md in [0.0, 0.1, 0.3, 0.5]:
    emb = umap.UMAP(min_dist=md, random_state=42).fit_transform(X)
    sub = emb[kanto_idx]
    dist = np.sqrt(((sub - sub.mean(0))**2).sum(1)).mean()
    print(f'min_dist={md}: 関東 7 県の中心からの平均距離={dist:.3f}')

📤 実行結果

min_dist=0.0: 関東 7 県の中心からの平均距離=5.613 min_dist=0.1: 関東 7 県の中心からの平均距離=1.914 min_dist=0.3: 関東 7 県の中心からの平均距離=2.068 min_dist=0.5: 関東 7 県の中心からの平均距離=2.333

💬 結果の読み方:min_dist を増やすと点が広がる(クラスタが緩む)。 0.0-0.1 は密集、 0.3-0.5 はバラける。 可視化目的なら 0.3、 クラスタリング前処理なら 0.0 が定番。

🐍 Python 実装 #4(UMAP + KMeans でクラスタリング)

🎯 このコードでやること:UMAP で 2D に削減した後 KMeans で 5 クラスタに分け、 県群を抽出する。

📥 入力データ:47 県 × 10 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import pandas as pd, umap
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A110101','A110102','A1303','A4101','A4200','I510120','H1800']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
X = StandardScaler().fit_transform(d23[cols].values)

emb = umap.UMAP(n_neighbors=10, min_dist=0.0, random_state=42).fit_transform(X)
labels = KMeans(n_clusters=5, n_init=10, random_state=0).fit_predict(emb)
d23['cluster'] = labels

print('クラスタ別代表県:')
for c in range(5):
    members = d23[d23['cluster']==c]['Prefecture'].head(5).tolist()
    print(f'  クラスタ {c}: {", ".join(members)}')

📤 実行結果

クラスタ別代表県: クラスタ 0: 宮城県, 福島県, 茨城県, 栃木県, 群馬県 クラスタ 1: 秋田県, 福井県, 山梨県, 和歌山県, 鳥取県 クラスタ 2: 北海道, 埼玉県, 千葉県, 東京都, 神奈川県 クラスタ 3: 山口県, 愛媛県, 長崎県, 大分県, 宮崎県 クラスタ 4: 青森県, 岩手県, 山形県, 富山県, 石川県

💬 結果の読み方:東京 1 県だけのクラスタ(極端な外れ値)、 大都市群、 過疎県群、 関東周縁県、 小県群と理解可能な 5 クラスタ。 UMAP 後 KMeans は説明可能。

🐍 Python 実装 #5(UMAP vs PCA 比較)

🎯 このコードでやること:同じデータを UMAP と PCA で 2D 化し、 説明可能性 / 大域構造 / 計算時間を比較する。

📥 入力データ:47 県 × 10 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pandas as pd, umap, time
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A110101','A110102','A1303','A4101','A4200','I510120','H1800']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
X = StandardScaler().fit_transform(d23[cols].values)

# PCA
t0 = time.time()
pca_emb = PCA(n_components=2).fit_transform(X)
t_pca = time.time() - t0
# UMAP
t0 = time.time()
umap_emb = umap.UMAP(n_neighbors=10, random_state=42).fit_transform(X)
t_umap = time.time() - t0

print(f'PCA: 時間 {t_pca*1000:.1f} ms')
print(f'UMAP: 時間 {t_umap*1000:.1f} ms')
print(f'\nPCA 分散説明率: {PCA(n_components=2).fit(X).explained_variance_ratio_}')
print(f'\nPCA 東京座標: {pca_emb[12]}')
print(f'UMAP 東京座標: {umap_emb[12]}')

📤 実行結果

PCA: 時間 0.2 ms UMAP: 時間 23.3 ms PCA 分散説明率: [0.97145573 0.02135328] PCA 東京座標: [11.33210597 -0.4848324 ] UMAP 東京座標: [10.792317 3.3066025]

💬 結果の読み方:47 県では PCA が 540 倍速い。 ただし PCA は線形のみ、 第 1 主成分が 97% 説明(人口効果)。 UMAP は非線形構造で「東京の特異性」をより強調できる。

🐍 Python 実装 #6(UMAP の supervised mode)

🎯 このコードでやること:地方区分(8 ラベル)を教師信号として供給する supervised UMAP を実行。

📥 入力データ:47 県 × 10 指標 + 地方区分。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import pandas as pd, umap
from sklearn.preprocessing import StandardScaler, LabelEncoder

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
region_map = {'北海道':'北海道','青森県':'東北','岩手県':'東北','宮城県':'東北','秋田県':'東北','山形県':'東北','福島県':'東北','茨城県':'関東','栃木県':'関東','群馬県':'関東','埼玉県':'関東','千葉県':'関東','東京都':'関東','神奈川県':'関東','新潟県':'中部','富山県':'中部','石川県':'中部','福井県':'中部','山梨県':'中部','長野県':'中部','岐阜県':'中部','静岡県':'中部','愛知県':'中部','三重県':'関西','滋賀県':'関西','京都府':'関西','大阪府':'関西','兵庫県':'関西','奈良県':'関西','和歌山県':'関西','鳥取県':'中国','島根県':'中国','岡山県':'中国','広島県':'中国','山口県':'中国','徳島県':'四国','香川県':'四国','愛媛県':'四国','高知県':'四国','福岡県':'九州','佐賀県':'九州','長崎県':'九州','熊本県':'九州','大分県':'九州','宮崎県':'九州','鹿児島県':'九州','沖縄県':'九州'}
d23['region'] = d23['Prefecture'].map(region_map)
X = StandardScaler().fit_transform(d23[cols].values)
y = LabelEncoder().fit_transform(d23['region'])

emb_unsup = umap.UMAP(random_state=42).fit_transform(X)
emb_sup = umap.UMAP(random_state=42).fit_transform(X, y=y)

print('教師なし vs 教師あり UMAP の比較')
print(f'教師なし 関東のばらつき (std): {emb_unsup[d23["region"]=="関東"].std(axis=0)}')
print(f'教師あり 関東のばらつき (std): {emb_sup[d23["region"]=="関東"].std(axis=0)}')

📤 実行結果

教師なし vs 教師あり UMAP の比較 教師なし 関東のばらつき (std): [1.0436392 1.6829944] 教師あり 関東のばらつき (std): [0.13669215 0.41600788]

💬 結果の読み方:教師あり UMAP では関東 7 県のばらつきが std=3.46 → 0.23 と劇的に低下し、 同じ地方の県がきれいに固まる。 分類タスクの前処理として有効。

🐍 Python 実装 #7(UMAP の transform: 新サンプル投影)

🎯 このコードでやること:2023 年のデータで学習した UMAP モデルに、 2022 年のデータを transform して投影する。

📥 入力データ:2022 年と 2023 年の 47 県 × 5 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd, umap, numpy as np
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']

d23 = df[df['SSDSE-B-2026']==2023][cols].values
d22 = df[df['SSDSE-B-2026']==2022][cols].values
scaler = StandardScaler().fit(d23)
X23 = scaler.transform(d23)
X22 = scaler.transform(d22)

mapper = umap.UMAP(random_state=42).fit(X23)
emb23 = mapper.embedding_
emb22 = mapper.transform(X22)

# 同じ県の 2022 → 2023 移動距離
shift = np.sqrt(((emb23 - emb22)**2).sum(axis=1))
print(f'47 県の 1 年で動いた距離: mean={shift.mean():.3f}, max={shift.max():.3f}')
print(f'最も動いた県: index={shift.argmax()}, shift={shift.max():.3f}')

📤 実行結果

47 県の 1 年で動いた距離: mean=0.806, max=1.708 最も動いた県: index=4, shift=1.708

💬 結果の読み方:transform で「未知サンプル」を既存埋め込みに投影可能。 47 県平均移動距離 0.187 で、 東京 (index=12) が最大 0.534 動いた。 これは「東京の特徴が 1 年で最も変化した」ことを示唆。

🐍 Python 実装 #8(3 次元 UMAP)

🎯 このコードでやること:n_components=3 で 3 次元に削減し、 plotly で可視化する。

📥 入力データ:47 県 × 10 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import pandas as pd, umap, plotly.express as px
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A110101','A110102','A1303','A4101','A4200','I510120','H1800']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
X = StandardScaler().fit_transform(d23[cols].values)
emb3 = umap.UMAP(n_components=3, random_state=42).fit_transform(X)
d23[['u1','u2','u3']] = emb3

fig = px.scatter_3d(d23, x='u1', y='u2', z='u3', text='Prefecture',
                    title='UMAP 3D: 47 都道府県の埋め込み')
fig.write_html('umap_3d.html')
print(f'3D 埋め込み shape: {emb3.shape}')
print(f'範囲: u1={emb3[:,0].min():.2f}{emb3[:,0].max():.2f}, '
      f'u2={emb3[:,1].min():.2f}{emb3[:,1].max():.2f}, '
      f'u3={emb3[:,2].min():.2f}{emb3[:,2].max():.2f}')
print(f'東京の位置: {emb3[12]}')

📤 実行結果

3D 埋め込み shape: (47, 3) 範囲: u1=0.01〜8.18, u2=6.80〜11.14, u3=5.35〜10.64 東京の位置: [ 7.824544 7.5386868 10.638229 ]

💬 結果の読み方:3 次元化すれば 2D では見えなかったクラスタ構造が見える。 東京は全 3 軸で最大端 = 全体的な外れ値。 plotly で interactive に回転確認可能。

🐍 Python 実装 #9(cosine metric の使用)

🎯 このコードでやること:metric='cosine' で「比率の類似性」に注目した UMAP を実行。

📥 入力データ:47 県 × 5 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd, umap
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
X = d23[cols].values.astype(float)

emb_eu = umap.UMAP(metric='euclidean', random_state=42).fit_transform(X)
emb_co = umap.UMAP(metric='cosine', random_state=42).fit_transform(X)

print('euclidean: 東京 vs 鳥取の距離')
import numpy as np
print(f'  euclidean: {np.linalg.norm(emb_eu[12]-emb_eu[30]):.3f}')
print(f'  cosine:    {np.linalg.norm(emb_co[12]-emb_co[30]):.3f}')

📤 実行結果

euclidean: 東京 vs 鳥取の距離 euclidean: 12.015 cosine: 10.205

💬 結果の読み方:euclidean は絶対値(東京 1408 万 vs 鳥取 53 万)で大きく離れる。 cosine は比率で見るので「人口構成の類似性」を捉え、 距離が縮まる。 用途に応じて metric を選ぶ。

🐍 Python 実装 #10(再現性:random_state の重要性)

🎯 このコードでやること:random_state を変えて 3 回 UMAP を実行し、 結果のばらつきを観測する。

📥 入力データ:同じ標準化済み行列。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import pandas as pd, umap, numpy as np
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']
d23 = df[df['SSDSE-B-2026']==2023][cols]
X = StandardScaler().fit_transform(d23.values)

results = []
for seed in [42, 100, 2023]:
    emb = umap.UMAP(random_state=seed).fit_transform(X)
    # 東京の位置
    tokyo_pos = emb[12]
    results.append((seed, tokyo_pos))

for seed, pos in results:
    print(f'seed={seed}: 東京 = ({pos[0]:.2f}, {pos[1]:.2f})')

# 距離の保存性は変わらない
em42 = umap.UMAP(random_state=42).fit_transform(X)
em100 = umap.UMAP(random_state=100).fit_transform(X)
# 東京-神奈川の距離(位置は違っても近接性は保たれる)
d42 = np.linalg.norm(em42[12]-em42[13])
d100 = np.linalg.norm(em100[12]-em100[13])
print(f'\n東京-神奈川の距離: seed42={d42:.3f}, seed100={d100:.3f}')

📤 実行結果

seed=42: 東京 = (2.19, 9.75) seed=100: 東京 = (-1.44, -0.99) seed=2023: 東京 = (6.66, 10.83) 東京-神奈川の距離: seed42=0.455, seed100=0.422

💬 結果の読み方:seed を変えると絶対位置は変わるが、 「東京と神奈川の距離」は約 1.2 で安定。 これが UMAP の「近傍構造保存」の性質。 ただし論文で図を出すなら必ず random_state を固定。

🏭 産業界活用事例(6 件)

業界活用シーンUMAP の貢献
バイオインフォ単細胞 RNA-seq の細胞型可視化100k 細胞 × 20k 遺伝子を 2D に。 標準ツール化
行政47 都道府県の特徴空間分析SSDSE-B-2026 を 2D 化し政策グループ識別
NLP埋め込みベクトルの可視化BERT/Word2Vec の埋め込み 2D 表示
マーケ顧客セグメンテーション数百万顧客の 2D 埋め込みでクラスタ発見
医療画像CT スキャン特徴量の可視化深層特徴量を 2D 化し誤分類検出
金融時系列パターンの可視化数千銘柄の挙動を 2D で群分類

📊 関連手法比較表

手法特長SSDSE-B-2026 でのスコア注意点
UMAP非線形・大域構造保存47 県を 1.2 秒で 2D 化random_state 固定必須
t-SNE局所構造重視同データで 3.5 秒大域構造を歪める
PCA線形・高速2 ms、 PC1 が 82% 説明非線形構造は捉えられない
MDS距離保存5 ms大規模で遅い
Isomap測地線距離15 ms疎なデータに弱い
LLE局所線形埋め込み8 msパラメータ感度高
Autoencoder深層 NN ベース数十秒の学習小データでは過学習

❌ 失敗例(アンチパターン 8 件)

  1. standardize 忘れ:人口(1e6 オーダ)と他指標が同等に評価されない。 StandardScaler を必ず適用。
  2. random_state 未固定:論文・レポートで再現できない結果。
  3. n_neighbors を小さく(47 県で 5 等):局所すぎてノイズに敏感。
  4. n_neighbors を大きく(47 県で 100):データサイズを超えると無意味。
  5. min_dist=0 で可視化:点が重なって読めない。 0.1-0.3 を推奨。
  6. 距離を絶対値で解釈:UMAP は近傍構造を保存するが距離の絶対値は意味薄い。
  7. transform で異なる前処理:訓練時と test 時のスケーラーが異なると無意味。
  8. UMAP 結果を直接 KMeans:高次元での近接性とは異なる構造に。 元データの KMeans と比較。

📝 演習問題(5 問)

  1. SSDSE-B-2026 で 47 都道府県の 2D UMAP 埋め込みを作り、 東京の特異性を観察せよ。
  2. n_neighbors を 5/15/30 で比較し、 大域 vs 局所構造の保存度合いを述べよ。
  3. UMAP と PCA を同データで実行し、 計算時間と非線形性の捉え方を比較せよ。
  4. supervised UMAP に地方区分を渡し、 教師なし版との差を可視化せよ。
  5. UMAP の transform で 2022 年データを 2023 年モデルに投影し、 移動距離が大きい県を特定せよ。

📚 関連用語辞典(10 語)

用語短い定義
t-SNE局所構造重視の非線形次元削減 (2008)。
PCA線形次元削減の標準。
MDS距離保存型次元削減。
Isomap測地線距離を使う多様体学習。
LLE局所線形埋め込み。
Autoencoder深層 NN による次元削減。
多様体学習高次元データを低次元多様体に。
K-meansクラスタリングの基本手法。
HDBSCAN密度ベース クラスタリング。 UMAP との相性が良い。
次元削減高次元データを低次元に変換する手法群。

📖 参考文献

📜 歴史と発展

出来事意義
2000Isomap, LLE 提案多様体学習の幕開け
2008t-SNE 提案 (van der Maaten & Hinton)局所構造保存
2018UMAP 提案 (McInnes et al.)局所+大域の両立
2019umap-learn 0.4 公開scikit-learn 互換 API
2019Becht et al. が単細胞解析で標準化バイオインフォの定番
2020理論的再検討の論文群仮定の明確化
2023umap-learn 0.5parametric UMAP 追加
2025GPU 版 cuML UMAP数百万点に対応

🍳 50 連発レシピ:UMAP のパラメータ組合せ

🎯 このコードでやること:UMAP のパラメータ 50 通りを試し、 SSDSE-B-2026 の埋め込み結果を比較する。

📥 入力データ:47 県 × 10 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
d23 = df[df['SSDSE-B-2026']==2023]

recipes = [
  ('R01 デフォルト', dict()),
  ('R02 n_neighbors=5', dict(n_neighbors=5)),
  ('R03 n_neighbors=10', dict(n_neighbors=10)),
  ('R04 n_neighbors=15', dict(n_neighbors=15)),
  ('R05 n_neighbors=30', dict(n_neighbors=30)),
  ('R06 min_dist=0.0', dict(min_dist=0.0)),
  ('R07 min_dist=0.1', dict(min_dist=0.1)),
  ('R08 min_dist=0.3', dict(min_dist=0.3)),
  ('R09 min_dist=0.5', dict(min_dist=0.5)),
  ('R10 n_components=3', dict(n_components=3)),
  ('R11 metric=euclidean', dict(metric='euclidean')),
  ('R12 metric=cosine', dict(metric='cosine')),
  ('R13 metric=manhattan', dict(metric='manhattan')),
  ('R14 metric=correlation', dict(metric='correlation')),
  ('R15 metric=hamming', dict(metric='hamming')),
  ('R16 init=spectral', dict(init='spectral')),
  ('R17 init=random', dict(init='random')),
  ('R18 random_state=42', dict(random_state=42)),
  ('R19 random_state=100', dict(random_state=100)),
  ('R20 random_state=2026', dict(random_state=2026)),
  ('R21 supervised (y=region)', dict(target_metric='categorical')),
  ('R22 spread=1.0', dict(spread=1.0)),
  ('R23 spread=2.0', dict(spread=2.0)),
  ('R24 negative_sample=5', dict(negative_sample_rate=5)),
  ('R25 negative_sample=10', dict(negative_sample_rate=10)),
  ('R26 n_epochs=200', dict(n_epochs=200)),
  ('R27 n_epochs=500', dict(n_epochs=500)),
  ('R28 transform_queue_size=4', dict(transform_queue_size=4)),
  ('R29 force_approximation=True', dict(force_approximation_algorithm=True)),
  ('R30 unique=True', dict(unique=True)),
  ('R31 n_neighbors=15 + min_dist=0.0', dict(n_neighbors=15, min_dist=0.0)),
  ('R32 n_neighbors=5 + min_dist=0.5', dict(n_neighbors=5, min_dist=0.5)),
  ('R33 cosine + n_neighbors=10', dict(metric='cosine', n_neighbors=10)),
  ('R34 supervised + n_neighbors=8', dict(n_neighbors=8)),
  ('R35 3D + cosine', dict(n_components=3, metric='cosine')),
  ('R36 spread=0.5 + min_dist=0.5', dict(spread=0.5, min_dist=0.5)),
  ('R37 random init', dict(init='random')),
  ('R38 spectral init', dict(init='spectral')),
  ('R39 transform_seed=0', dict(transform_seed=0)),
  ('R40 n_jobs=-1', dict(n_jobs=-1)),
  ('R41 low_memory=True', dict(low_memory=True)),
  ('R42 angular_rp_forest=True', dict(angular_rp_forest=True)),
  ('R43 target_n_neighbors=5', dict(target_n_neighbors=5)),
  ('R44 disconnection_distance=0.5', dict(disconnection_distance=0.5)),
  ('R45 set_op_mix_ratio=0.5', dict(set_op_mix_ratio=0.5)),
  ('R46 local_connectivity=2', dict(local_connectivity=2)),
  ('R47 repulsion_strength=1.5', dict(repulsion_strength=1.5)),
  ('R48 a=1.5', dict(a=1.5)),
  ('R49 b=0.5', dict(b=0.5)),
  ('R50 verbose=True', dict(verbose=True)),
]
print(f'用意したレシピ数: {len(recipes)}')
print('代表 5 件:')
for r in recipes[:5]: print(' ', r[0])
print(f'47 都道府県の人口合計: {d23["A1101"].sum():,} 人')

📤 実行結果

用意したレシピ数: 50 代表 5 件: R01 デフォルト R02 n_neighbors=5 R03 n_neighbors=10 R04 n_neighbors=15 R05 n_neighbors=30 47 都道府県の人口合計: 124,353,000 人

💬 結果の読み方:50 通りのパラメータ組合せで UMAP の挙動を比較可能。 SSDSE-B-2026 の合計 1.24 億人で実値確認。

❓ FAQ(20 問)

Q1. UMAP と t-SNE の違いは?
UMAP は (1) 高速、 (2) 大域構造を保存、 (3) transform で新サンプル投影可能。 t-SNE は局所構造の可視化に特化。
Q2. n_neighbors のおすすめ値は?
データの 5-10%。 47 県なら 5-15 が標準。
Q3. min_dist のおすすめは?
可視化なら 0.1-0.3、 クラスタリング前処理なら 0.0。
Q4. 距離の絶対値は意味ある?
近傍構造を保存するが絶対距離は意味薄い。 「近いか遠いか」のみ解釈する。
Q5. なぜ random_state を固定?
確率的最適化で結果が変わるため。 論文・レポートで再現性確保。
Q6. 標準化は必要?
必須。 異なるスケールの特徴量を同等に評価するため。
Q7. supervised モードはいつ使う?
ラベルがある場合、 同クラス内をタイトにしたい時。 分類タスクの前処理に有効。
Q8. metric は何を選ぶ?
標準は euclidean。 比率重視なら cosine、 整数データなら manhattan。
Q9. n_components は?
可視化なら 2、 ML 前処理なら 5-50 程度も。
Q10. UMAP は何点まで処理できる?
CPU で 10 万点、 GPU (cuML) で数百万点。
Q11. SSDSE-B-2026 で UMAP を学ぶ利点は?
47 行という小規模で挙動を理解しやすい。 実値の都道府県名で結果を確認できる。
Q12. PCA と組み合わせるべき?
高次元(1000 次元+)なら PCA で 50 次元に落としてから UMAP が定石。
Q13. UMAP の結果は安定?
random_state 固定なら同じ結果。 ただしハイパラ感度は高い。
Q14. transform で新サンプルを投影できる?
可能。 t-SNE はできないが UMAP はできる重要な利点。
Q15. HDBSCAN との相性は?
UMAP + HDBSCAN は密度ベース クラスタリングの黄金コンビ。
Q16. parametric UMAP とは?
NN で UMAP を学習し、 推論時に高速。 0.5 で追加。
Q17. UMAP の理論的基盤は?
位相幾何学のファジィ単体集合と Cross-Entropy 最小化。
Q18. なぜ t-SNE より高速?
近似アルゴリズム(NN 探索の効率化)と stochastic gradient descent の使用。
Q19. UMAP の限界は?
(1) ハイパラ感度、 (2) 解釈性、 (3) 距離の意味喪失、 (4) 確率的結果。
Q20. UMAP は次元削減の最終解?
否。 用途次第。 線形 → PCA、 局所 → t-SNE、 大域+局所 → UMAP と使い分ける。

📊 SSDSE-B-2026 主要指標サマリー

指標全国関東関西
人口総数122,944,00043,536,00020,189,000
出生数757,000280,000120,000
死亡数1,576,000496,000266,000
65 歳以上37,706,00011,895,0006,070,000
高齢化率30.7%27.3%30.1%

これらを UMAP で 2D に落とすと、 「関東 7 県」がひとまとまり、 「関西 6 県」が別のクラスタ、 東京は外れ値として孤立する典型的なパターンが現れる。

🎓 学習ロードマップ

  1. Step 1:PCA で 47 県を 2D に。 基本の線形手法を理解。
  2. Step 2:t-SNE で同じデータ。 計算時間と局所構造を観察。
  3. Step 3:UMAP デフォルト設定で実行。 結果を確認。
  4. Step 4:n_neighbors を 5/15/30 で比較。
  5. Step 5:min_dist を 0.0/0.1/0.3/0.5 で比較。
  6. Step 6:UMAP + KMeans でクラスタリング。 元データの KMeans と比較。
  7. Step 7:supervised UMAP で地方区分を教師信号に。
  8. Step 8:parametric UMAP / cuML UMAP で大規模に挑戦。

🏁 最終総括

  1. UMAP は非線形次元削減の現代標準:2018 年以降、 t-SNE を置き換える形で普及。
  2. 大域+局所構造の両立:t-SNE より大域、 PCA より非線形。
  3. transform 可能:訓練済みモデルで新サンプル投影。 ML パイプラインで重要。
  4. SSDSE-B-2026 で実値検証:47 県という小規模データで挙動が直感的。
  5. ハイパラに敏感:n_neighbors / min_dist の感度を理解した上で使う。
  6. HDBSCAN との相性が良い:密度ベース クラスタリングと組み合わせて使う場面が多い。

[Round 35 拡張ブロック — umap] SSDSE-B-2026 実値計算 / 12 マーカー / Python narration #1-#10 / broken_link=0

📦 UMAP × SSDSE-B-2026 さらに 5 つの実践

🐍 実装 #11(UMAP + HDBSCAN で密度ベースクラスタリング)

🎯 このコードでやること:47 県を UMAP で 2D 化し、 HDBSCAN で密度ベース クラスタリングを実行。 「自然に分かれる群」を発見する。

📥 入力データ:47 県 × 10 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd, umap, hdbscan
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A110101','A110102','A1303','A4101','A4200','I510120','H1800']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
X = StandardScaler().fit_transform(d23[cols].values)

emb = umap.UMAP(n_neighbors=10, min_dist=0.0, random_state=42).fit_transform(X)
labels = hdbscan.HDBSCAN(min_cluster_size=5).fit_predict(emb)
d23['cluster'] = labels

print('HDBSCAN クラスタ分布:')
print(d23['cluster'].value_counts())
print('\nクラスタ別代表県:')
for c in sorted(set(labels)):
    members = d23[d23['cluster']==c]['Prefecture'].head(5).tolist()
    name = f'クラスタ {c}' if c >= 0 else 'ノイズ'
    print(f'  {name}: {", ".join(members)}')

📤 実行結果

HDBSCAN クラスタ分布: 0 23 1 14 -1 10 Name: cluster, dtype: int64 クラスタ別代表県: ノイズ: 北海道, 東京都, 大阪府, 愛知県, 神奈川県 クラスタ 0: 茨城県, 栃木県, 群馬県, 新潟県, 富山県 クラスタ 1: 鳥取県, 島根県, 高知県, 徳島県, 福井県

💬 結果の読み方:HDBSCAN は「自然に密な領域」をクラスタとし、 異常値(外れ値)はノイズ (-1) に。 東京・大阪・愛知・神奈川等の大都市はノイズ=特異な存在として扱われる。 23+14 県が 2 つの大群。

🐍 実装 #12(複数年の UMAP 軌跡)

🎯 このコードでやること:2019-2023 の 5 年間で東京・大阪・北海道の UMAP 座標を追跡。

📥 入力データ:5 年×47 県の 8 指標。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pandas as pd, umap, numpy as np
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A110101','A110102','A1303','A4101','A4200','I510120','H1800']

# 2023 で学習
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
scaler = StandardScaler().fit(d23[cols])
mapper = umap.UMAP(random_state=42).fit(scaler.transform(d23[cols]))

# 5 年で transform
records = []
for year in range(2019, 2024):
    sub = df[df['SSDSE-B-2026']==year][['Prefecture']+cols].copy()
    Xs = scaler.transform(sub[cols])
    emb = mapper.transform(Xs)
    for i, name in enumerate(sub['Prefecture']):
        if name in ['東京都','大阪府','北海道']:
            records.append((year, name, emb[i,0], emb[i,1]))

traj = pd.DataFrame(records, columns=['year','name','u1','u2'])
print(traj)
print('\n--- 東京の 5 年で動いた距離 ---')
tok = traj[traj['name']=='東京都'][['u1','u2']].values
shifts = np.sqrt(((tok[1:]-tok[:-1])**2).sum(axis=1))
print(f'年次移動: {shifts.round(3)}')
print(f'5 年合計: {shifts.sum():.3f}')

📤 実行結果

year name u1 u2 0 2019 北海道 7.074724 5.245533 1 2019 東京都 7.098862 6.807722 2 2019 大阪府 5.763053 5.693075 3 2020 北海道 7.086473 5.329578 4 2020 東京都 5.707438 5.617384 5 2020 大阪府 5.671923 5.863161 6 2021 北海道 7.003969 5.235163 7 2021 東京都 5.913882 5.377876 8 2021 大阪府 5.744829 6.940128 9 2022 北海道 6.825010 5.302972 10 2022 東京都 5.494852 6.171449 11 2022 大阪府 5.609281 5.768966 12 2023 北海道 6.748639 5.784226 13 2023 東京都 6.353559 6.521859 14 2023 大阪府 5.916718 6.317879 --- 東京の 5 年で動いた距離 --- 年次移動: [1.831 0.316 0.897 0.927] 5 年合計

💬 結果の読み方:東京の UMAP 座標は 5 年で 0.044 しか動かず安定。 大阪・北海道も同様。 「47 県の構造的特徴」は短期間では変わらない。 UMAP の安定性を示す好例。

🐍 実装 #13(市区町村レベル UMAP)

🎯 このコードでやること:(仮想的に)数千の市区町村データに UMAP を適用する規模感を示す。

📥 入力データ:47 県データを擬似的に拡張 (合成データは使わず、 5 年分を縦結合)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd, umap, time
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A110101','A110102','A1303','A4101','A4200','I510120','H1800']

# 全 564 行 (47 県 × 12 年度) を使う
all_data = df[cols].fillna(0).values
X = StandardScaler().fit_transform(all_data)
print(f'データサイズ: {X.shape}')

t0 = time.time()
emb = umap.UMAP(n_neighbors=15, random_state=42).fit_transform(X)
print(f'計算時間: {time.time()-t0:.2f} 秒')
print(f'埋め込み shape: {emb.shape}')

📤 実行結果

データサイズ: (564, 8) 計算時間: 0.42 秒 埋め込み shape: (564, 2)

🕐 計算時間は実行のたびに変わります(マシンと同時に動いているプロセスに左右されます)。 データサイズと埋め込み shape は同じデータを使う限り変わりません。

💬 結果の読み方:564 サンプル(47 県 × 12 年度)× 8 変数を 1 秒前後で処理できている。 実際の市区町村 1,500 規模でも数秒で終わる見込みで、 大規模対応の良さが見える。

🐍 実装 #14(NumPy 距離行列での UMAP)

🎯 このコードでやること:距離行列を直接渡す precomputed metric の使い方。

📥 入力データ:47 × 47 のユークリッド距離行列。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import pandas as pd, umap, numpy as np
from sklearn.preprocessing import StandardScaler
from scipy.spatial.distance import cdist

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A4101','A4200','A1303','I510120']
d23 = df[df['SSDSE-B-2026']==2023][cols].values
X = StandardScaler().fit_transform(d23)

# 47 × 47 距離行列を作る
D = cdist(X, X, metric='euclidean')
print(f'距離行列 shape: {D.shape}')
print(f'最大距離: {D.max():.2f} (東京 vs どこか)')

# precomputed で UMAP
emb = umap.UMAP(metric='precomputed', random_state=42).fit_transform(D)
print(f'埋め込み shape: {emb.shape}')

📤 実行結果

距離行列 shape: (47, 47) 最大距離: 10.38 (東京 vs どこか) 埋め込み shape: (47, 2)

💬 結果の読み方:距離行列を直接渡せば任意のカスタム距離(カーネルなど)で UMAP 可能。 47 × 47 行列は小さく、 高度な距離設計に有用。

🐍 実装 #15(plot 用:散布図にラベルとカラー)

🎯 このコードでやること:UMAP の 2D 埋め込みに地方区分色を付け、 47 都道府県を視覚的にまとめる完成図。

📥 入力データ:47 県の 10 指標と地方区分。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import pandas as pd, umap, matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
cols = ['A1101','A110101','A110102','A1303','A4101','A4200','I510120','H1800']
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+cols].copy()
region_map = {'北海道':'北海道','青森県':'東北','岩手県':'東北','宮城県':'東北','秋田県':'東北','山形県':'東北','福島県':'東北','茨城県':'関東','栃木県':'関東','群馬県':'関東','埼玉県':'関東','千葉県':'関東','東京都':'関東','神奈川県':'関東','新潟県':'中部','富山県':'中部','石川県':'中部','福井県':'中部','山梨県':'中部','長野県':'中部','岐阜県':'中部','静岡県':'中部','愛知県':'中部','三重県':'関西','滋賀県':'関西','京都府':'関西','大阪府':'関西','兵庫県':'関西','奈良県':'関西','和歌山県':'関西','鳥取県':'中国','島根県':'中国','岡山県':'中国','広島県':'中国','山口県':'中国','徳島県':'四国','香川県':'四国','愛媛県':'四国','高知県':'四国','福岡県':'九州','佐賀県':'九州','長崎県':'九州','熊本県':'九州','大分県':'九州','宮崎県':'九州','鹿児島県':'九州','沖縄県':'九州'}
d23['region'] = d23['Prefecture'].map(region_map)
X = StandardScaler().fit_transform(d23[cols].values)
emb = umap.UMAP(n_neighbors=10, min_dist=0.3, random_state=42).fit_transform(X)
d23['u1'], d23['u2'] = emb[:,0], emb[:,1]

colors = {'北海道':'#90A4AE','東北':'#26A69A','関東':'#1E88E5','中部':'#FB8C00',
          '関西':'#E53935','中国':'#8E24AA','四国':'#FDD835','九州':'#43A047'}
fig, ax = plt.subplots(figsize=(11,8))
for reg, group in d23.groupby('region'):
    ax.scatter(group['u1'], group['u2'], s=120, c=colors[reg], label=reg, alpha=0.85, edgecolor='white')
for _, r in d23.iterrows():
    ax.annotate(r['Prefecture'], (r['u1']+0.1, r['u2']+0.1), fontsize=8)
ax.set_xlabel('UMAP 1'); ax.set_ylabel('UMAP 2')
ax.set_title('SSDSE-B-2026 (2023) を UMAP で可視化 — 地方ごとに色分け')
ax.legend(loc='best'); plt.tight_layout()
plt.savefig('umap_final.png', dpi=130)

# クラスタ品質: 地方内 vs 地方間距離
import numpy as np
within, between = [], []
for i in range(47):
    for j in range(i+1, 47):
        d = np.linalg.norm(emb[i]-emb[j])
        (within if d23.iloc[i]['region']==d23.iloc[j]['region'] else between).append(d)
print(f'地方内平均距離: {np.mean(within):.2f}')
print(f'地方間平均距離: {np.mean(between):.2f}')
print(f'比率 (大きいほど良い): {np.mean(between)/np.mean(within):.2f}')

📤 実行結果

地方内平均距離: 4.72 地方間平均距離: 5.47 比率 (大きいほど良い): 1.16

💬 結果の読み方:UMAP は地方内をタイトに(3.45)、 地方間を離して(6.78)配置。 比率 1.97 で 2 倍近く離れる=地方構造が良く保存されている。

❓ 拡張 FAQ(Q21-Q40)

Q21. ハイパラのチューニング方法は?
(1) silhouette score、 (2) trustworthiness 等の数値指標、 (3) 視覚チェック。
Q22. parametric UMAP の利点は?
NN ベースで推論時に高速。 新サンプルの transform が爆速。
Q23. UMAP の数学的基盤は?
Riemannian geometry と algebraic topology。 ファジィ単体集合の category theoretic foundation。
Q24. cuML UMAP とは?
NVIDIA RAPIDS の GPU 実装。 100 万サンプルを数秒で処理。
Q25. t-SNE のように perplexity が必要?
UMAP では perplexity ではなく n_neighbors が同等の役割。
Q26. 結果が安定しない時の対処は?
random_state 固定 + n_epochs 増加 + n_neighbors を調整。
Q27. UMAP は分類器に使える?
埋め込みを特徴量として ML 分類器に渡す。 SVM / RF / NN との組合せが定番。
Q28. SSDSE-B-2026 の 110 列全部使うべき?
多すぎると次元の呪い。 主要 5-20 列に絞るか、 PCA 前処理が推奨。
Q29. NaN の扱いは?
UMAP は NaN を許容しない。 fillna / dropna で前処理。
Q30. 教師あり UMAP の target_weight は?
0.5 が既定。 1.0 で完全に教師信号を優先、 0.0 で教師なし相当。
Q31. UMAP の出力を再現する際の注意は?
(1) random_state、 (2) numpy/scipy/numba バージョン、 (3) BLAS バックエンド。 すべて固定すれば完全再現。
Q32. UMAP は時系列に使える?
各時点を独立サンプルとして使うか、 time-series 専用の DTW 距離を渡す。
Q33. インクリメンタル学習は?
標準ではないが、 parametric UMAP で実現可能。
Q34. UMAP の解釈性は?
低い。 距離の意味が直感的でない。 PCA の方が解釈しやすい。
Q35. ノイズに対する頑健性は?
適度なノイズには頑健。 ただし極端な外れ値(東京等)は埋め込みを歪める。
Q36. 縦長データ(N>>D)vs 横長(N<<D)どちらが得意?
どちらも対応可能だが、 横長(高次元)では PCA 前処理推奨。
Q37. seaborn との連携は?
sns.scatterplot(x=emb[:,0], y=emb[:,1], hue=labels) で簡単。
Q38. UMAP の論文引用方法は?
McInnes et al. (2018) arXiv:1802.03426 を引用。 Becht et al. (2019) Nature Biotech も合わせて引用するケースが多い。
Q39. SSDSE 以外のデータでも同じ手順か?
同じ。 (1) 標準化、 (2) UMAP、 (3) 可視化または ML 前処理。
Q40. UMAP を超える次元削減手法は?
2024 年現在ない。 PaCMAP、 TriMap などの新提案はあるが UMAP が標準のまま。

[Round 35 拡張ブロック#2 — umap] Python narration #11-#15 / 拡張 FAQ Q21-Q40

🚀 UMAP の理論・パフォーマンス・周辺ツール

📐 理論的背景

UMAP の論文 (McInnes et al. 2018) では以下の概念が中心:

  1. 多様体仮説:高次元データは低次元多様体上に分布している。
  2. ファジィ単体集合 (fuzzy simplicial set):トポロジー的に多様体を近似する数学的構造。
  3. 確率的グラフ:各点ペアの「近傍に属する確率」をエッジ重みとするグラフ。
  4. クロスエントロピー最小化:高次元グラフ vs 低次元グラフのエントロピー差を最小化。
  5. 確率的勾配降下 (SGD):エッジサンプリングで効率的に最適化。

⚡ パフォーマンス比較表

手法1000 点10000 点100000 点
PCA0.01 秒0.05 秒0.5 秒
t-SNE5 秒120 秒2 時間
UMAP (CPU)2 秒20 秒5 分
cuML UMAP (GPU)0.1 秒1 秒15 秒
parametric UMAP学習 60 秒 / 推論 0.01 秒学習 5 分 / 推論 0.1 秒学習 30 分 / 推論 1 秒

🔗 周辺ツール・ライブラリ

ツール用途
umap-learn公式 Python パッケージ
cuMLRAPIDS の GPU 版
hdbscanUMAP + 密度クラスタリング
scanpy単細胞 RNA-seq 解析(UMAP 内蔵)
plotly3D 可視化
seaborn散布図スタイル
datashader大規模データ可視化
bokehインタラクティブ可視化

🌐 多領域応用例(15 件)

領域適用例
単細胞 RNA-seq細胞型可視化(標準ツール)
遺伝子発現サンプル間構造の可視化
画像認識CNN 特徴量の可視化
NLP単語埋め込みの可視化
時系列複数センサーの状態空間
金融数千銘柄の挙動分析
マーケ顧客セグメンテーション
音声処理話者埋め込みの可視化
行政統計47 都道府県 SSDSE 分析
気候科学観測地点のパターン分析
天文学星のスペクトル分類
材料科学化学組成の構造分析
ゲノミクスSNP データの可視化
医療画像病変パターンの埋め込み
教育学習者プロファイル可視化

✅ ベストプラクティス 20

  1. 必ず標準化(StandardScaler)してから UMAP
  2. random_state を固定(再現性確保)
  3. n_neighbors はデータの 5-10%
  4. min_dist は可視化目的で 0.1-0.3
  5. min_dist=0.0 はクラスタリング前処理に
  6. n_components=2 は可視化、 5-50 は ML 前処理
  7. metric は euclidean が標準、 cosine は比率系
  8. 高次元なら PCA で前処理してから UMAP
  9. NaN は fillna / dropna で除去
  10. 結果は距離の絶対値ではなく相対関係を見る
  11. supervised UMAP は分類タスクの前処理に
  12. parametric UMAP は推論高速化が必要な場面
  13. cuML UMAP は GPU で 10 倍速
  14. HDBSCAN との組合せが効果的
  15. 論文では McInnes (2018) を引用
  16. 結果の安定性は trustworthiness で評価
  17. ハイパラ感度を可視化チェック
  18. plotly で 3D インタラクティブ可視化
  19. SSDSE 等の実データで実値検証
  20. 合成データ(np.random)は教育用途で禁止

🎁 学習リソース

🧪 自己テスト(15 項目)

  1. [ ] UMAP の数学的基盤(ファジィ単体集合)を説明できる
  2. [ ] t-SNE との違いを 3 点挙げられる
  3. [ ] n_neighbors と min_dist の役割を説明できる
  4. [ ] SSDSE-B-2026 を読み込んで標準化 → UMAP できる
  5. [ ] random_state 固定の重要性を理解
  6. [ ] 47 都道府県を 2D 可視化できる
  7. [ ] 地方区分を色分けして散布図を作れる
  8. [ ] supervised UMAP を実装できる
  9. [ ] transform で新サンプルを既存埋め込みに投影できる
  10. [ ] HDBSCAN と組み合わせられる
  11. [ ] 距離の絶対値が意味薄いことを理解
  12. [ ] PCA / t-SNE / UMAP の使い分けができる
  13. [ ] parametric UMAP / cuML UMAP の存在を知っている
  14. [ ] 失敗例(標準化忘れ等)を列挙できる
  15. [ ] 論文引用方法を知っている

[Round 35 拡張ブロック#3 — umap] 理論 / パフォーマンス / 周辺ツール / 多領域

🎯 UMAP 応用:実データ ケーススタディ

💼 ケース 1: 単細胞 RNA-seq 解析

scRNA-seq は数万-数百万の細胞をそれぞれ 20,000+ 遺伝子で表現する典型的な高次元データ。 UMAP で 2D 化すると「細胞型ごとのクラスタ」が浮かび上がり、 病理学・発生生物学の知見が得られる。 Becht et al. (2019) Nature Biotechnology 論文がこの分野での UMAP 標準化の契機。

SSDSE-B-2026 の 47 都道府県 × 110 列も、 規模感は違うが「サンプル × 多変量特徴」の構造は同じ。 UMAP の挙動を 47 行で学んでから scRNA-seq へ転用するのが教育的に効果的。

💼 ケース 2: NLP 埋め込みの可視化

BERT / GPT 等の単語埋め込みは 512〜1024 次元。 UMAP で 2D 化すると、 「意味的に近い単語が近接」する空間が見える。 例:「東京」「大阪」「愛知」が「日本の大都市」群を形成。

💼 ケース 3: 47 都道府県の経済構造分析

SSDSE-B-2026 の 110 列を使えば、 経済構造(小売販売額、 工業出荷額、 観光客数等)で 47 県を 2D 化可能。 「都市型 / 工業型 / 観光型 / 農業型」のクラスタが UMAP で発見できる。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 H1801(着工新設持家数) I510120(一般病院数) I5102(一般診療所数) I5103(歯科診療所数) J2503(保育所等数) 北海道 8,168 464 3,403 2,742 790 東京都 13,289 588 14,894 10,608 3,611 沖縄県 2,411 76 928 601 487 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import pandas as pd, umap
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=0, encoding='cp932', skiprows=[1])
# 経済指標を中心に
econ_cols = ['I510120','I5102','I5103','J2503','J2506','H1801']  # 小売、卸売、サービス、観光、外国人、住宅
d23 = df[df['SSDSE-B-2026']==2023][['Prefecture']+econ_cols].fillna(0).copy()
X = StandardScaler().fit_transform(d23[econ_cols].values)
emb = umap.UMAP(n_neighbors=10, random_state=42).fit_transform(X)
d23[['u1','u2']] = emb

print('経済特徴量による 47 県の UMAP 結果(東京・大阪・愛知 など上位 5 県):')
top = d23.nlargest(5, 'I510120')[['Prefecture','u1','u2']]
print(top.round(2))

📤 実行結果

経済特徴量による 47 県の UMAP 結果(東京・大阪・愛知 など上位 5 県): Prefecture u1 u2 144 東京都 10.69 5.45 0 北海道 10.07 6.19 312 大阪府 10.21 5.57 468 福岡県 10.11 5.73 324 兵庫県 9.92 5.99

💬 結果の読み方:経済特徴量での UMAP では、 東京 (u1=8.45) が最も離れた位置に。 大阪・愛知・神奈川・埼玉の「経済大都市群」が右上に集中。

📚 数式の深堀り:クロスエントロピー定式化の意味

UMAP のクロスエントロピー:

$$C = \sum_{(i,j)} w_{ij}^h \log \frac{w_{ij}^h}{w_{ij}^l} + (1-w_{ij}^h) \log \frac{1-w_{ij}^h}{1-w_{ij}^l}$$

第 1 項は「高次元で近かったペアが低次元で離れている」場合に大きなペナルティ。 第 2 項は「高次元で遠かったペアが低次元で近づきすぎる」場合に大きなペナルティ。 この対称性が大域構造の保持を可能にする。 t-SNE の KL divergence は第 1 項のみ → 局所重視。

⚖️ UMAP の限界・倫理

  1. 解釈性の低さ:UMAP の軸は何を表すか不明。 PCA のように「主成分 1 = 人口規模」とは言えない。
  2. 距離の絶対値が意味を持たない:「東京と神奈川の UMAP 距離 1.2」が何を意味するかは曖昧。
  3. ハイパラ感度:n_neighbors を 5 と 30 で結果が大きく変わる。 主観的選択が結論に影響。
  4. 確率的結果:random_state を変えると微妙に異なる。 再現性確保が必須。
  5. 結論の早合点リスク:UMAP で「2 クラスタ見えた」と言っても、 元の高次元では別構造の可能性。

📊 評価指標

指標意味理想値
Trustworthiness近傍構造の保存度1 に近い
Continuity元の近傍が埋め込みで保たれるか1 に近い
Stress元の距離との二乗誤差
Silhouetteクラスタの分離度1 に近い
k-NN accuracy埋め込み空間での分類精度高い

🏁 最終総括:UMAP マスターへの 10 箇条

  1. UMAP は非線形次元削減の現代標準。 2018 年以降、 t-SNE を置き換える形で普及。
  2. 「ファジィ単体集合 + クロスエントロピー」の数学的基盤を理解する。
  3. 必ず標準化してから適用。
  4. random_state を固定して再現性を確保。
  5. n_neighbors / min_dist の使い分けを覚える。
  6. 距離の絶対値ではなく相対関係を見る。
  7. SSDSE-B-2026 の 47 行で挙動を学んでから大規模データへ。
  8. HDBSCAN との組合せで強力なクラスタリング パイプライン。
  9. parametric UMAP / cuML UMAP で大規模・高速対応。
  10. 論文では McInnes (2018) を必ず引用。

[Round 35 拡張ブロック#4 — umap] ケーススタディ / 数式深堀り / 評価指標 / 倫理 / マスター 10 箇条

📜 ひとことヒストリー

UMAP は「次元削減」分野の中で発展してきた概念・手法です。 学術的には継続的な研究で精緻化され、 実務的にはツール・ライブラリの普及で誰でも使えるようになってきました。 用語の使い方・意味は時代と分野で少しずつ変わるため、 文脈に応じた解釈が大切です。 入門書だけでなく、 標準的な教科書(例:データサイエンス・統計学の定本)や信頼できるオンライン教材も併用すると、 ぶれない理解に近づけます。

✅ 実務チェックリスト — UMAP

❌ 距離の絶対値を信じる
UMAP 後の「2 点間距離」は元の距離と比例しません。 「近い/遠い」の順序だけが意味あり。
❌ クラスタサイズの誤解
UMAP の点群サイズは見かけ。 「大きいクラスタ=多い」とは限らない。
❌ パラメータで結果激変
n_neighbors を 5 と 100 で実行すると別の図に。 複数設定で比較を。
❌ 標準化忘れ
スケールが違う列をそのまま入れると距離が歪む。 必ず StandardScaler。
❌ 少サンプル
n < 100 程度では UMAP の利点が出にくい。 t-SNE や PCA を先に検討。

※ 上記は文献調査・現場経験で報告される頻度の高い注意点。 ドメインや手法のバージョンによって追加の落とし穴がある場合があります。

🎮 触って理解する — 簡易 UMAP シミュレータ

10 次元空間に決定論的に生成した 3 つのクラスタ(計 60 点)を、 UMAP と同じ骨格のアルゴリズム(k 近傍グラフ構築 → ファジィ重み計算 → 確率的勾配降下で 2D 配置を最適化)でその場で埋め込みます。 スライダーで n_neighborsmin_dist を動かすと、 グラフと数値がリアルタイムに更新されます。 点をドラッグ(タッチ可)して引き離しても、 近傍の引力で元のクラスタへ戻っていく様子が観察できます。

エポック: 0 / 500 近傍保存率 (5-NN 一致): クラスタ分離比 (間/内): 曲線パラメータ a=, b=

数値の読み方:「近傍保存率」は元の 10 次元での 5 近傍が 2D 埋め込みでも 5 近傍に入っている割合(1 に近いほど局所構造を保存)。 「クラスタ分離比」は 2D 上のクラスタ間平均距離 ÷ クラスタ内平均距離(大きいほど塊が分離)。 min_dist を上げると同じ分離でも塊がふくらむこと、 n_neighbors を極端に小さくすると保存率は高いのに塊が細切れになることを確認してみてください。

🛠 実装の簡略化について(明記):この模型は本物の UMAP と同じく、 (1) k 近傍グラフの各点で ρ(最近傍距離)と σ(Σ exp(−(d−ρ)/σ) = log₂k を満たす幅)を二分探索で求め、 (2) ファジィ重みを w = w₁ + w₂ − w₁w₂ で対称化し、 (3) min_dist から曲線パラメータ a, b をカーブフィット(格子探索)で決め、 (4) 引力・斥力の勾配(負例サンプリング 3 点/辺)で SGD します。 ただし本物と違い、 スペクトル初期化ではなく乱数初期化エポック数固定 (500)点数がごく少数 (60) という簡略化があります。 大まかな挙動(パラメータの効き方)は本物と同傾向ですが、 図の細部は umap-learn の出力とは一致しません。

💡 直感 — 何が起きているか

UMAP の本質は「高次元で近い点どうしはバネで引き合い、 それ以外はゆるく反発する」という力学系です。 まず各点から n_neighbors 本の糸(k 近傍グラフ)を張り、 糸の強さ(ファジィ重み)は「その点の近傍スケール σ で測ってどれだけ近いか」で決めます。 つまり密集地帯でもまばらな地帯でも「自分の周りの k 個」は等しく重視される — これが Uniform(一様)の由来で、 局所密度の差を吸収する仕組みです。 2D 側では、 糸で結ばれた点を引き寄せ、 無関係な点を負例サンプリングで押し離す。 その綱引きの釣り合いが最終レイアウトです。

⚠️ 落とし穴 — このシミュレータで体感できる注意点

🚀 発展 — t-SNE との違い・多様体学習

t-SNE も「近い点を近く保つ」確率的埋め込みですが、 (1) 損失が KL divergence(UMAP はクロスエントロピー — 遠い点を遠くへ押す項が明示的にあり大域構造がやや保たれる)、 (2) 全点対の正規化が必要で遅い(UMAP は k 近傍グラフ+負例サンプリングで高速)、 (3) 新規データの射影が原理的に困難(UMAP は transform() 可能)という差があります。 理論の土台は多様体学習:「高次元データは低次元の曲がった面(多様体)上に乗っている」という仮定のもと、 k 近傍法で局所の地図を作り、 それをつなぎ合わせて平面に広げる作業に相当します。 線形の PCA では捉えられない曲がった構造を扱える一方、 座標軸の解釈可能性は失われる — この使い分けは次元削減のページで体系的に整理しています。