luggage baggage

Machine learning, data analysis, web technologies and things around me.

メモ:行列式の補題(matrix determinant lemma)

論文を読んでいて matrix determinant lemma の証明が思い浮かばなかったのでメモ(情けない。。)。

内容としては、適当な次元の単位行列  I と、それと同じ次元のベクトル  u, v に対して
\begin{equation}
\det(I+uv^T) = 1 + v^Tu
\end{equation}が成り立つ、というシンプルなものですが、結論、英語版 wikipedia*1 に1行の証明が書いてあり、次の恒等式に対して単に行列式をとれば終了です。

\begin{equation}
\left(\begin{array}{cc} I & 0 \\ v^T & 1 \\ \end{array} \right) \left(\begin{array}{cc} I+uv^T & u \\ 0 & 1 \\ \end{array} \right) \left(\begin{array}{cc} I & 0 \\ -v^T & 1 \\ \end{array} \right) = \left(\begin{array}{cc} I & u \\ 0 & 1+v^Tu \\ \end{array} \right)
\end{equation}左辺の1つ目と3つ目の行列は三角行列で、対角要素が全て1のため行列式を取ると消えるのですね。

PRML でも式自体は書かれているものの、著者にとっては自明なのか証明が書いてなかったり、そもそも matrix determinant lemma という名称がテクニカルタームだということにも当初気が付かず、調べるのに時間を要したので、こちらで共有しておきます。

なお、PRML 上巻の (C.14) 式は、上の式で  u A,  v B と形式的に置き換えるだけで全く同様に成り立つことが示せます。

Mac のターミナル上で docker コンテナにて作業をすると勝手に折り返されたり表示がおかしくなる現象の対処

Mac で iTerm などを使ってターミナルを開き、(SSH 経由でサーバ上の)docker コンテナをおもむろに立ち上げた際、

  • 設定されているはずの列数よりもかなり少ないところで表示が折り返されてしまい、画面上で長めのコマンドを打つのが難しくなる
  • Python コンソールを立ち上げると、本来表示されるべき行が表示されない一方で入力の受け付けはしているので、適切に作業できない

という現象を度々経験していました。

後者の例としては、こんな感じの表示がされてしまっていました。
f:id:yoshidabenjiro:20181113222913p:plain
見ると分かる通り、本来は表示されるはずの行番号や入力済みの文字が見えていません(キャプチャが適当になってしまいましたが、NameError の後には何の行も出力されていない状態です)。一方で入力自体はされており、困惑します。

とは言うものの対処は簡単にできて、画面を一度全画面化してから全画面化を解除する、もしくはその逆、と操作するだけで解消します。
f:id:yoshidabenjiro:20181113223210p:plain
これは上の画像の状態から、全画面化解除 → 通常サイズ → 再度全画面化、としたものですが、次の行を表す [2] がちゃんと表示されていますね。

TensorFlow Probability で VAE (Variational AutoEncoder): TFP 入門所感、tfp.distributions の初歩

最近になり、TensorFlow の肩に乗って確率的プログラミングをするためのライブラリ TensorFlow Probability (TFP) v0.5 がリリースされました。私は画像系タスクを TensorFlow を使って解くことが多く、特にこの記事では、画像生成系タスクに取り組むためのツールとして TFP を実際に使った際に学んだ内容について記録しておきます。

TFP に入門してみた所感

今のところのざっくりとした感触は、総じてデータサイエンティスト/アナリストではなく機械学習エンジニア向けの確率的プログラミング言語だなという感じです(ある意味当然ですが)。いくつか項目を挙げると、

  1. eight schools 的な、いわゆる確率モデリングをするのであれば、もっとこなれた他のライブラリを使ったほうが良さそう
  2. VAE (Variational AutoEncoder: 変分オートエンコーダ), Flow-based generative models などニューラルネットの構築が必要となる確率モデルを実装する上では強力なツール
  3. GPU/TPU による高速化の恩恵を受けられる点も Good(私は未検証なので論文ベースの知見)

と思いました。

1番目についていうと、やはり TensorFlow 特有のやりづらさは引き継いでいるところがあります(下の方の「ありがちなミス」欄に書きます)。個人的には2番めの項目が TFP を使う主な動機になります。Pyro という PyTorch ベースの類似ライブラリもありますが、私は TensorFlow ユーザなのでいったん放置です。3番めについては、Google Brain より論文*1が出ており、

With NUTS, we see a 100x speedup on GPUs over Stan and 37x over PyMC3

ということなので、使い方によっては速度面で大きな恩恵を得られる可能性がありそうです。

この記事では、上の2番めの項目に挙げた「ニューラルネット+確率プログラミング」をやる良い事例として、公式に提供されている VAE (Variational AutoEncoder) のサンプルコードを理解できるように、確率分布の作り方・使い方を中心として TFP の基本事項を簡単にまとめます*2。特に重要だと思った batch_shapeevent_shape はある程度厚めに解説したつもりです。VAE の実装や実際に動かした結果は次の記事に集約したいと思います。

(2018.11.14 WIP ですがいったん公開。)

続きを読む

多変数クラメル・ラオの不等式の証明(フィッシャー情報量の意味づけの一つ)

統計学の分野で、クラメル・ラオ (Cramer-Rao) の不等式と呼ばれる有名な式があります:
\begin{equation}
V(t(z)) \geq \frac{1}{I(\theta)}.
\end{equation}ここで  z は確率変数で、一つのパラメータ  \theta で指定される確率分布  f_{\theta}(z) に従って生成されると仮定します。 t(z) は不偏推定量、 V(t(z)) はやはり確率変数である  t の分散、そして  I(\theta) はフィッシャー情報量です。不偏推定量とは、その期待値が  \theta に一致する、つまり「偏りのない」推定量のことです。最後にフィッシャー情報量とは  I \equiv -E[\partial_{\theta}^2f_{\theta}] で定義されるある種の「推定の良さ」を示すような量です( E は期待値を取る演算)。

クラメル・ラオの不等式によれば、不偏推定量の分散には下限が存在し、それがフィッシャー情報量の逆数に一致します。 I(\theta)が大きければ大きいほど不偏推定量の分散は小さくしうる、つまり期待値まわりでより狭い範囲での(=良い)推定ができるようになる、ということですね。

ところで、ここで書いた式は確率分布関数のパラメータが1次元の場合です。これが多次元になった場合でも同様の式がもちろん成立するのですが、その証明が意外と手元にある本に書いてなかったので、簡単に証明を残しておこうかと思います。

続きを読む

julialang でカルマンフィルタを書く

最近カルマンフィルタの勉強を少ししており、行列を含む数式を素直にプログラムできる言語があるといいなと感じていました。Python を長年書いてきたものの、毎回 numpy.array を用意したり numpy 関数を呼んだりするのが少し面倒になってきました。

そこで今回は、scientific computation に強みがあると言われ、最近 v1.0 の出た Julia 言語(julialang)を使って簡単なカルマンフィルタを実装してみたいと思います。julialang は数日前に使い始めたばかりなので、パフォーマンス最適化などは考えずにやっていきます。

続きを読む

multiprocessing で tfrecord 作成を高速化する話

お久しぶりです。

TensorFlow でモデル学習をする際、便利に使われるのがtf.dataAPI です。以前はtf.contribで提供されていましたが、非常に使い勝手の良い機能だったこともあり、現在は独立したモジュールとして存在しています。様々な形式のデータ入力に対応している中でも、公式に推奨されているのは
.tfrecordというバイナリ形式のデータを読み取るtf.data.TFRecordDatasetだと思います(むかしの Caffe でいう LMDB みたいなやつ)。

私はいま画像認識系の仕事をしているのですが、先日扱った画像は百数十万枚ほどあり、一枚一枚も10数MBと小さくはなかったため、単純に tfrecord を作成すると30時間以上もかかる状態でした。この記事では、その時に使った非常に雑な高速化手法をご紹介していきます。CPU 数が稼げる環境であれば、10倍速とかは十分に達成できる感じでした。

続きを読む

Python 機械学習コードを Cython でラップして C/C++ から使う

お久しぶりです。吉田弁二郎です。

Cython という便利なトランスパイラ(言語と言語の中間にある言語のようなもの)があります。Python ライクな文法で書ける Cython スクリプトは C/C++ コードに変換・コンパイルされた後に Python から呼び出し可能で、C/C++ ライブラリを Cython スクリプトから呼び出すことも難しくないので、Python ライブラリの高速化作業を効率良くおこなうためによく使われています。

著名なプロジェクトで言うと scikit-learn や pandas だったり、最近利用が広がり始めた cupy などで Cython が使われています。scikit-learn の例で言うと、例えばツリー系のアルゴリズムを実装したこのスクリプトは Cython によるものですね。

また逆の方向として、Python で書いたライブラリを C/C++ コードから手軽に呼び出したい、という時にも Cython を使うことができます。双方向のラッパーとして機能するのですね。今回の記事では、この方向で Cython を使うための簡単な例を紹介していきます。Cython の文法については詳しくは書かないので、ドキュメントもしくはデモコードなどを見ていただけるとよいと思います。

続きを読む