セマンティックセグメンテーションモデルはバックボーンとしてVGG、ResNetといった代表的なCNNモデルを使ったり、ファインチューニングすることが可能です。segmentation_modelsというライブラリでその辺が簡単にできるので紹介していきます。
セマンティックセグメンテーションモデルのU-Netについて~実装までは↓にまとめてあります。基本的な環境設定も③と同じですので良かったら併せてご覧ください。今回はこのU-Netをベースに説明していきます。
Segmentation modelsを導入
Segmentation modelsを導入すると、セマンティックセグメンテーションで必要な様々なモノがそろいます。
- バックボーンの設定(VGG、ResNetなど)
- ファインチューニング
- 損失関数の設定
使ってて便利なのはこの辺りですので、説明していきます。
Segmentation modelsの導入はpipで可能です。↓のコードをAnaconda Promptへ入れて実行してください。
pip install segmentation-models
そのほかに必要なライブラリのバージョンは下記になります。
- keras_applications>=1.0.7,<=1.0.8
- image-classifiers==1.0.0
- efficientnet==1.0.0
TensorFlowを使っていきますが前の記事と同様の環境設定となっています。
バックボーン(Backbone)について
Backboneって何?という話ですが、U-Netのエンコーダ(CNN)部の構造のことを言います。
U-Netはエンコーダ、デコーダを併せ持つ構造となっていることは前にも説明しました。エンコーダでは画像の特徴をうまく取得する必要があるので、ここでどのようなCNNモデルを設定するかが特徴量を取得することに大きく影響してきます。ここでエンコーダへ設定するCNNモデルのことをBackboneと言います。
Segmentation modelsライブラリでは多くのBackboneをサポートしています。↓迷ってしまいますが、CNNで実施して精度が出るモデルを選ぶと良いと思います。
Backbones
Type | Names |
---|---|
VGG | 'vgg16' 'vgg19' |
ResNet | 'resnet18' 'resnet34' 'resnet50' 'resnet101' 'resnet152' |
SE-ResNet | 'seresnet18' 'seresnet34' 'seresnet50' 'seresnet101' 'seresnet152' |
ResNeXt | 'resnext50' 'resnext101' |
SE-ResNeXt | 'seresnext50' 'seresnext101' |
SENet154 | 'senet154' |
DenseNet | 'densenet121' 'densenet169' 'densenet201' |
Inception | 'inceptionv3' 'inceptionresnetv2' |
MobileNet | 'mobilenet' 'mobilenetv2' |
EfficientNet | 'efficientnetb0' 'efficientnetb1' 'efficientnetb2' 'efficientnetb3' 'efficientnetb4' 'efficientnetb5' efficientnetb6' efficientnetb7' |
Pythonコード説明
コードの説明をしていきます。ディレクトリ構成は前の記事と同じモノを使います。unetディレクト直下へJupyterNotebookでPython3のNotebookを作成してください。
↓のコードをコピペして実行するだけで学習が始まります。
from model import *
from data import *
from sklearn.model_selection import train_test_split
import segmentation_models as sm
import keras
BACKBONE = 'resnet50' #Backboneはここで設定する。
preprocess_input = sm.get_preprocessing(BACKBONE)
# load your data
X,Y = geneTrainNpy("data/membrane/train/aug/","data/membrane/train/aug/")
x_train, x_val, y_train, y_val = train_test_split(X, Y, test_size=0.20)
# preprocess input
x_train = preprocess_input(x_train)
x_val = preprocess_input(x_val)
opt = keras.optimizers.Adam(learning_rate=1e-5)
# define model
model = sm.Unet(BACKBONE,encoder_weights=None,classes=1,encoder_freeze=True,
input_shape=(None, None, 1)) #weight="imagenet"でファインチューニング可能
model.compile(
optimizer=opt,
loss=sm.losses.bce_jaccard_loss, #損失関数としてJaccard係数を使用
metrics=[sm.metrics.iou_score])
# fit model
history = model.fit(x=x_train, y=y_train, batch_size=16, epochs=1500, validation_data=(x_val, y_val))
これだけで学習できてしまうのですが、Segmentation modelsを導入するメリットを説明していこうと思います。
- セマンティックセグメンテーションモデルについて
モデルはUnet, Linknet, FPN, PSPNetの4種類をサポートしています。それぞれ特徴的なモデルですので課題に合わせ良いもを選ぶ必要があります。コード21行目の「Unet」を書き換えれば変更することが可能です。
- BACKBONEについて
コードの7行目に「BACKBONE = ‘resnet50’」とありますが、ここを書き換えるだけでOKです。例えばVGG16を使いたい場合はBACKBONE = ‘vgg16’とすればOKです。上でも説明しましたが、ここでは「画像の特徴をどれだけBACKBONEで捉えられるか」がポイントとなります。
- ファインチューニングについて
Segmentation modelsではBACKBONEで設定できるモデルに対し、imagenetを用いて学習した重みを設定することが可能です。やり方は、21行目の「encoder_weights = None」を「encoder_weights = “imagenet”」へ書き換えるだけでOKです。注意点は22行目のinput_shape=(None, None, 3)でないとエラーが発生する場合があります。ここを書換え、さらに入力データ(x_train)の形状も3チャンネルにすることも確認してください。
- 損失関数の設定
セグメンテーションでは損失関数を’binary_crossentropy’や’categorical_cross_entropy’を用いるとうまくいかないことがあります。それはpixel毎に判定を繰返しているため、集団として意識できていないためです。Jaccard係数やDice係数は2つの集団がどのくらい重なっているか?を評価する指標となります。損失関数はモデルの精度へ影響してきますので調整していきましょう。25行目で設定できます。
Segmentation-modelsの便利なところを説明しました。いずれも自分で1から書き直したりするのは大変ですので有用と思います。
以上、備忘録を兼ねてまとめました。
コメント
他の記事でも質問したのですが、当方入力をカラー画像で行いたいと思っています。
しかしエラーが出ておりまして困っています。
segmentation_modelでカラー画像を用いた機械学習を行うとき、コードに変更はありますでしょうか?
何回も申し訳ありません。