Skip to content
第14回:トポロジーという顕微鏡 ~穴とループの発見~

第14回:トポロジーという顕微鏡 ~穴とループの発見~

注意事項

  • パーシステントホモロジーは数学的に厳密な手法だが、「何を測っているか」の解釈はデータ・タスク依存である。
  • 「ResNetがトポロジーを保存する」等の主張は特定の研究の議論であり、一般的に確立された結論ではない。
  • TDAの深層学習への応用は発展途上の分野であり、実務での有効性は限定的な場面にとどまる。
  • 本回は「形ではなく構造を測る」という視点の導入が主目的であり、TDAの数学的厳密性は別途専門書を参照されたい。

導入:形を超えて構造を見る

これまでの講義では、表現空間の「形」を測る道具を整えてきた。距離、角度、曲率——これらは幾何学の言葉であり、「どれだけ離れているか」「どの方向を向いているか」を定量化する。

しかし、空間には「形」だけでは捉えられない性質がある。

コーヒーカップとドーナツを考えよう。幾何学的には全く異なる形状だ。一方は取っ手があり、もう一方は環状。距離も曲率も異なる。しかし、ある視点から見ると、両者は「同じ」である。どちらも「穴が1つある」という構造を共有している。

この「穴」を数える数学が トポロジー(位相幾何学) である。

トポロジーは、連続変形(伸ばす、曲げる、ねじる——ただし切ったり貼ったりしない)で保存される性質を研究する。この視点から見ると、深層学習の表現空間にも「穴」や「ループ」といった構造が潜んでいることがある。そして、その構造が学習の質や汎化性能に関係している可能性がある。

本回では、トポロジカルデータ解析(TDA)の基本概念を導入し、深層学習への応用可能性を探る。

幾何学とトポロジー:二つの視点

何を測るか

幾何学とトポロジーは、空間を見る二つの異なるレンズである。

視点問い測るもの変換に対する不変性
幾何学どれだけ「離れている」か距離、角度、曲率等長変換(回転・平行移動)
トポロジーどのように「つながっている」か穴、ループ、連結成分連続変形(切らない・貼らない)

幾何学は「定量的」な測定を行う。2点間の距離が3なのか5なのかは、幾何学的に重要な区別である。

一方、トポロジーは「定性的」な性質を捉える。穴が「ある」か「ない」かは重要だが、穴の「大きさ」は(基本的には)問わない。

コーヒーカップとドーナツ

トポロジーの定番の例を詳しく見よう。

コーヒーカップを粘土でできていると想像する。取っ手を少しずつ太くし、本体を小さくしていく。この変形を続けると、最終的にドーナツ(トーラス)の形になる。この過程で、粘土を切ったり、新しく穴を開けたり、穴を塞いだりしていない。

このとき、コーヒーカップとドーナツは 同相(homeomorphic) であるという。同相とは、位相空間として両者の間に「連続かつ逆も連続な全単射(同相写像)」が存在することを意味する。直感的には「切らずに連続的に変形できる」ということだ。

NOTE

同相の直感: 二つの空間が同相であるとは、一方を「ゴムのように」伸び縮みさせて他方に変形できることを意味する。ただし、切断・接着は許されない。この条件下で保存される性質が「位相的性質」である。

ベッチ数:穴を数える

トポロジーで最も基本的な不変量が ベッチ数(Betti numbers) である。

ベッチ数意味直感
β0連結成分の数「島」がいくつあるか
β11次元の穴(ループ)の数「トンネル」がいくつあるか
β22次元の穴(空洞)の数「空洞」がいくつあるか
βnn 次元の穴の数高次元の「穴」

具体例を見よう:

図形β0β1β2説明
100連結成分1つ、穴なし
円周 S11101つのループ
球面 S2101内部に空洞
トーラス1212つのループ(縦・横)と1つの空洞
8の字1202つのループ

CAUTION

ベッチ数の限界: ベッチ数は「穴の数」を数えるが、穴の「配置」や「関係」は捉えない。例えば、2つの離れた円と8の字はどちらも β1=2 だが、構造は異なる。より精密な不変量(ホモロジー群の構造、持続ベッチ数など)が必要になる場合がある。

パーシステントホモロジー:スケールを超えた穴の追跡

問題:どのスケールで見るか

実データは「きれいな」図形ではない。点群として与えられ、ノイズを含み、どのスケールで「穴」を認識すべきか自明ではない。

例えば、円周上にサンプリングされた点群を考えよう。点と点の間には隙間がある。この隙間を「穴」と見なすべきか?それとも、点群全体が作る「円」としての穴を見るべきか?

パーシステントホモロジー(Persistent Homology) は、この問いに対する洗練された回答を与える。核心的なアイデアは:

スケールを連続的に変化させ、各スケールで「穴」を数え、その「寿命」を記録する。

長く生き残る穴は「本質的な構造」を反映し、すぐに消える穴は「ノイズ」である可能性が高い。

フィルトレーション:スケールの掃引

パーシステントホモロジーの計算は、以下の手順で行われる。

Step 1: 点群から始める

データ点の集合 X={x1,x2,,xn} が与えられる。

Step 2: 各点の周りに「球」を描く

パラメータ ϵ0 を導入し、各点 xi の周りに半径 ϵ の球を描く。

Step 3: 球が重なったら「つなぐ」

2つの球が重なったら(つまり、2点間の距離が 2ϵ 以下なら)、その2点を辺で結ぶ。3つ以上の球が共通部分を持てば、三角形や高次元の単体を作る。これにより、スケール ϵ での 単体複体(simplicial complex) が構成される。

Step 4: ϵ を0から∞まで動かす

ϵ=0 では孤立した点のみ。 ϵ を大きくすると、点がつながり始め、ループができ、やがて全体が一つの塊になる。

この過程で得られる単体複体の列を フィルトレーション(filtration) と呼ぶ:

K0K1K2Km

NOTE

Vietoris-Rips複体とČech複体: 上記の構成法には複数のバリエーションがある。Vietoris-Rips複体 は「全ての点対が 2ϵ 以内にある」場合に単体を作る(同値に、距離閾値以内の辺でできるグラフのクリーク(完全部分グラフ)から単体を構成する)。Čech複体 は「球の共通部分が非空」な場合に単体を作る。Rips複体の方が計算が容易だが、Čech複体の方が幾何学的に正確。実用上はRips複体が多く使われる。

閾値の流儀: 文献によって閾値を ϵ (球の半径)で書くか 2ϵ (直径)で書くかが異なる。実装や論文を参照する際は、どちらの流儀かを確認すること。

パーシステンス図:穴の「寿命」を可視化する

フィルトレーションを追跡すると、各「穴」には 誕生時刻(birth)死亡時刻(death) が定まる。

  • 誕生(birth):その穴が初めて現れる ϵ の値
  • 死亡(death):その穴が消える(塞がる) ϵ の値

これを2次元平面上にプロットしたものが パーシステンス図(persistence diagram) である。

txt
death
  ^
  |     *          * は「穴」を表す点
  |   *   *        対角線から遠いほど「長寿命」
  |  *     *
  | *   *
  |*__________> birth
  • 対角線上の点:誕生と同時に死亡(寿命0)→ ノイズ
  • 対角線から遠い点:長寿命 → 本質的な構造

TIP

パーシステンス図の読み方: 対角線からの距離(death - birth)を persistence(持続性) と呼ぶ。持続性が大きい点は、広いスケール範囲で観測される「頑健な」構造を表す。逆に、持続性が小さい点はノイズや局所的な揺らぎを反映していることが多い。

バーコード:もう一つの可視化

パーシステンス図と等価な情報を持つ バーコード(barcode) も広く使われる。各穴を、誕生から死亡までの区間として水平線で表す。

txt
       birth          death
         |--------------|   長いバー = 重要な構造
         |---|              短いバー = ノイズ?
           |----|

バーコードは、穴の「寿命」を直感的に把握しやすい。

深層学習への応用

表現空間のトポロジー

深層学習モデルは、入力データを高次元の表現空間に写像する。この表現空間のトポロジー的構造と、モデルの性能や振る舞いの間に 相関が観察される ことがある。ただし、これが因果関係(トポロジーが性能を決める)なのか、単なる相関なのか、あるいは共通の原因による見かけの関係なのかは、多くの場合まだ明らかではない。

以下では、TDAが表現空間の「診断・観察ツール」として使われている例を紹介する。

応用例1:クラスタリングの質の評価

良い表現は、同じクラスの点を近くに、異なるクラスの点を遠くに配置する。しかし、「近い」「遠い」だけでは不十分な場合がある。

例えば、あるクラスの表現が「リング状」になっていると、ユークリッド距離に基づく分類器は中心付近で混乱する可能性がある。パーシステントホモロジーは、このような「トポロジー的な複雑さ」を検出できる。

応用例2:学習過程のモニタリング

学習の進行に伴い、表現空間の構造はどう変化するか?

初期のランダムな重みでは、表現は無秩序に分布している。学習が進むと、クラスごとにクラスタが形成され、やがて分離が明確になる。この過程を、各エポックでのパーシステンス図として追跡できる。

CAUTION

解釈の難しさ: 表現空間のトポロジーが「良い」とは何を意味するか?この問いに対する普遍的な答えはない。タスクによっては、トポロジー的に複雑な表現が必要な場合もあれば、単純な方が良い場合もある。TDAは「何があるか」を測るが、「何が望ましいか」は別の問いである。

研究事例:ニューラルネットワークの決定境界

Naitzat et al. (2020) は、ニューラルネットワークの決定境界のトポロジーを研究した("Topology of Deep Neural Networks", arXiv:2004.06093)。

主な知見:

  1. ReLUネットワークの表現力:ReLU活性化関数を持つネットワークは、層を深くすることで、入力空間の複雑なトポロジー(多数の穴やループ)を単純化できる。
  2. Skip connectionの効果:ResNetのskip connectionは、各層でのトポロジー変化を緩やかにする傾向がある。これにより、「急激なトポロジー変化」による情報損失を防いでいる可能性がある。

NOTE

「トポロジーを保存する」の意味: この文脈での「保存」は、厳密な位相同型を意味しない。むしろ、ベッチ数の急激な変化を抑えるという、より緩い意味で使われている。この主張の一般性と限界については、まだ議論が続いている。

TDAの現在地

TDAの深層学習への応用は、以下のような段階にある:

応用領域成熟度状況
表現空間の可視化・分析研究ツールとして一定の有用性
学習過程のモニタリング低〜中興味深い知見はあるが、実用性は限定的
損失関数への組み込み勾配計算の困難さ等の課題
アーキテクチャ設計への指針示唆はあるが、直接的な設計原理には至っていない

IMPORTANT

TDAは「診断ツール」として有用: 現時点でのTDAの最大の価値は、表現空間の構造を「別の角度から見る」ことにある。幾何学的な指標(距離、角度)では見えない構造が、トポロジー的な視点から見えることがある。ただし、TDAの出力を直接最適化する手法は、まだ発展途上である。

まとめ

概念定義深層学習での役割
トポロジー連続変形で保存される性質の研究幾何では見えない構造を捉える視点
ベッチ数各次元の「穴」の数表現空間の複雑さの指標
パーシステントホモロジースケールを変えながら穴を追跡ノイズに頑健な構造抽出
パーシステンス図穴の誕生・死亡を2次元で可視化構造の「重要度」の判定

本回のメッセージ

形(幾何)だけでなく、構造(トポロジー)を見る目を持つ。

幾何学は「どれだけ」を測り、トポロジーは「どのように」を測る。両者は補完的であり、表現空間を理解するための異なるレンズを提供する。

TDAは万能ではない。しかし、「この表現空間には、隠れたループ構造があるのではないか」「学習の過程で、トポロジーが急激に変化していないか」といった問いを立てることができる——その視点自体に価値がある。

次回予告

第15回「次の時代を設計する」では、これまでの14回で学んだ視点を統合する。平坦な空間から曲がった空間へ、幾何から位相へ、静的な構造から動的なプロセスへ——これらのパラダイムシフトを俯瞰し、未来の深層学習設計に向けた問いを提示する。

実装ノート:Ripserによるパーシステントホモロジー計算

NOTE

以下のコードは ripser (pip install ripser) と persim (pip install persim) を使用する。Python >= 3.8 を推奨。

CAUTION

実務上の注意点:

  • スケーリング:データの標準化・正規化により距離の意味が変わる。前処理の選択がパーシステンス図に大きく影響するため、目的に応じて慎重に選ぶこと。
  • サブサンプリング:高次元埋め込みでは、データ次元・maxdim・実装に依存するが、数百〜数千点程度でも計算が重くなりうる。まずはサブサンプリングを検討すること。
  • 統計的安定性:点数が少ないとパーシステンス図は不安定になる。ブートストラップや複数回のサンプリングで安定性を確認すること。
  • クラス間比較:ラベル別に解析する場合、クラス間で点数を揃えるか、点数の違いを考慮した解釈が必要。

基本的な使い方

コード例: 14_ripser_basic.py
python
import numpy as np
from ripser import ripser


def compute_persistence(data, maxdim=1):
    """点群のパーシステントホモロジーを計算

    Args:
        data: 点群 (n_points, n_features)
        maxdim: 計算する最大次元(0=連結成分, 1=ループ, 2=空洞, ...)

    Returns:
        パーシステンス図のリスト(各次元に対して1つ)
    """
    result = ripser(data, maxdim=maxdim)
    return result["dgms"]


# 例1: ノイズ付きの円
np.random.seed(42)
n_points = 100
theta = 2 * np.pi * np.random.rand(n_points)
noise = 0.1 * np.random.randn(n_points, 2)
circle = np.column_stack([np.cos(theta), np.sin(theta)]) + noise

# パーシステンス図の計算
diagrams = compute_persistence(circle, maxdim=1)

print("H0 (連結成分):", diagrams[0].shape[0], "個の特徴")
print("H1 (ループ):", diagrams[1].shape[0], "個の特徴")

# 最も持続性の高いH1特徴(円の「穴」に対応)
h1_persistence = diagrams[1][:, 1] - diagrams[1][:, 0]
print(f"最大持続性: {h1_persistence.max():.3f}")

パーシステンス図の可視化

コード例: 14_visualization.py
python
import matplotlib.pyplot as plt
import numpy as np
from persim import plot_diagrams
from ripser import ripser


def visualize_persistence(data, title="Persistence Diagram"):
    """点群とパーシステンス図を並べて表示"""
    result = ripser(data, maxdim=1)
    diagrams = result["dgms"]

    fig, axes = plt.subplots(1, 2, figsize=(12, 5))

    # 点群の表示
    axes[0].scatter(data[:, 0], data[:, 1], s=20, alpha=0.7)
    axes[0].set_aspect("equal")
    axes[0].set_title("Point Cloud")

    # パーシステンス図の表示
    plot_diagrams(diagrams, ax=axes[1])
    axes[1].set_title(title)

    plt.tight_layout()
    return fig


# 例: 異なる形状の比較
np.random.seed(42)
n = 100

# 円
theta = 2 * np.pi * np.random.rand(n)
circle = np.column_stack([np.cos(theta), np.sin(theta)]) + 0.1 * np.random.randn(n, 2)

# 2つの円(8の字に近い)
theta1 = 2 * np.pi * np.random.rand(n // 2)
theta2 = 2 * np.pi * np.random.rand(n // 2)
two_circles = np.vstack(
    [
        np.column_stack([np.cos(theta1) - 1, np.sin(theta1)]),
        np.column_stack([np.cos(theta2) + 1, np.sin(theta2)]),
    ]
)
two_circles += 0.1 * np.random.randn(n, 2)

# ランダムな点群
random_cloud = np.random.randn(n, 2)

# 可視化(実行時)
# visualize_persistence(circle, "Circle: 1 loop expected")
# visualize_persistence(two_circles, "Two circles: 2 loops expected")
# visualize_persistence(random_cloud, "Random: no persistent loops expected")

表現空間の解析

コード例: 14_representation_analysis.py
python
import numpy as np
from ripser import ripser


def analyze_representation_topology(embeddings, labels, maxdim=1):
    """表現空間のトポロジーをクラスごとに解析

    Args:
        embeddings: 表現ベクトル (n_samples, n_features)
        labels: クラスラベル (n_samples,)
        maxdim: 計算する最大次元

    Returns:
        各クラスのトポロジー的特徴の要約
    """
    results = {}
    unique_labels = np.unique(labels)

    for label in unique_labels:
        mask = labels == label
        class_embeddings = embeddings[mask]

        # パーシステントホモロジー計算
        dgms = ripser(class_embeddings, maxdim=maxdim)["dgms"]

        # 各次元の持続性統計
        stats = {}
        for dim in range(maxdim + 1):
            if len(dgms[dim]) > 0:
                # 無限大の死亡時刻を除外
                finite_mask = np.isfinite(dgms[dim][:, 1])
                if finite_mask.any():
                    persistence = dgms[dim][finite_mask, 1] - dgms[dim][finite_mask, 0]
                    stats[f"H{dim}_count"] = len(persistence)
                    stats[f"H{dim}_max_persistence"] = persistence.max()
                    stats[f"H{dim}_mean_persistence"] = persistence.mean()
                else:
                    stats[f"H{dim}_count"] = 0

        results[label] = stats

    return results


# 使用例(モデルの表現を取得した後)
# embeddings = model.get_embeddings(data)
# topology_stats = analyze_representation_topology(embeddings, labels)
# for label, stats in topology_stats.items():
#     print(f"Class {label}: {stats}")

学習過程のトポロジー追跡

コード例: 14_training_topology.py
python
import numpy as np
from ripser import ripser


def track_topology_during_training(
    model,
    data_loader,
    epochs,
    sample_size=500,
    maxdim=1,
):
    """学習中の表現空間トポロジーを追跡

    Args:
        model: PyTorchモデル(get_embeddingsメソッドを持つ)
        data_loader: データローダー
        epochs: エポック数
        sample_size: 各エポックでサンプリングする点数
        maxdim: 計算する最大次元

    Returns:
        各エポックのトポロジー統計
    """
    topology_history = []

    for epoch in range(epochs):
        # モデルを1エポック学習
        # train_one_epoch(model, data_loader)

        # 表現を取得(サンプリング)
        # embeddings = sample_embeddings(model, data_loader, sample_size)

        # ダミーデータで例示
        embeddings = np.random.randn(sample_size, 64)

        # パーシステントホモロジー計算
        dgms = ripser(embeddings, maxdim=maxdim)["dgms"]

        # H1の持続性統計を記録
        h1_dgm = dgms[1]
        finite_mask = np.isfinite(h1_dgm[:, 1])
        if finite_mask.any():
            h1_persistence = h1_dgm[finite_mask, 1] - h1_dgm[finite_mask, 0]
            epoch_stats = {
                "epoch": epoch,
                "h1_count": len(h1_persistence),
                "h1_max": h1_persistence.max(),
                "h1_mean": h1_persistence.mean(),
                "h1_total": h1_persistence.sum(),
            }
        else:
            epoch_stats = {
                "epoch": epoch,
                "h1_count": 0,
                "h1_max": 0,
                "h1_mean": 0,
                "h1_total": 0,
            }

        topology_history.append(epoch_stats)

    return topology_history

CAUTION

計算コストに注意: パーシステントホモロジーの計算は、単体複体のサイズに依存する。Vietoris-Rips複体では、点の数 n に対して単体数が組合せ爆発的に増加しうるため、高次元や大規模データでは計算が非常に重くなる。実務では、サブサンプリング、次元の制限(maxdim=1程度)、近似手法(利用可能であればRipser++、Approximate Rips等)の使用を検討すること。

参考文献

パーシステントホモロジー(数学的基礎)

  • Edelsbrunner, H., & Harer, J. (2010). Computational Topology: An Introduction. American Mathematical Society.
    • 計算トポロジーの標準的教科書。パーシステントホモロジーの理論的基盤を厳密に扱う。
  • Carlsson, G. (2009). Topology and Data. Bulletin of the American Mathematical Society, 46(2), 255–308. DOI: 10.1090/S0273-0979-09-01249-X
    • TDAの創始者による解説論文。データ解析へのトポロジー応用の動機と基本概念を説明。

深層学習への応用

  • Naitzat, G., Zhitnikov, A., & Lim, L.-H. (2020). Topology of Deep Neural Networks. JMLR, 21(184), 1–40. arXiv: arXiv:2004.06093
    • ニューラルネットワークの決定境界のトポロジーを研究。ReLUネットワークとskip connectionの効果を議論。
  • Gabrielsson, R. B., & Carlsson, G. (2019). Exposition and Interpretation of the Topology of Neural Networks. ICML 2019 Workshop on Topology and Geometry.
    • ニューラルネットワークの活性化空間のトポロジー解析手法を提案。

ソフトウェア

  • Tralie, C., Saul, N., & Bar-On, R. (2018). Ripser.py: A Lean Persistent Homology Library for Python. JOSS, 3(29), 925. DOI: 10.21105/joss.00925
  • GUDHI Project. GUDHI Library. https://gudhi.inria.fr/
    • より包括的なTDAライブラリ。Čech複体、 α 複体など多様な構成法をサポート。

関連するサーベイ

  • Hensel, F., Moor, M., & Rieck, B. (2021). A Survey of Topological Machine Learning Methods. Frontiers in Artificial Intelligence, 4, 681108. DOI: 10.3389/frai.2021.681108
    • TDAと機械学習の交差点に関する包括的なサーベイ。応用事例と課題を整理。