Mac + PyTorch + Mask R-CNN
PyTorchのサンプル ( https://pytorch.org/tutorials/ )にあるInstance Segmentation のサンプルを動かそうとしたら大変だったのでその時のメモ。
大変だった理由はバージョンが上がったから。昔のバージョンで動くように作られているのか、手順通りにやってもエラーになって困った。
あとサンプルコード(tv-training-code.py)だと毎回学習するし、モデル保存とかもしないし、推論単体もできないし、推論結果も画像として出力されない。
ので、その辺りができるように変更をしようと思ったけど疲れたので後ほど。
まずは正解の手順
https://pytorch.org/tutorials/intermediate/torchvision_tutorial.htmlの動かし方。
いろいろやって最終的にできた手順だけを載せる。
環境を汚染したくないので、pipenvで。
$ mkdir torchvision_tutorial
$ cd torchvision_tutorial
$ pipenv --python 3.9
$ pipenv shell
んで、
$ git clone https://github.com/pytorch/tutorials.git
$ cd tutorials
$ pip install -r requirements.txt
$ cd ../
チュートリアルのコードはtv-training-code.py。
(tutorials配下にいるので別にwgetじゃなくてもよかったが)
$ wget https://pytorch.org/tutorials/_static/tv-training-code.py
で、使うデータが、PennFudanPed。ペンシルバニア大学とFudan大学が提供してくれてる歩行者(pedestrian)のデータだからPennFudanPed。
を落として展開しておく。
$ wget https://www.cis.upenn.edu/~jshi/ped_html/PennFudanPed.zip
$ unzip PennFudanPed.zip
そのままだと動かないので、別のところからコードを持ってきてコピーする必要がある。
なんで?と言われても知らん。
git clone https://github.com/pytorch/vision.git
cd vision
git checkout v0.8.2
cp ./references/detection/*.py ../
cd ../
あと、pycocotoolsが必要!とか言われるのでいれとく(ならrequirements.txtに入れろや、とは思うが)
pip install -U pycocotools
これで動くはずなのにMacというかCUDAの無いPC(Macだとほとんどそうなはず)だと失敗する。
engine.pyの中で、torch.cuda.synchronize()とおもくそcudaありきコードが書かれているからだ。
ので、ソースを書き換える。(if文でガードを入れる)
$ vi engine.py
if torch.cuda.is_available():
torch.cuda.synchronize()
これでとりあえず動くが、CUDAの無いMacは大変時間がかかる。
特にデフォルトではエポック数が10もあり、自分のノートでは5時間以上かかってしまったのでここはエポックを1にしとく。
$ vi tv-training-code.py
# let's train it for 10 epochs
num_epochs = 1 // 1に変更
んで、実行!
$ python tv-training-code.py
Epoch: [0] [ 0/60] eta: 0:34:47 lr: 0.000090 loss: 3.4201 (3.4201) loss_classifier: 0.7583 (0.7583) loss_box_reg: 0.5379 (0.5379) loss_mask: 2.0765 (2.0765) loss_objectness: 0.0412 (0.0412) loss_rpn_box_reg: 0.0061 (0.0061) time: 34.7849 data: 0.9059
Epoch: [0] [10/60] eta: 0:28:18 lr: 0.000936 loss: 1.5568 (1.8886) loss_classifier: 0.4987 (0.4644) loss_box_reg: 0.2781 (0.2923) loss_mask: 0.5972 (1.1031) loss_objectness: 0.0170 (0.0233) loss_rpn_box_reg: 0.0054 (0.0056) time: 33.9775 data: 0.0850
Epoch: [0] [20/60] eta: 0:22:25 lr: 0.001783 loss: 0.9186 (1.3440) loss_classifier: 0.2163 (0.3320) loss_box_reg: 0.2537 (0.2887) loss_mask: 0.2956 (0.6966) loss_objectness: 0.0165 (0.0211) loss_rpn_box_reg: 0.0042 (0.0056) time: 33.5696 data: 0.0025
Epoch: [0] [30/60] eta: 0:16:57 lr: 0.002629 loss: 0.6633 (1.1089) loss_classifier: 0.1245 (0.2544) loss_box_reg: 0.2952 (0.2846) loss_mask: 0.2231 (0.5486) loss_objectness: 0.0049 (0.0155) loss_rpn_box_reg: 0.0043 (0.0058) time: 33.9002 data: 0.0028
Epoch: [0] [40/60] eta: 0:11:07 lr: 0.003476 loss: 0.4611 (0.9406) loss_classifier: 0.0587 (0.2037) loss_box_reg: 0.2052 (0.2596) loss_mask: 0.1993 (0.4584) loss_objectness: 0.0032 (0.0134) loss_rpn_box_reg: 0.0056 (0.0055) time: 33.1567 data: 0.0041
Epoch: [0] [50/60] eta: 0:05:32 lr: 0.004323 loss: 0.3578 (0.8265) loss_classifier: 0.0355 (0.1727) loss_box_reg: 0.1318 (0.2334) loss_mask: 0.1636 (0.4023) loss_objectness: 0.0025 (0.0119) loss_rpn_box_reg: 0.0061 (0.0062) time: 32.1556 data: 0.0039
Epoch: [0] [59/60] eta: 0:00:33 lr: 0.005000 loss: 0.3403 (0.7552) loss_classifier: 0.0355 (0.1536) loss_box_reg: 0.1069 (0.2185) loss_mask: 0.1575 (0.3667) loss_objectness: 0.0015 (0.0103) loss_rpn_box_reg: 0.0068 (0.0062) time: 32.0224 data: 0.0027
Epoch: [0] Total time: 0:33:21 (33.3639 s / it)
[W ParallelNative.cpp:229] Warning: Cannot set number of intraop threads after parallel work has started or after set_num_threads call when using native parallel backend (function set_num_threads)
creating index...
index created!
Test: [ 0/50] eta: 0:04:59 model_time: 4.6199 (4.6199) evaluator_time: 0.0032 (0.0032) time: 5.9842 data: 1.3610
Test: [49/50] eta: 0:00:04 model_time: 4.3537 (4.5109) evaluator_time: 0.0041 (0.0068) time: 4.4422 data: 0.0009
Test: Total time: 0:04:07 (4.9467 s / it)
Averaged stats: model_time: 4.3537 (4.5109) evaluator_time: 0.0041 (0.0068)
Accumulating evaluation results...
DONE (t=0.02s).
Accumulating evaluation results...
DONE (t=0.01s).
IoU metric: bbox
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.717
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.993
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.897
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.680
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.720
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.334
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.766
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.766
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.790
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.763
IoU metric: segm
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.732
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.993
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.919
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.444
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.744
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.334
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.762
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.763
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.690
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.770
That's it!
成功した。疲れた。
ModuleNotFoundError: No module named 'engine'
ModuleNotFoundError: No module named 'engine' が無い、と怒られる場合。
vison を持ってきてカレントディレクトリにコピーしよう。
この時最新ではなく v0.8.2 で チェックアウトすること。(PyTorchのサンプルコードが古いので)
git clone https://github.com/pytorch/vision.git
cd vision
git checkout v0.8.2
cp ./references/detection/*.py ../
cd ../
ModuleNotFoundError: No module named 'pycocotools'
pip install -U pycocotools
pycocotoolsもvision同様、他所から持ってきてカレントにコピー。なんでかは知らん。
git clone https://github.com/cocodataset/cocoapi.git
cp cocoapi/PythonAPI/pycocotools/*.py .
AssertionError: Torch not compiled with CUDA enabled
engine.pyの中にcudaありきのコードが混じっているために起きる。
ので書き換える。
$ vi engine.py
if torch.cuda.is_available():
torch.cuda.synchronize()
以上!