Wed Nov 11 2020

非対称行列分解

情報幾何では距離ではなくダイバージェンスが要になることがよくある. というかめちゃくちゃ基礎にそれがある.

大雑把に言えばダイバージェンスというのは, 距離から対称律 \(d(x,y) = d(y,x)\)除いた ものである. 例えば KL ダイバージェンスが有名だが, これは「点 \(x\) から点 \(y\) へのダイバージェンス」というように, 行き先と元を明確にする必要がある. 点 \(y\) から点 \(x\) へのダイバージェンスとは一致しないからである.

なんだかこれが本質のような気がしてならない. ダイバージェンスは局所的には対称律が成り立っていて距離として振る舞う. 勝手に距離のように思っているものは実はダイバージェンスで, それを近似的に距離だと扱ってきたのかもしれない.

点を適当なベクトル表示したときに, 距離をL2距離(内積)で決めてしまうことがとてもよくある. これは距離である. 典型例は行列分解である. 内積とは行列積のことに他ならない. アイテムどうしの距離を内積によって決めてしまう. ここから対称律を取り除くと, それだけで表現力が豊かになる. 損なわれるのではない. できることが多くなるのである. 例えば時系列の情報が込められる. コレの後にはコレが来やすいというのをダイバージェンスで表せる. 因果関係なんかもそうだと思う.

cumin v0.9.0

表現力としては当初欲しかったものが十分手に入ったと思ってる. 機能はまだまだだし, 仮にこれを人が使いだしたら止めるレベルではあるけれど, これをそのまま拡大すればいいだけだと思えるくらいには一通り揃った. というわけでリリースタグを打った. v0.9.0 からこの3つ目の数字をひたすら増やしていって, これ以上できることが無いと思えるようになったら v1.0.0 にするつもり.

設定ファイルという静的なデータを表現するだけの言語のその処理系とはなにか. 私はそれを JSON への変換器ということにした. cumin compiler なので cuminc というコマンド名にした.

基本的な文法については散々書いた. そこからの進捗を語るなら, まずは無名 struct, そして環境変数とブロックを追加した.

無名 struct は要するに中身に何の制約もないただの辞書である.

{{
    x = 1,
    y = {{
        z = 2
    }}
}}
$ cuminc test.cumin
{"x":1,"y":{"z":2}}

環境変数は常に文字列で, $X とか ${X} で参照できる.

{{
    env = {{
        shell = $SHELL
    }}
}}
$ cuminc test.cumin
{"env":{"shell":"zsh"}}

これはシェルスクリプトを意識した書式にしている. 環境変数はその場でセットして cuminc することで, 即席のテンプレートとしても役立つ.

またデフォルト値が使えると便利だと思う. これもシェルスクリプトそのままの書式を流用して ${X:-HOGE} と書けるようにした.

{{
    hoge = ${HOGE:-default}
}}
$ cuminc test.cumin
{"hoge":"default"}

$ HOGE=hello cuminc test.cumin
{"hoge":"hello"}

最後はブロック. これは Rust そのものを知っていれば, あるいは ML から類推してもらえれば特に不自然なことはないと思うけれど,

{} で括って,

{
    文;
    文;
    文;
    式
}

と書いて, この {...} を評価すると何を計算するか. 中の文を順に実行して最後に式を評価する. そしてその値を {...} 全体の評価結果にする. ここで ; は単に文と文, または文と式の区切り文字でしかないことに注意. 文末につける終端文字というわけではない.

cumin で言う文というのは三種類しかなくて,

  1. 構造体 (struct) の定義,
  2. 列挙子 (enum) の定義,
  3. let 束縛

のいずれかである. 構造体, 列挙子, let 束縛で作られる変数はその {} の中だけで参照できて有効である.

例えば,

let x = {
    let a = 1;
    let b = 2;
    a + b  // ここでは a, b が見える
};  // x には a+b の結果が入る

// ここでは a, b は見えない

{{
    three = x
}}
$ cuminc test.cumin
{"three":3}

プライベートな変数を作るのに便利だし, それよりも, このデータはこのデータを構築するために必要だという, 意図表示に役立つ.