tkm2261's blog

研究員(OR屋) → データ分析官 → MLエンジニア → ニート → 米国CS PhDが諸々書いてます

KagglerのためのGit入門

お久しぶりです。絶賛ニートを楽しんでるtkm2261です。

今日はTwitterで意見が諸々散見されたので、私のKaggleでのgit活用法を共有しようと思います。

Gitの独学はハードルが高いですよね。。。

gitの運用は開発プロセスと密接なのであまり外に出てこなかったり、
実際に自分でやらないと覚えない系なので独学は結構難しいと思ってます。
(同じ理由で、テストコード系も広まらなかったり)

私も学生時代はSVNに馴染めなくて、業務でプロダクト開発して初めてバージョン管理が身についたタイプです。
最初はSourceTreeで慣れ親しんで、gitコマンドという流れを辿りました。いきなりGitコマンドのハードルの高さは理解してるつもりです。

www.sourcetreeapp.com

とはいえ、慣れるとこんなに便利なものはないので、出来る限り平易に語りたいと思います。

Kaggle利用特化(一人開発用)の最低限な要素を詰めましたので参考になれば幸いです。

変なとこあればTwitterまで

KaggleでのGitの有用性

個人的には複数環境で並行でタスクをこなすので、無いとやってられないです。

AWSのスポットインスタンスGCPマシン($300クーポンで確保)、自宅マシンの3マシンは大体いつも管理してます。

ある環境で上手く行ったものを、うまく行った箇所だけ全体に共有するのはGitが最適です。

勿論ですが作業ログが残るので結果の再現性に絶大な威力を発揮します。

フォルダ管理との長所短所

もう一つの有力な選択肢として、作業フォルダ丸ごとS3とかに定期的に上げてしまう方法が有力かと思います。

結論からいうと、たまにフォルダをs3に保存、普段はGitが最強かと思います。

長所

  • 作業が楽
  • ある地点に戻るのが楽
  • データも一緒に保存するので、再現性が高い

短所

  • サイズが大きいと時間がかかる
  • 結局しっちゃかめっちゃかになる
  • 別環境との同期がしづらい。
  • 差分管理がしづらい

Git入門したてだと『Gitで全部やるぞー』と気負いがちですが、組み合わせて一番楽な方法を取りましょう。

とりあえずこれだけ覚えておけばOK

GitやGithubは複数人開発するために様々な機能がありますが、Kaggle用に作業ログと再現性のためなら至ってシンプルに使えます。

  • 1: git add (gitにファイルを追加)
    • git add *.py *.R
    • git add -u
  • 2: git status (現在の状態確認)
  • 3: git commit -m “なにかコメント” (addしたファイルの変更確定)
  • 4: git push origin master (commitをアップロード)
  • 5: git pull (リモートの変更を手元に反映)
  • 6: git checkout (ブランチ切替、ファイル変更取消)
    • git checkout ファイル名
    • git checkout ブランチ名orハッシュ値
    • git checkout --ours ファイル名
  • 7: git reset --hard (変更全取消)

これだけで問題ないでしょう。応用編でstashとbranchは触れますが使わなくてもいけます。

各コマンドの詳細は後述

Git初心者最大の問題: どうやってある時点に戻るの?

ここでgit revert使いたい方もいるかもしれませんが、revertは色々面倒なことになるので止めましょう。

筆者推奨の戻し方は超原始的に、戻したいファイルに上書くだけです。

  • 別のフォルダに、新たにクローン
  • git checkout ハッシュ値 で戻したいところのコミットに戻る
  • このフォルダから戻したいファイルを、元のフォルダにコピー

あとはコミットコメントに戻した旨を書いておけば十分でしょう

Git初心者の気になりポイント

  • Q: プルリクとか言うもの使った方が良いんじゃないの?
    • A: 必要ありません。あれは複数人開発用&公開済みサービス用なのでKaggleでは使いません。業務でも公開前の最初期はプルリクでなくmaster pushでやる事も多いです。
  • Q: コンフリクト怖い
    • A: git checkout --ours ファイル名 を覚えるだけで大丈夫です。(後述)
  • Q: ブランチってやつ切るんでしょ?
    • A: 必要ありません。実験的なコードを残す方法として応用編で触れますが、実験的なコードはファイル名別にしてmaster pushで良いかと
  • Q: master push怖い
    • A: 自分しか使わないので存分に壊しましょう。最悪リポジトリ作り直せばいいですし
  • Q: いまどういう状態かわからなくなった
    • A: git statusでみれます。ただ初心者にはわかりづらいので慣れるまではSorceTreeを使いましょう

.gitignoreの運用

Git初心者ありがちなミスとして、巨大ファイルをgitに入れてしまうミスがあります。

これやると巨大ファイルの差分管理してしまい、元のファイル以上にgitを圧迫して、フォルダ管理より取り回しが悪いものになってしまいます

間違って入れたら、git rm --cached ファイル名 で消すしか無いですが、その前に.gitignoreを書いて未然に防ぎましょう。

data/
input/
*.csv
*.gz
*.pkl
*~
*.swp

Kagglerなら公式カーネル準拠でinput/以下にデータを入れることが多いと思いますので指定しておくと安全です。
あと私は加工データをdata/以下によく入れてるので追加してあります。

各コマンド詳細

あとは補足内容なので、分からない箇所だけ参考にしてください。

1. git add (gitにファイルを追加)

ファイルをgit管理以下に追加するコマンドです。

  • git add *.py *.R (PythonとかRのコードを追加)
  • git add -u (変更のあった管理下に入ってるファイルを追加)

これで十分かと思います。git add -Aとかは.gitignoreがしっかり指定してあればOKですが、巨大ファイルを入れる危険性があるので微妙です。

2. git status (現在の状態確認)

いまのGitの状態を確認するコマンド。全部addが終わった後や、コミット前には必ず見る習慣を付けましょう。

3. git commit -m “なにかコメント” (addしたファイルの変更確定)

コメントをつけてaddしたファイルの変更を確定します。

コメントは適当でよいですが、作業が思い出せるレベルではあったほうが良いです。

Kagglerの場合は作業でわけられない時があると思うので、日付だけとかでも良いです

理想的には毎submit後にはcommitしてLBスコアとかをコメントに入れておくと良いです

4. git push origin master (commitをアップロード)

リモートにcommit内容をアップロードします。他環境から先にpushがあるとrejectされますが、その時は先にpullします。

Kaggleの場合はアップロードためらう要素はないので、commitしたらpushする癖を付けましょう。

5. git pull (リモートの変更を手元に反映)

リモート内容を手元に反映します。ブランチを指定した方が丁寧ですが、Kaggle用途なら省略可です。

他環境で先にpushがあると失敗します。手元の変更と被らなければpullするだけで解決しますが、失敗する場合は下記で対処。

  • リモートのファイルを正としたい場合 ・・・ git checkout ファイル名 で戻してpullしましょう。手元の変更が全て要らないならgit reset --hard
  • 手元のファイルを正としたい場合 ・・・ 手元ファイルを何処かにコピーして、↑でリモートのファイルを正とした後、コピーで戻しましょう
  • 両方の変更を保持したい場合 ・・・ 対象ファイルをcommitしてpullしましょう。コンフリクトが起きる可能性がありますがgit checkout --ours ファイル名 を使いましょう。(後述)

6. git checkout (ブランチ切替、ファイル変更取消)

checkoutの用途としては、ブランチの切り替えとファイルの変更を取り消すの2つがありますが、

ここではブランチは使わないので、ファイルの変更を前のcommitに戻すコマンドとしてgit checkout ファイル名 を覚えておきましょう。

これは消してしまったファイルにも有効で、ミスってrmしてしまったらcheckoutでザオリクしましょう。

git checkout --ours ファイル名

度々登場しました、コンフリクトを解消するコマンドです。

勿論分かる人はファイルを直接編集してコンフリクト解消しても良いですが、Kagglerは手元のファイルを正としたい場合がほとんどと思います。

『--ours』の通り、手元環境を正としてコンフリクトを解決してくれます。一応、リモートを正とするgit checkout --theirsもあります。

7. git reset --hard (変更全取消)

通称バルスコマンド。手元の変更を全て破棄して直前commitの状態に戻します。

git管理下のファイルだけなので、作ったデータファイルとかは消えません。

応用編

git diff (ファイル差分確認)

前のcommitとの変更差分が見れます。ファイル名を指定するとそのファイルのdiffだけ見れます。

学習実行前のチェックに流すと良いです。

git rm --cached ファイル名 (git管理から除外)

ファイルをGit管理下から外します。--cachedが無いとファイル自体も消えるので注意

git log (コミット履歴確認)

コミット履歴を見れます。checkoutであるcommitに戻るときのハッシュ値を調べるのに重宝します。

git branch ブランチ名 (ブランチ作成)

ブランチを作ります。Kaggleではブランチで残したいケースは少ないと思いますが、Gitのメイン機能なので覚えて起きましょう。

作ったあとcheckoutで切り替えるのを忘れずに。

用途としては、

  • 実験的なコード書いて、ファイル別にするのも面倒だからブランチとして残す
  • configファイルを別にして、CPU用、並列実行用、GPU用に分ける

とか考えられます。

特に後者はdevelopブランチの変更をmaster, parallel, gpuブランチに適用みたいな、
hotfixをmasterとreleaseに適用する的な業務レベルのgit使いが要求されるのでKaggleではそこまでやらないかと

そこまで出来るgit使いはご自由どうぞ

git stash (手元変更の一時保存)

手元の変更を一時保存して、git stash popで元に戻せるコマンドです。

変更がかぶると、git stash popで戻せなくなることがあるので、これを使うならbranchを切りましょう

変更前のコードを見たいならgthubかBitbucketをブラウザから見ましょう

トラブルシューティング

何かあれば随時増やします

間違ってaddしてしまった

git reset --sorf HEAD ファイル名で外せます。

ただ新ファイルとかの場合は少し違うので、git statusすると外し方書いてあるので読みましょう。

間違ってcommitしてしまった。

git reset –soft HEAD^ で戻ります。

ファイルのadd忘れや、コメント直したいだけの場合はgit commit –amendで変更できます。

ただし、これはPush前の話なのでPushしちゃったら諦めて、直したコミットを更に上げましょう

commitログがちょっと汚くなるレベルなのでKaggleでは気にする事ないです。

gitってどのサービス使えば良いの?

サービス使わずに自分でホストしても良いですが。スポットインスタンスから見れるように

githubやBitbucketを使う方が良いでしょう。

特にBitbucketはプライベートリポジトリが無限に持てるのと、SourceTree連携があるので初心者にはBitbucketをオススメします

bitbucket.org

結局お前はどう使ってるの?

大した事はしてません。よくやるのは特徴量作成と学習は別のマシンでやって、上手くいったら各自pushで気が向いたらpullみたいな感じです。

ファイルがそもそも違うので、ほとんどコンフリクトも起こらないので単純です。

パラメタサーチの時は同じファイルいじりますが、変更が大きければcommitしてmergeしますが、コピペで片方に持ってって片方はgit resetで破棄とか普通にやります。

私は業務で慣れることが出来たので大体対処出来ますが、『何か起きたら。。。』といった不安がgit導入の最大障壁ですよね。。。