前の記事でNiftyNetの紹介をしました。
(https://qiita.com/takeajioka/items/84321b7d3f1eebcb4e5d)
今回はそれを使って実際にセグメンテーションをしてみました。
環境は以下です。
Ubuntu 18.04.2 LTS
GPUはGTX1070 (8GB)
メインメモリは16GB
Cuda 10
cuDNN 7.6.3
Anaconda
Python3.6
tensorflow-gpu==1.14.0
niftynet==0.6.0
その他必要なパッケージについて
tiffのスタック画像を読み込むために、他にもscikit-imageやpyYAMLもインストールする必要があります。(Anacondaにはデフォルトで入っている。)
他にはsimpleITKやopenCVを入れないと警告が出ますが、openCVは入れると逆にエラーで実行できなくなるので入れないでおきましょう。
使用したデータ
データセットはKaggleのElectron Microscopy 3D Segmentationを用いました。
(https://www.kaggle.com/kmader/electron-microscopy-3d-segmentation)
海馬CA1領域の電子顕微鏡画像におけるミトコンドリアのセグメンテーションです。
ラベルデータが輝度値0と255の2値画像になっていました。輝度値がクラスを表すようにするため、輝度値255を1に置き換えました。これでNiftyNetで読み込めます。
セグメンテーションを実行する
使用するネットワークですが、NiftyNetでは様々なネットワークを選べます。
(https://github.com/NifTK/NiftyNet/blob/dev/niftynet/network/README.md)
最初はVnetで試しましたが、上手くいかなかったため、DenseVnetで行いました。
またloss関数も重要で、通常用いられるDice係数では全てとラベル0と認識され、反応はありませんでした。クラス不均衡時などに生じるようです。(それに対応したTverskyというロス関数もあるようです。)
選べるloss関数の一覧などはここで確認できます。
(https://github.com/NifTK/NiftyNet/blob/dev/niftynet/layer/README.md)
今回はloss関数はCrossEntropyで上手くいきました。
また重要なのは活性化関数で、デフォルトのreluでは上手くいきませんでした。(dying ReLUしたようです)。対策としてprelu(Parametric ReLU)に変更しました。preluはreluより高度ですが、その分パラメータが増えてGPUを圧迫します。
configファイルは以下のようになりました。
############################ input configuration sections
[EM]
path_to_search = ./data/EM3D/vnet
filename_contains = input
spatial_window_size = (128, 128, 128)
[label]
path_to_search = ./data/EM3D/vnet
filename_contains = groundtruth
spatial_window_size = (128, 128, 128)
############################## system configuration sections
[SYSTEM]
cuda_devices = ""
num_threads = 1
num_gpus = 1
model_dir = models/EM3D_vnet/
queue_length = 1
[NETWORK]
name = dense_vnet
activation_function = prelu
batch_size = 1
window_sampling = uniform
[TRAINING]
optimiser = adam
sample_per_volume = 1
lr = 0.01
loss_type = CrossEntropy
starting_iter = 0
save_every_n = 100
max_iter = 1000
[INFERENCE]
save_seg_dir = ./segmentation_output/
############################ custom configuration sections
[SEGMENTATION]
image = EM
label = label
label_normalisation = False
output_prob = False
num_classes = 2
実行コマンドは以下です。
net_segment train -c <configファイルのパス>
net_segment inference -c <configファイルのパス>
spatial_window_sizeはGPUの容量の都合でこれが限界でした。
電子顕微鏡画像は解像度が非常に大きいため、画素数も多く、spatial_window_sizeをもう少し増やしたいところです。
そうなるとサーバーの利用が望ましいと思います。
他には以下の項目などを加えることでData Augmentationもできるようです。
rotation_angle = (-10.0, 10.0)
scaling_percentage = (-10.0, 10.0)
次は3D U-Netで試したものを記事にする予定です。