DeepLabCutを使う

DeepLabCutは環境構築が結構大変なのがネックだと思います。自分も沼にハマりました。
[Githubレポジトリの説明](https://github.com/DeepLabCut/DeepLabCut/blob/master/docs/installation.md)はかなり充実していますし、日本語の記事も詳しく説明してあるのが見つかります。
ただ、これらだけだと詰まってしまったので、そのポイントをまとめました。

## 誰向けか
- DeepLabCutを使いたい人
- GPUサーバーを持っている人（持っていない人は[Colabを使う記事](https://qiita.com/riichirohira/items/b92723278ba92fb42db9)が参考になります）
- **GPUサーバーが共有のもので、根幹となるnvidia-driverなどを勝手にアップデートできない人**（アップデートできる人はアップデートして本家の説明に従えばすぐ出来ます。）

## 結論
自分の使えるサーバーの環境と、GUI環境があるかによって最適解が変わります
そもそもCUDAもNVIDIA Driverも入っていない場合はこちらの記事のカバー範囲外なので、別の記事を参照してください。すみません。

**CUDA**
CUDAのバージョンは、`nvidia-smi`のコマンドで確認できます。
CUDA10, CUDA9→可能です
CUDA8→不可能です。[Google Colabを使ったやり方](https://qiita.com/riichirohira/items/b92723278ba92fb42db9)に切り替えましょう。

**GUI環境**
CUDA9,10 × GUI環境　→　ラベリングも学習もできます。
CUDA9,10のみ　→　ラベリングと学習は別の環境で行います。

**自分の場合**
自分が使えるGPU環境は2つあり、1つはGUI環境付きだけどCUDA8.0で、もう1つはCLIだけでCUDA9.0でした。
どちらも共有のサーバーで、nvidia-driverのアップデートは出来ない状況でした。
ラベリングはWindowsで行いました。


以下は、CUDA9.0以上であるという前提で話を進めます。


## デスクトップ環境がある場合
[DeepLabCut公式の説明](https://github.com/DeepLabCut/DeepLabCut/blob/master/conda-environments/README.md)に従ってAnacondaを使って環境構築すれば直ぐにできます。簡単。

ただし、デフォルトではCUDA10を持っていることが想定されているので、CUDA9の場合は[設定ファイル](https://github.com/DeepLabCut/DeepLabCut/blob/master/conda-environments/DLC-GPU.yaml
)の書き換えを行う必要があります。
[こちら](https://www.tensorflow.org/install/source?hl=ja#gpu)を見ながらpython・tensorflow-gpu・cudnnのバージョンをCUDAに合わせて選ぶ必要があります。
tensorflow-gpuとcudnnについては、[Anaconda Cloud](https://anaconda.org/anaconda/tensorflow-gpu/files)を見て欲しいバージョンがあるかどうかを確認してください。
Anaconda Cloudで公開されていないパッケージを指定すると、`Resolve Package not found`のエラーが出ます。依存関係とかではなく、単純にその指定されたバージョンが見つからないということです。

CUDA9の場合は、cudnn=7.3.1などにすれば上手くいくと思います。この場合のtensorflowは1.5から1.12の間のものであれば何でもいい気がしています。
pythonは3.6にする必要があります。
最終的に、

```bash:
dependencies:
   - python=3.6
   - tensorflow-gpu==1.12.0
   - cudnn=7
```
としておけば上手く行くはずです。
この編集が終われば後は本家の説明に戻って大丈夫です。記事の続きは無関係です。

## デスクトップ環境がない場合
他の記事でも使われている手法ですが、ラベリングはGUI環境のあるCPUで行って、学習をGPU環境でやるのが一番楽です。（色々と頑張ればSSH先のDeepLabCutをローカルでGUI操作できるのかもしれませんが、自分では無理でした。やり方分かる方いらっしゃったら是非教えて下さいm(_ _)m）
少しめんどくさいですが、適当なCPUでラベリング環境を作り、GPUサーバーに学習環境を作りましょう。

CPUのラベリング環境は、[公式の説明](https://github.com/DeepLabCut/DeepLabCut/blob/master/conda-environments/README.md)に従えば良くて、GPUかCPUかを選ぶ時にCPUをちゃんと選択するだけです。

次に、サーバーの学習環境を作る時は、少し面倒です。
>This base container is mainly useful for server deployment for training networks and video analysis (i.e. you can move this to your server, University Cluster, AWS, etc) as it assumes you have no display.

と[書いてある通り](https://github.com/DeepLabCut/Docker4DeepLabCut2.0)、Dockerコンテナを使うのが良いです。

ここで、必要になってくるのが
- Docker
- nvidia-docker(dockerのバージョンが19.03以降であれば不要です)
です。こちらが入っているかはそれぞれ
`docker version`や`nvidia-docker`と打てばわかります。（なかったら`command not found`になります）
入っていない場合は頑張ってインストールしてください。
これらは絶対に必要になるので、共有サーバーであっても管理者にお願いしていれてもらうしか有りません。
後はレポジトリの説明に従ってコマンドを打っていけばOKです。





## まとめ
- ラベリングと学習を別環境で行うことも許容する
- CUDAのバージョンが大事
がポイントだと思います。

このセットアップにかなりの時間を溶かしてしまいました、、、
皆さんの時間が救われますように。


本家の論文執筆時にはtensorflow-gpu=1.0.0が使われたらしいのですが、Anaconda Cloudの方を見ると公開されていなかったです。

## CUDA8が無理な理由
対応するcudnnがないからです。対応表を見ると、cudnnは5.1か6が必要なのですが、Anaconda Cloudを見ると公開されていません。
ただし、CUDA8.0で使えるcudnn7.1.3があったので、もしかしたらこのバージョンを指定すれば上手くいくかもしれません。
また、CUDA8.0の場合も怪しくて、対応表を見る限りtensorflowは1.4.0までしか動きません。linuxであれば、2020/7現在では1.4.1なら公開されているので、こちらは使えるかもしれません。
tensorflow-gpu == 1.4.1に変更した場合、package conflictのエラーが出ました。恐らくAnacondaの設定ファイルを使って一気に全てをインストールするのは無理なので、とりあえず仮想環境だけ作って、バージョンコンフリクトが起きないものを一個ずつ入れていく必要があると思います。
pipenvやPoetryをうまく使えば依存関係を解決してくれそうでしたが、そこまでは確認していません。
ここまでしてローカルで動かしたいか？ってことなので、Colabを使うのが良いと思います。



## Deeplabcutを使う上で詰まったこと
[こちらの記事](https://qiita.com/Cony-san/items/62df5365878baaa5e275)にあるように、promptを立ち上げる時に管理者権限で行う必要があります。右クリックから選択できます。
そうしないと、Manage ProjectでProjectの作成ができません。
また、DeepLabCutを使っていく上で、

```
deeplabcut.extract_frames(config_path)
```

とする場面が出てきますが、この時に管理者権限で立ち上げていないと、labeled_dataに画像が入っていないという現象が起きます。

また、ここまでしっかりやっていても、なぜかbrowseを押したときに画像が入っていないということがあります。
このとき、見えていないだけで画像はありますので、そのままロードボタンを押せば良いです。



## おまけ
DeepLabCut周りの環境構築したりする中で、デバッグにはまったポイントです。もしかしたら役に立つかも？

#### nvidia-dockerの使い方
これまでは、docker run --runtime=nvidiaで指定するものとばかり思っていたが、
今使っているサーバーでは、nvidia-docker runでコマンドを打てばうまくいく。

#### どうしてもjupyter labのトークンが通らない時
jupyter notebook passwordを使って、パスワードを設定する。そのパスワードを入れても通らない場合は、もう何かがバグっている。