ホーム » MONAI (ページ 5)
「MONAI」カテゴリーアーカイブ
MONAI 0.7 : tutorials : 2D 分類 – MedNIST データセットによる医用画像分類
MONAI 0.7 : tutorials : 2D 分類 – MedNIST データセットによる医用画像分類 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/05/2021 (0.7.0)
* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- テレワーク & オンライン授業を支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ ; Facebook |
MONAI 0.7 : tutorials : 2D 分類 – MedNIST データセットによる医用画像分類
このノートブックは MONAI 機能を既存の PyTorch プログラムに容易に統合する方法を示します。それは MedNIST データセットに基づいています、これは初心者のためにチュートリアルとして非常に適切です。このチュートリアルはまた MONAI 組込みのオクルージョン感度の機能も利用しています。
また、このチュートリアルでは、MONAIに内蔵されているオクルージョン感度機能も利用しています。
このチュートリアルでは、MedNIST データセットに基づく end-to-end な訓練と評価サンプルを紹介します。
以下のステップで進めます :
- 訓練とテストのためにデータセットを作成する。
- データを前処理するために MONAI 変換を利用します。
- 分類のために MONAI から DenseNet を利用します。
- モデルを PyTorch プログラムで訓練します。
- テストデータセット上で評価します。
環境のセットアップ
!python -c "import monai" || pip install -q "monai-weekly[pillow, tqdm]"
!python -c "import matplotlib" || pip install -q matplotlib
%matplotlib inline
インポートのセットアップ
# Copyright 2020 MONAI Consortium
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import shutil
import tempfile
import matplotlib.pyplot as plt
import PIL
import torch
import numpy as np
from sklearn.metrics import classification_report
from monai.apps import download_and_extract
from monai.config import print_config
from monai.data import decollate_batch
from monai.metrics import ROCAUCMetric
from monai.networks.nets import DenseNet121
from monai.transforms import (
Activations,
AddChannel,
AsDiscrete,
Compose,
LoadImage,
RandFlip,
RandRotate,
RandZoom,
ScaleIntensity,
EnsureType,
)
from monai.utils import set_determinism
print_config()
MONAI version: 0.6.0rc1+15.gf3d436a0 Numpy version: 1.20.3 Pytorch version: 1.9.0a0+c3d40fd MONAI flags: HAS_EXT = True, USE_COMPILED = False MONAI rev id: f3d436a09deefcf905ece2faeec37f55ab030003 Optional dependencies: Pytorch Ignite version: 0.4.5 Nibabel version: 3.2.1 scikit-image version: 0.15.0 Pillow version: 8.2.0 Tensorboard version: 2.5.0 gdown version: 3.13.0 TorchVision version: 0.10.0a0 ITK version: 5.1.2 tqdm version: 4.53.0 lmdb version: 1.2.1 psutil version: 5.8.0 pandas version: 1.1.4 einops version: 0.3.0 For details about installing the optional dependencies, please visit: https://docs.monai.io/en/latest/installation.html#installing-the-recommended-dependencies
データディレクトリのセットアップ
MONAI_DATA_DIRECTORY 環境変数でディレクトリを指定できます。これは結果をセーブしてダウンロードを再利用することを可能にします。指定されない場合、一時ディレクトリが使用されます。
directory = os.environ.get("MONAI_DATA_DIRECTORY")
root_dir = tempfile.mkdtemp() if directory is None else directory
print(root_dir)
/workspace/data/medical
データセットをダウンロードする
MedMNIST データセットは TCIA, RSNA Bone Age チャレンジ と NIH Chest X-ray データセット からの様々なセットから集められました。
データセットは Dr. Bradley J. Erickson M.D., Ph.D. (Department of Radiology, Mayo Clinic) のお陰により Creative Commons CC BY-SA 4.0 ライセンス のもとで利用可能になっています。
MedNIST データセットを使用する場合、出典を明示してください。
resource = "https://drive.google.com/uc?id=1QsnnkvZyJPcbRoV_ArW8SnE1OTuoVbKE"
md5 = "0bc7306e7427e00ad1c5526a6677552d"
compressed_file = os.path.join(root_dir, "MedNIST.tar.gz")
data_dir = os.path.join(root_dir, "MedNIST")
if not os.path.exists(data_dir):
download_and_extract(resource, compressed_file, root_dir, md5)
再現性のために決定論的訓練を設定する
set_determinism(seed=0)
データセットフォルダから画像ファイル名を読む
まず最初に、データセットファイルを確認して幾つかの統計を表示します。
データセットには 6 つのフォルダがあります : Hand, AbdomenCT, CXR, ChestCT, BreastMRI, HeadCT,
これらは分類モデルを訓練するためにラベルとして使用されるべきです。
class_names = sorted(x for x in os.listdir(data_dir)
if os.path.isdir(os.path.join(data_dir, x)))
num_class = len(class_names)
image_files = [
[
os.path.join(data_dir, class_names[i], x)
for x in os.listdir(os.path.join(data_dir, class_names[i]))
]
for i in range(num_class)
]
num_each = [len(image_files[i]) for i in range(num_class)]
image_files_list = []
image_class = []
for i in range(num_class):
image_files_list.extend(image_files[i])
image_class.extend([i] * num_each[i])
num_total = len(image_class)
image_width, image_height = PIL.Image.open(image_files_list[0]).size
print(f"Total image count: {num_total}")
print(f"Image dimensions: {image_width} x {image_height}")
print(f"Label names: {class_names}")
print(f"Label counts: {num_each}")
Total image count: 58954 Image dimensions: 64 x 64 Label names: ['AbdomenCT', 'BreastMRI', 'CXR', 'ChestCT', 'Hand', 'HeadCT'] Label counts: [10000, 8954, 10000, 10000, 10000, 10000]
データセットから画像をランダムに選択して可視化して確認する
plt.subplots(3, 3, figsize=(8, 8))
for i, k in enumerate(np.random.randint(num_total, size=9)):
im = PIL.Image.open(image_files_list[k])
arr = np.array(im)
plt.subplot(3, 3, i + 1)
plt.xlabel(class_names[image_class[k]])
plt.imshow(arr, cmap="gray", vmin=0, vmax=255)
plt.tight_layout()
plt.show()
訓練、検証とテストデータのリストを準備する
データセットの 10% を検証用に、そして 10% をテスト用にランダムに選択します。
val_frac = 0.1
test_frac = 0.1
length = len(image_files_list)
indices = np.arange(length)
np.random.shuffle(indices)
test_split = int(test_frac * length)
val_split = int(val_frac * length) + test_split
test_indices = indices[:test_split]
val_indices = indices[test_split:val_split]
train_indices = indices[val_split:]
train_x = [image_files_list[i] for i in train_indices]
train_y = [image_class[i] for i in train_indices]
val_x = [image_files_list[i] for i in val_indices]
val_y = [image_class[i] for i in val_indices]
test_x = [image_files_list[i] for i in test_indices]
test_y = [image_class[i] for i in test_indices]
print(
f"Training count: {len(train_x)}, Validation count: "
f"{len(val_x)}, Test count: {len(test_x)}")
Training count: 47156, Validation count: 5913, Test count: 5885
データを前処理するために MONAI 変換、Dataset と Dataloader を定義する
train_transforms = Compose(
[
LoadImage(image_only=True),
AddChannel(),
ScaleIntensity(),
RandRotate(range_x=np.pi / 12, prob=0.5, keep_size=True),
RandFlip(spatial_axis=0, prob=0.5),
RandZoom(min_zoom=0.9, max_zoom=1.1, prob=0.5),
EnsureType(),
]
)
val_transforms = Compose(
[LoadImage(image_only=True), AddChannel(), ScaleIntensity(), EnsureType()])
y_pred_trans = Compose([EnsureType(), Activations(softmax=True)])
y_trans = Compose([EnsureType(), AsDiscrete(to_onehot=True, num_classes=num_class)])
class MedNISTDataset(torch.utils.data.Dataset):
def __init__(self, image_files, labels, transforms):
self.image_files = image_files
self.labels = labels
self.transforms = transforms
def __len__(self):
return len(self.image_files)
def __getitem__(self, index):
return self.transforms(self.image_files[index]), self.labels[index]
train_ds = MedNISTDataset(train_x, train_y, train_transforms)
train_loader = torch.utils.data.DataLoader(
train_ds, batch_size=300, shuffle=True, num_workers=10)
val_ds = MedNISTDataset(val_x, val_y, val_transforms)
val_loader = torch.utils.data.DataLoader(
val_ds, batch_size=300, num_workers=10)
test_ds = MedNISTDataset(test_x, test_y, val_transforms)
test_loader = torch.utils.data.DataLoader(
test_ds, batch_size=300, num_workers=10)
ネットワークと optimizer を定義する
- バッチ毎にモデルがどのくらい更新されるかについて学習率を設定します。
- 合計エポック数を設定します、シャッフルしてランダムな変換を行ないますので、総てのエポックの訓練データは異なります。そしてこれは get start チュートリアルに過ぎませんので、4 エポックだけ訓練しましょう。10 エポック訓練すれば、モデルはテストデータセット上で 100% 精度を達成できます。
- MONAI からの DenseNet を使用して GPU デバイスに移動します、この DenseNet は 2D と 3D 分類タスクの両方をサポートできます。
- Adam optimizer を使用します。
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = DenseNet121(spatial_dims=2, in_channels=1, out_channels=num_class).to(device) loss_function = torch.nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), 1e-5) max_epochs = 4 val_interval = 1 auc_metric = ROCAUCMetric()
モデル訓練
典型的な PyTorch 訓練を実行します、これはエポック・ループとステップ・ループを実行して、総てのエポック後に検証を行ないます。ベストの検証精度を得た場合、モデル重みをファイルにセーブします。
best_metric = -1 best_metric_epoch = -1 epoch_loss_values = [] metric_values = [] for epoch in range(max_epochs): print("-" * 10) print(f"epoch {epoch + 1}/{max_epochs}") model.train() epoch_loss = 0 step = 0 for batch_data in train_loader: step += 1 inputs, labels = batch_data[0].to(device), batch_data[1].to(device) optimizer.zero_grad() outputs = model(inputs) loss = loss_function(outputs, labels) loss.backward() optimizer.step() epoch_loss += loss.item() print( f"{step}/{len(train_ds) // train_loader.batch_size}, " f"train_loss: {loss.item():.4f}") epoch_len = len(train_ds) // train_loader.batch_size epoch_loss /= step epoch_loss_values.append(epoch_loss) print(f"epoch {epoch + 1} average loss: {epoch_loss:.4f}") if (epoch + 1) % val_interval == 0: model.eval() with torch.no_grad(): y_pred = torch.tensor([], dtype=torch.float32, device=device) y = torch.tensor([], dtype=torch.long, device=device) for val_data in val_loader: val_images, val_labels = ( val_data[0].to(device), val_data[1].to(device), ) y_pred = torch.cat([y_pred, model(val_images)], dim=0) y = torch.cat([y, val_labels], dim=0) y_onehot = [y_trans(i) for i in decollate_batch(y)] y_pred_act = [y_pred_trans(i) for i in decollate_batch(y_pred)] auc_metric(y_pred_act, y_onehot) result = auc_metric.aggregate() auc_metric.reset() del y_pred_act, y_onehot metric_values.append(result) acc_value = torch.eq(y_pred.argmax(dim=1), y) acc_metric = acc_value.sum().item() / len(acc_value) if result > best_metric: best_metric = result best_metric_epoch = epoch + 1 torch.save(model.state_dict(), os.path.join( root_dir, "best_metric_model.pth")) print("saved new best metric model") print( f"current epoch: {epoch + 1} current AUC: {result:.4f}" f" current accuracy: {acc_metric:.4f}" f" best AUC: {best_metric:.4f}" f" at epoch: {best_metric_epoch}" ) print( f"train completed, best_metric: {best_metric:.4f} " f"at epoch: {best_metric_epoch}")
---------- epoch 1/4 1/157, train_loss: 1.7898 2/157, train_loss: 1.7560 3/157, train_loss: 1.7461 4/157, train_loss: 1.7241 5/157, train_loss: 1.6973 6/157, train_loss: 1.6706 7/157, train_loss: 1.6388 8/157, train_loss: 1.6210 9/157, train_loss: 1.5989 10/157, train_loss: 1.5599 11/157, train_loss: 1.5826 12/157, train_loss: 1.5339 13/157, train_loss: 1.5235 14/157, train_loss: 1.5098 15/157, train_loss: 1.4746 16/157, train_loss: 1.4584 17/157, train_loss: 1.4365 18/157, train_loss: 1.4328 19/157, train_loss: 1.4274 20/157, train_loss: 1.4327 21/157, train_loss: 1.4017 22/157, train_loss: 1.3231 23/157, train_loss: 1.3180 24/157, train_loss: 1.3001 25/157, train_loss: 1.2958 26/157, train_loss: 1.3021 27/157, train_loss: 1.2336 28/157, train_loss: 1.2154 29/157, train_loss: 1.2595 30/157, train_loss: 1.2050 31/157, train_loss: 1.2161 32/157, train_loss: 1.2106 33/157, train_loss: 1.1495 34/157, train_loss: 1.1550 35/157, train_loss: 1.1246 36/157, train_loss: 1.1607 37/157, train_loss: 1.1126 38/157, train_loss: 1.0987 39/157, train_loss: 1.0694 40/157, train_loss: 1.1181 41/157, train_loss: 1.0576 42/157, train_loss: 1.0703 43/157, train_loss: 1.0414 44/157, train_loss: 1.0446 45/157, train_loss: 1.0313 46/157, train_loss: 0.9786 47/157, train_loss: 0.9767 48/157, train_loss: 0.9579 49/157, train_loss: 0.9659 50/157, train_loss: 1.0069 51/157, train_loss: 0.9868 52/157, train_loss: 0.9637 53/157, train_loss: 0.9301 54/157, train_loss: 0.9382 55/157, train_loss: 0.8923 56/157, train_loss: 0.9034 57/157, train_loss: 0.8674 58/157, train_loss: 0.8707 59/157, train_loss: 0.8876 60/157, train_loss: 0.8628 61/157, train_loss: 0.7709 62/157, train_loss: 0.8494 63/157, train_loss: 0.8264 64/157, train_loss: 0.8011 65/157, train_loss: 0.8186 66/157, train_loss: 0.8016 67/157, train_loss: 0.7813 68/157, train_loss: 0.7447 69/157, train_loss: 0.7201 70/157, train_loss: 0.7323 71/157, train_loss: 0.7332 72/157, train_loss: 0.7379 73/157, train_loss: 0.7495 74/157, train_loss: 0.7157 75/157, train_loss: 0.7007 76/157, train_loss: 0.7058 77/157, train_loss: 0.6814 78/157, train_loss: 0.6738 79/157, train_loss: 0.6449 80/157, train_loss: 0.6393 81/157, train_loss: 0.6238 82/157, train_loss: 0.6234 83/157, train_loss: 0.6262 84/157, train_loss: 0.6044 85/157, train_loss: 0.6005 86/157, train_loss: 0.5783 87/157, train_loss: 0.5570 88/157, train_loss: 0.5569 89/157, train_loss: 0.5633 90/157, train_loss: 0.5199 91/157, train_loss: 0.5846 92/157, train_loss: 0.5915 93/157, train_loss: 0.5612 94/157, train_loss: 0.5785 95/157, train_loss: 0.5654 96/157, train_loss: 0.5437 97/157, train_loss: 0.5429 98/157, train_loss: 0.5053 99/157, train_loss: 0.5221 100/157, train_loss: 0.4928 101/157, train_loss: 0.5064 102/157, train_loss: 0.5104 103/157, train_loss: 0.4830 104/157, train_loss: 0.4901 105/157, train_loss: 0.4957 106/157, train_loss: 0.4913 107/157, train_loss: 0.4722 108/157, train_loss: 0.4756 109/157, train_loss: 0.4803 110/157, train_loss: 0.4534 111/157, train_loss: 0.4383 112/157, train_loss: 0.4437 113/157, train_loss: 0.4264 114/157, train_loss: 0.4067 115/157, train_loss: 0.4268 116/157, train_loss: 0.4136 117/157, train_loss: 0.4115 118/157, train_loss: 0.4082 119/157, train_loss: 0.4246 120/157, train_loss: 0.4018 121/157, train_loss: 0.4161 122/157, train_loss: 0.3475 123/157, train_loss: 0.4233 124/157, train_loss: 0.4043 125/157, train_loss: 0.3192 126/157, train_loss: 0.3611 127/157, train_loss: 0.3475 128/157, train_loss: 0.3580 129/157, train_loss: 0.3286 130/157, train_loss: 0.3688 131/157, train_loss: 0.3205 132/157, train_loss: 0.3745 133/157, train_loss: 0.3709 134/157, train_loss: 0.3535 135/157, train_loss: 0.3729 136/157, train_loss: 0.2839 137/157, train_loss: 0.3614 138/157, train_loss: 0.2981 139/157, train_loss: 0.3280 140/157, train_loss: 0.3031 141/157, train_loss: 0.2994 142/157, train_loss: 0.3296 143/157, train_loss: 0.3032 144/157, train_loss: 0.2965 145/157, train_loss: 0.2955 146/157, train_loss: 0.3379 147/157, train_loss: 0.3339 148/157, train_loss: 0.3092 149/157, train_loss: 0.2723 150/157, train_loss: 0.3171 151/157, train_loss: 0.2933 152/157, train_loss: 0.2841 153/157, train_loss: 0.2723 154/157, train_loss: 0.2954 155/157, train_loss: 0.2955 156/157, train_loss: 0.2969 157/157, train_loss: 0.2674 158/157, train_loss: 0.2465 epoch 1 average loss: 0.7768 saved new best metric model current epoch: 1 current AUC: 0.9984 current accuracy: 0.9618 best AUC: 0.9984 at epoch: 1 ---------- epoch 2/4 1/157, train_loss: 0.2618 2/157, train_loss: 0.2525 3/157, train_loss: 0.2640 4/157, train_loss: 0.2566 5/157, train_loss: 0.2526 6/157, train_loss: 0.2337 7/157, train_loss: 0.2311 8/157, train_loss: 0.2351 9/157, train_loss: 0.2332 10/157, train_loss: 0.2783 11/157, train_loss: 0.2521 12/157, train_loss: 0.2458 13/157, train_loss: 0.2261 14/157, train_loss: 0.2362 15/157, train_loss: 0.2702 16/157, train_loss: 0.2399 17/157, train_loss: 0.2113 18/157, train_loss: 0.2452 19/157, train_loss: 0.2202 20/157, train_loss: 0.2124 21/157, train_loss: 0.2050 22/157, train_loss: 0.2297 23/157, train_loss: 0.2410 24/157, train_loss: 0.2254 25/157, train_loss: 0.2276 26/157, train_loss: 0.2344 27/157, train_loss: 0.1969 28/157, train_loss: 0.2110 29/157, train_loss: 0.2114 30/157, train_loss: 0.2424 31/157, train_loss: 0.2111 32/157, train_loss: 0.1963 33/157, train_loss: 0.1799 34/157, train_loss: 0.1925 35/157, train_loss: 0.2277 36/157, train_loss: 0.2327 37/157, train_loss: 0.1968 38/157, train_loss: 0.2165 39/157, train_loss: 0.1924 40/157, train_loss: 0.1959 41/157, train_loss: 0.1764 42/157, train_loss: 0.2327 43/157, train_loss: 0.1955 44/157, train_loss: 0.1669 45/157, train_loss: 0.1829 46/157, train_loss: 0.1894 47/157, train_loss: 0.2079 48/157, train_loss: 0.1984 49/157, train_loss: 0.2035 50/157, train_loss: 0.1879 51/157, train_loss: 0.1839 52/157, train_loss: 0.1885 53/157, train_loss: 0.1887 54/157, train_loss: 0.1733 55/157, train_loss: 0.1828 56/157, train_loss: 0.1593 57/157, train_loss: 0.1906 58/157, train_loss: 0.1494 59/157, train_loss: 0.1740 60/157, train_loss: 0.1791 61/157, train_loss: 0.1763 62/157, train_loss: 0.1659 63/157, train_loss: 0.1961 64/157, train_loss: 0.1593 65/157, train_loss: 0.1468 66/157, train_loss: 0.1576 67/157, train_loss: 0.1567 68/157, train_loss: 0.1751 69/157, train_loss: 0.1640 70/157, train_loss: 0.1702 71/157, train_loss: 0.1406 72/157, train_loss: 0.1519 73/157, train_loss: 0.1552 74/157, train_loss: 0.1581 75/157, train_loss: 0.1564 76/157, train_loss: 0.1741 77/157, train_loss: 0.1474 78/157, train_loss: 0.1473 79/157, train_loss: 0.1402 80/157, train_loss: 0.1402 81/157, train_loss: 0.1471 82/157, train_loss: 0.1556 83/157, train_loss: 0.1329 84/157, train_loss: 0.1578 85/157, train_loss: 0.1364 86/157, train_loss: 0.1413 87/157, train_loss: 0.1170 88/157, train_loss: 0.1332 89/157, train_loss: 0.1369 90/157, train_loss: 0.1500 91/157, train_loss: 0.1320 92/157, train_loss: 0.1265 93/157, train_loss: 0.1444 94/157, train_loss: 0.1278 95/157, train_loss: 0.1348 96/157, train_loss: 0.1403 97/157, train_loss: 0.1246 98/157, train_loss: 0.1125 99/157, train_loss: 0.1509 100/157, train_loss: 0.1270 101/157, train_loss: 0.1286 102/157, train_loss: 0.1160 103/157, train_loss: 0.1239 104/157, train_loss: 0.1052 105/157, train_loss: 0.1238 106/157, train_loss: 0.1110 107/157, train_loss: 0.1429 108/157, train_loss: 0.1097 109/157, train_loss: 0.1099 110/157, train_loss: 0.1403 111/157, train_loss: 0.1460 112/157, train_loss: 0.1216 113/157, train_loss: 0.1079 114/157, train_loss: 0.1187 115/157, train_loss: 0.1519 116/157, train_loss: 0.1128 117/157, train_loss: 0.1174 118/157, train_loss: 0.1094 119/157, train_loss: 0.1106 120/157, train_loss: 0.1179 121/157, train_loss: 0.1278 122/157, train_loss: 0.1331 123/157, train_loss: 0.1484 124/157, train_loss: 0.1140 125/157, train_loss: 0.1302 126/157, train_loss: 0.1201 127/157, train_loss: 0.1038 128/157, train_loss: 0.1108 129/157, train_loss: 0.1446 130/157, train_loss: 0.0905 131/157, train_loss: 0.1323 132/157, train_loss: 0.0995 133/157, train_loss: 0.0998 134/157, train_loss: 0.0937 135/157, train_loss: 0.1240 136/157, train_loss: 0.0871 137/157, train_loss: 0.1131 138/157, train_loss: 0.1349 139/157, train_loss: 0.1316 140/157, train_loss: 0.0989 141/157, train_loss: 0.1081 142/157, train_loss: 0.1240 143/157, train_loss: 0.1104 144/157, train_loss: 0.0980 145/157, train_loss: 0.1081 146/157, train_loss: 0.0906 147/157, train_loss: 0.1624 148/157, train_loss: 0.1025 149/157, train_loss: 0.1071 150/157, train_loss: 0.0988 151/157, train_loss: 0.1151 152/157, train_loss: 0.1425 153/157, train_loss: 0.1092 154/157, train_loss: 0.0831 155/157, train_loss: 0.1252 156/157, train_loss: 0.0960 157/157, train_loss: 0.1076 158/157, train_loss: 0.0725 epoch 2 average loss: 0.1612 saved new best metric model current epoch: 2 current AUC: 0.9997 current accuracy: 0.9863 best AUC: 0.9997 at epoch: 2 ---------- epoch 3/4 1/157, train_loss: 0.1095 2/157, train_loss: 0.0810 3/157, train_loss: 0.1085 4/157, train_loss: 0.1033 5/157, train_loss: 0.1527 6/157, train_loss: 0.0988 7/157, train_loss: 0.0935 8/157, train_loss: 0.0903 9/157, train_loss: 0.0941 10/157, train_loss: 0.0742 11/157, train_loss: 0.1127 12/157, train_loss: 0.0803 13/157, train_loss: 0.0937 14/157, train_loss: 0.0810 15/157, train_loss: 0.0965 16/157, train_loss: 0.0705 17/157, train_loss: 0.0802 18/157, train_loss: 0.1040 19/157, train_loss: 0.0940 20/157, train_loss: 0.0758 21/157, train_loss: 0.1002 22/157, train_loss: 0.0720 23/157, train_loss: 0.0773 24/157, train_loss: 0.0906 25/157, train_loss: 0.1002 26/157, train_loss: 0.0948 27/157, train_loss: 0.0731 28/157, train_loss: 0.0938 29/157, train_loss: 0.0731 30/157, train_loss: 0.1004 31/157, train_loss: 0.0829 32/157, train_loss: 0.0864 33/157, train_loss: 0.0729 34/157, train_loss: 0.0773 35/157, train_loss: 0.0719 36/157, train_loss: 0.0875 37/157, train_loss: 0.0897 38/157, train_loss: 0.0740 39/157, train_loss: 0.1091 40/157, train_loss: 0.0652 41/157, train_loss: 0.0899 42/157, train_loss: 0.0853 43/157, train_loss: 0.0727 44/157, train_loss: 0.0843 45/157, train_loss: 0.0878 46/157, train_loss: 0.1135 47/157, train_loss: 0.1041 48/157, train_loss: 0.0935 49/157, train_loss: 0.0879 50/157, train_loss: 0.0922 51/157, train_loss: 0.0862 52/157, train_loss: 0.0692 53/157, train_loss: 0.0784 54/157, train_loss: 0.0986 55/157, train_loss: 0.0707 56/157, train_loss: 0.1013 57/157, train_loss: 0.0598 58/157, train_loss: 0.0639 59/157, train_loss: 0.0587 60/157, train_loss: 0.1027 61/157, train_loss: 0.0711 62/157, train_loss: 0.0775 63/157, train_loss: 0.1045 64/157, train_loss: 0.0655 65/157, train_loss: 0.0621 66/157, train_loss: 0.0636 67/157, train_loss: 0.0774 68/157, train_loss: 0.0875 69/157, train_loss: 0.0664 70/157, train_loss: 0.0707 71/157, train_loss: 0.0814 72/157, train_loss: 0.1022 73/157, train_loss: 0.0820 74/157, train_loss: 0.0829 75/157, train_loss: 0.0809 76/157, train_loss: 0.0975 77/157, train_loss: 0.0684 78/157, train_loss: 0.0686 79/157, train_loss: 0.0831 80/157, train_loss: 0.0671 81/157, train_loss: 0.0647 82/157, train_loss: 0.0574 83/157, train_loss: 0.0611 84/157, train_loss: 0.0886 85/157, train_loss: 0.0674 86/157, train_loss: 0.0609 87/157, train_loss: 0.0582 88/157, train_loss: 0.0584 89/157, train_loss: 0.0751 90/157, train_loss: 0.0720 91/157, train_loss: 0.0727 92/157, train_loss: 0.0664 93/157, train_loss: 0.0681 94/157, train_loss: 0.0791 95/157, train_loss: 0.0880 96/157, train_loss: 0.0746 97/157, train_loss: 0.0730 98/157, train_loss: 0.0818 99/157, train_loss: 0.0617 100/157, train_loss: 0.0646 101/157, train_loss: 0.0607 102/157, train_loss: 0.0749 103/157, train_loss: 0.0656 104/157, train_loss: 0.0607 105/157, train_loss: 0.0713 106/157, train_loss: 0.0725 107/157, train_loss: 0.0711 108/157, train_loss: 0.0642 109/157, train_loss: 0.0624 110/157, train_loss: 0.0685 111/157, train_loss: 0.0542 112/157, train_loss: 0.0771 113/157, train_loss: 0.0786 114/157, train_loss: 0.0580 115/157, train_loss: 0.0698 116/157, train_loss: 0.0847 117/157, train_loss: 0.0542 118/157, train_loss: 0.0760 119/157, train_loss: 0.0817 120/157, train_loss: 0.0904 121/157, train_loss: 0.0705 122/157, train_loss: 0.0541 123/157, train_loss: 0.0521 124/157, train_loss: 0.0555 125/157, train_loss: 0.0491 126/157, train_loss: 0.0504 127/157, train_loss: 0.0598 128/157, train_loss: 0.0417 129/157, train_loss: 0.0470 130/157, train_loss: 0.0584 131/157, train_loss: 0.0498 132/157, train_loss: 0.0532 133/157, train_loss: 0.0515 134/157, train_loss: 0.0575 135/157, train_loss: 0.0506 136/157, train_loss: 0.0519 137/157, train_loss: 0.0727 138/157, train_loss: 0.0796 139/157, train_loss: 0.0469 140/157, train_loss: 0.0509 141/157, train_loss: 0.0501 142/157, train_loss: 0.0603 143/157, train_loss: 0.0499 144/157, train_loss: 0.0585 145/157, train_loss: 0.0590 146/157, train_loss: 0.0447 147/157, train_loss: 0.0699 148/157, train_loss: 0.0595 149/157, train_loss: 0.0372 150/157, train_loss: 0.0446 151/157, train_loss: 0.0576 152/157, train_loss: 0.0735 153/157, train_loss: 0.0464 154/157, train_loss: 0.0742 155/157, train_loss: 0.0356 156/157, train_loss: 0.0492 157/157, train_loss: 0.0644 158/157, train_loss: 0.0630 epoch 3 average loss: 0.0743 saved new best metric model current epoch: 3 current AUC: 0.9999 current accuracy: 0.9924 best AUC: 0.9999 at epoch: 3 ---------- epoch 4/4 1/157, train_loss: 0.0563 2/157, train_loss: 0.0645 3/157, train_loss: 0.0497 4/157, train_loss: 0.0579 5/157, train_loss: 0.0442 6/157, train_loss: 0.0588 7/157, train_loss: 0.0501 8/157, train_loss: 0.0402 9/157, train_loss: 0.0432 10/157, train_loss: 0.0465 11/157, train_loss: 0.0546 12/157, train_loss: 0.0548 13/157, train_loss: 0.0430 14/157, train_loss: 0.0448 15/157, train_loss: 0.0533 16/157, train_loss: 0.0521 17/157, train_loss: 0.0406 18/157, train_loss: 0.0426 19/157, train_loss: 0.0471 20/157, train_loss: 0.0570 21/157, train_loss: 0.0611 22/157, train_loss: 0.0500 23/157, train_loss: 0.0532 24/157, train_loss: 0.0549 25/157, train_loss: 0.0488 26/157, train_loss: 0.0574 27/157, train_loss: 0.0587 28/157, train_loss: 0.0488 29/157, train_loss: 0.0509 30/157, train_loss: 0.0299 31/157, train_loss: 0.0404 32/157, train_loss: 0.0345 33/157, train_loss: 0.0569 34/157, train_loss: 0.0361 35/157, train_loss: 0.0623 36/157, train_loss: 0.0686 37/157, train_loss: 0.0376 38/157, train_loss: 0.0528 39/157, train_loss: 0.0367 40/157, train_loss: 0.0466 41/157, train_loss: 0.0551 42/157, train_loss: 0.0374 43/157, train_loss: 0.0681 44/157, train_loss: 0.0386 45/157, train_loss: 0.0636 46/157, train_loss: 0.0555 47/157, train_loss: 0.0449 48/157, train_loss: 0.0481 49/157, train_loss: 0.0382 50/157, train_loss: 0.0682 51/157, train_loss: 0.0511 52/157, train_loss: 0.0606 53/157, train_loss: 0.0490 54/157, train_loss: 0.0497 55/157, train_loss: 0.0476 56/157, train_loss: 0.0457 57/157, train_loss: 0.0545 58/157, train_loss: 0.0426 59/157, train_loss: 0.0445 60/157, train_loss: 0.0528 61/157, train_loss: 0.0597 62/157, train_loss: 0.0376 63/157, train_loss: 0.0555 64/157, train_loss: 0.0571 65/157, train_loss: 0.0475 66/157, train_loss: 0.0577 67/157, train_loss: 0.0393 68/157, train_loss: 0.0397 69/157, train_loss: 0.0536 70/157, train_loss: 0.0516 71/157, train_loss: 0.0595 72/157, train_loss: 0.0473 73/157, train_loss: 0.0624 74/157, train_loss: 0.0426 75/157, train_loss: 0.0474 76/157, train_loss: 0.0474 77/157, train_loss: 0.0516 78/157, train_loss: 0.0332 79/157, train_loss: 0.0403 80/157, train_loss: 0.0401 81/157, train_loss: 0.0397 82/157, train_loss: 0.0526 83/157, train_loss: 0.0429 84/157, train_loss: 0.0306 85/157, train_loss: 0.0433 86/157, train_loss: 0.0376 87/157, train_loss: 0.0430 88/157, train_loss: 0.0433 89/157, train_loss: 0.0575 90/157, train_loss: 0.0349 91/157, train_loss: 0.0273 92/157, train_loss: 0.0395 93/157, train_loss: 0.0474 94/157, train_loss: 0.0464 95/157, train_loss: 0.0310 96/157, train_loss: 0.0597 97/157, train_loss: 0.0403 98/157, train_loss: 0.0684 99/157, train_loss: 0.0371 100/157, train_loss: 0.0570 101/157, train_loss: 0.0468 102/157, train_loss: 0.0317 103/157, train_loss: 0.0322 104/157, train_loss: 0.0472 105/157, train_loss: 0.0351 106/157, train_loss: 0.0430 107/157, train_loss: 0.0319 108/157, train_loss: 0.0459 109/157, train_loss: 0.0448 110/157, train_loss: 0.0486 111/157, train_loss: 0.0538 112/157, train_loss: 0.0290 113/157, train_loss: 0.0567 114/157, train_loss: 0.0455 115/157, train_loss: 0.0502 116/157, train_loss: 0.0338 117/157, train_loss: 0.0541 118/157, train_loss: 0.0496 119/157, train_loss: 0.0461 120/157, train_loss: 0.0353 121/157, train_loss: 0.0569 122/157, train_loss: 0.0282 123/157, train_loss: 0.0299 124/157, train_loss: 0.0366 125/157, train_loss: 0.0397 126/157, train_loss: 0.0339 127/157, train_loss: 0.0417 128/157, train_loss: 0.0515 129/157, train_loss: 0.0433 130/157, train_loss: 0.0435 131/157, train_loss: 0.0310 132/157, train_loss: 0.0497 133/157, train_loss: 0.0366 134/157, train_loss: 0.0436 135/157, train_loss: 0.0387 136/157, train_loss: 0.0291 137/157, train_loss: 0.0480 138/157, train_loss: 0.0377 139/157, train_loss: 0.0346 140/157, train_loss: 0.0265 141/157, train_loss: 0.0497 142/157, train_loss: 0.0352 143/157, train_loss: 0.0264 144/157, train_loss: 0.0349 145/157, train_loss: 0.0409 146/157, train_loss: 0.0488 147/157, train_loss: 0.0541 148/157, train_loss: 0.0506 149/157, train_loss: 0.0451 150/157, train_loss: 0.0280 151/157, train_loss: 0.0349 152/157, train_loss: 0.0344 153/157, train_loss: 0.0307 154/157, train_loss: 0.0550 155/157, train_loss: 0.0521 156/157, train_loss: 0.0478 157/157, train_loss: 0.0295 158/157, train_loss: 0.1089 epoch 4 average loss: 0.0462 saved new best metric model current epoch: 4 current AUC: 1.0000 current accuracy: 0.9944 best AUC: 1.0000 at epoch: 4 train completed, best_metric: 1.0000 at epoch: 4
損失とメトリックをプロットする
plt.figure("train", (12, 6)) plt.subplot(1, 2, 1) plt.title("Epoch Average Loss") x = [i + 1 for i in range(len(epoch_loss_values))] y = epoch_loss_values plt.xlabel("epoch") plt.plot(x, y) plt.subplot(1, 2, 2) plt.title("Val AUC") x = [val_interval * (i + 1) for i in range(len(metric_values))] y = metric_values plt.xlabel("epoch") plt.plot(x, y) plt.show()
テストデータセット上でモデルを評価する
訓練と検証の後、検証テスト上のベストモデルを既に得ています。モデルをテストデータセット上でそれが堅牢で over fitting していないかを確認するために評価する必要があります。分類レポートを生成するためにこれらの予測を使用します。
model.load_state_dict(torch.load( os.path.join(root_dir, "best_metric_model.pth"))) model.eval() y_true = [] y_pred = [] with torch.no_grad(): for test_data in test_loader: test_images, test_labels = ( test_data[0].to(device), test_data[1].to(device), ) pred = model(test_images).argmax(dim=1) for i in range(len(pred)): y_true.append(test_labels[i].item()) y_pred.append(pred[i].item())
print(classification_report( y_true, y_pred, target_names=class_names, digits=4))
Note: you may need to restart the kernel to use updated packages. precision recall f1-score support AbdomenCT 0.9816 0.9917 0.9867 969 BreastMRI 0.9968 0.9831 0.9899 944 CXR 0.9979 0.9928 0.9954 973 ChestCT 0.9938 0.9990 0.9964 959 Hand 0.9934 0.9934 0.9934 1055 HeadCT 0.9960 0.9990 0.9975 985 accuracy 0.9932 5885 macro avg 0.9932 0.9932 0.9932 5885 weighted avg 0.9932 0.9932 0.9932 5885
データディレクトリのクリーンアップ
一時ディレクトリが使用された場合ディレクトリを削除します。
if directory is None: shutil.rmtree(root_dir)
以上
MONAI 0.7 : モジュール概要 (1) 医用画像データI/O, 前処理と増強
MONAI 0.7 : モジュール概要 (1) 医用画像データI/O, 前処理と増強 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/05/2021 (0.7.0)
* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- テレワーク & オンライン授業を支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ ; Facebook |
MONAI 0.7 : モジュール概要 (1) 医用画像データI/O, 前処理と増強
MONAI は医用画像解析における深層学習を様々な粒度でサポートすることを目的としています。この図は end-to-end ワークフローの典型的な例を示します :
MONAI アーキテクチャ
MONAI の設計原理は様々な専門知識を持つユーザのために柔軟で軽量な API を提供することです。
- 総てのコアコンポーネントは独立したモジュールで、これらは任意の既存の PyTorch プログラムに容易に統合できます。
- ユーザは、研究実験のための堅固な訓練や評価プログラムを素早くセットアップするために MONAI のワークフローを活用できます。
- 主要な機能を実演するために豊富なサンプルとデモが提供されます。
- COVID-19 画像解析、モデル並列等を含む、最新の研究課題のための最先端技術に基づいて研究者が実装を提供しています。
全体的なアーキテクチャとモジュールは次の図で示されます :
医用画像データ I/O、(前) 処理と増強
医用画像は I/O、前処理と増強のための高度に特化された方法を必要とします。医用画像は豊富なメタ情報を持つ特別な形式にあることが多く、データボリュームは高次元であることが多いです。これれは注意深く設計された操作手続きを必要とします。MONAI の医用画像フォーカスは強力で柔軟な画像変換により可能になります、これは使い勝手の良い、再現性のある、最適化された医療データ前処理パイプラインを容易にします。
1. 辞書と配列形式データの両方をサポートする変換
- (torchvision のような) 広く使用されているコンピュータビジョン・パッケージは空間的に 2D な配列画像処理にフォーカスしています。MONAI は空間的に 2D と 2D の両方のためによりドメイン固有な変換を提供し、そして柔軟な変換 “compose” 機能を保持しています。
- 医用画像前処理は追加の極め細かいシステムパラメータを必要とすることが多いので、MONAI は python 辞書にカプセル化された入力データのための変換を提供します。ユーザは複雑な変換を構成するために想定されるデータフィールドに対応するキーとシステムパラメータを指定できます。
6 つのカテゴリー内の変換の豊富なセットがあります : Crop & Pad, 強度, IO, 後処理, Spatial とユティリティです。詳細は、MONAI の変換の総て にアクセスしてください。
殆ど総ての変換は入力データがチャネル first の shape 形式を持つことを想定しています : [Channel dim, spatial dim 1, spatial dim 2, …] です。柔軟な ベース API がまた提供されます。monai.transforms モジュールは簡単に拡張可能です。
2. 医療に特化した変換
MONAI は包括的な医療に特化した変換を提供することを目的としています。これらが現在、例えば以下を含みます :
- LoadImage: 指定されたパスから医療固有の形式のファイルをロードする
- Spacing: 入力画像を指定された pixdim に再サンプリングする
- Orientation: 画像の方向を指定された axcodes に変更する
- RandGaussianNoise: 統計的なノイズを追加して画像強度を摂動を与える
- NormalizeIntensity: 平均と標準偏差に基づく強度正規化
- Affine: アフィン・パラメータに基づいて画像を変換する
- Rand2DElastic: ランダムな elastic 変形と 2D のアフィン
- Rand3DElastic: ランダムな elastic 変形と 3D のアフィン
2D 変換チュートリアル は幾つかの MONAI 医用画像特有の変換の詳細な使用方法を示します。
3. 変換は NumPy 配列と PyTorch テンソルの両方をサポートします (CPU or GPU accelerated)
MONAI v0.7 から変換で PyTorch テンソルベースの計算を導入しましたが、多くの変換は入力タイプと計算バックエンドとして NumPy 配列とテンソルを既にサポートしています。総ての変換のサポートされているバックエンドを取得するには、次を実行してください : python monai/transforms/utils.py.
変換を高速化するためには、一般的なアプローチは GPU 並列計算を利用することです。ユーザは最初に ToTensor または EnsureType 変換により入力データを GPU テンソルに変換し、それから続く変換を PyTorch テンソル API に基づいて GPU 上で実行できます。GPU 変換チュートリアルは Spleen 高速訓練チュートリアル で利用可能です。
4. 融合した空間変換
医用画像ボリュームは (多次元配列にあるので) 通常は大規模ですので、前処理パフォーマンスは全体的なパイプライン速度に影響します。MONAI は融合した空間操作を実行するアフィン変換を提供します。
例えば :
# create an Affine transform
affine = Affine(
rotate_params=np.pi/4,
scale_params=(1.2, 1.2),
translate_params=(200, 40),
padding_mode='zeros',
)
# convert the image using bilinear interpolation
new_img = affine(image, spatial_size=(300, 400), mode='bilinear')
実験とテスト結果は 融合した変換テスト で利用可能です。
現在、総ての幾何学的画像変換 (Spacing, ズーム, 回転, リサイズ 等) は PyTorch ネイティブ・インターフェイスに基づいて設計されています。そのためそれらの総ては高性能のための GPU テンソル演算を通して GPU 高速化をサポートしています。
幾何学的変換チュートリアル は 3D 医用画像でアフィン変換の使用方法を示します。
5. ポジティブ/ネガティブ比率に基づいてランダムにクロップ
医用画像データボリュームは GPU メモリに収まらないほど大きい場合があります。広く使用されているアプローチは、訓練の間は小さいデータサンプルをランダムにドローして推論のために「スライディング・ウィンドウ」ルーチンを実行することです。MONAI は現在、パッチベースの訓練プロセスを安定化させるのに役立つ可能性のある、クラス・バランスの取れた固定比率サンプリングを含む一般的なランダム・サンプリング・ストラテジーを提供しています。典型的な例は 脾臓 3D セグメンテーション・チュートリアル で、これは RandCropByPosNegLabel 変換とともにクラス・バランスのとれたサンプリングを実現しています。
6. 再現性のための決定論的訓練
決定論的訓練のサポートは深層学習研究、特に医療分野では必要で重要です。ユーザは MONAI の総てのランダム変換にランダムシードをローカルで簡単に設定できてユーザのプログラムの他の非決定論的モジュールに影響を与えません。
例えば :
# define a transform chain for pre-processing
train_transforms = monai.transforms.Compose([
LoadImaged(keys=['image', 'label']),
RandRotate90d(keys=['image', 'label'], prob=0.2, spatial_axes=[0, 2]),
... ...
])
# set determinism for reproducibility
train_transforms.set_random_state(seed=0)
ユーザはまた訓練プログラムの最初に決定論的 (動作) を有効/無効にできます :
monai.utils.set_determinism(seed=0, additional_settings=None)
7. マルチ変換チェイン
同じデータに様々な変換を適用して結果を連結するために、MONAI は、データ辞書の指定された項目のコピーを作成する CopyItems 変換と想定される次元の指定項目を組み合わせるために ConcatItems 変換を提供し、そしてまたメモリを節約するために不要な項目を削除するための DeleteItems 変換も提供します。
典型的な使用方法は同じ画像の強度を異なる範囲にスケールして結果を一緒に連結します。
8. DataStats で変換をデバッグする
変換が “compose” 関数と組み合わされるとき、特定の変換の出力を追跡することは容易ではありません。合成された変換のエラーをデバッグするのを手助けするために、MONAI は、データ shape, 値範囲, データ値, 追加情報等の中間的なデータ特性を表示するために DataStats のようなユティリティ変換を提供しています。それは自己充足的な変換で任意の変換チェインに統合できます。
9. モデル出力のための後処理変換
MONAI はまたモデル出力を処理するための後処理変換も提供しています。現在、変換は以下を含みます :
- 活性化層の追加 (Sigmoid, Softmax, etc.)。
- 下図 (b) のように、離散値 (Argmax, One-Hot, Threshold 値等) に変換します。
- マルチチャネル・データを複数のシングル・チャネルに分割する。
- 下図 (c) のように、接続コンポーネント分析に基づいてセグメンテーション・ノイズを除去する。
- 下図 (d) と (e) のように、セグメンテーション結果の輪郭を抽出します、これは元の画像へのマップに使用できてモデルを評価できます。
モデル出力のバッチデータを切り離し (= decollate) 後処理変換を適用した後では、メトリックを計算し、モデル出力をファイルにセーブし、あるいは TensorBoard でデータを可視化することは容易になります。後処理変換チュートリアル は後処理のための幾つかの主要な変換を使用するサンプルを示しています。
10. サードパーティの変換の統合
MONAI 変換の設計はコードの可読性と使い易さを重視しています。それは配列データや辞書ベースのデータのために動作します。MONAI はまた 3rd パーティの変換の異なるデータ形式に対応するためにアダプタ・ツールも提供しています。データ shape やタイプを変換するために ToTensor, ToNumpy, SqueezeDim のようなユティリティ変換も提供されます。従って、ITK, BatchGenerator, TorchIO と Rising を含む外部パッケージから変換をシームレスに統合することにより変換チェインを強化することは簡単です。
詳細は、チュートリアル: integrate 3rd party transforms into MONAI program を確認してください。
デジタル病理 (= pathology) 訓練では、画像のロードの膨大な負荷のために、CPU は画像のロードに先取りされてデータの前処理が追いつきません。これはパイプラインが IO に束縛されることを引き起こし GPU の使用率低下という結果になります。このボトルネックを解消するため、cuCIM は (私達がデジタル病理パイプラインで使用している) 幾つかの一般的な変換の最適化バージョンを実装しました。これらの変換は GPU 上でネイティブに実行されて CuPy 配列上動作します。MONAI は cuCIM ライブラリを統合するために CuCIM と RandCuCIM アダプタを提供しています。例えば :
RandCuCIM(name="color_jitter", brightness=64.0 / 255.0, contrast=0.75, saturation=0.25, hue=0.04)
CuCIM(name="scale_intensity_range", a_min=0.0, a_max=255.0, b_min=-1.0, b_max=1.0)
それは転移検出モデルの病理学の訓練で大幅なスピードアップを示しました。
11. 医用画像形式のための IO ファクトリー
多くのポピュラーな画像形式が医療ドメインに存在し、それらは豊富なメタデータ情報を持ち非常に異なります。同じパイプラインで異なる医用画像形式を簡単に処理するため、MONAI は LoadImage 変換を提供します、これはサポートされるサフィックスに基づいて以下の優先順位で画像リーダーを自動的に選択できます :
- このローダを呼び出すとき実行時にユーザに指定されたリーダー。
- 登録されたリーダー、リストの最新のものから最初のものへ。
- デフォルトのリーダ : (nii, nii.gz -> NibabelReader), (png, jpg, bmp -> PILReader), (npz, npy -> NumpyReader), (others -> ITKReader)。
ImageReader API は非常に簡単で、ユーザはカスタマイズされた画像リーダーのためにそれを簡単に拡張できます。
これらの事前定義された画像リーダーにより、MONAI は次の形式で画像をロードできます : NIfTI, DICOM, PNG, JPG, BMP, NPY/NPZ, 等々。
12. 変換データを NIfTI または PNG ファイルにセーブする
画像をファイルに変換したり、変換チェインをデバッグするため、MONAI は SaveImage 変換を提供しています。結果をセーブするためユーザはこの変換を変換チェインに注入できます。
13. チャネル first データ shape を自動的に確実にする
医用画像は様々な shape 形式を持ちます。それらはチャネル last、チャネル first あるいはノーチャネルでさえある可能性があります。例えば、幾つかのノーチャネル画像をロードしてそれらをチャネル first データとしてスタックすることを望むかもしれません。ユーザ体験を改善するため、MONAI はメタ情報に従ってデータ shape を自動的に検出してそれを一貫してチャネル first 形式に変換する EnsureChannelFirst 変換を提供しました。
14. 空間的変換とテスト時増強を反転する
深層学習ワークフローでは前に適用した空間的変換 (リサイズ, 反転, 回転, ズーム, クロップ, pad 等) を反転する (= inverse) ことが望ましい場合があります、例えば、正規化されたデータ空間で画像データを処理した後で元の画像空間に戻すためです。多くの空間的変換が 0.5 から反転演算で強化されています。モデル推論チュートリアル が基本的なサンプルを示しています。
パイプラインがランダムな変換を含む場合、ユーザは出力上でこれらの変換が持つ効果を観察することを望むかもしれません。典型的なアプローチは、異なるランダムな具現化で複数回変換を通して同じ入力を渡すことです。そして総ての結果を共通の空間に移すために反転変換を使用して、メトリクスを計算します。MONAI はこの機能のために TestTimeAugmentation を提供しました、これはデフォルトで 最頻値, 平均値, 標準偏差と volume 変動係数を計算します。
Invert transforms and TTA チュートリアル は使用サンプルとともに API について詳細を紹介しています。
(1) 最後のカラムはモデル出力の反転されたデータです :
(2) 最頻値, 平均と標準偏差の TTA 結果 :
以上
MONAI 0.7 : PyTorch ユーザのための MONAI
MONAI 0.7 : PyTorch ユーザのための MONAI (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/05/2021 (0.7.0)
* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- テレワーク & オンライン授業を支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ ; Facebook |
MONAI 0.7 : PyTorch ユーザのための MONAI
このチュートリアルは MONAI API を簡単に紹介してその柔軟性と使い易さにハイライトを当てます。それは PyTorch の基本的な理解を前提とし、MONAI がヘルスケア画像の深層学習のためにドメインに最適化された機能を提供する方法を示します。
パッケージのインストール
MONAI のコア機能は Python (3.6+) で書かれていて Numpy (1.17+) and Pytorch (1.4+) にのみ依存しています。
このセクションは MONAI の最新版をインストールしてインストールを検証します。
# install the latest weekly preview version of MONAI
%pip install -q "monai-weekly[tqdm, nibabel, gdown, ignite]"
|████████████████████████████████| 652 kB 11.0 MB/s |████████████████████████████████| 221 kB 52.5 MB/s
import warnings
warnings.filterwarnings("ignore") # remove some scikit-image warnings
import monai
monai.config.print_config()
MONAI version: 0.7.dev2138 Numpy version: 1.19.5 Pytorch version: 1.9.0+cu102 MONAI flags: HAS_EXT = False, USE_COMPILED = False MONAI rev id: bfc42f02d3bbbc1bfa36abbc71df8a6ca863bd76 Optional dependencies: Pytorch Ignite version: 0.4.5 Nibabel version: 3.0.2 scikit-image version: 0.16.2 Pillow version: 7.1.2 Tensorboard version: 2.6.0 gdown version: 3.6.4 TorchVision version: 0.10.0+cu102 tqdm version: 4.62.2 lmdb version: 0.99 psutil version: 5.4.8 pandas version: 1.1.5 einops version: NOT INSTALLED or UNKNOWN VERSION. transformers version: NOT INSTALLED or UNKNOWN VERSION. For details about installing the optional dependencies, please visit: https://docs.monai.io/en/latest/installation.html#installing-the-recommended-dependencies
数行のコードでパブリックな医療画像データセットへアクセス
公開されているベンチマークの使用はオープンで再現性のある研究のために重要です。MONAI は良く知られた公開データセットへの素早いアクセスを提供することを目的としています。このセクションは医療セグメンテーション・デカスロン (= Medical Segmentation Decathlon ) のデータセットから始めます。
DecathlonDataset オブジェクトは torch.data.utils.Dataset の薄いラッパーです。それは __getitem__ と __len__ を実装していて、PyTorch の組込みデータローダ torch.data.utils.DataLoader と完全に互換です。
PyTorch データセット API と比較して、DecathlonDataset は以下の追加機能を持ちます :
- 自動的なデータのダウンロードと解凍
- データと前処理の中間結果のキャッシング
- 訓練、検証とテストのランダムな分割
from monai.apps import DecathlonDataset
dataset = DecathlonDataset(root_dir="./", task="Task05_Prostate", section="training", transform=None, download=True)
print(f"\nnumber of subjects: {len(dataset)}.\nThe first element in the dataset is {dataset[0]}.")
Task05_Prostate.tar: 229MB [00:15, 15.8MB/s] Downloaded: ./Task05_Prostate.tar Verified 'Task05_Prostate.tar', md5: 35138f08b1efaef89d7424d2bcc928db. Writing into directory: ./. Loading dataset: 100%|██████████| 26/26 [00:00<00:00, 107018.55it/s] number of subjects: 26. The first element in the dataset is {'image': 'Task05_Prostate/imagesTr/prostate_46.nii.gz', 'label': 'Task05_Prostate/labelsTr/prostate_46.nii.gz'}.
コードセクションは公開レポジトリから "Task05_Prostate.tar" (download=True) をダウンロードして、それを解凍し、そしてアーカイブにより提供される JSON ファイルを解析することにより DecathlonDataset を作成しました。
これは前立腺 (= prostate) 移行 (= transitional) ゾーンと周辺 (= peripheral) ゾーンの輪郭を描く (= delineate) ための 3 クラス・セグメンテーション・タスクです (背景, TZ, PZ クラス)。入力は 2 つの様式、つまり T2 と ADC MRI を持ちます。
len(dataset) と dataset[0] は、それぞれデータセットのサイズを問い合わせ、データセットの最初の要素を取り出します。データセットのためのどのような画像変換も指定していませんので、この iterable なデータセットの出力は画像とセグメンテーション・ファイル名の単なるペアです。
柔軟な画像データ変換
このセクションはファイル名をメモリ内のデータ配列に変換する MONAI 変換を導入します、これは深層学習モデルにより消費される準備ができます。前処理パイプラインのより多くのサンプルは tutorial レポジトリと開発者ガイドで利用可能です。ここでは画像前処理の主要な機能を簡単にカバーします。
配列 vs 辞書ベースの変換
配列変換は MONAI の基本的なビルディングブロックで、それは torchvision.transforms と同様な単純な callable です。2 つの違いがあります :
- MONAI 変換は医療画像特有の処理機能を実装しています。
- MONAI 変換は入力が numpy 配列、pytorch テンソルかテンソル like なオブジェクトであることを前提としています。
以下はローダー変換を開始します、これはファイル名文字列を実際の画像データに変換します。この変換への その他のオプションのドキュメント を参照してください。
from monai.transforms import LoadImage
loader = LoadImage(image_only=True)
img_array = loader("Task05_Prostate/imagesTr/prostate_02.nii.gz")
print(img_array.shape)
(320, 320, 24, 2)
辞書変換は配列バージョンのラッパーに過ぎません。配列ベースのものと比べて、同じ種類の演算やステートメントを複数のデータ入力に適用することが簡単です。
以下のセクションは画像とセグメンテーション・マスクのペアを読みます、変換が辞書のどの項目が処理されるべきかを知れるようにキーが指定される必要があることに注意してください。
from monai.transforms import LoadImageD
dict_loader = LoadImageD(keys=("image", "label"))
data_dict = dict_loader({"image": "Task05_Prostate/imagesTr/prostate_02.nii.gz",
"label": "Task05_Prostate/labelsTr/prostate_02.nii.gz"})
print(f"image shape: {data_dict['image'].shape}, \nlabel shape: {data_dict['label'].shape}")
image shape: (320, 320, 24, 2), label shape: (320, 320, 24)
変換の構成
多くの場合、変換のチェインを構築して、前処理パラメータを調整して、高速な前処理パイプラインを作成することは有益です。monai.transforms.Compose はこれらのユースケースのために設計されています。
以下のコードは複数の前処理ステップを行なうために変換チェインを開始しています :
- Nifti 画像を (画像メタデータ情報と共に) ロードします
- 画像とラベルの両方をチャネル first にする (画像を reshape してラベルのためにチャネル次元を追加します)
- 画像とラベルを 1 mm 四方にする
- 画像とラベルの両方を "RAS" 座標系にあるようにする
- 画像強度をスケールする
- 画像とラベルを空間サイズ (64, 64, 32) mm にリサイズする
- 画像をランダムに回転とスケールしますが、出力サイズは (64, 64, 32) mm に保持します。
- 画像とラベルを torch テンソルに変換する
import numpy as np
from monai.transforms import \
LoadImageD, EnsureChannelFirstD, AddChannelD, ScaleIntensityD, ToTensorD, Compose, \
AsDiscreteD, SpacingD, OrientationD, ResizeD, RandAffineD
KEYS = ("image", "label")
xform = Compose([
LoadImageD(KEYS),
EnsureChannelFirstD("image"),
AddChannelD("label"),
SpacingD(KEYS, pixdim=(1., 1., 1.), mode=('bilinear', 'nearest')),
OrientationD(KEYS, axcodes='RAS'),
ScaleIntensityD(keys="image"),
ResizeD(KEYS, (64, 64, 32), mode=('trilinear', 'nearest')),
RandAffineD(KEYS, spatial_size=(-1, -1, -1),
rotate_range=(0, 0, np.pi/2),
scale_range=(0.1, 0.1),
mode=('bilinear', 'nearest'),
prob=1.0),
ToTensorD(KEYS),
])
data_dict = xform({"image": "Task05_Prostate/imagesTr/prostate_02.nii.gz",
"label": "Task05_Prostate/labelsTr/prostate_02.nii.gz"})
print(data_dict["image"].shape, data_dict["label"].shape)
torch.Size([2, 64, 64, 32]) torch.Size([1, 64, 64, 32])
MONAI には有用な変換のセットがあり、今後更に増えます。詳細は https://docs.monai.io/en/latest/transforms.html を見てください。
データセット、変換とデータローダ
私達が持っているものをまとめると :
- Dataset : torch.utils.data.Dataset の薄いラッパー
- Transform : callable、Compose により作成される変換チェインの一部です。
- データセットへの変換のセットはデータロードと前処理パイプラインを可能にします。
パイプラインは pytorch ネイティブのデータローダと連携できて、これはマルチプロセスのサポートと柔軟なバッチサンプリング・スキームを提供します。
けれども、MONAI データローダ monai.data.DataLoader と連携することが推奨されます、これは pytorch ネイティブのラッパーです。MONAI データローダは以下の機能を主として追加します :
- マルチプロセスのコンテキストでランダム化された増強を正しく処理します。
- マルチサンプルデータのリストを個々の訓練サンプルに平坦化するためのカスタマイズされた collate 関数
import torch
from monai.data import DataLoader
# start a chain of transforms
xform = Compose([
LoadImageD(KEYS),
EnsureChannelFirstD("image"),
AddChannelD("label"),
SpacingD(KEYS, pixdim=(1., 1., 1.), mode=('bilinear', 'nearest')),
OrientationD(KEYS, axcodes='RAS'),
ScaleIntensityD(keys="image"),
ResizeD(KEYS, (64, 64, 32), mode=('trilinear', 'nearest')),
RandAffineD(KEYS, spatial_size=(-1, -1, -1),
rotate_range=(0, 0, np.pi/2),
scale_range=(0.1, 0.1),
mode=('bilinear', 'nearest'),
prob=1.0),
ToTensorD(KEYS),
])
# start a dataset
dataset = DecathlonDataset(root_dir="./", task="Task05_Prostate", section="training", transform=xform, download=True)
# start a pytorch dataloader
# data_loader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, num_workers=1)
data_loader = DataLoader(dataset, batch_size=1, shuffle=True, num_workers=1)
Verified 'Task05_Prostate.tar', md5: 35138f08b1efaef89d7424d2bcc928db. File exists: ./Task05_Prostate.tar, skipped downloading. Non-empty folder exists in ./Task05_Prostate, skipped extracting. Loading dataset: 100%|██████████| 26/26 [00:17<00:00, 1.51it/s]
data_dict で何が起きているか覗いてみましょう (以下のセクションの再実行はデータセットからのランダムに増強されたサンプルを生成します) :
import matplotlib.pyplot as plt
import numpy as np
data_dict = next(iter(data_loader))
print(data_dict["image"].shape, data_dict["label"].shape, data_dict["image_meta_dict"]["filename_or_obj"])
plt.subplots(1, 3)
plt.subplot(1, 3, 1); plt.imshow(data_dict["image"][0, 0, ..., 16])
plt.subplot(1, 3, 2); plt.imshow(data_dict["image"][0, 1, ..., 16])
plt.subplot(1, 3, 3); plt.imshow(data_dict["label"][0, 0, ..., 16])
plt.show()
print(f"unique labels: {np.unique(data_dict['label'])}")
torch.Size([1, 2, 64, 64, 32]) torch.Size([1, 1, 64, 64, 32]) ['Task05_Prostate/imagesTr/prostate_42.nii.gz']
データローダは、深層学習モデルに対応できるように、画像とラベルの両方にバッチ次元を追加しました。
ラベルのために "nearest" 補完モードが使用されますので、変換中に一意のクラスの数が保持されます。
層、ブロック、ネットワークと損失関数
データ入力パイプラインを通り抜けました。適切に前処理されたデータは、2 つの様式の入力を使用して 3 クラス・セグメンテーション・タスクのための準備ができました。
このセクションは UNet モデル、そして損失関数と optimzer を作成します。これら総てのモジュールは (torch.nn.Module のような) PyTorch インターフェイスの直接的な使用か拡張です。それらは、コードが標準 PyTorch API に従うのであれば、任意のカスタマイズされた Python コードで置き換え可能です。
MONAI のモジュールは医療画像解析のために拡張モジュールを提供することに焦点を当てています :
- 柔軟性とコード可読性の両者を目的とした参照ネットワークの実装
- 1D, 2D と 3D ネットワークと互換な事前定義された層とブロック
- ドメイン固有の損失関数
from monai.networks.nets import UNet
from monai.networks.layers import Norm
from monai.losses import DiceLoss
device = torch.device('cuda:0')
net = UNet(dimensions=3, in_channels=2, out_channels=3, channels=(16, 32, 64, 128, 256),
strides=(2, 2, 2, 2), num_res_units=2, norm=Norm.BATCH).to(device)
loss = DiceLoss(to_onehot_y=True, softmax=True)
opt = torch.optim.Adam(net.parameters(), 1e-2)
`UNet` は `dimensions` パラメータで定義されます。それは Conv1d, Conv2d と Conv3d のような、pytorch API の空間次元の数を指定します。同じ実装で、1D, 2D, 3D とマルチモーダル訓練のために容易に構成できます。
`torch.nn.Module` の拡張としての `UNet` は特定の方法で体系化された MONAI ブロックと層のセットです。ブロックと層は、"Conv. + Feature Norm. + Activation" のような一般に使用される組合せのように、再利用可能なサブモジュールとして設計されています。
スライディング・ウィンドウ推論
この一般に使用されるモジュールについて、MONAI は単純な PyTorch ベースの実装を提供します、これはウィンドウサイズと入力モデル (これは torch.nn.Module 実装であり得ます) の仕様だけを必要とします。
以下のデモは、総ての空間位置を通して実行される (40, 40) 空間サイズ・ウィンドウ を集約することにより、(1, 1, 200, 200) の入力画像上のスライディング・ウィンドウ推論の toy を示します。
roi_size, sw_batch_size と overlap パラメータをそれらのスライディング・ウィンドウ出力上のインパクトを見るために変更することができます。
from monai.inferers import SlidingWindowInferer
class ToyModel:
# A simple model generates the output by adding an integer `pred` to input.
# each call of this instance increases the integer by 1.
pred = 0
def __call__(self, input):
self.pred = self.pred + 1
input = input + self.pred
return input
infer = SlidingWindowInferer(roi_size=(40, 40), sw_batch_size=1, overlap=0)
input_tensor = torch.zeros(1, 1, 200, 200)
output_tensor = infer(input_tensor, ToyModel())
plt.imshow(output_tensor[0, 0]); plt.show()
訓練ワークフローの開始 (エポック毎に検証)
入力パイプライン、ネットワーク・アーキテクチャ、損失関数は総て既存の pytorch ベースのワークフローと互換です。様々なユースケースについてはチュートリアルを参照してください : https://github.com/Project-MONAI/tutorials
ここで PyTorch-Ignite ベースで MONAI により構築された、ワークフロー・ユティリティにハイライトを当てたいです。主要な目標は、比較的標準的な訓練ワークフローを構築する際にユーザの労力を軽減することです。
import ignite
print(ignite.__version__)
0.4.5
以下のコマンドは SupervisedTrainer インスタンスを起動します。PyTorch ignite の機能の拡張として、それは前に言及した総ての要素を結合します。trainer.run() の呼び出しは 2 エポックの間ネットワークを訓練して、総てのエポックの最後に訓練データに基づいて MeadDice メトリックを計算します。
key_train_metric はモデルの品質向上の進捗を追跡するために使用されます。
早期停止と学習率スケジューリングを行なうために追加のハンドラが設定可能です。StatsHandler は診断情報を stdout にプリントするために各訓練反復でトリガーされます。これらはユーザ指定の頻度で詳細な訓練ログを生成するように構成できます。イベント処理システムの詳細は、ドキュメント https://docs.monai.io/en/latest/handlers.html を参照してください。
注目すべき点は、これらの機能は通常の訓練と検証パイプラインの高速なプロトタイピングを容易にすることです。ユーザは前のセクションで述べたモジュールを利用して、独自のパイプラインを構築することを常に選択できます。
from monai.engines import SupervisedTrainer
from monai.inferers import SlidingWindowInferer
from monai.handlers import StatsHandler, MeanDice, from_engine
from monai.transforms import AsDiscreteD
import sys
import logging
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
trainer = SupervisedTrainer(
device=device,
max_epochs=2,
train_data_loader=data_loader,
network=net,
optimizer=opt,
loss_function=loss,
inferer=SlidingWindowInferer((32, 32, -1), sw_batch_size=2),
postprocessing=AsDiscreteD(keys=["pred", "label"], argmax=(True, False), to_onehot=True, n_classes=3),
key_train_metric={"train_meandice": MeanDice(output_transform=from_engine(["pred", "label"]))},
train_handlers=StatsHandler(tag_name="train_loss", output_transform=from_engine(["loss"], first=True)),
)
trainer.run()
INFO:ignite.engine.engine.SupervisedTrainer:Engine run resuming from iteration 0, epoch 0 until 2 epochs INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 1/26 -- train_loss: 0.8139 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 2/26 -- train_loss: 0.7707 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 3/26 -- train_loss: 0.6901 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 4/26 -- train_loss: 0.6979 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 5/26 -- train_loss: 0.7192 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 6/26 -- train_loss: 0.6859 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 7/26 -- train_loss: 0.6445 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 8/26 -- train_loss: 0.6273 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 9/26 -- train_loss: 0.6346 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 10/26 -- train_loss: 0.6078 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 11/26 -- train_loss: 0.5424 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 12/26 -- train_loss: 0.5851 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 13/26 -- train_loss: 0.5647 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 14/26 -- train_loss: 0.5551 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 15/26 -- train_loss: 0.5925 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 16/26 -- train_loss: 0.5389 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 17/26 -- train_loss: 0.5662 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 18/26 -- train_loss: 0.6309 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 19/26 -- train_loss: 0.6168 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 20/26 -- train_loss: 0.5556 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 21/26 -- train_loss: 0.5243 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 22/26 -- train_loss: 0.5801 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 23/26 -- train_loss: 0.5132 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 24/26 -- train_loss: 0.4951 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 25/26 -- train_loss: 0.4870 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/2, Iter: 26/26 -- train_loss: 0.5108 INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_meandice: 0.4181462824344635 INFO:ignite.engine.engine.SupervisedTrainer:Epoch[1] Metrics -- train_meandice: 0.4181 INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_meandice best value: 0.4181462824344635 at epoch: 1 INFO:ignite.engine.engine.SupervisedTrainer:Epoch[1] Complete. Time taken: 00:00:08 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 1/26 -- train_loss: 0.5620 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 2/26 -- train_loss: 0.5373 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 3/26 -- train_loss: 0.4764 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 4/26 -- train_loss: 0.5111 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 5/26 -- train_loss: 0.5922 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 6/26 -- train_loss: 0.5519 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 7/26 -- train_loss: 0.6246 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 8/26 -- train_loss: 0.4363 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 9/26 -- train_loss: 0.5052 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 10/26 -- train_loss: 0.5900 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 11/26 -- train_loss: 0.5997 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 12/26 -- train_loss: 0.4996 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 13/26 -- train_loss: 0.4969 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 14/26 -- train_loss: 0.5740 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 15/26 -- train_loss: 0.5852 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 16/26 -- train_loss: 0.5460 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 17/26 -- train_loss: 0.5034 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 18/26 -- train_loss: 0.5233 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 19/26 -- train_loss: 0.5109 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 20/26 -- train_loss: 0.4877 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 21/26 -- train_loss: 0.5745 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 22/26 -- train_loss: 0.5044 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 23/26 -- train_loss: 0.4623 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 24/26 -- train_loss: 0.4399 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 25/26 -- train_loss: 0.4553 INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/2, Iter: 26/26 -- train_loss: 0.5245 INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_meandice: 0.4688393473625183 INFO:ignite.engine.engine.SupervisedTrainer:Epoch[2] Metrics -- train_meandice: 0.4688 INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_meandice best value: 0.4688393473625183 at epoch: 2 INFO:ignite.engine.engine.SupervisedTrainer:Epoch[2] Complete. Time taken: 00:00:08 INFO:ignite.engine.engine.SupervisedTrainer:Engine run complete. Time taken: 00:00:16
決定論的訓練
決定論的訓練サポートは再現可能な研究のために重要です。MONAI は現在 2 つのメカニズムを提供しています :
- 総てのランダム変換のランダム状態を設定します。これはグローバルなランダム状態には影響しません。例えば :
# define a transform chain for pre-processing train_transforms = monai.transforms.Compose([ LoadNiftid(keys=['image', 'label']), RandRotate90d(keys=['image', 'label'], prob=0.2, spatial_axes=[0, 2]), ... ... ]) # set determinism for reproducibility train_transforms.set_random_state(seed=0)
- 1行のコードでグローバルに python, numpy と pytorch のための決定論的訓練を有効にします、例えば :
monai.utils.set_determinism(seed=0, additional_settings=None)
まとめ
MONAI の主要なモジュールを通り抜けてきました。高度に柔軟な拡張とラッパーを作成することにより、MONAI は医療画像解析の観点から pytorch API を強化しています。
以下のような、この短いチュートリアルではカバーされなかったソフトウェア機能があります :
- 後処理変換
- 視覚化インターフェイス
- サードパーティの医療画像ツールキットからの組み込めるデータ変換
- 他の人気のある深層学習フレームワークを使用するワークフローの構築
- MONAI 研究
最新のマイルストーンのハイライトの詳細については、https://docs.monai.io/en/latest/highlights.html にアクセスしてください。
MONAI を深く理解するには、examples レポジトリは良い開始点です : https://github.com/Project-MONAI/tutorials
API ドキュメントについては、https://docs.monai.io にアクセスしてください。
以上
MONAI 0.7 : 概要 (README)
MONAI 0.7 : README (概要) (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/03/2021 (0.7.0)
* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- テレワーク & オンライン授業を支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ ; Facebook |
MONAI 0.7 : 概要 (README)
Medical Open Network for AI
MONAI は PyTorch エコシステムの一部で、ヘルスケア画像化における深層学習のための PyTorch ベース、オープンソースのフーレムワークです。その目標は :
- 共通基盤で協力して取り組める学術的、産業的そして臨床的な研究者のコミュニティを構築すること ;
- ヘルスケア画像化のための最先端な、end-to-end な訓練ワークフローを作成すること ;
- 深層学習モデルを作成して評価するために研究者に最適化され標準化された方法を提供すること。
機能
コードベースは現在活発な開発下にあります。現在のマイルストーン・リリースの テクニカル・ハイライト と What’s New を参照してください。
- 多次元医療画像データのための柔軟な前処理 ;
- 既存のワークフローとの簡単な統合のための構成的 & 可搬な API ;
- ネットワーク、損失、評価メトリクス等のためのドメイン固有実装 ;
- 様々なユーザ専門性のためのカスタマイズ可能なデザイン ;
- マルチ GPU データ並列サポート。
インストール
現在のリリース をインストールするには、単純に以下を実行します :
pip install monai
他のインストール方法 (デフォルト GitHub ブランチの使用、Docker の使用等) については、インストールガイド を参照してください。
Getting Started
MedNIST デモ と MONAI for PyTorch Users が Colab で利用可能です。
サンプルとノートブック・チュートリアルは Project-MONAI/tutorials にあります。
技術文書は docs.monai.io で利用可能です。
Contributing
MONAI への contribution (貢献) を行なうガイダンスについては、contributing ガイドライン を参照してください。
コミュニティ
Twitter @ProjectMONAI の会話に参加するか Slack チャネル に参加してください。
MONAI’s GitHub Discussions タブ で質問したり回答したりしてください。
リンク
- Website : https://monai.io/
- API ドキュメント : https://docs.monai.io
- Code: https://github.com/Project-MONAI/MONAI
- Project tracker: https://github.com/Project-MONAI/MONAI/projects
- Issue tracker: https://github.com/Project-MONAI/MONAI/issues
- Wiki : https://github.com/Project-MONAI/MONAI/wiki
- Test status: https://github.com/Project-MONAI/MONAI/actions
- PyPI package: https://pypi.org/project/monai/
- Weekly previews: https://pypi.org/project/monai-weekly/
- Docker Hub: https://hub.docker.com/r/projectmonai/monai
以上