Kaggle初心者向けgithub Tips 

#プロローグ
データサイエンスをやると、必ず耳にするのがkaggleという、世界中のデータサイエンティストがしのぎを削って予測精度を競うデータサイエンスの競技会コミュニティです。
kaggleは日本でどんどん知られるようになり、参加するためのハードルはどんどん下がってはいるものの、エンジニアのバックグラウンドがないと競争力を高めにくいところがいまだに多くあります。その一つが[github](https://github.com/)(gitのウェブサービスの一つ)です。

この記事を通して、kaggleで競争力を上げるため条件の一つである試行錯誤のサイクル加速をするためのツール、githubの活用に焦点を当てます。githubでできる事、できないこと、とりあえず使えるようにするために最低限必要な前提をかいつまんでご紹介します。ある意味自分の備忘と学びの記録としても作っているため、網羅性と体系だった整理については担保できませんが、自分と同じようにエンジニアのバックグラウンドでない人がkaggleに参加するときに、githubをうまく活用するための助けになればよいと思います。

#なぜkaggleでGithubを使うか、その前提
コンペを進める中で様々な試行錯誤をしながら、常に再現性を担保しなければなりません。そこで重要なのが、計算をさせる為のPython、jupyter notebook、Rなどのコードのバージョン管理です。それを便利に実現してくれるのが[github](https://github.com/)です。

##gitの概要
githubの前に、おおもとのgitの概念についてです。「gitとは」で検索すればいくらでも情報は出ますが、簡単に説明します。gitはlinuxの開発者がチームで開発をするときに、メンバー間でプログラムソースコードのバージョン管理に使用された分散型の管理システムです。githubはそのような管理システムのウェブサービスの一つです。法人向けにはgitlabなどがあります。

##便利なところ
-当たり前ですが、いちいちファイル名を変えるなどせずにバージョン管理がしやすい。
-コードの使いまわしがやりやすくなるので、新たな開発プロジェクトに着手しやすい。
-githubを使うと、いつでもどこでも自分・他人のプログラムコードを参照・共有できる。

##不便なところ
-ちょっとしたコマンドが必要。
-clone, pull, push, branch, fetchなどいろいろ門外漢にはなじめない概念があり、且つそれらが平易な言葉で説明されていない。（エンジニアにはわかるかもしれないが…）
-git, github, gitbucketといろいろあり、ローカルで使用する場合、クラウド上のインスタンスで使用する場合と様々なシチュエーションがあるためまとまった情報源がない。



##githubでよく使う言葉
色々言葉はありますが、私はとりあえず下の3つの重要な概念さえわかればkaggleではなんとかなると思います。あとは必要に応じて調べればいいです。
###clone
言葉の通り、クローンすることで、他人が開発した環境やディレクトリ群をそのまま自分の環境にダウンロードして持ってくることです。
###commit
バージョンを変えたとき、gitに「変更したよ」と宣言するときに使います。commitをしないとバージョン変更が認識されないです。ゲームでいう所の「セーブ」の事です。
###push
githubでは、ローカルで開発し、マスターをウェブ上の「リモート」と言われるところで管理します。変更をcommitによって宣言しただけではリモートでは変更は反映されません。変更したことをリモートに伝える事がpushです。ここで重要なのが、この時にローカルからリモートへのデータ転送が生じることです。転送するファイルサイズが100MBを超えるとエラーになります。また、グラフやログが記録されているjupyter notebookのipynbファイルはサイズが大きいとgithubのウェブページで見る時に重くて何回リフレッシュしても見られないことも発生しうるので要注意です。


##とりあえず使えるようになるには
githubを例に、ローカルの環境をgitで管理できるようにするまでを見てみます。


```
$ mk dir directory_name　#gitで管理したいディレクトリを作る

#github上でレポジトリを新規作成する

$ echo "kaggle_starter" >> README.md　
#空のディレクトリでは認識されないので、
#READMEファイルを作成します。

#後述するが、無駄にファイルを作りたくない時は以下でも可。
#echo -n > .gitkeep

$ git init 
#ディレクトリをgitで認識させる範囲として初期化します。
#ですので、この階層より上の階層ではgitのコマンドは認識範囲外なので反応しません。

$ git add README.md　
#ファイル管理する為には管理対象として追加する必要があります。

$ git add -A 
#管理範囲内全ての管理対象をcommitの対象に追加するときに使用します。

$ git commit -m "first commit" 
#ディレクトリ内の変化を一回セーブすることをgit用語でコミットと言います。
#コメントを付け加えることもできます。

$ git remote add origin https://github.com/[アカウント名]/[レポジトリー名].git 
#ウェブ上のgithubにローカルの変化を反映させます。
#SSH設定していない場合は、このあとgithubのアカウント名とパスワードの入力が求められます。
```

あとは、コードのバージョン変更を反映させたい度に、以下をおまじないのように使えばよいです。

```
$ cd {gitで管理対象になっているディレクトリ}
$ git add -A
$ git commit -m "何かしら変更に関するコメント"
$ git push -u origin master

```

##gitはファイルしか管理してくれない
とりあえずgithubを使ってファイルのバージョン管理をするようになり、使い始めて数カ月でやっとわかったことです。githubは何ができるかはいくらでも情報があったのですが、これは結構初めに言ってほしかったことです。**github(というかgit)ではファイルのない空のディレクトリは管理してくれないのです。**
それまで、フォルダを切ってディレクトリを作成して、ソースコードを配置していたので、特に問題にならなかったのですが、何回かコンペに参加するうちに、共通するフォルダ構造をあらかじめ整理して使いまわせるしようと思いました。
そこでまだソースコードを配置していない、空のフォルダ構成だけがあるディレクトリをpushしようとしていました。結果は変化はなく、更新がリモートつまりgithub上のレポジトリに反映されず、エラーメッセージで調べてもcommitしていないから、addしてないからという当たり前の事しか出てこなかったのです。

このようなときは、「.gitignore」というファイルで、githubで管理したいファイル、管理したくないファイルを定義したものを配置する必要があります。例えば、ファイルサイズが大きく、バージョン管理する必要がない、インプットデータや処理済みデータがあるinputやoutputのフォルダにあるファイルは全て無視し、逆にまだファイルがないがフォルダとして認識させたいものがあるときの.gitignoreのファイルの中身は以下のようになります。

```
/input/*
/output/*
/submission/*
!.gitkeep
```
「!.gitkeep」は「.gitkeep」というファイルは無視しないということですので、「.gitkeep」というファイルを空のフォルダに配置すればgitが認識してくれます。認識させたいフォルダのディレクトリで、`echo -n > .gitkeep`とコマンドを打てばファイルが作成されます。
なお、.gitignoreファイルをコマンドラインで作成するとき以下のようにすればよいです。

```
$ vi .gitignore #viエディダで.gitignoreファイルを開く
##以下はエディダ内での編集##
i #「i」と打って、insert mode　にして編集する
/output/*
/submission/*
!.gitkeep
## 「Esc」+ 「:」 + 「wq」とキーを入力して上書き保存する
```

#最後に
kaggleに参戦するにあたってgithubを使った方がよい理由、良し悪し、そして重要な前提について簡単に紹介しました。
**手軽なバージョン管理による便利なコードの使いまわしで、試行錯誤や開発サイクルを早め、いつでもどこでも、自他ともに活用できるのがgithubの良さです。
他人のリモートにある環境をcloneでそのまま持ってきて、ローカルで開発し、変更をセーブしたいときはcommitした上で、リモートに反映するためにpushします。
また、githubには管理したいディレクトリの中でしか機能せず、ファイルしか認識しないため、空のフォルダは認識しません。そのため、.gitignoreや.gitkeepなどを作成するなど工夫が必要です。**
以上を意識してgithubを使いこなしていきましょう！