Generalized Mahalanobis depth in the reproducing kernel Hilbert spaceをPythonで実装した話

はじめに

2011年に以下の論文が出版されている.

Yonggang Hu, Yong Wang, Yi Wu, Qiang Li & Chenping Hou, "Generalized Mahalanobis depth in the reproducing kernel Hilbert space," Statistical Papers volume 52, pages 511-522 (2011). link.springer.com

この論文において,再生核ヒルベルト空間(Reproducing Kernel Hilbert Space; RKHS)上でMahalanobis depthを計算する方法が提案された. それを具体的にPythonで実装してみたので紹介するのが本記事の主旨である.

統計的depthとは

統計的depthは多次元空間のmedianを考える際に出てくる統計量である. 多数のサンプルデータ点(一般には多次元ベクトルの集合)からなるdata cloudが与えられたとき, depthにより各点がdata cloudの「中心」からどれくらい近いか・離れているか (= centrality)が定量化される. 値は0から1の範囲を取り,最大値を与える点をmedianと呼ぶ(ことにする). たとえ多次元空間であってもdepthの計算手段/アルゴリズムを与えさえすれば,medianが定義できるというわけである.

depthにより,多次元空間における各点ごとに一次元の順序 (order) が導入される. このときの順序は 「中心から外向き (center-outward)」である.当然ながらその「中心」にはmedianがいる.順序を用いることで多次元データ群上で分位数(quantile)と階数(rank)に相当するものが計算可能となり,統計的depthは統計学分野に幅広い応用を持つ.

depth を計算するための手段(depth関数)も様々なものが提案されており,具体的には

  • Halfspace depth
  • Mahalanobis depth
  • Simplicial depth
  • Simplicial volume depth
  • Zonoid depth
  • Lens depth
  • Spatial depth
  • Projection depth

などがある(各depthの出典は省略).

Mahalanobis depthとは

ある多次元空間のデータ点 $\mathbf{x}$ に対して, data cloud $X$ から計算されるマハラノビス距離を $d^{2} (\mathbf{x}, X)$ と書いたとき,Mahalanobis depth (MHD) は次式で計算できる.

$$ MHD (\mathbf{x} \mid X) = \frac{1}{1 + d^{2}(\mathbf{x}, X)} $$

論文とnotationが全然違うが許してほしい(ただのサボり!).

$x \in [0, \infty) $ なる $x$に対して

$$ y = \frac{1}{1+x} $$

のグラフを思い浮かべれば,depthの値の範囲が $(0, 1]$ となることはすぐに分かる.

MHDはマハラノビス距離の逆数もどきなので,その等高線は楕円(一般には超楕円体)に限られる. データを生成する(真の)分布 が楕円対称ならばうまくdepthもフィットするが, 一般のサンプルデータ群は複雑な形状をしているため,必ずしも最適とは限らない.さらにマハラノビス距離を計算する際の分散共分散行列の正定値性を仮定している点も制約になる. 一般には必ずしも正定値にならず特異 (singular)な行列となり,逆行列が計算できない,つまりマハラノビス距離が計算できなくなる.

Generalized Mahalanobis depth およびその実装

論文ではまず上記MHDの欠点を克服するための Generalized Mahalanobis depth (GMHD) が導入される. さらにGMHDの具体的な実現方法として, 再生核カーネル関数に対応するRKHS上でGMHDを計算する式が定理として与えられる. 具体的にはkernel PCAに相当する固有値問題を解き,固有値固有ベクトルから計算できる. 論文中ではこのdepthは特にkernel mapped GMHD (kmGMHD)と呼ばれている.

kmGMHDの実装は簡単である.scikit-learnベースで話をすると,

  1. 学習データに対してkernel PCAをfitし,データ全体をtransformする.手元には変換された特徴ベクトルが手に入る(RKHSにおける座標成分に相当).
  2. 非ゼロの固有値に対応する特徴ベクトル群を取り,固有値平方根の逆数によりベクトルの各成分をスケーリングする.
  3. 特徴ベクトルの各成分の二乗和を計算する.この量を仮にrと置く.
  4. depth = 1 / (1 + r) により計算される.

以下のリンクより,実際に実装したクラスを確認することができる.

上記の説明に対応しているのは以下のコードたちである(抜粋).

x_transformed = self.kpca.fit_transform(X)  # [n_samples, n_components]
non_zeros = np.flatnonzero(self.kpca.eigenvalues_)
x_transformed = x_transformed[:, non_zeros]
x_transformed = x_transformed / np.sqrt(self.kpca.eigenvalues_[non_zeros])
self.depth_values = 1 / (1 + np.sum(x_transformed**2, axis=1))

実験結果

depth のデモは下記のnotebookを参考に.

これらのnotebookにおいて,各種のtoy datasetに対してdepthを計算した.Figure 1にMHDの結果を,Figure 2 にkmGMHDの結果をそれぞれ示す. Figure 1より,MHDの等高線は楕円型であり,data cloudに必ずしもきれいにフィットしていないことが分かる.

Fig. 1: Mahalanobis depth

一方でFigure 2から,kmGMHDはカーネル関数のhyper parameterの調整が必要であるものの(カーネル法の宿命),data cloudにうまくフィットする形でdepthの等高線が得られていることが見て取れる.

Fig. 2: Kernel mapped generalized Mahalanobis depth

おわりに

本記事ではkmGMHDをRKHSで計算する方法を具体的に実装した. 複数のtoy datasetで検証し,実装がうまくいったことを確認した.

冒頭に示した論文では計算方法のみならず,統計的depthが備えておくべき望ましい性質を証明つきで検証しており,ユーザーは安心して使うことができる.

統計的depthの世界はなかなかに奥が深く,長年の研究が蓄積された層の厚い分野だと感じている.

余談

RKHS上でprojection depthを計算し,外れ値検知に応用する論文を最近書いた. arxiv.org

bibファイルのコメント開始記号について(Emacs)

bibファイルにコメントを入れる場合, bibtexだと"@Comment"が開始記号として指定されている.Emacsの設定は

(setq bibtex-comment-start "@Comment")

が初期設定となっている.モダンなbiberを使う場合,コメント開始記号は"%"にしたいので,以下を設定に追記した.

(add-hook 'TeX-mode-hook
          #'(lambda ()
              (setq bibtex-comment-start "%") ;backend=biber
              ;; (setq bibtex-comment-start "@Comment") ;backend=bibtex
              ))

非線形適応信号処理への凸解析的アプローチに関する連載記事のリンクまとめ

日本音響学会誌にて,慶應義塾大学の湯川 正裕先生による「非線形適応信号処理への凸解析的アプローチ 」という連載記事がある.

本記事ではそれら記事へのリンクをまとめておく. 2023年5月時点で最終回の記事は「フリー」ではないのですぐには読めないが,6月には「フリー」になるもよう.

関数解析の応用として興味深い.

第一回:凸解析的アプローチへのプロムナード

第二回:凸解析に基づく信号処理への招待

第三回:不動点近似型適応アルゴリズムと応用

第四回:再生核に基づく非線形数理モデル

第五回(最終):非線形適応フィルタと応用:再生核と不動点近似型アルゴリズムの出会い

Kernel k-meansのコードを整理した

Mathieu Blondel氏によるKernel k-meansのPythonコードがあった。

上記のコードはPython 2系で書かれていたので、Python 3系で動くように整理した。

簡単なデモンストレーションを行うnotebookは以下の通り。 当該のコードをkernel_kmeans.pyとして保存して動かしたときのもの。

gist.github.com

拡散モデルの勉強に役立つかもしれないリンク集

拡散モデルに関する備忘録として。

大量に関連リンクを集めてもそれだけで満足してしまいがちなので、この記事では少なめで。

書籍

解説論文

解説記事

解説動画

その他

実装

PyODにコミットしたKernel PCAのコードのバグを修正した

PyODにおけるKernel PCAのコードは最近私がコミットしたものである。

ところで最近、PyODに以下のIssueが上がっていた。

github.com

SUODでインスタンスを複製して使うときに、すべての引数がNoneとして与えられる現象が起きているようだ。 引数がNoneになる状況は想定していなかったが、クラスのattributeを増やしてうまく対応できた。

github.com

PyOD本家にプルリクを送った。

github.com

うまくマージされることを祈る。

AIミュージックバトル!『弁財天』スターターキットのPyTorch版Google Colabノートブックを作った話

はじめに

AIミュージックバトル!『弁財天』が配布しているスターターキットについて、PyTorch版を作成した記事を以前書いたことがあった。

tam5917.hatenablog.com

その記事の段階では、Google Colabのノートブックを用意していなかったので、今回作ってみたということである。

ノートブックの場所

以下のURLに置いてある。

各自のGoogle Driveにコピーして使うのがよいだろう。

colab.research.google.com

動かし方

  1. Google Driveのマイドライブ直下にbenzaitenフォルダを作成
  2. 以下のURLからyamlファイルをダウンロードして、上記benzaitenフォルダに置く https://gist.github.com/tam17aki/3ea977954d9ab7e152bf907c140a22b3
  3. 「ランタイム」→「ランタイムのタイプを変更」から、ハードウェアアクセラレータとして「GPU」を選択(最初はNoneが選択されている)
  4. 「ランタイム」→「すべてのセルを実行」

おわりに

AIミュージックバトル!『弁財天』 の成功を祈る。Let's ad-lib!