計算機科学研究での記録のとり方

[こっち](http://qiita.com/guicho271828/items/9307ae12248329b71f12) のほうが新しい内容です。

実験、スクリプト、結果の管理についてつらつらと。猛者の方たくさんいると思うんで、ほかにもあれば教えてください。

実装プログラムをバージョン管理するのは当然。(なお以下、「バージョン管理」を「git」と略記するので注意)問題は、ある程度実装が完成した場合の、実験スクリプトと結果の管理。実装のアイディア自体は既に十分吟味されているものとする。

追記:実験ノートのページも参照。
http://ja.wikipedia.org/wiki/%E5%AE%9F%E9%A8%93%E3%83%8E%E3%83%BC%E3%83%88

情報系の実験はほぼすべての実験状況を完璧にログできるので、上で述べられている

    網羅性,ログ機能,検索性,可読性,保存性,書きやすさ,状況の可視化,アクセス権の適切な設定

は比較的簡単に得ることができる。残るのは実証性と「ワーキングメモリ」機能。実証性には電子署名を残せば良さそうだから、残された問題は「ワーキングメモリ」、すなわち「なんのための実験か」と「何が得られたか」。

## 一番重要なこと

研究Advisor(教授,上司)と密な連絡を取ること。なにか大きな進歩があり次第skypeでチャット、報告。Advisorである必要はない(友人でも可能)が、さすがに無理だと思う。報告ごとにAdvisorの良い意見やノウハウを引き出せるのはもちろんだが、重要なのは第三者の意見があること。必要な仕事、つまり実験&実装&執筆を同時並行でしていると、そればかりに頭が行ってしまい、一人では大局的な判断をし辛くなる。

## 実験の前に行うこと

自分の現在の分野・現在の実証内容に対して、一つの実験インスタンスが何次元なのか考える。そしてそれを2次元まで落とす。

+ 二次元以上は人間が視覚的に効率的に管理できない。
+ どちらにせよ論文に載せられるのは二次元プロットまで。(やりようはあるけど)
+ コンフィグ,データセット,メモリ制限,時間制限 ...
+ 落とし方:
    1. 別の実験インスタンスとする。(例:一つのインスタンス内ではメモリ・時間は統一。実質的に3次元目)
    2. カテゴリ内を無視する。(例:一つのドメイン内の問題は後に集約するから無視)

+ 実験した時や内容,結果の分析などを普通にファイルにメモし、gitで管理
    + そもそもメモを取り忘れる||めんどう
    + 実験結果がたくさんできるときに管理しきれない、時々メモしたファイルをリセットしたくなる
    + 同時並行の実験の管理が難しい ~~自宅でredmineとかを使うか？~~
    + *
+ 一つの実験は`[スクリプト,実験結果,メモ]`の3-tupleのハズ。これを全部gitに打ち込む
    + リポジトリがウンGBになって困る
    + git logを表示するだけでemacs/magitがフリーズ
+ 実験スクリプトだけgit管理
    + 意味ある「実験セット」だけtarでまとめて保存しておく。バグとかある時もあるので残りは捨てる
        + 注) 一つの実験セット内の不都合なデータを取り除くのはもちろん研究不正(^^;)
        + バグにより全体的に参考にならないデータの時が該当。
            + バグのあるプログラム自体は実装のリポジトリに保存されているので問題ないはず。
                + gitでrewriteとかpush -f とからどうなるかはお察し
    + なんとかやって行けているがはたして効率的/安全か?
    + バグ/incompatble changesがあっても論文に使える結果もある.そのときにもったいない
        + e.g. postprocessing phaseのみにバグがある場合、preprocessingの時間計測は正確だから使えるはず
        + 実験の時間が制限されている時。論文締め切り間近など。**研究のご利用は計画的に!**
        + バージョン違いでログ形式だけ異なるが、出力データの中身自体は正しい場合
    + 結果の履歴がわからない

## 関連の話題とあわせて今の状況

+ 可能なら、Dropboxで開発環境と同期
    + リポジトリ&実験結果のみ,作業フォルダは別
    + できればバックアップを取る。
        + -- 論文出したらとりあえず整理してgithubに上げる。研究室サーバと自宅PC、予備HDDにそれぞれ入れる
+ 実験に様々なバリエーションがあるばあい、それぞれのスクリプトをどう管理するか?
    + ブランチを切ると管理大変、できれば一つのフォルダで
    + なるべく抽象化することでファイル数を少なく、ひと目で見られるようにする
        + 入力データへの繰り返し部分から,ループ個々の設定を切り分けられる
+ それらのスクリプトで共有されるスクリプトの管理
    + 解1:submoduleにする
        + 弱点:実験バリエーションをbranchに分けていると、後に全てrebaseしておかないといけない
            + 現在やってる実験は8コンフィギュレーションある
            + マシな方、多いひとはもっとあるはず
        + 面倒くさいしアップデートし忘れて痛い目をみる
        + 安定していて滅多に更新されないならsubmoduleにしてもいいかもしれない
            + しかし自分で書いているスクリプトなら頻繁に更新するはず
    + 解2:別repoで管理、実験repoからそこへsymlink
        + 新規実験時は常に最新版
        + 実験ログと別repoとの対応は?
            + 実験結果の圧縮、圧縮ファイル命名、転送を自動化するスクリプトを作っておく(共有スクリプト内)
            + ex. `mv <reponame>-<branch>-<hash>-<date/time>.tar.gz ~/Dropbox/path/to/results/`
            + 注:実行イメージのバージョンもログをとっておく
                + あるいは、 `./<binary>` でバージョンを出力させるように作っておき自動生成
                + あるいは、バイナリのmd5ハッシュを記録
                + ssh-keygenみたいにハッシュ値を絵にするスクリプトって無い？？

## 実験

+ 複数のジョブを投げて、その終了時期が前後する場合,いつ何をやっていたか忘れる
    + ジョブAを9/1に投げる
    + 終了するまでのあいだ論文を執筆
    + 執筆中、議論を補強できる実験を思いつく
    + ジョブBを9/2に投げる
    + 9/3にジョブAが上がってくる
        + どのフォルダでなんのためにやった実験だっけ？
        + 生物は基本「鳥頭」、過去に起こったことは全て忘れる可能性がある
+ 実験スクリプトを書く上で、ジョブを投げるときに自動でエディタが開かれて入力できるようにする
    + `git commit` で `-m comment` を忘れると怒られるのと同様。
    + 結果をgitにすべてぶっこむ形式の場合,ジョブ投入と同時にgit commitを呼び出す形式は無理,だから独自スクリプトがいる
        + jobを投げるときにはまだ実験結果を手に入れていない
        + 複数のジョブを同時に投げていて、実験結果が同じディレクトリに帰ってくる場合、むやみにcommitすると混ざってしまう
    + ディレクトリに分けるとまた管理が大変(何がなんのディレクトリだったっけ？)

## 結果の取り扱い

+ 命名規則/フォルダ構成をしっかりするのは当然の鉄則
+ 基本全てのデータをとっておくこと
+ エラーがあったら単体テストをメインのプログラムに追加することを忘れないこと
+ 全実験結果に対して、結果の正しさの検証ができるスクリプトを用意しておくこと
    + 途中のバージョン変更で万が一出力結果がタコになった場合に備える


## 現状メモ

* git-auto-commit-mode でセーブのたびに自動コミット。
* org-mode で進捗管理。
* TODO : 実験スクリプトから 上記の進捗管理を自動で更新するようにする。