M2Detを試してみた

# はじめに
M2Detというニューラルネットワークが定義され、2019年3月1日にソースが公開されました。([Paperデーター](https://qijiezhao.github.io/imgs/m2det.pdf))
という事で早速試してみました。

# 環境

|OS|Ubuntu 14.04.6|
|:--|:--|
|**GPU**|**Nvidia GeForce 2080Ti × 2**|
|**CPU**|**Intel Core i7-8700**|
# 事前にインストールしておくもの
|Package|Version|
|:--|:--|
|CUDA(apt)|10.1|
|Python(apt)|3.6|
|Cython(pip)|0.29.6|
|opencv-python(pip)|3.4.5.20|
|tqdm(pip)|4.31.1|
|tensorflow(pip)|1.13.1|
|addict(pip)|2.2.0|
|torch-nightly(pip)|1.0.0|
|torchvision-nightly(pip)|0.2.1|
|anaconda(DL)|3.0|

GithubにあるREADMEではanacondaに同封されているpythonにインストールするよう書かれていますが、今回はpython3.6での動作検証になります。
python3.6での検証のため、python実行の際にバージョン指定で実行する必要があります。

pytorchをインストールしておく必要がありますが、2019年3月5日時点にあるパッケージでは動作しませんでした。
"THCudaCheck FAIL file=/pytorch/aten/src/THC/THCGeneral.cpp line=XXX error=11"
というエラーで停止します。

調べると2080Ti+cuda10+pytorchでは正常動作しないようなのでhttps://github.com/datapink/robosat.pink/issues/3 にしたがってtorch-nightlyをインストールしました。
(1080tiでは生じていないエラーのようでした。https://discuss.pytorch.org/t/a-error-when-using-gpu/32761)


# 事前準備
Githubにリリースされている[ソース](https://github.com/qijiezhao/M2Det) のREADMEによると事前にpythorch版ssdのdatasetで用いたvggモデルが必要なようなのでダウンロードします。

```
wget https://s3.amazonaws.com/amdegroot-models/vgg16_reducedfc.pth
```

また、COCOのannotation、imageをダウンロードします。。
COCOのdataseを[公式](http://cocodataset.org/#download)から取得します。

```
cd
mkdir data
mkdir data/coco
mkdir data/coco/images
cd data/coco/images
wget http://images.cocodataset.org/zips/train2014.zip
wget http://images.cocodataset.org/zips/val2014.zip
wget http://images.cocodataset.org/zips/test2014.zip
wget http://images.cocodataset.org/zips/test2015.zip
wget http://images.cocodataset.org/zips/train2017.zip
wget http://images.cocodataset.org/zips/val2017.zip
wget http://images.cocodataset.org/zips/test2017.zip
unzip train2014.zip
unzip train2017.zip
unzip val2014.zip
unzip val2017.zip
unzip test2014.zip
unzip test2015.zip
unzip test2017.zip
rm *.zip
cd ..
wget http://images.cocodataset.org/annotations/annotations_trainval2014.zip
wget http://images.cocodataset.org/annotations/image_info_test2014.zip
wget http://images.cocodataset.org/annotations/image_info_test2015.zip
wget http://images.cocodataset.org/annotations/annotations_trainval2017.zip
unzip annotations_trainval2014.zip
unzip image_info_test2014.zip
unzip image_info_test2015.zip
unzip annotations_trainval2017.zip
rm *.zip
cd annotations
wget http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/coco_minival2014.tar.gz
tar xfz coco_minival2014.tar.gz
rm coco_minival2014.tar.gz
```

# M2Detを動かしてみる

M2DetのソースをGithubからクローンします。

```
git clone https://github.com/qijiezhao/M2Det.git
cd M2Det
```

make.shを変更します。

```
CUDA_PATH=/usr/local/cuda/

python build.py build_ext --inplace

         ↓

CUDA_PATH=/usr/local/cuda/
PATH=${PATH}:/home/atluser/anaconda3/bin
python3.6 build.py build_ext --inplace
```

data/coco.pyを環境に合わせて修正します。
line:31

```
self.cache_path = os.path.join(self.data_path, 'coco_cache')
　　　　　　　　　↓
self.cache_path = os.path.join(self.data_path, 'coco')
```

make.shを実行します。

```
sh make.sh
```

m2det512_vgg.pthをダウンロードします。
このモデルは作成者の[Googleドライブ](https://drive.google.com/file/d/1NM1UDdZnwHwiNDxhcP-nndaWj24m-90L/view?usp=sharing) にありますので、ターミナル上ではなくGUIでダウンロードします。
AWSなどSSHで接続している場合はscpなどを使ってクライアントPCからコピーします。

```
mkdir weights
cd weights
"scpやmvでm2det512_vgg.pthを置く"
```

vgg16_reducedfc.pthも同じ場所におきます。

```
mv ~/vgg16_reducedfc.pth ~/M2Det/weights/
```


# 動作確認
動作確認をします。

```
python3.6 demo.py -c=configs/m2det512_vgg.py -m=weights/m2det512_vgg.pth --show
```
画像が問題なく表示されれば動作確認は終了です。

# PKLファイルを作成する
学習するにあたって、pklというファイルを作成する必要があり、これは一度検知をかけたファイルの結果を保存するようなファイルのようです。
そこでtest.pyを実行します。

```
python3.6 test.py -c=configs/m2det512_vgg.py -m=weights/m2det512_vgg.pth
```

~/data/coco配下にpklファイルが作成されます。

# 学習をしてみる
学習方法です。
READMEにあるtrain.pyを動かします。

まずconfigファイルを修正します。
configファイルはconfig/m2det512_vgg.pyになります。
line30あたりにバッチサイズを指定するところがあるのでそこを修正します。

```
per_batch_size = 16,
　　　　↓
per_batch_size = 4,
```

train.pyを実行します。

```
CUDA_VISIBLE_DEVICES=0,1 python3.6 train.py -c=configs/m2det512_vgg.py --ngpu 2 -t True
```

以上で学習が実行されます。

次回以降configあたりの調査をしようと思います。

# 外部カメラデバイスで動作させてみる（2019年3月14日にREADMEが更新されましたので記載します）

<u>※demo.pyをupdateする必要があります。</u>
外部カメラデバイスでM2Detを動作させてみます。

```
python3.6 demo.py -c=configs/m2det512_vgg.py -m=weights/m2det512_vgg.pth --show --cam=0
```

**--cam** の引数にカメラデバイスIDを指定すれば動作します。