データ分析系研究者のためのgitによるバージョン管理


2014年は研究の再現性ということが非常に話題になった年だったと思います。ソフトウェア開発の世界の技術であるバージョン管理システムが、データ分析のコードの管理と再現性の確保にも非常に便利だと思ったので簡単なまとめです。分析のコードは書くけどバージョン管理になじみがない研究者やwannabe(私とか)を対象にしています。

というわかりやすい記事を参照しながら、データ分析の文脈で解説します。

とりあえずファイル名でバージョン管理

データハンドリングや解析のコードを変更するにあたって、ファイル名に日付などの目印を付けてみたりして区別をしたという経験があると思います。

"サルGit"によるとこんなのですね。
http://www.backlog.jp/git-guide/intro/intro1_1.html

何もしないよりは履歴も残って、変更点が上手くいかなければ、戻れてとりあえず便利です。ただ、x-Final.Rとか名前を付けて、また変更して x-FinalFinal.Rとかなってくるとわけがわからなくなってきます。また、バージョン間で何が変化したのかを調べるのも大変です。また、データ分析の場合はコードに加えて分析結果のファイルをどう管理するかということもでてきます。どれがどのコードに対応しているかをファイル名のみで区別するのは大変です。

ですので、コンピュータ側でファイルのバージョン管理をしてくれれば楽です。もうすでにお使いかもしれない簡易なものとしては、DropBox, SugarSyncなどのクラウドサービス(過去一定変更回数や一定日数の間の変更履歴を保存)やMacだとTimeMachineバックアップシステムがあります。昨日の分析コードに戻りたい、というぐらいの簡単なニーズでしたら、これらでとりあえず何とかなります。ただ、何日前のものに戻るべきなのかは良くわからないし、現在のコードと過去のコードの違いというのは自力で探すことになります。

gitによるバージョン管理とは?

ざっくり言うと前述のDropBoxやTimeMachineによる履歴管理のすごいやつです。過去の状態に戻るのみならず、複数の歴史を分岐させて別々に進めたり、あるいは統合させたり、変更点(差分)を明確に表示したり、と自由自在です。こういったことが出来るソフトウェアはいろいろあるようですが、いまはgit(ギット)というものが一般的になっているようです。

参考: Gitで何ができるの?
http://naichilab.blogspot.jp/2014/01/git-1sourcetreegitgit.html

データ分析におけるコードと分析結果ファイルの管理

データ分析のコードをバージョン管理するのはもちろんですが、私が個人的に便利と思ったのは分析結果をテキストファイルとして出力していっしょにバージョン管理してしまうという方法です。これで分析結果についても前述のようなバージョン管理システムの恩恵にあずかれます。

データ分析におけるバージョン管理の実践

gitの使いやすいフロントエンドを使う

git単体ではコマンドラインのみで敷居が高いですので、SourceTree (https://www.atlassian.com/ja/software/sourcetree/overview )というGUIフロントエンド(無骨なgitにきれいな皮を貼ってとっつきやすくしている)がよさそうです。コマンドラインの方が好きなひとはtigという半GUIフロントエンドが便利なようです。私自身はemacsエディタ使いなので、普段はmagitというフロントエンドを使っています。

参考: SourceTreeのインストール
http://naichilab.blogspot.jp/2014/01/git-2sourcetreegit.html
http://www.backlog.jp/git-guide/intro/intro2_1.html

参考: 初期設定
http://www.backlog.jp/git-guide/intro/intro2_2.html

リポジトリとして管理下に置く

研究プロジェクトごとにフォルダを作って、そのフォルダをSourceTree側でリポジトリとして管理下に置くと履歴管理がはじまります。

参考: リポジトリの作成
http://naichilab.blogspot.jp/2014/01/git-2sourcetreegit.html
http://www.backlog.jp/git-guide/intro/intro2_3.html

分析結果もテキストファイルに保存

結果ファイルもバージョン管理したいので、テキストファイルとして保存します。SASであればバッチ処理すれば勝手に.lstという結果ファイルを作成してくれるはずです。Rではsink()という関数をファイルの最初で設定する必要があります。私は下記のようなテンプレートでxyz.Rファイルをシェルスクリプトとして実行、結果はxyz.R.txtというファイルになる、という風にしています。

Rの分析ファイルをシェルスクリプトにする
https://github.com/kaz-yos/emacs/blob/master/autoinsert/Rscript.R

Rで確実にテキストファイルに結果を落しこむには、コードでprint()を明示しておくのがよいです。結果だけだとなんの分析結果なのかわからなくなることがあるのでcat()で目次を付けておきます。下記みたいな感じです。

cat("回帰分析の結果\n")
print(resultOfRegression)

変更の保存

保存(commit)しないと履歴が残りません。この部分は手動です。ひとつひとつの保存という行為がファイルレベルではなくて、複数のファイルへの関連した変更をまとめて一つのcommitにしてもOKです。また、ひとつのファイルに大幅な変更を行った場合は前半をcommit 1、後半をcommit 2という風にファイルレベル以下の粒度で保存することもできます。こうすれば、後半部分だけもとに戻すといった作業が楽です。

参考: ファイルをコミットしてみよう
http://naichilab.blogspot.jp/2014/01/git-2sourcetreegit.html
参考: 変更を記録するコミット
http://www.backlog.jp/git-guide/intro/intro1_3.html

ちょっとややこしいのですが、

  • 1. 必要なファイルへの変更をおこなう。
  • 2. SourceTreeでひとつの保存(commit)にまとめたい内容を"stage"してまとめる。
  • 3. SourceTreeで実際に"commit"して保存。
  • 4. まだ、保存してない変更点があれば、2をくりかえす。

という手順になります。(2)の"stage"というのがややこしいですが、これのおかげで、複数のファイルから一部のみをcommit 1として保存、ファイル1の残りの変更点をcommit 2として保存、他の残りをcommit 3として保存といった柔軟な保存ができます。やりすぎない程度に細かく保存しておいた方が、やりなおしの効く人生がおくれます。

参考: チュートリアル1 Gitの基本 ファイルをコミットする
http://www.backlog.jp/git-guide/intro/intro2_4.html

過去をふりかえる履歴管理、タグ付け、差分の閲覧

こんな感じで簡潔なメッセージを付けて履歴を保存していきます。Graphが枝分れしているのは後述する"branch"です。

青い四角が付いているのは"tag"というものです。この場合は学会発表に使用した時点のコード/結果に印を付けてあります(ACR = American College of Rheumatology)。論文の提出時などもタグを付けておくと目立って良いでしょう。タグを付けたいcommitを右クリックしてTag...でできます。

また、commitを選択するとそのcommitでの変更点がファイルごとに表示されます。赤が削除され緑が追加になったという形です。ここでは自作のtableone (https://github.com/kaz-yos/tableone )というRパッケージ(CRANにあります)の表示設定を変更したようです。

commitをダブルクリックすれば、そのの時点にすべてのファイルをいったん戻すこともできます。

参考: コミット履歴を見てみよう; ファイルを過去に戻してみよう
http://naichilab.blogspot.jp/2014/01/git-2sourcetreegit.html

過去の変更点を打ち消す

また、このcommitはやっぱりもとに戻したい、という場合は、commitを選択してReverse commit...でできます。過去の変更の履歴は消されずに残り、もとに戻したという新な履歴が追加されて、ファイルがもとに戻ります。過去を消しさるような変更方法も可能ですが、研究のコードではやるべきではないでしょう。

参考: コミットを打ち消す処理
http://sqlazure.jp/r/sourcetree/340/

歴史を分岐させる

大きな変更を行う前には"branch"を作成します。これは歴史を分岐させる方法で、もともとのmasterという名前の履歴にいっさい手を加えずに安全に保ったまま、分岐先で大胆な変更を行えます。過去に書いてわかりにくくなっているデータハンドリングのコードを大幅に手直ししたい、とか、変数の追加で大幅なデータハンドリングの追加が必要、というような場合に便利です。分岐はいくつでも作れるので、変更途中に更に実験的なコード変更を行いたいときなどは二回目の分岐をしても良いしょう。

ここでは、変更したらちゃんと動くか、以前動いていた部分が壊れていないかというのが、重要になってきます。これには解析結果をバージョン管理しておいたのが有用になってきます。変更したデータハンドリングスクリプト後に、もう一回解析をしてみて結果のファイルの差分を確認します。差分が発生しなければ全く同じ結果です。意図した追加部分だけが差分にあらわれれば良いですし、過去の解析部分に差分が発生している場合は間違いがないかチェックが必要です。

変更点がうまくいっていて、こちらを本番コードとして採用したいとなったら、mergeという機能でもともとのmasterという履歴に合流させることができます。ワークフローとしては、大きな変更前にbranchを作成、データハンドリングと解析結果に問題がないことが確認できたらmasterにmergeするというような形になるでしょう。

こちらの例ではrejectされて返ってきた論文(残念!)の解析に査読者から提案のあったpseudo-R^2の解析を追加するときに一回分岐/統合がされています。その後は、2013年度のデータセットが追加になったので取り込みの際に再度分岐しています。見えませんが上の方で再度統合されています。

参考: ブランチを切ってみよう; 別のブランチの変更を取り込む
http://naichilab.blogspot.jp/2014/01/git-3sourcetreegit.html
参考: 変更履歴の統合 変更履歴のマージ
http://www.backlog.jp/git-guide/intro/intro5_1.html

それぞれのbranchには別個に変更を追加していくことができます。この場合は統合するときに一部変更点がかぶって警告がでることがあります。競合の解決については下記。

参考: マージの競合
http://naichilab.blogspot.jp/2014/01/git-4sourcetreegit.html
参考: 変更履歴の統合 競合の解決
http://www.backlog.jp/git-guide/intro/intro5_2.html

遠隔バックアップ、コードの一般公開、あるいは、共同研究者との結果の限定共有

gitと連携できるコード公開サービスとしてgithub (私のアカウント https://github.com/kaz-yos )やbitbucket (https://www.atlassian.com/ja/software/bitbucket/overview )というものがあります。SourceTreeからこれらのサービスに手元のコードと履歴を送りこむ("push"する)ことができます。

参考: チュートリアル2 リポジトリの共有 リモートリポジトリにプッシュする
http://www.backlog.jp/git-guide/intro/intro4_2.html

githubは完全公開であれば無料です。論文掲載と共にコード開示が要求されるような分野では便利と思います。履歴までは公開したくない場合は完成時点のコードを別のフォルダにコピー、まっさらなレポジトリを作成して、すべてを一回でまとめてcommitして、そちらをpushすればよいでしょう。

また、bitbucketというサービスは無料で非公開のレポジトリが作成できます。私は自分のアカウント以外に、研究チーム用にアカウントをもうひとつ作成して、限定共有をしました。解析結果もバージョン管理しているので、前回の解析からの変更点を差分としてハイライト(下記)するなど便利です。とりあえずメールで送るよりは結果のレイアウトがくずれないという地味な利点もありました。

まとめ

データ分析にバージョン管理をどう活用するかという観点からまとめました。gitもSourceTreeも高機能すぎて、使いはじめの敷居が高いですが、とりあえず履歴をのこすだけでもはじめてみるとよいと思います。コード管理の安心感が違ってきます。ちなみに、SourceTreeの使用については"Web制作者のためのGitHubの教科書"という本がわかりやすい印象でした。
http://www.amazon.co.jp/-チームの効率を最大化する共同開発ツール-塩谷-啓/dp/4844337009

ちなみに"Git can facilitate greater reproducibility and increased transparency in science."なる論文がありました。なんでもpublicationにする姿勢、みならいたいものです。
http://www.ncbi.nlm.nih.gov/pubmed/23448176