2013年3月20日水曜日

論文を書こう・自動化のススメ

先週、諸般の事情によって実に3年ぶり(!)に論文を投稿しました。いろいろと時代は変わったわけで、やや出遅れ感はありますが時代にあわせた執筆スタイルにしようとしていろいろ試行錯誤してみました。普段バリバリ論文書いている方々にはむしろ時代遅れの内容のような気がしますが、未来の自分のためにも結果をまとめておきたいと思います。

自動化は正義

自動化できることはなんでも自動化することで、未来の自分を救います。「どうせ一度しかやらないし」と思っているあなた、本当に一度ですむと思っていますか? LaTexのコンパイルは論文提出までに何百回実行しますか? その評価のパラメータ、本当に正しいですか? 実験データは何回更新されますか? むしろ、今まで一度で済んだことがあるんですか? (ということで、一度ですんだことがある人にこの記事は不要です)

自動化のメリットは主に2つだと思っています。1つ目は言わずもがなですが、人間の作業を省力化できること。これは単純に作業時間を短縮できるというだけでなく、いちいち気持ちの切替をしなくていいというメリットがあります。論文執筆では思いの外いろいろな作業をしなければならないので、なるべく大切な作業に集中できるように、機械ができる仕事は機械にやらせるのがよいです。2つ目は各種作業の再現性が高いことです。論文投稿した結果、めでたく(?)条件付き採録で返って来ました。でも評価が足りないからもう少しデータを足してね、という査読者からの指摘があったとき、「あれ、この評価ってどういう手順でやったっけ?」という記憶喪失事件は枚挙に暇がありません。その結果、同じデータを使っているはずなのになんか結果が微妙に違うのはなぜなんだぜ…、と悩んで時間を無為に消費してしまうこともあるあるだと思います(僕だけ?)。

もちろん自動化するということは、それだけ初期投資が高くつくというのは間違いなく、かつ忙しい時にそんなことをしている暇など無い!という考えも、もっともだと思います。ただ、忙しくなるほど手間を省き手順通りに作業を実行してくれる自動化の恩恵が大きくなるのも事実です。最終的には個人のバランス感覚だと思いますが、個人的には今後も積極的に自動化していきたいと思っております。

LaTexからPDFの作成

自作のautobuildというツールを使いました。指定したファイルの更新を検知して、特定のコマンドを走らせるOMakeなどのツールと同じ発想ですが、極力シンプルに動作するものが欲しかったので、ちょろっと作りました。nodejsで動く60行ほどのしょっぼいコードです。(oremakeというツールを参考にさせてもらいました)これを使って*.texや*.epsファイルを指定し、変更があったらplatexなどを自動的に走らせることが可能です。私はMakefileにコマンドをまとめていたので、設定ファイル(build.js)はこんな感じ。同一ディレクトリの*.texファイルとfigsディレクトリの*.epsファイルを指定しています。

{"build_command": "make",
  "build_args":  [],
  "file_list": {".": [".*\\.tex"], 
                "figs": [".*\\.eps"]}
}

執筆はMac上でやっていたので、PDF viewerにはSkimを使っていました。Skimはファイルの変更を検知してファイルの再読み込みをしてくれるので、継続的に自動ビルドされれば勝手に表示を更新してくれます。今まで「ファイル保存 → ターミナルに移動 → makeコマンド実行 → 完了後にPDF viewerを一度閉じる → PDF viewerを再度開く」みたいな行程が必要だったのが、ふと横を見ると常に最新版のPDFが見れるようになります。

テストの実行

皆大好きJenkinsさんの登場です。今回は実装の一部をC++で書いていたので、コンパイルは先程のautobuildというツールを使っていましたが、デバッグ作業をしている時は変更とコンパイルを繰り返さなければならないので、その度にテストが走るというのは少々、いやかなり鬱陶しいわけです。というわけで、今回はJenkins(またのなを高機能crontab)を利用して定期的にテストを実行するようにしました。これはこれでテスト結果がおかしいままだと、際限なく「早く直せよー、おらー」と言うメッセージが出続けるので別の鬱陶しさがありますが、ToDoをせっつかれるという意味では良いのかもしれません。

設定は5分毎にコンパイル実行&テストコード実行で、終了後にPost build taskでスクリプトを実行させました。実行時にテスト結果などのステータスを直接環境変数で渡せないのがちょっと面倒でしたが、HTTPでJenkinsをたたけば結果を返してくれるのでお手軽です。こんな感じのスクリプトを用意して実行していました。テストに失敗するとGrowlが失敗メッセージを表示し、マリオが死んだ時のSEが流れます。(本当はGrowl pluginとJenkins sound pluginで実行すればいいだけなんですが、なんかうまく行かなかったので)


評価の実行

普通、評価は条件をそろえてやるものなので、継続的に結果を出力し続ける必要はないと思うのですが、手順をまとめて実行できるようにしておくことは必要だと考えられます。あくまで個人的な経験ですが、ソフトウェア(あるいはPoCコード的なプロトタイプ)を実装して、その出力をそのまま評価結果として使えるというケースは稀だと思います。だいたいは10段階ぐらいのone liner shell scriptをかませたり、適当なスクリプトを書いたりして結果を正規化、集計することが多いと思います。しかし、往々にして後からどういうone linerを実行したかわからなくなったり、断片的なコードが散乱したりという自体に陥ります(僕だけかもしれませんが)したがって、テストの実行とデータの加工までを一気通貫で実行できるというのがとても便利でオススメです。

特にこれといったツールやフレームワークがあるわけではないですが、データの加工まで一気にやることを考えると、Shell scriptで頑張るのはちょっとしんどい事が多いので、少なくとも一部はPythonやRubyなどお手軽にデータ集計ができるLLを導入するのがよいかと思いますが、そこは個人の趣味で。

グラフの作成

いくつかグラフ作成ツールを試してみましたが、結局某先輩に教えてもらったmatplotlibに落ち着きました。最大のポイントは自分がPythonでデータ加工など大まかな処理はPythonにべったりだったので、習得が容易である&データをそのまま流し込めるという2つのメリットがありました。ggplot2とかも検討したのですが某氏の「ggplot23日経つと使い方忘れるあたりで挫折した」という発言に胸を打たれて諦めました。

評価とグラフ作成は別々のスクリプトでまとめていましたが、Makefileで連続実行できるようにしておくと、make testとか打ち込むだけで、

  1. 自分の実装と関連研究の実装を順次実行
  2. 実行結果の集計
  3. グラフ作成 + epsに出力
  4. epsの変更を検知してPDFを再出力
  5. 最新のPDFを表示

までをフルオートでやってくれるようになります。

さいごに

まとめてみたものの、改めて見返してみるとほとんど当たり前のことばかりでしたが、これで救われる学生さんとかが1人でもいれば嬉しいです。あと「なんという時代遅れ。今時こっちのツールだろうJK」みたいなツッコミがあればぜひこっそり教えてください。