セマンティックセグメンテーション
画像解析による物体認識の一手法として,セマンティックセグメンテーションというものがあります.これは,画像において物体にラベルを付けて,元画像とラベル化画像を使ってモデルを学習させ,ピクセル単位で画像からラベル(つまり物体)を予測しようとするAI手法です(たぶん).
これを使って河川に浮遊する物質動態を把握しようと考え,Python環境のPytorchで動くSegmentation Modelsを動かした際の注意点について忘備録的にまとめてみます.
なお,著者は画像解析については素人同然なのでそのつもりでお読みください.
今回試したPC環境については以下です.
OS:Windows 10
GPU:NVIDIA RTX A6000
また,Pythonについては,Anaconda 3のJupyternotebookで動かします.さらに,CUDA-CPU環境についても前回記事で行っていますのでそちらも参照ください.
サンプルコード
Segmentation Modelsにある自動車を分類するテストコードを実行してみます.
構築した環境ではいくつかうまくいかないところがあったので,そこを中心に説明していきます.
いろいろインストール
モデル本体であるsegmentation modelsをインストール.Anaconda promptで下記実行.
pip install segmentation_models_pytorch
OpenCVも必要.
pip install opencv-python
以下の部分においてはgithubのリポジトリから画像とラベルデータを引っ張ってきています.
DATA_DIR = './data/CamVid/'
# load repo with data if it is not exists
if not os.path.exists(DATA_DIR):
print('Loading data...')
os.system('git clone https://github.com/alexgkendall/SegNet-Tutorial ./data')
print('Done!')
これにはgitのインストールが必要みたいです.
ダウンロード→デフォルトでインストールで問題ないと思いますが,PCを再起動しないといけないかもしれません.
kernelが落ちる
ここで試している環境では下記部分でkernel appears to have diedになり,jupyterがクラッシュしました.コマンドから実行すると,
Initializing libiomp5md.dll, but found libiomp5md.dll already initialized
とエラーが返ってくる.どうやらanaconda3のフォルダに複数のlibiomp5md.dllがあるのが問題みたい.なので1つを残して削除する.
デフォルトだと,anaconda3は以下のフォルダにインストールされている.
C:/Users/(ユーザー名)/AppData/Local/anaconda3
ただ,Appdataは隠しフォルダになっているので,フォルダオプションから隠しフォルダを表示にする.anaconda3フォルダでlibiomp5md.dllを1つ残して削除.どれを残してもうごく(他への影響は不明ですが..).
データ拡張ライブラリalbumentationsのインストール
このコードでは,データ数をかさましするために,学習毎に動的に画像に回転や縮小などを施していて,その処理にライブラリalbumentationsを使っています.
このインストールはanaconda promptで
pip install -U albumentations --user
で可能ですが,Jupyternotebookで使う場合,以下にあるように予期せぬ場所にインストールされていて読み込めないバグがある様子.
なので想定しているフォルダにファイルをコピーする.ここでの環境だと,
C:/Users/(ユーザー名)/AppData/Roaming/Python/PythonXXX/site-packages
にあるフォルダをすべてコピーしてanaconda3のインストールフォルダである以下に張り付けます.
※XXXはpythonのバージョンで変わります.
C:/Users/(ユーザー名)/AppData/Local/anaconda3/Lib/site-packages
また,get_training_augumentation内の以下の関数は最新のalbumentaitonsでは動かないので書き換えるととりあえず動きます.
albu.IAAAdditiveGaussianNoise(p=0.2)
albu.IAAPerspective(p=0.5)
albu.IAASharpen(p=1)
↓
albu.GaussNoise(p=0.2)
albu.Perspective(p=0.5)
albu.Sharpen(p=1)
※albumentations version 1.4ではrandombrightnessとrandomcontrastが動かない.とりあえず,両方ともRandomBrightnessContrastに変更すると動く.
num workerの値
デフォルトではtrain_loaderでnum_worker=12,valid_loaderでnum_worker=4になっているが動かない場合,これらは0にするとよい.
結果
最後まで動くとこんな感じの結果が得られます.左が元画像,中央が正解データ,右が学習モデルによる予測値ですね.
モデルやエンコーダ部分は一覧のものから簡単に変更できます.今回は以下で動かしています.
ENCODER = 'resnext50_32x4d'
ENCODER_WEIGHTS = 'imagenet'
CLASSES = ['car']
ACTIVATION = 'sigmoid' # could be None for logits or 'softmax2d' for multiclass segmentation
DEVICE = 'cuda'
#DEVICE = 'cpu'
# create segmentation model with pretrained encoder
model = smp.FPN(
encoder_name=ENCODER,
encoder_weights=ENCODER_WEIGHTS,
classes=len(CLASSES),
activation=ACTIVATION,
)
preprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)
例えば,モデルをUnetに変更したければ,FPN → Unetとすれば動きます.
ただ,モデルやエンコーダは組み合わせによっては動かないものもあるので,いろいろと試してみる必要があります.
おわりに
とりあえずサンプルコードを動かすところまでまとめてみました.次は別のデータセットを使ってみるところもやってみます.