2022年1月5日
Mask-RCNNを使って、画像解析しよう。
昨日、ブログ記事を参考にして細胞のインスタンスセグメンテーションを学ぼうとしていた。Mask-RCNNモデルをGitHubからもってきて、インストールまでできた。しかしながら、今朝からcocoで学習させたweightをダウンロードしようとして行き詰まってしまった。行き詰まりの原因の1つは、辿った先のGitHubのレポジトリーがなくなっていたことにある。
9:12 作戦変更
Kaggleコンペで、PyTorchでMask R-CNNを使っているコードがあったので、それから学んでみよう。
Anaconda3のjupyter notebookにアップロードして動かしてみた。
ModuleNotFoundError: No module named 'torchvision'
pytorch.orgで調べてみよう。
関係ないと思うが、pytorchのバージョンが1.6.0だったので、1.10.1 にアップデートしてみる。conda update pytorch。
9:40頃完了。しかし、1.6.0のままだった。なぜだろう。ならば、1.6.0をuninstallしてから、あらためてpytorchをインストールしようと思って、conda uninstall pytorch=1.6.0としてみたら、途中で作業が進まなくなった。環境が、inconsistentなのだそうだ。
10:12 進まないので、anacondaプロンプトを強制終了し、torchvisionをインストールすることにした。conda install torchvision。見つからない。channelを追加したらインストールできたが、情報が古くて、python2だった。
Kaggleで何でもできるようになった(機械学習が身に付いた)と思っていたのだが、大間違いだった。
Kaggleの計算環境は理想的(至れり尽くせり)であった。だから、いろんなことができるようになったと勘違いした。Kaggleの計算環境を、Anaconda/Windowsで、再現することから始めよう。
10:50頃 pytorch.orgのgetstartedを見ていると、start locallyの下にある表が、現在の自分のパソコンの環境を読み取っていることがわかった(違う環境を手動で設定してから更新すると、適切な環境が自動的に選択されている)。Run this Command:のところに、conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorchと表記されているので、この通りに、Anaconda promptから入力したら、上記と同様にinconsistent情報が現れ、少し停滞していたが、しばらく待っていると、内容変更候補が現れ、実行するかどうか聞いてきたので、 y を選択した。pytorch 1.10.1のインストールが始まった。
これでうまくいったら、これからは、pytorchを使うしかない!と思う。
終了したので、conda listで、pytorch 1.10.1とtorchvision 0.11.2がインストールされていることが確認できた。
jupyter notebookにアップロードしたKaggleコンペのMask-RCNNのコードの最初のセルの、パッケージ/モジュールのimportを、ほんの小さなエラーのみで、無事通過した。
これで、自分のパソコン(Windows 10)でPyTorch: Mask-RCNNを使う準備ができた。
11:55 pytorchのデフォルトで使えるモデルの情報を集めよう。
Mask R-CNN
torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=False, progress=True, num_classes=91, pretrained_backbone=True, trainable_backbone_layers=None, **kwargs)
Constructs a Mask R-CNN model with a ResNet-50-FPN backbone.
pretrained (bool) – If True, returns a model pre-trained on COCO train2017
torchvisionを使えば、COCOによる学習済みモデルが使えるのだ!!
それは、これから取り組む画像解析でも同じだが、Kaggleコンペとの最も大きな違いは、データ集めである。
モデルの訓練には元画像の他に次のデータを用意する必要がある。
During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing:
boxes (FloatTensor[N, 4]): the ground-truth boxes in [x1, y1, x2, y2] format, with 0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
labels (Int64Tensor[N]): the class label for each ground-truth box
masks (UInt8Tensor[N, H, W]): the segmentation binary masks for each instance
ラベルは、粒径計測の場合はバックグラウンドとそれ以外ということで、1か0ということで問題は無い。
boxとmaskは、基本的には、手作業で作ることになるのだろう。テスト段階では、maskは、二値化ソフトで出力したもので間に合うかもしれない。boxは、手作業になるかもしれない。
Faster-R-CNNを使えば、bounding boxを出力してくれるのだが、それでも、訓練データは必要になる。
そうではなく、マスクができれば、マスクに外接する長方形がbounding boxだから、変換するプログラムを作ればよい。
maskからbaunding boxをつくる(変換する)プログラムが、pytorchで用意されているようだ。
torchvision.ops.masks_to_boxes(masks: torch.Tensor) → torch.Tensor
Compute the bounding boxes around the provided masks.
Returns a [N, 4] tensor containing bounding boxes. The boxes are in (x1, y1, x2, y2) format with 0 <= x1 < x2 and 0 <= y1 < y2.
計算式:
if masks.numel() == 0:
return torch.zeros((0, 4), device=masks.device, dtype=torch.float)
n = masks.shape[0]
bounding_boxes = torch.zeros((n, 4), device=masks.device, dtype=torch.float)
for index, mask in enumerate(masks):
y, x = torch.where(masks[index] != 0)
bounding_boxes[index, 0] = torch.min(x)
bounding_boxes[index, 1] = torch.min(y)
bounding_boxes[index, 2] = torch.max(x)
bounding_boxes[index, 3] = torch.max(y)
return bounding_boxes
これからは、PyTorchを使って、自分でコードを書かなければならない。
21:16 今から、jupyter notebook上で、pytorchのtutorialに従って、練習する。
23:03 Quickstartをダウンロードし、jupyter notebookにアップロードし、動かしてみた。
今日の午前中に、最新のPyTorchをインストールできたおかげで、Quickstart(FashionMNISTを使った簡単なNNモデルの学習と予測の練習)が自分のパソコンの計算環境Anaconda3で実行できたのはよかった。
これで、Mask-R-CNNによるインスタンスセグメンテーションも、自前の計算環境で行えるような気がしてきた。ハイパーパラメータを調整するチューナーからプログラムを組み立てることができるデータサイエンティストに変身しよう!正月だし、これを今年の目標にしよう。
「ハイパーパラメータを調整するチューナー」は、出来上がったコードを借用して、ハイパーパラメータを調整して、その結果を投稿する人を指している。これは、もちろん、初心者にはできない事だし、チューナーもレベルが上がってくると、loss functionやoptimizerを入れ替えたり、モデルも入れ替えることができるようになり、見た目がすっかり変わっていて、全く別のコードに変えてしまうこともできるようになる。さらにレベルが上がると、入力データを加工したり、後処理もするようになる。結局はすべてマスターしてしまうようになる人もいるだろうと思う。
これとは逆の人もいて、コードは書けるのだが、スコアが上がらない人がいる。discussionを見ていると、データ処理から入った方々に多く見られ、データ加工ができるから、入力部分や出力部分は書けるし、モデルはゼロから作るわけではなく借用するのが普通だからそこも問題なくできる。ただし、予測まで含めた全体を仕上げるところをやった経験がないと、loss functionやoptimizerの選択、そのパラメータの設定などが適切でなければ、スコアは上がらず、学習すら進まないことも普通におきる。
1月8日:
今日はテンソルを勉強している。
今更ですが、jupyter notebookを使うと、パラメータの変更と演算を繰り返すことができて、途中の変数と演算結果も即座に表示できるので、テキストを読むより理解が進む。
torchvision.ops.masks_to_boxes(masks: torch.Tensor) の演算を理解するために、テンソルを勉強しているのだから、 torch.min(x)と torch.max(x)も理解しておこう。
y, x = torch.where(masks[index] != 0)
bounding_boxes[index, 0] = torch.min(x)
bounding_boxes[index, 1] = torch.min(y)
bounding_boxes[index, 2] = torch.max(x)
bounding_boxes[index, 3] = torch.max(y)
return bounding_boxes
マスクが領域内に1つだけ存在するのであれば、マスク領域のx座標の最大値と最小値、y座標の最大値と最小値が、bounding_boxの位置/サイズになる。
複数個所にマスク領域が存在する場合はどうするのだろう。
1月16日(日)
機械学習はPyTorchの枠組みの中でやるとしても、科学技術全体を見渡した時には、ベースになる言語をマスターしておくことが必要になる。昔はfortranやbasicだったが、今は、Pythonである。
Kaggleをやっていて、結局身に着かなかったのが、ベースとなるプログラミング技術である。fortranでもbasicでもない。Pytonである。機械学習やディープラーニングのテキストのはじめの方にPython入門、超入門、概要などの章が設けられていて、簡単な説明がなされていて、defやclassが理解できないまま終わる。しかし、実際のプログラムの中身は、KerasでもTensorFlowでもPyTorchでもない。Python(+C++)なのだ。
主題のMask-RCNNからはずれてしまったが、Mask-RCNNを使いこなすためにも、Pythonで自在にプログラムが書けるようになろう。