病みつきエンジニアブログ

機械学習、iPhoneアプリ、Javascript,Ruby on Railsなどなど。

情報系実験をやりやすくするアイディア

※先に言っておくと、がーーーーーーーーーっとアイデアを書いて、「あ、いけそう」と自己完結するエントリーである。しかし、皆様のアイデアを頂きたく、とりあえず考えながら書いた。

情報系実験の常なのか、それとも僕が悪いのかわからないが、情報系実験はとにかく失敗する。というか、無限に失敗して逐次良くしていけるのが、情報系実験手法の面白いところなのかもしれない。

それはともかく、実験結果がコケるときは2種類コケ方があって、1つは例外が発生するとき。segfaultとか、そういうやつだ。これはコケた場所がわかる、ありがたい実験失敗だ。

こういうときは、gdb(もしくはlldb)を使う。本題ではないのですごく適当に書けば、gdb上で実行して、例外が発生したらスタックトレースを実行し、何行目でコケたのかを特定する。あとはブレークポイントなどを設定して、該当箇所の変数の中身をpコマンドで表示するなり、何度も何度も修正を加えていけば良いだろう。ここらへんは「デバッグの仕方」と言われるもので、「スタックトレース gdb」とか「ブレークポイント gdb」みたいなキーワードで検索すれば、いろいろ出てくる。

もう1つはパラメータの更新が誤っているなど、例外が発生しないパターンだ。こういうときはコケているのに、コケていることが最後までわからない。コケながらも走り続ける。収束するまで結果を表示しないプログラムを書いてしまったら、まだ収束してないのかプログラムがバグっているのかすらわからない。こういうものに対して、どう対処すべきかを考える。

まず、どんなに酷くても、nイテレーションごとに結果を表示するべきだ。特に各イテレーションごとに、別個のファイルとして出力したほうが、あとから追跡しやすい(output-i.csv的な)。そうすれば、とりあえず実験が失敗したことがわかる可能性が高いだろう。

また、「結果の出力」は3種類ほどあると思う。

  • ファイルとして出力イテレーションごとに保存できるなどすれば、あとから追いやすいのが利点。反面、ファイルが多かったり大きかったりすると、いろいろ問題がある。
  • 標準出力に出力:つまり、ターミナルに出力する。特に何も操作しなくても、リアルタイムに結果を表示してくれるのが利点。しかし、出力が整理されてなかったり、わかりにくいことがある。
  • 両方に出力:ファイルに出力しつつ、リアルタイムに標準出力する。何もしなくても結果を見れるし、ファイルであとから追うこともできる。逆に言うと、両方の欠点を引き継ぐ。

とはいえ、結果だけ表示すれば問題がわかるわけではない。問題が発生したかはわかるかもしれないが、一番知りたいのは、どこでコケたのか、もしくは何が原因なのか、だ。

これに対する対処法を言うと、全てのパラメータを表示するのが恐らく真っ当な手段だ。私だけかもしれないが、パラメータの数は、そこまでべらぼうには多くないのではないだろうか。

しかしこれには一つ問題がある。パラメータの種類が少なくても、1つのパラメータが持っている値の数が、大量にある場合がある。巨大な行列や、行列の配列などだ。

ここからは多少抽象的になるが、これを解決するような出力関数は、以下の特性を持っていることになる。

  1. C++であるのが望ましい(人による)
  2. ファイルの出力と、標準出力を、フラグなどで上手く切り替えられる
  3. 関数はファイル名を入力に取る(例:output(x_vector, i, "before-resampling");でx_vector-i-before-resampling.csvファイルが生成される等、便利であるのが望ましい)
  4. 表示する量を指定できる。たとえば、80文字×n行、など
  5. 配列をわかりやすく表示する。たとえば行列の配列であれば、行列を横に並べる、など
  6. 行列をわかりやすく表示するオプションがある。乏しいアイディアだが、0を白、オーバーフローを赤で絵で表示する、など
  7. ターミナル上やブラウザで画像を表示するなど、何もしなくても画像を表示する
  8. ただし標準出力は、RubyJavascriptなどのLLを使って、ファイルが更新されたら表示する、などでも良いだろう

これを全てC++で満たすのは難しいだろう。そこで、8.を使って、スクリプト言語の力を借りれば、以下のようになるような気がした。

以下の機能は、C++であるのが望ましい(人による)

  1. ファイルの出力できる
  2. 関数はファイル名を入力に取る(例:output(x_vector, i, "before-resampling");でx_vector-i-before-resampling.csvファイルが生成される等、便利であるのが望ましい)
  3. 行列の配列などでも、うまく出力される

以下の機能は、RubyJavascriptPythonなど、好きなLLとHTMLで実現する

  1. ファイルの更新を検知して、以下の仕様を満たすような出力をする
  2. 表示する量を指定できる。たとえば、80文字×n行、など
  3. 配列をわかりやすく表示する。たとえば行列の配列であれば、行列を横に並べる、など
  4. 行列をわかりやすく表示するオプションがある。乏しいアイディアだが、0を白、オーバーフローを赤で絵で表示する、など
  5. ターミナル上やブラウザで画像を表示するなど、何もしなくても画像を表示する

これで、多少は現実味が帯びてきただろうか。もっとも、C++の要件は、恐らくマストではないだろうし、行列の配列みたいなものをcsvとして綺麗に出力できるのか、疑問である。

LLの側はどうだろうか。イメージとしては、HTML(と画像?)のジェネレータだ。そして私たちはHTMLで良い感じに出力を確認できるような、レシピを記すことになる。1.は言語に備わっていることがある。2.もLLなら文字列操作は簡単そうだ。3.は行列の配列の配列までだったら、まともに書けそうだ。4.は、言語によって難易度が異なるだろう。5.は、WebSocket的なことか、LiveReloadを組み合わせればよいと思う。

行列や文字列の扱いや、HTMLの出力の楽さを考えて、私だったらRubyで作る(もちろん、自分が慣れているというのも理由の一つだ)。

作れそうなイメージは、湧いてきたかもしれない。アイディアや、知っているライブラリなどがあったら、ぜひ教えていただきたい