完全無知からHDDにubuntu入れてyolov3する話

#はじめに
LINUXってそもそも何？ってレベルなのにオブジェクト検出をやることになりました。
数か月レベルで苦しんだので道を残しておきます。

CUIとかlinuxとか触らんわ、って人向けです。
私自身ほとんどわかっていないので、間違いや冗長な部分もありますがそこは雰囲気で。

##環境
GPU:RTX2060
(windows10 pro)

windowsとubuntu両方ストレスフリーに使いたいのでHDDを二つ用意して構築しました。

#構築
##ubuntuインストール
###必要なもの
・HDD
・4GB以上のUSBメモリ
HDDもUSBも再利用はできますが、**中身は消し飛ぶ**ので使っていないものを用意してください。

###ubuntuのインストールメディア作成

[こちら](https://www.ubuntulinux.jp/download/ja-remix)から`Ubuntu 18.04`のisoをダウンロードします。
新しいものは情報が少ないので情弱は18.04です。
20.04を入れると初心者は悲惨な目に遭います。
これをUSBメモリにぶち込めばいいわけです。

そしてぶち込むためのソフトがいるのでそちらも用意します。
私は[Universal USB Installer](https://universal-usb-installer.jp.uptodown.com/windows)を使いました。
こちらを使う場合は、書き込み先はもちろんUSBメモリを選択してください。

ubuntu用のHDDは挿しましたか？挿したら次です。

###ubuntuの起動
先ほどのUSBメモリからubuntuを起動します。
SHIFTを押しながらwindowsを再起動するか、起動中にブートメニューを開いてUSBメモリっぽいやつを選びます。
ブートメニューの開き方は、PCの起動中にチラッと出てくるF8とかF11とか書いてる謎の文章に書いてあります。あの瞬間に対応するキーを押します。
これはメーカーによって異なるので各自調べてください。
私はF11で開きました。

起動するとよくわからないメニューが出てくるので、`ubuntu without install`と書いてあるやつでubuntuを起動します。

ここでubuntuが起動します。
あとはデスクトップにあるインストールを起動するだけです。
インストール先を聞かれますが、空のHDDを選択します。
**決してwindowsが入ってるHDDを選択しないでください。データがすべて死にます。**

途中で
「ubuntu 20.04 LTS っていう新しいubuntuあるよ！」
と言われることがありますが無視してください。

最後まで終わったらUSBメモリは取り出してよいです。

###ドライブの起動順位の変更(HDD２本差しの人向け)
このままだと、ubuntuを起動しようとする度にF11連打大会が始まります。
そこで、BIOSというwindowsやらubuntuやらを起動してくれる子に、ubuntuを優先的に起動してもらうようにします。

先ほどブートメニューを開いた時のように、今度は起動画面でF2とかDeleteキーとかを押します。これまたメーカーによりますが、私はDeleteでした。

これでBIOSの画面が開いたと思います。
OSの設定やらが転がってますが、`Boot Device Priority`もしくはそれに近い名前を探してください。
探し当てたらubuntuが入っているHDDの起動順を1番にします。
ほとんどは元々刺さってたHDDが若い数字のHDDです。

ubuntuは 何を起動するか聞いてくれる良い子なので、これで快適に起動するようになりました。

##基礎構築
###初動
左下にソフト一覧があるのでターミナル(端末)を開きます。
なんかプログラマーっぽい黒いアレです。
見当たらなくとも一覧のどこかにあるので探します。

開いたら以下を入力します。
＄マークは入力する行の目印です。コレを除いた部分を入力します。

```
$ sudo apt update
$ sudo apt upgrade
```

`sudo`はroot権限を使う子です(Super-User/Substitute-User DO:ルート権限で実行)。「権限/許可がない」とか「rootで実行しろ」とか言われたらコレを冒頭に入れたら大抵解決します。
`apt`はパッケージ管理コマンド(Advanced Packaging Tool)です。
何か変更を加えたら`update`と`upgrade`をしておきます。新しいほうがいいですもんね。

長文の場合は、冒頭を少し入力してTABキーを押すとある程度補完してくれるので活用しましょう。

ちなみに`sudo`が面倒だと思ったらルートにログインすることで解決します。

```
$ sudo su -

//ルートからログアウトするときはexitを使う
$ exit
```

`CTRL+V`が使えないぞ！という方は`CTRL+SHIFT+V`で幸せになれます。

今後うまく行かなかったら`update`と`sudo`を真っ先に試してください。
割と解決します。

###NVIDIAドライバーを入れる
GPUを動かす子です。
https://qiita.com/kawazu191128/items/8a46308be6949f5bda57 を参考にしました。

まずはオススメのドライバーを教えてもらいましょう。
※ドライバー：制御ソフト

```
$ ubuntu-drivers devices
```

これでrecommendされたドライバーをインストールします。
私はnvidia-driver-455でした。

```
$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt update
$ sudo apt install nvidia-driver-455
```

これでドライバーは入りましたので再起動します。

```
$ sudo reboot
```

再起動後にGPUを認識していることを確認したら完了です。

```
$ nvidia-smi
```

smi = System Management Interface
私の場合はRTX2060という文字が出てきました。

###OpenCVのインストール
計算に必要な子です。
下記事の丸パクリ
https://qiita.com/usk81/items/98e54e2463e9d8a11415

まずリポジトリを追加しておきます。

```
$ sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu bionic-security main"
```

次は依存ライブラリをバシバシ入れていきます。

```
$ sudo apt -y install build-essential checkinstall cmake unzip pkg-config yasm
$ sudo apt -y install git gfortran python3-dev
$ sudo apt -y install libjpeg-dev libpng-dev libtiff-dev libtbb-dev
$ sudo apt -y install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libatlas-base-dev libxvidcore-dev libx264-dev libgtk-3-dev
```

やっとOpenCVを入れていきます。

```
$ cd /usr/local/src
$ sudo git clone https://github.com/opencv/opencv.git
$ sudo git clone https://github.com/opencv/opencv_contrib.git
$ cd opencv_contrib
$ sudo git checkout -b 3.4.3 refs/tags/3.4.3
$ cd ../opencv/
$ sudo git checkout -b 3.4.3 refs/tags/3.4.3
```
`cd`は現在位置(ディレクトリ)を移動するコマンド(Change Directory)です。
`cd 行先` で移動できますし `cd ../`のように点を2つで一階層戻れます。
`cd ~/`で最初にいた場所に戻っても来れます。

`git`はコードのバージョン管理用のツールです。大抵はgithubからなんやかんやするコマンドです。
何かインストールしろと言われたら素直に従ってください。

次はダウンロードしてきたOpenCVを使えるようにします。

```
$ sudo mkdir build
$ cd build
```

`mkdir`はMaKe DIRectory、つまりディレクトリを作ります。
ちなみにディレクトリ≒フォルダです。
この記事を見ているレベルなら違いは全く気にせず構いません。

buildに移動したら使えるようにしていきます。
めちゃくちゃ時間かかるのでビビらないように。

```
$ sudo cmake -D CMAKE_BUILD_TYPE=Release \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D WITH_TBB=ON \
    -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules ..
$ sudo make -j12
$ sudo make install

//うまくいったか確認
$ echo /usr/local/lib > /etc/ld.so.conf.d/opencv.conf
$ ldconfig -v
```
`\`は「次の行でも入力するからまだ実行するな」のサインです。`￥`と表記されることもあります。
`make`でビルド、つまり使えるようにします。その時に使う子を`cmake`で作成しています。
`-j12`は使うCPUのコア数を指定しています。よくわからなかったら省略してください。
`echo`はprintみたいなものです。私はよくわかりません。

最後にOpenCVが入ったか確認します。
バージョン(今回は3.4.3)が表示されたら成功です。

```
$ opencv_version
```

###CUDA Toolkitのインストール
GPUを幅広い用途に使えるようにしてくれます。
https://qiita.com/okubo999/items/79e1d97a7a3a3de70de2 参考です。

[公式サイト](https://developer.nvidia.com/cuda-toolkit-archive)からCUDA Toolkitを持ってきます。
掲示板の海外アニキ曰く10.2が良いらしいので、私は10.2にしました。
追記：将来TensorFlow触ってみたなー、と思ってる方は10.0にしてください。10.2には対応していません。

Linux -> x84_64 -> Ubuntu -> 18.04 -> deb(network)
と押していくとやり方が書いてあります。
しかし、最後だけ少し変えます。

```
$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
$ sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
$ sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
$ sudo add-apt-repository "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
$ sudo apt update
$ sudo apt -y install cuda-toolkit-10-2
```

`wget`でダウンロードできます。www+getが由来です。
今回はtoolkitだけ欲しいので、最後にtoolkitだけ指定しています。

このままだとPCがうまく使ってくれないのでpathを追加します。

```
$ nano ~/.bashrc
```

そして下記を最後の行に追加します。

```:.bashrc
## CUDA and cuDNN paths
export PATH=/usr/local/cuda-10.2/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-10.2/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
```

`nano`はテキストエディタです。下にいろいろ出ると思うのでそれを参考にしてください。
`^X`とかの `^` は CTRL同時押し の意味です。
`YES`or`NO` を聞かれたら`y`か`n`を入力します。

最後にpathを反映させます。

```
$ source ~/.bashrc

//以下でいろいろ出てきたら成功してる
$ nvcc -V
$ echo $PATH
```

###cuDNNのインストール
CUDAを人工知能向けに使いやすくしてくれます。
[公式サイト](https://developer.nvidia.com/rdp/cudnn-archive)からCUDAのバージョンに合うものをインストールします。
今回は7.6.5です。

登録しろと言われたら大人しく従います。

アーカイブを開くと
`Download cuDNN v7.6.5 (November 18th, 2019), for CUDA 10.2`
というのがあるので、そちらから
`cuDNN Runtime Library for Ubuntu18.04 (Deb)
cuDNN Developer Library for Ubuntu18.04 (Deb)
cuDNN Code Samples and User Guide for Ubuntu18.04 (Deb)`
をダウンロードします。

そのままダウンロードするとダウンロードフォルダに入りますが、汚いので私はworkspaceを作りそちらに入れました。

```
$ mkdir workspace
$ cd workspace
```

ダウンロードしたら、ダウンロードしたパスまで移動(cd を使う)してください。
それでは展開します。

```
$ sudo dpkg -i libcudnn7_7.6.5.32-1+cuda10.2_amd64.deb 
$ sudo dpkg -i libcudnn7-dev_7.6.5.32-1+cuda10.2_amd64.deb 
$ sudo dpkg -i libcudnn7-doc_7.6.5.32-1+cuda10.2_amd64.deb 
```

`dpkg` は.debを操作する子です。

ここまで来たらほぼ勝利です。

##機械学習編
やっと機械学習パートに入ります。
https://qiita.com/okubo999/items/79e1d97a7a3a3de70de2 を参考
###darknetの用意
最初にフレームワークであるdarknetを用意します。

ここからは散らかるのでworkspaceとか作って作業してください。
(追記：本家のdarknetでは自作データの学習が上手く行かなかったのでAlexeyさんの改良版(？)に変えました。)

```
$ git clone https://github.com/AlexeyAB/darknet.git
$ cd darknet
$ nano Makefile
```

`Makefile`を開いたら以下のようにします。

```:Makefile
GPU=1
cuDNN=1
OPENCV=1 
```

`Makefile`はmakeするときに使う設定です。
今回はGPUを使いたいので少し書き換えました。

これでmakeすれば使えるようになります。

```
$ make
```

darknetを実行してエラーが出なければ勝利です。

```
$ ./darknet 
usage: ./darknet [function]
```

###YOLOv3を使う
やっと本題です。
まずは学習済みデータを持ってきます。

```
$ wget https://pjreddie.com/media/files/yolov3.weights
```

もし`wget`がエラーなどで止まっても `--continue` を使うと再開できます。
今回の場合はこんな感じですね。
`$ wget --continue https://pjreddie.com/media/files/yolov3.weights`

いよいよ実行します。

```
$ ./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
```
出力画像が得られたら完全勝利です。
おつかれさまでした。

###YOLO止まるんだが？

```
CUDA Error:out of memory
darknet: ./src/cuda.c:36: check_error: Assertion '0' failed.
```
などと言われたら、GPUの性能がクソザコだと煽られています。
そうなったらキレ散らかすのを我慢して設定を落とします。
**darknet/cfg/yolov3.cfg**にサイズ設定があるので32の倍数で小さくします。

```:darknet/cfg/yolov3.cfg
width=416
height=416
```
他にも効果のある設定はありますが、サイズ変更が一番効果的で直感的だと思ってます。
自転車の前にいるワンちゃんが見えたらクソザコ卒業です。
おつかれさまでした。

###オプションを加えたい
yolov3には色々なオプションをつけられるのですが、上記のものに付け足しても**無視されます**。
画像出力をナシにする`-dont_show`を加えてみましょう。

```
//結果画像を表示しない
$ ./darknet detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights data/dog.jpg -dont_show
```

`detect`が`detector`になったり、`cfg/coco.data`が追加されたりしてますね。
`detect`のままだとオプションは１種類くらいしか通りませんし、`test`でとんでもない量のウィンドウが出たりします。

###yolov4にしてみたい
実は`darknet`の中にyolov1~v4が入っています。
yolov4を試すのは簡単で、

```
$ ./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/dog.jpg -dont_show
```

と、数字を3->4に変えるだけです。
ちょっと速度は下がりますが、精度は相応に上がります。
yolov3の方がネットの記事が多いのですが、好きな方を選んでください。

#おわりに
私のubuntuが先日、firefoxのクラッシュした連鎖で地獄と化し再インストールしたので備忘録として残しました。
WSLとか ubuntu 20.04 とか彷徨いましたが、やはり安定感は大事ですね。

このあと、私の本来の目標である自前データでの学習を[こちらの記事を参考に](https://qiita.com/okubo999/items/5435e1813d1d62c85689)行いました。

<img width = "400" alt = "urlukg.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774083/2b56940a-d6cf-c898-fee7-26d51cf617a2.jpeg">

素晴らしい猫耳です。