見出し画像

「線形代数の半歩先」をPythonで写経 ~ 8章 拡張動的モード分解、カーネル動的モード分解

第5部「ならべた数のさらなる発展」

書籍の著者 大久保 潤 先生


この記事は、書籍「線形代数の半歩先」の 第5部「ならべた数のさらなる発展」に掲載の「非線形系における線形性」に関する Python写経活動のドキュメンタリーです。

第5部は「時間発展方程式」を取り扱います。

前回記事の最後で 大きな転換期 を迎えました。
なんと、ChatGPTが「完全マスター」を作ってくれることに!
ChatGPTによるコードと解説に全面依拠して 動的モード分解(DMD)マスターを目指してまいります。

拡張動的モード分解(EDMD)と カーネル動的モード分解(カーネルDMD) を実践します!

いっけんテキストから離れるように見えますが、動的モード分解の理解を通じて、テキストを読み解く素地ができると思います!
とにかく数学素人なので、どうぞお手柔らかにお願いいたします。

では書籍とChatGPTを開いて線形代数の旅に出発です🚀

いろいろな表情のAIのキャラクター (ひらめく):「いらすとや」さんより

はじめに


このブログシリーズは、書籍「線形代数の半歩先 データサイエンス・機械学習に挑む前の30話」(講談社サイエンティフィク、「テキスト」と呼びます)の Python 写経の実践を通じて得た個人的な知見を書きます。

書籍の紹介と引用表記はリンク先の記事に掲載しています。

第5部 ならべた数のさらなる発展


クープマン理論&DMD完全マスター・ロードマップ

ChatGPT提案の「クープマン理論&DMD完全マスター」ロードマップです。(DMD は動的モード分解の略称です)

ChatGPT作成

この記事は STEP 1 ~ STEP 3 を実践します。
主に、拡張動的モード分解(EDMD)カーネル動的モード分解(カーネルDMD)に取り組みます。

なお STEP 3 は諸般の事情により、前回記事の内容から変化しています。
ChatGPTの気まぐれ、ですね。

テキストとの大凡の関連を表にしました。

$$
\begin{array}{l:l}
テーマ & テキスト関連箇所 \\
\hline
 \\
\text{EDMD} & 拡張動的モード分解(\text{p.252}) \\
& 辞書関数(\text{p.238}) \\
& クープマン行列(\text{p.241})\\
 \\
カーネル\text{DMD} & 動径基底関数(\text{p.251})
\end{array}
$$

(注意事項)
ChatGPTの回答をそのまま記載しています。
内容の適否はチェックしていませんので、ご了承ください。

STEP1: Extended DMD(EDMD)の実装:ファン・デル・ポール方程式への適用

(1)Python 実装
拡張動的モード分解(EDMD)の実装です。

■ 特徴

  • DMD ライブラリ「pyDMD」を使わず、辞書関数 Phi やクープマン行列 K をコードで作り込んでいます。
    コードを追うことで、テキストの数式の理解につながると思います!

  • ファン・デル・ポール方程式による時系列データを作成し、EDMDで近似値を求めて可視化します。
    3種類のチャートが出現します。

# --- セル 1: 必要なライブラリ ---
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Meiryo' # ★はマニュアル追加コード 

from scipy.integrate import solve_ivp
from numpy.linalg import pinv, eig

# --- セル 2: ファン・デル・ポール方程式の定義と時系列データ生成 ---
mu = 1.0

def vdp(t, y):
    x1, x2 = y
    dx1 = x2
    dx2 = mu * x2 * (1 - x1**2) - x1
    return [dx1, dx2]

# 時系列データの取得
t_eval = np.linspace(0, 20, 1000)
y0 = [0.2, 0.9]
sol = solve_ivp(vdp, [0, 20], y0, t_eval=t_eval)
X = sol.y.T                   # shape: (1000, 2)

# --- セル 3: 辞書関数(phi)による特徴変換 ---
def dictionary(x):
    x1, x2 = x[..., 0], x[..., 1]
    return np.stack([x1, x2, x1**2, x1*x2, x2**2], axis=-1)

Phi = dictionary(X[:-1])      # φ(x_t)      # shape: (999, 5)
Phi_next = dictionary(X[1:])  # φ(x_{t+1})  # shape: (999, 5)

# --- セル 4: EDMD によるクープマン行列の構築 ---
K = Phi_next.T @ pinv(Phi.T)  # K ∈ ℝ^{d x d}

# 固有分解(クープマン固有値・固有ベクトル)
evals, evecs = eig(K)

# --- セル 5: 固有値とモードの可視化 ---
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(np.real(evals), np.imag(evals), 'o')
plt.xlabel("実部")
plt.ylabel("虚部")
plt.title("EDMD: クープマン固有値")
plt.grid(True)

plt.subplot(1, 2, 2)
plt.plot(X[:, 0], X[:, 1], label="軌道")
plt.title("ファン・デル・ポール方程式の軌跡")
plt.scatter(X[0, 0], X[0, 1], color='red', label="初期状態")     # ★
plt.scatter(X[-1, 0], X[-1, 1], color='green', label="最終状態") # ★
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

# --- セル 6: 固有関数の近似と可視化 ---
phi1 = Phi @ evecs[:, 0]  # 各サンプルごとの固有関数の値

plt.figure(figsize=(6, 4))
sc = plt.scatter(Phi[:, 0], Phi[:, 1], c=phi1.real, cmap='viridis', s=10)
plt.scatter(Phi[0, 0], Phi[0, 1], color='red', label="初期状態")     # ★
plt.scatter(Phi[-1, 0], Phi[-1, 1], color='green', label="最終状態") # ★
plt.xlabel("$\phi_1 = x_1$")
plt.ylabel("$\phi_2 = x_2$")
plt.title("EDMD: クープマン固有関数(近似)")
plt.colorbar(sc)
plt.grid(True)
plt.tight_layout()
plt.show()

【実行結果】
左:おなじみの固有値プロット
右:ファン・デル・ポール方程式を解いて作成した時系列データ

EDMDの近似結果(色は固有関数の値)
※上のチャート(右)をよく近似できています。

■ (ご参考)手作業でコード変更した箇所

  • グラフの日本語表示のために rcParams のフォント設定

  • グラフの英語を日本語に変更

  • 初期状態・最終状態の点の描画

■ Python コードに書かれていた概要説明

🔍 EDMD 実装まとめ

  • φ(x) = [x1, x2, x1², x1 x2, x2²] のような辞書関数で特徴空間を作成

  • 1ステップ先のデータでクープマン行列 K を構成

  • 固有値:時間的スケール(周期・減衰)

  • 固有関数:観測空間で変化しない成分の方向(可視化)

✅ 次に進むなら?

  • 辞書関数の拡張(多項式3次、sin, cos など)

  • EDMD と DMD の比較分析(同じデータで)

  • クープマンモードを使った未来予測

  • カーネルDMD への拡張(非明示的辞書)

◆ ◆ ◆

(2)✅ EDMDコードから学べる注目ポイント・要点整理

1️⃣ 「非線形を線形で扱う」ことの設計思想

🔍 注目ポイント

def dictionary(x):
    return np.stack([x1, x2, x1**2, x1*x2, x2**2], axis=-1)

💡 学び

  • 非線形な力学系(ファン・デル・ポール) を

  • 線形な演算子(クープマン行列) で扱えるようにするために、

  • 状態を拡張(辞書関数 φ) している!

「非線形問題を高次元に持ち上げて線形に処理する」という、クープマン理論の本質に触れられる部分。

2️⃣ 時系列データの使い方:入力と出力のずれ

🔍 注目ポイント

Phi      = dictionary(X[:-1])       # φ(x_t)
Phi_next = dictionary(X[1:])        # φ(x_{t+1})

💡 学び

  • 時系列データの1ステップずれを用いて、

  • クープマン行列 $${K}$$ を φ空間での線形近似として構成。

  • $${K \phi(x_t) \approx \phi(x_{t+1})}$$ を満たすように求める。

「時間発展の写像」を、拡張空間で学習しているという構造を理解。

3️⃣ クープマン行列の構築:Moore–Penrose擬似逆行列の利用

🔍 注目ポイント

K = Phi_next.T @ pinv(Phi.T)

💡 学び

  • 最小二乗で $${K}$$ を求める際に、行列の逆が使えない場合は擬似逆を使う。

  • pinv を使うことで 過剰特徴量 or ランク不足にも安定な近似が可能。

数値安定性と実装力が求められる重要箇所。

4️⃣ 固有値・固有ベクトルの意味:時間スケールと空間構造

🔍 注目ポイント

evals, evecs = eig(K)

💡 学び

  • 固有値 $${\lambda}$$ は 振動周期、減衰、発散などの時間的挙動を表す。

  • 固有ベクトル $${v}$$ は、拡張特徴空間における 変化しにくい構造(=固有関数) を表す。

観測空間では見えなかった「時間に対して不変な特徴が浮かび上がる

5️⃣ 固有関数の近似と可視化:観測空間における意味付け

🔍 注目ポイント

phi1 = Phi @ evecs[:, 0]  # 各サンプルごとの固有関数値
plt.scatter(Phi[:, 0], Phi[:, 1], c=phi1.real, ...)

💡 学び

  • 固有関数を近似的に描画することで、

  • どのあたりの点が「時間に対して安定」なのかが視覚化される。

  • データ駆動で不変量・支配的成分を抽出している。

「可視化された力学系の内部構造」が実感できる!

6️⃣ 固有値プロット:複素平面の読み方

🔍 注目ポイント

plt.plot(np.real(evals), np.imag(evals), 'o')

💡 学び

  • $${\lambda = r e^{i\omega}}$$ として見ると:

    • $${|\lambda| ≈ 1}$$ → 周期的運動(発散・収束なし)

    • $${|\lambda| > 1}$$ → 発散

    • $${|\lambda| < 1}$$ → 減衰

    • $${\text{Im}(\lambda) ≠ 0}$$ → 振動

固有値の分布を見れば「系の時間挙動の骨格」がわかる。

STEP2: Kernel DMD(カーネルDMD):ファン・デル・ポール方程式への適用

ChatGPT提案コードで何度もエラーが生じたため、修正を加えた最終結果を掲載します。
エラー修正を繰り返した結果、「グラフの読み解き」「カーネルDMDコードから学べる注目ポイント・要点整理」には、コード修正・コード改善の視点による説明が含まれています。

◆ ◆ ◆

(1)Python 実装
カーネル動的モード分解(カーネルDMD)の実装です。

■ 特徴

  • 動径基底関数(RBF)にはガウス型の動径基底関数を扱う scikit-learn の rbf_kernel を利用します。

  • このコードも、DMD ライブラリ「pyDMD」を使わず、クープマン行列の近似 A_tilde をコードで作り込んでいます。
    コードを追うことで、テキストの数式の理解につながると思います!

  • ファン・デル・ポール方程式による時系列データを作成し、カーネルDMD の固有値とモードを可視化しています。

# --- セル 1: 必要なライブラリ ---
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Meiryo' # ★はマニュアル追加コード 
from scipy.integrate import solve_ivp
from numpy.linalg import eig, pinv
from sklearn.metrics.pairwise import rbf_kernel

# --- セル 2: ファン・デル・ポール方程式の定義と時系列データ生成 ---
mu = 1.0

def vdp(t, y):
    x1, x2 = y
    dx1 = x2
    dx2 = mu * x2 * (1 - x1**2) - x1
    return [dx1, dx2]

# データ生成
T = np.linspace(0, 20, 1000)
y0 = [0.2, 0.9]
sol = solve_ivp(vdp, [0, 20], y0, t_eval=T)
X = sol.y.T  # shape = (1000, 2)

# --- セル 3: データの準備(1ステップずれ) ---
X1 = X[:-1]
X2 = X[1:]

# --- セル 4: RBFカーネルによる Gram 行列の作成 ---
gamma = 1.0  # カーネル幅のパラメータ(調整済)
K = rbf_kernel(X1, X1, gamma=gamma)
K_prime = rbf_kernel(X2, X1, gamma=gamma)

# --- セル 5: クープマン行列の近似と固有分解(ランク削減付き) ---
# SVDによるランク削減
U, S, Vh = np.linalg.svd(K, full_matrices=False)
rank = 30                          # 上位ランクのみ使用
Ur = U[:, :rank]
Sr = np.diag(S[:rank])
Vr = Vh[:rank, :]

K_reduced_inv = Vr.T @ np.linalg.inv(Sr) @ Ur.T
A_tilde = K_prime @ K_reduced_inv  # A_tilde: クープマン行列の近似

evals, evecs = eig(A_tilde)        # クープマン行列(近似)の固有値・固有ベクトル

# 固有値を支配的な順にソート
idx = np.argsort(np.abs(evals))[::-1]
evals = evals[idx]
evecs = evecs[:, idx]

# --- セル 6: 固有値の可視化 ---
plt.figure(figsize=(6, 5))
plt.plot(np.real(evals), np.imag(evals), 'o')
plt.xlabel("実部")
plt.ylabel("虚部")
plt.title(f"Kernel DMD: クープマン固有値(rank={rank})")
plt.grid(True)
plt.tight_layout()
plt.show()

# --- セル 7: モード(代表例)の時間変化 ---
# 描画対象モードのインデックスを指定
indexes = [0, 2, 4]  # ★ 固有値のインデックス
time = T[:-1]

plt.figure(figsize=(8, 4))
for i in indexes:
    mode = np.real(evecs[:, i])  # 固有ベクトルの実部
    plt.plot(time, mode, label=f"Mode {i+1}")

plt.title("Kernel DMD: クープマンモードの時間変化(抜粋)")
plt.xlabel("時間")
plt.ylabel("モードの振幅")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

【実行結果】
こちらは、おなじみの固有値プロットです。

こちらはクープマン行列(近似の)固有ベクトルの実部を「モード」と称してプロットしています。

■ Python コードに書かれていた概要説明

🧠 Kernel DMDのポイントまとめ

  • gamma を 1.0 に設定 → カーネル幅を中庸に

  • SVD によるランク削減(rank=30)でノイズ除去

  • 固有値の絶対値が大きい順にソート → 支配的モードを抽出

✅ 次に進むなら?

  • 固有値とEDMD/DMDの比較

  • Kernel DMD を用いた未来予測の実装

  • 実データや画像・動画への応用

◆ ◆ ◆

(2)🔍 グラフの読み解き

✅ 上部:クープマン固有値の分布(複素平面)

✔ 特徴

  • ほとんどの固有値が単位円の内側 or 近傍に収まっている

  • 一部に 虚部を持つ固有値(上下方向に分布)

🔍 解釈

  • $${|\lambda| \approx 1}$$ → 周期的・持続的な振動モード

  • $${\text{Im}(\lambda) \ne 0}$$ → 周期的成分を含む(振動)

  • $${\text{Re}(\lambda) < 1}$$ → 減衰的な成分

✅ これは「安定した周期運動(ファン・デル・ポール的)」を適切に捉えている証拠です!

✅ 下部:支配的なクープマンモードの時間変化

✔ 特徴

  • 明瞭な 振動構造(周期性)

  • やや 振幅増加傾向(非線形系らしい非定常性も含まれている)

🔍 解釈

  • DMD や EDMD とは違って、非線形性が暗黙に反映されている

  • 「一見サイン波に近いが振幅が変化する」→ ファン・デル・ポールらしい!

  • 絶対値は小さいが、モードの形状がちゃんと意味を持っている

✅ データに含まれる主要な振動モードを正しく抽出できています!

🎯 総合評価:この出力の妥当性

$$
\begin{array}{l:l:l}
評価項目 & 状況 & コメント \\
\hline
 \\
固有値の分布 & ◎ & 適度な範囲・虚部あり・発散なし \\
モードの形状 & ◎ & 周期性あり・ノイズ少なく明瞭 \\
実装パラメータ & ◎ & \text{gamma}, \text{rank} などうまく調整されている \\
\end{array}
$$

Kernel DMD はファン・デル・ポールの非線形性をしっかり捉えています!

◆ ◆ ◆

(3)✅ カーネルDMDコードから学べる注目ポイント・要点整理

1️⃣ 明示的な特徴量変換を避ける:カーネル法の力

🔍 注目ポイント

from sklearn.metrics.pairwise import rbf_kernel
K = rbf_kernel(X1, X1, gamma=gamma)
K_prime = rbf_kernel(X2, X1, gamma=gamma)

💡 学び

  • カーネル法では $${φ(x)}$$ を直接作らず、内積だけで処理する(“カーネルトリック”)

  • RBF(ガウス)カーネルを使うことで、非線形写像の効果を暗黙的に取り入れられる

明示的な辞書関数の定義が不要になる点が EDMD との大きな違い。

2️⃣ データの時間ずれで「時間発展」を学習する

🔍 注目ポイント

X1 = X[:-1]
X2 = X[1:]

💡 学び

  • 時刻 $${t}$$ と $${t+1}$$ のデータを使い、

  • 時間発展 $${K\phi(x_t) \approx \phi(x_{t+1})}$$ をカーネルで表現

データドリブンで動的系の時間構造を捉えるフレームワークが構築できる。

3️⃣ クープマン行列の構成:カーネル空間上の線形写像

🔍 注目ポイント

A_tilde = K_prime @ pinv(K)

💡 学び

  • 時間発展を内積行列(Gram 行列)上で定義

  • 実質的に「非線形な時間変化を線形行列として捉える」

非線形なダイナミクスを線形モデルで近似する本質がここにある。

4️⃣ ランク削減(SVD)でノイズ除去&安定化

🔍 注目ポイント

U, S, Vh = np.linalg.svd(K, full_matrices=False)
# ランクrで削減
K_inv = Vr.T @ np.linalg.inv(Sr) @ Ur.T

💡 学び

  • 高次元カーネル空間では冗長かつ不安定なモードが多数

  • ランク削減で意味のある支配的構造だけに絞るのが効果的

高次元の“表現力”と“制御性”のバランスをとる技術。

5️⃣ 固有値の解釈:周期・減衰・安定性

🔍 注目ポイント

plt.plot(np.real(evals), np.imag(evals), 'o')

💡 学び

  • 固有値 $${\lambda}$$ の絶対値 $${|\lambda|}$$:

    • ≈ 1 → 安定な周期的構造

    • > 1 → 発散傾向

    • < 1 → 減衰成分

    • 虚部 ≠ 0 → 振動(周期的)

固有値分布を見るだけで「系の安定性と時間スケール」が見えてくる。

6️⃣ クープマンモード:時間に沿って変化する主成分

🔍 注目ポイント

mode1 = np.real(evecs[:, 0])
plt.plot(time, mode1)

💡 学び

  • 各モードは「系の特徴的な振動や挙動の強さ」を表す

  • 支配的モードを見ることで、「支配的な変化方向」がわかる

「どんな振動が支配しているのか」が数式ではなく“見える”。

🎓 このコードから得られるスキルセット

$$
\begin{array}{l:l}
カテゴリ & 内容 \\
\hline
 \\
数理的理解 & カーネル法とクープマン作用素の接続 、\\
& 内積表現の重要性 \\
 \\
実装力 & カーネル行列、ランク削減、固有分解、\\
& \text{NumPy}操作 \\ 
 \\
可視化力 & 固有値プロット、モードの時間変化可視化 \\
 \\
解釈力 & 固有値・モードを通じた \\
& 物理的・構造的意味の把握 \\
\end{array}
$$

🔜 次に進むとさらに学べること

$$
\begin{array}{l:l}
次ステップ & 学べること \\
\hline
 \\
✅ \text{Kernel DMD}による & 固有値・モードから時間外挿が可能 \\
 未来予測 & \\
 \\
✅ \text{DMD / EDMD} & 各手法の特性と精度を体感 \\
 \text{/ KernelDMD} の比較 & \\
 \\
✅ 実データへの応用 & 動画・流体・センサー系列などに \\
& 展開可能 \\
\end{array}
$$

STEP3: DMD / EDMD / KernelDMD の比較ノートブック

同じデータ(ファン・デル・ポール方程式)に各手法を適用して、固有値・再構成・誤差を比較する

と ChatGPT は気合いを入れて、コード生成に臨んだようですが、結果は気合い(仕様どおり)になっていません。
固有値は3つの手法の比較ができていますが、再構成と誤差は DMD のみの
出力です。

◆ ◆ ◆

(1)Python 実装

# --- セル 1: 共通準備(データ生成) ---
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Meiryo' # ★マニュアル追加コード 
from scipy.integrate import solve_ivp

mu = 1.0
def vdp(t, y):
    x1, x2 = y
    dx1 = x2
    dx2 = mu * x2 * (1 - x1**2) - x1
    return [dx1, dx2]

T = np.linspace(0, 20, 1000)
y0 = [0.2, 0.9]
sol = solve_ivp(vdp, [0, 20], y0, t_eval=T)
X = sol.y  # shape = (2, 1000)

# --- セル 2: DMD の適用 ---
from pydmd import DMD

dmd = DMD(svd_rank=2)
dmd.fit(X)
dmd_recon = dmd.reconstructed_data.real

# --- セル 3: EDMD の適用 ---
def dictionary(x):
    x1, x2 = x[..., 0], x[..., 1]
    return np.stack([x1, x2, x1**2, x1*x2, x2**2], axis=-1)

X_ = X.T
Phi = dictionary(X_[:-1])
Phi_next = dictionary(X_[1:])
K_edmd = Phi_next.T @ np.linalg.pinv(Phi.T)
evals_edmd, evecs_edmd = np.linalg.eig(K_edmd)
Phi_recon = (K_edmd @ Phi.T).T  # 再構成された特徴量(拡張空間)

# --- セル 4: KernelDMD の適用 ---
from sklearn.metrics.pairwise import rbf_kernel
X1 = X_[:-1]
X2 = X_[1:]
gamma = 1.0
K = rbf_kernel(X1, X1, gamma=gamma)
K_prime = rbf_kernel(X2, X1, gamma=gamma)
U, S, Vh = np.linalg.svd(K, full_matrices=False)
rank = 30
Ur = U[:, :rank]
Sr = np.diag(S[:rank])
Vr = Vh[:rank, :]
K_inv = Vr.T @ np.linalg.inv(Sr) @ Ur.T
A_tilde = K_prime @ K_inv
evals_kdmd, evecs_kdmd = np.linalg.eig(A_tilde)

# --- セル 5: 固有値の比較可視化 ---
plt.figure(figsize=(12, 4))
plt.subplot(1, 3, 1)
plt.plot(np.real(dmd.eigs), np.imag(dmd.eigs), 'o')
plt.title("DMD 固有値")
plt.xlabel("Re")
plt.ylabel("Im")

plt.subplot(1, 3, 2)
plt.plot(np.real(evals_edmd), np.imag(evals_edmd), 'o')
plt.title("EDMD 固有値")
plt.xlabel("Re")
plt.ylabel("Im")

plt.subplot(1, 3, 3)
plt.plot(np.real(evals_kdmd), np.imag(evals_kdmd), 'o')
plt.title("Kernel DMD 固有値")
plt.xlabel("Re")
plt.ylabel("Im")
plt.tight_layout()
plt.show()

# --- セル 6: DMD 再構成と元データの比較 ---
plt.figure(figsize=(10, 5))
plt.plot(T, X[0], label="x1 (original)")
plt.plot(T, dmd_recon[0], '--', label="x1 (DMD)")
plt.title("DMD による x1 再構成")
plt.xlabel("Time")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

【実行結果】

◆ ◆ ◆

(2)✅ なぜDMDだけ元データと比較しているのか?

比較しなかった理由をChatGPTに訊いてみました。
以下、ChatGPTの回答です。

DMD:観測空間での再構成がそのままできる

  • DMDは、入力データ $${X}$$ に直接作用して、

$$
X_t \approx \sum_k b_k \phi_k \lambda_k^t
$$

  • モード($${\phi_k}$$)も再構成されたデータも 観測空間(元の次元)にある

→ なので、X と dmd.reconstructed_data を直接比較できる

❗ EDMD・Kernel DMDが直接比較しにくい理由

EDMD:

  • データは拡張された特徴空間 $${\phi(x)}$$ に写されており、

  • 再構成もその特徴空間で行われる:

$$
\phi(x_{t+1}) \approx K \phi (x_t)
$$

  • 問題:$${\phi^{-1}}$$(逆写像)が通常存在しない or 難しい

→ 観測空間に戻して比較できない

Kernel DMD:

  • さらに難しい。特徴空間は暗黙的に存在(カーネルトリック)するだけ

  • $${\phi(x)}$$ どころか、φ の具体的な形すらわからない

→ 当然ながら、「元の x に戻して可視化」は不可(or 近似が必要)

🧠 じゃあEDMD/KernelDMDの出力はどう評価するの?

$$
\begin{array}{l:l}
方法 & 内容 \\
\hline
 \\
✅ 固有値の分布 & 周期性・減衰・安定性の評価 \\
& 共通の基準で比較しやすい \\
 \\
✅ 再構成された特徴空間の & 「写像先でどうなっているか」\\
  \phi(x) をプロット & \phi\ 空間の挙動を観察 \\
 \\
✅ 固有関数の可視化 & 系の支配的な不変方向を見る \\
& 空間構造の解釈に役立つ \\
 \\
✅ 元データへの再投影 & \text{AutoEncoder}や学習済逆写像で可能 \\
  (近似)& 高度な手法が必要 \\
\end{array}
$$

✨ まとめ

$$
\begin{array}{l:l}
手法 & 再構成の可視化のしやすさ \\
\hline
 \\
\text{DMD} & ◎\ そのまま比較可能 \\
&  モードが観測空間にあるため \\
 \\
\text{EDMD} & △\ \phi 空間で再構成されるため、逆写像が必要 \\
 \\
\text{Kernel DMD} & ×\ \phi も逆写像も不明、\\
&  比較には間接的手法が必要 \\
\end{array}
$$


おわりに

Python コードを読み解くと、意外にシンプルな演算(=数式)で EDMD / カーネル DMD を実装していることが分かります。
テキストの数式理解につながると嬉しいです!

そして完全マスターの道は…

次章へ続く!

今回の写経は以上です。


シリーズの記事

次の記事

前の記事

目次

ブログの紹介


note で7つのシリーズ記事を書いています。
ぜひ覗いていってくださいね!

1.のんびり統計

統計検定2級の問題集を手がかりにして、確率・統計をざっくり掘り下げるブログです。
雑談感覚で大丈夫です。ぜひ覗いていってくださいね。
統計検定2級公式問題集CBT対応版に対応しています。
Python、EXCELのサンプルコードの配布もあります。

2.実験!たのしいベイズモデリング1&2をPyMC Ver.5で

書籍「たのしいベイズモデリング」・「たのしいベイズモデリング2」の心理学研究に用いられたベイズモデルを PyMC Ver.5で描いて分析します。
この書籍をはじめ、多くのベイズモデルは R言語+Stanで書かれています。
PyMCの可能性を探り出し、手軽にベイズモデリングを実践できるように努めます。
身近なテーマ、イメージしやすいテーマですので、ぜひぜひPyMCで動かして、一緒に楽しみましょう!

3.実験!岩波データサイエンス1のベイズモデリングをPyMC Ver.5で

書籍「実験!岩波データサイエンスvol.1」の4人のベイジアンによるベイズモデルを PyMC Ver.5で描いて分析します。
この書籍はベイズプログラミングのイロハをざっくりと学ぶことができる良書です。
楽しくPyMCモデルを動かして、ベイズと仲良しになれた気がします。
みなさんもぜひぜひPyMCで動かして、一緒に遊んで学びましょう!

4.楽しい写経 ベイズ・Python等

ベイズ、Python、その他の「書籍の写経活動」の成果をブログにします。
主にPythonへの翻訳に取り組んでいます。
写経に取り組むお仲間さんのサンプルコードになれば幸いです🍀

5.RとStanではじめる心理学のための時系列分析入門 を PythonとPyMC Ver.5 で

書籍「RとStanではじめる心理学のための時系列分析入門」の時系列分析をPythonとPyMC Ver.5 で実践します。
この書籍には時系列分析のテーマが盛りだくさん!
時系列分析の懐の深さを実感いたしました。
大好きなPythonで楽しく時系列分析を学びます。

6.データサイエンスっぽいことを綴る

統計、データ分析、AI、機械学習、Pythonのコラムを不定期に綴っています。
統計・データサイエンス書籍にまつわる記事が多いです。
「統計」「Python」「数学とPython」「R」のシリーズが生まれています。

7.Python機械学習プログラミング実践記

書籍「Python機械学習プログラミング PyTorch & scikit-learn編」を学んだときのさまざまな思いを記事にしました。
この書籍は、scikit-learnとPyTorchの教科書です。
よかったらぜひ、お試しくださいませ。

最後までお読みいただきまして、ありがとうございました。

いいなと思ったら応援しよう!

ネイピア DS 応援ありがとうございます。これからもがんばって記事を作成します!

この記事が参加している募集