コンテンツにスキップ

Top

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()

以上!