ホーム » 「MONAI 0.7」タグがついた投稿

タグアーカイブ: MONAI 0.7

MONAI 0.7 : tutorials : 3D セグメンテーション – 脳腫瘍 3D セグメンテーション

MONAI 0.7 : tutorials : 3D セグメンテーション – 脳腫瘍 3D セグメンテーション (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 11/08/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

MONAI 0.7 : tutorials : 3D セグメンテーション – 脳腫瘍 3D セグメンテーション

このチュートリアルは MSD 脳腫瘍データセットに基づくマルチラベル・タスクの訓練ワークフローを構築する方法を示します。

このチュートリアルはマルチラベル・セグメンテーション・タスクの訓練ワークフローを構築する方法を示します。

そしてそれは以下の機能を含みます :

  1. 辞書形式データのための変換。
  2. MONAI 変換 API に従って新しい変換を定義する。
  3. メタデータと共に Nifti 画像をロードし、画像のリストをロードしてそれらをスタックする。
  4. データ増強のために強度をランダムに調整する。
  5. 訓練と検証を高速化する Cache IO と変換。
  6. 3D セグメンテーション・タスクのための 3D SegResNet モデル, Dice 損失関数, 平均 Dice メトリック。
  7. 再現性のための決定論的訓練。

データセットは http://medicaldecathlon.com/ に由来します。
ターゲット: Gliomas segmentation necrotic/active tumour and oedema
Modality: Multimodal multisite MRI データ (FLAIR, T1w, T1gd,T2w)
サイズ: 750 4D volumes (484 訓練 + 266 テスト)
ソース: BRATS 2016 と 2017 データセット。
チャレンジ: Complex and heterogeneously-located targets

下図は、様々なモダリティでアノテートされている腫瘍部分領域の画像パッチ (左上) とデータセット全体のための最終的なラベル (右) を示します。(図は BraTS IEEE TMI 論文 から引用)

画像パッチは左から右へ以下を示します :

  1. T2-FLAIR で見える腫瘍全体 (黄色) (Fig.A)。
  2. T2 で見える腫瘍のコア (赤色) (Fig. B)。
  3. T1Gd で見える enhancing 腫瘍構造 (ライトブルー)、これはコアの嚢胞 (のうほう) (= cystic) / 壊死 (=necrotic) 成分 (緑色) を取り囲んでいます (Fig. C)。
  4. セグメンテーションは 腫瘍部分領域の最終的なラベル (Fig.D) を生成するために組み合わされます : 浮腫 (= edema) (黄色), non-enhancing ソリッドコア (赤色), 嚢胞/壊死コア (緑色), enhancing コア (青色) です。

 

環境のセットアップ

!python -c "import monai" || pip install -q "monai-weekly[nibabel, tqdm]"
!python -c "import matplotlib" || pip install -q matplotlib
#!pip install pytorch-ignite
%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 time
import matplotlib.pyplot as plt
import numpy as np
from monai.apps import DecathlonDataset
from monai.config import print_config
from monai.data import DataLoader, decollate_batch
from monai.handlers.utils import from_engine
from monai.losses import DiceLoss
from monai.inferers import sliding_window_inference
from monai.metrics import DiceMetric
from monai.networks.nets import SegResNet
from monai.transforms import (
    Activations,
    Activationsd,
    AsDiscrete,
    AsDiscreted,
    Compose,
    Invertd,
    LoadImaged,
    MapTransform,
    NormalizeIntensityd,
    Orientationd,
    RandFlipd,
    RandScaleIntensityd,
    RandShiftIntensityd,
    RandSpatialCropd,
    Spacingd,
    EnsureChannelFirstd,
    EnsureTyped,
    EnsureType,
)
from monai.utils import set_determinism

import torch

print_config()
MONAI version: 0.4.0+618.g69b44596
Numpy version: 1.20.3
Pytorch version: 1.9.0a0+c3d40fd
MONAI flags: HAS_EXT = False, USE_COMPILED = False
MONAI rev id: 69b4459650fb6943b9e729e724254d2db2b2a1f2

Optional dependencies:
Pytorch Ignite version: 0.4.5
Nibabel version: 3.2.1
scikit-image version: 0.15.0
Pillow version: 8.3.1
Tensorboard version: 2.5.0
gdown version: 3.13.0
TorchVision version: 0.10.0a0
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

 

再現性のために決定論的訓練を設定する

set_determinism(seed=0)

 

脳腫瘍のラベルを変換するための新しい変換を定義する

ここでは多クラスラベルを One-Hot 形式のマルチラベルのセグメンテーション・タスクに変換します。

class ConvertToMultiChannelBasedOnBratsClassesd(MapTransform):
    """
    Convert labels to multi channels based on brats classes:
    label 1 is the peritumoral edema
    label 2 is the GD-enhancing tumor
    label 3 is the necrotic and non-enhancing tumor core
    The possible classes are TC (Tumor core), WT (Whole tumor)
    and ET (Enhancing tumor).

    """

    def __call__(self, data):
        d = dict(data)
        for key in self.keys:
            result = []
            # merge label 2 and label 3 to construct TC
            result.append(np.logical_or(d[key] == 2, d[key] == 3))
            # merge labels 1, 2 and 3 to construct WT
            result.append(
                np.logical_or(
                    np.logical_or(d[key] == 2, d[key] == 3), d[key] == 1
                )
            )
            # label 2 is ET
            result.append(d[key] == 2)
            d[key] = np.stack(result, axis=0).astype(np.float32)
        return d

 

訓練と検証のための変換のセットアップ

train_transform = Compose(
    [
        # load 4 Nifti images and stack them together
        LoadImaged(keys=["image", "label"]),
        EnsureChannelFirstd(keys="image"),
        ConvertToMultiChannelBasedOnBratsClassesd(keys="label"),
        Spacingd(
            keys=["image", "label"],
            pixdim=(1.0, 1.0, 1.0),
            mode=("bilinear", "nearest"),
        ),
        Orientationd(keys=["image", "label"], axcodes="RAS"),
        RandSpatialCropd(keys=["image", "label"], roi_size=[224, 224, 144], random_size=False),
        RandFlipd(keys=["image", "label"], prob=0.5, spatial_axis=0),
        RandFlipd(keys=["image", "label"], prob=0.5, spatial_axis=1),
        RandFlipd(keys=["image", "label"], prob=0.5, spatial_axis=2),
        NormalizeIntensityd(keys="image", nonzero=True, channel_wise=True),
        RandScaleIntensityd(keys="image", factors=0.1, prob=1.0),
        RandShiftIntensityd(keys="image", offsets=0.1, prob=1.0),
        EnsureTyped(keys=["image", "label"]),
    ]
)
val_transform = Compose(
    [
        LoadImaged(keys=["image", "label"]),
        EnsureChannelFirstd(keys="image"),
        ConvertToMultiChannelBasedOnBratsClassesd(keys="label"),
        Spacingd(
            keys=["image", "label"],
            pixdim=(1.0, 1.0, 1.0),
            mode=("bilinear", "nearest"),
        ),
        Orientationd(keys=["image", "label"], axcodes="RAS"),
        NormalizeIntensityd(keys="image", nonzero=True, channel_wise=True),
        EnsureTyped(keys=["image", "label"]),
    ]
)

 

DecathlonDataset でデータを素早くロードする

ここではデータセットを自動的にダウンロードして抽出するために DecathlonDataset を使用します。それは MONAI CacheDataset を継承し、より少ないメモリを使用したい場合には、訓練のために N 項目をキャッシュするために cache_num=N を設定して検証のために総ての項目をキャッシュするために default args を使用できます、それはメモリサイズに依存します。

# here we don't cache any data in case out of memory issue
train_ds = DecathlonDataset(
    root_dir=root_dir,
    task="Task01_BrainTumour",
    transform=train_transform,
    section="training",
    download=True,
    cache_rate=0.0,
    num_workers=4,
)
train_loader = DataLoader(train_ds, batch_size=1, shuffle=True, num_workers=4)
val_ds = DecathlonDataset(
    root_dir=root_dir,
    task="Task01_BrainTumour",
    transform=val_transform,
    section="validation",
    download=False,
    cache_rate=0.0,
    num_workers=4,
)
val_loader = DataLoader(val_ds, batch_size=1, shuffle=False, num_workers=4)

Verified 'Task01_BrainTumour.tar', md5: 240a19d752f0d9e9101544901065d872.
File exists: /workspace/data/medical/Task01_BrainTumour.tar, skipped downloading.
Non-empty folder exists in /workspace/data/medical/Task01_BrainTumour, skipped extracting.

 

データ shape を確認して可視化する


# pick one image from DecathlonDataset to visualize and check the 4 channels
print(f"image shape: {val_ds[2]['image'].shape}")
plt.figure("image", (24, 6))
for i in range(4):
    plt.subplot(1, 4, i + 1)
    plt.title(f"image channel {i}")
    plt.imshow(val_ds[2]["image"][i, :, :, 60].detach().cpu(), cmap="gray")
plt.show()
# also visualize the 3 channels label corresponding to this image
print(f"label shape: {val_ds[2]['label'].shape}")
plt.figure("label", (18, 6))
for i in range(3):
    plt.subplot(1, 3, i + 1)
    plt.title(f"label channel {i}")
    plt.imshow(val_ds[2]["label"][i, :, :, 60].detach().cpu())
plt.show()
image shape: torch.Size([4, 240, 240, 155])

 

モデル, 損失, Optimizer を作成する

max_epochs = 300
val_interval = 1
VAL_AMP = True

# standard PyTorch program style: create SegResNet, DiceLoss and Adam optimizer
device = torch.device("cuda:0")
model = SegResNet(
    blocks_down=[1, 2, 2, 4],
    blocks_up=[1, 1, 1],
    init_filters=16,
    in_channels=4,
    out_channels=3,
    dropout_prob=0.2,
).to(device)
loss_function = DiceLoss(smooth_nr=0, smooth_dr=1e-5, squared_pred=True, to_onehot_y=False, sigmoid=True)
optimizer = torch.optim.Adam(model.parameters(), 1e-4, weight_decay=1e-5)
lr_scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=max_epochs)

dice_metric = DiceMetric(include_background=True, reduction="mean")
dice_metric_batch = DiceMetric(include_background=True, reduction="mean_batch")

post_trans = Compose(
    [EnsureType(), Activations(sigmoid=True), AsDiscrete(threshold_values=True)]
)


# define inference method
def inference(input):

    def _compute(input):
        return sliding_window_inference(
            inputs=input,
            roi_size=(240, 240, 160),
            sw_batch_size=1,
            predictor=model,
            overlap=0.5,
        )

    if VAL_AMP:
        with torch.cuda.amp.autocast():
            return _compute(input)
    else:
        return _compute(input)


# use amp to accelerate training
scaler = torch.cuda.amp.GradScaler()
# enable cuDNN benchmark
torch.backends.cudnn.benchmark = True

 

典型的な PyTorch 訓練プロセスの実行

best_metric = -1
best_metric_epoch = -1
best_metrics_epochs_and_time = [[], [], []]
epoch_loss_values = []
metric_values = []
metric_values_tc = []
metric_values_wt = []
metric_values_et = []

total_start = time.time()
for epoch in range(max_epochs):
    epoch_start = time.time()
    print("-" * 10)
    print(f"epoch {epoch + 1}/{max_epochs}")
    model.train()
    epoch_loss = 0
    step = 0
    for batch_data in train_loader:
        step_start = time.time()
        step += 1
        inputs, labels = (
            batch_data["image"].to(device),
            batch_data["label"].to(device),
        )
        optimizer.zero_grad()
        with torch.cuda.amp.autocast():
            outputs = model(inputs)
            loss = loss_function(outputs, labels)
        scaler.scale(loss).backward()
        scaler.step(optimizer)
        scaler.update()
        epoch_loss += loss.item()
        print(
            f"{step}/{len(train_ds) // train_loader.batch_size}"
            f", train_loss: {loss.item():.4f}"
            f", step time: {(time.time() - step_start):.4f}"
        )
    lr_scheduler.step()
    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():

            for val_data in val_loader:
                val_inputs, val_labels = (
                    val_data["image"].to(device),
                    val_data["label"].to(device),
                )
                val_outputs = inference(val_inputs)
                val_outputs = [post_trans(i) for i in decollate_batch(val_outputs)]
                dice_metric(y_pred=val_outputs, y=val_labels)
                dice_metric_batch(y_pred=val_outputs, y=val_labels)

            metric = dice_metric.aggregate().item()
            metric_values.append(metric)
            metric_batch = dice_metric_batch.aggregate()
            metric_tc = metric_batch[0].item()
            metric_values_tc.append(metric_tc)
            metric_wt = metric_batch[1].item()
            metric_values_wt.append(metric_wt)
            metric_et = metric_batch[2].item()
            metric_values_et.append(metric_et)
            dice_metric.reset()
            dice_metric_batch.reset()

            if metric > best_metric:
                best_metric = metric
                best_metric_epoch = epoch + 1
                best_metrics_epochs_and_time[0].append(best_metric)
                best_metrics_epochs_and_time[1].append(best_metric_epoch)
                best_metrics_epochs_and_time[2].append(time.time() - total_start)
                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 mean dice: {metric:.4f}"
                f" tc: {metric_tc:.4f} wt: {metric_wt:.4f} et: {metric_et:.4f}"
                f"\nbest mean dice: {best_metric:.4f}"
                f" at epoch: {best_metric_epoch}"
            )
    print(f"time consuming of epoch {epoch + 1} is: {(time.time() - epoch_start):.4f}")
total_time = time.time() - total_start
print(f"train completed, best_metric: {best_metric:.4f} at epoch: {best_metric_epoch}, total time: {total_time}.")
train completed, best_metric: 0.7914 at epoch: 279, total time: 90155.70936012268.

 

損失とメトリックのプロット

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, color="red")
plt.subplot(1, 2, 2)
plt.title("Val Mean Dice")
x = [val_interval * (i + 1) for i in range(len(metric_values))]
y = metric_values
plt.xlabel("epoch")
plt.plot(x, y, color="green")
plt.show()

plt.figure("train", (18, 6))
plt.subplot(1, 3, 1)
plt.title("Val Mean Dice TC")
x = [val_interval * (i + 1) for i in range(len(metric_values_tc))]
y = metric_values_tc
plt.xlabel("epoch")
plt.plot(x, y, color="blue")
plt.subplot(1, 3, 2)
plt.title("Val Mean Dice WT")
x = [val_interval * (i + 1) for i in range(len(metric_values_wt))]
y = metric_values_wt
plt.xlabel("epoch")
plt.plot(x, y, color="brown")
plt.subplot(1, 3, 3)
plt.title("Val Mean Dice ET")
x = [val_interval * (i + 1) for i in range(len(metric_values_et))]
y = metric_values_et
plt.xlabel("epoch")
plt.plot(x, y, color="purple")
plt.show()

 

入力画像とラベルでベストモデル出力を確認する

model.load_state_dict(
    torch.load(os.path.join(root_dir, "best_metric_model.pth"))
)
model.eval()
with torch.no_grad():
    # select one image to evaluate and visualize the model output
    val_input = val_ds[6]["image"].unsqueeze(0).to(device)
    roi_size = (128, 128, 64)
    sw_batch_size = 4
    val_output = inference(val_input)
    val_output = post_trans(val_output[0])
    plt.figure("image", (24, 6))
    for i in range(4):
        plt.subplot(1, 4, i + 1)
        plt.title(f"image channel {i}")
        plt.imshow(val_ds[6]["image"][i, :, :, 70].detach().cpu(), cmap="gray")
    plt.show()
    # visualize the 3 channels label corresponding to this image
    plt.figure("label", (18, 6))
    for i in range(3):
        plt.subplot(1, 3, i + 1)
        plt.title(f"label channel {i}")
        plt.imshow(val_ds[6]["label"][i, :, :, 70].detach().cpu())
    plt.show()
    # visualize the 3 channels model output corresponding to this image
    plt.figure("output", (18, 6))
    for i in range(3):
        plt.subplot(1, 3, i + 1)
        plt.title(f"output channel {i}")
        plt.imshow(val_output[i, :, :, 70].detach().cpu())
    plt.show()

 

元の画像 spacings 上の評価

val_org_transforms = Compose(
    [
        LoadImaged(keys=["image", "label"]),
        EnsureChannelFirstd(keys=["image"]),
        ConvertToMultiChannelBasedOnBratsClassesd(keys="label"),
        Spacingd(keys=["image"], pixdim=(1.0, 1.0, 1.0), mode="bilinear"),
        Orientationd(keys=["image"], axcodes="RAS"),
        NormalizeIntensityd(keys="image", nonzero=True, channel_wise=True),
        EnsureTyped(keys=["image", "label"]),
    ]
)

val_org_ds = DecathlonDataset(
    root_dir=root_dir,
    task="Task01_BrainTumour",
    transform=val_org_transforms,
    section="validation",
    download=False,
    num_workers=4,
    cache_num=0,
)
val_org_loader = DataLoader(val_org_ds, batch_size=1, shuffle=False, num_workers=4)

post_transforms = Compose([
    EnsureTyped(keys="pred"),
    Invertd(
        keys="pred",
        transform=val_org_transforms,
        orig_keys="image",
        meta_keys="pred_meta_dict",
        orig_meta_keys="image_meta_dict",
        meta_key_postfix="meta_dict",
        nearest_interp=False,
        to_tensor=True,
    ),
    Activationsd(keys="pred", sigmoid=True),
    AsDiscreted(keys="pred", threshold_values=True),
])
model.load_state_dict(torch.load(
    os.path.join(root_dir, "best_metric_model.pth")))
model.eval()

with torch.no_grad():
    for val_data in val_org_loader:
        val_inputs = val_data["image"].to(device)
        val_data["pred"] = inference(val_inputs)
        val_data = [post_transforms(i) for i in decollate_batch(val_data)]
        val_outputs, val_labels = from_engine(["pred", "label"])(val_data)
        dice_metric(y_pred=val_outputs, y=val_labels)
        dice_metric_batch(y_pred=val_outputs, y=val_labels)

    metric_org = dice_metric.aggregate().item()
    metric_batch_org = dice_metric_batch.aggregate()

    dice_metric.reset()
    dice_metric_batch.reset()

metric_tc, metric_wt, metric_et = metric_batch[0].item(), metric_batch[1].item(), metric_batch[2].item()

print("Metric on original image spacing: ", metric)
print(f"metric_tc: {metric_tc:.4f}")
print(f"metric_wt: {metric_wt:.4f}")
print(f"metric_et: {metric_et:.4f}")
Metric on original image spacing:  0.7912478446960449
metric_tc: 0.8422
metric_wt: 0.9129
metric_et: 0.6187

 

データディレクトリのクリーンアップ

一時ディレクトリが使用された場合ディレクトリを削除します。

if directory is None:
    shutil.rmtree(root_dir)
 

以上



MONAI 0.7 : tutorials : 3D セグメンテーション – UNet による 3D セグメンテーション

MONAI 0.7 : tutorials : 3D セグメンテーション – UNet による 3D セグメンテーション (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 11/07/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

 

MONAI 0.7 : tutorials : 3D セグメンテーション – UNet による 3D セグメンテーション

このノートブックは合成データセットに基づく 3D セグメンテーションの end-to-end な訓練 & 評価サンプルです。サンプルは PyTorch Ignite プログラムで MONAI の幾つかの主要な機能を示します、特に医療ドメイン固有の変換とプロファイリング (ロギング, TensorBoard, MLFlow 等) のためのイベントハンドラを使用します。

 

環境のセットアップ

!python -c "import monai" || pip install -q "monai-weekly[ignite, nibabel, tensorboard, mlflow]"

 

インポートのセットアップ

# 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 glob
import logging
import os
from pathlib import Path
import shutil
import sys
import tempfile

import nibabel as nib
import numpy as np
from monai.config import print_config
from monai.data import ArrayDataset, create_test_image_3d, decollate_batch
from monai.handlers import (
    MeanDice,
    MLFlowHandler,
    StatsHandler,
    TensorBoardImageHandler,
    TensorBoardStatsHandler,
)
from monai.losses import DiceLoss
from monai.networks.nets import UNet
from monai.transforms import (
    Activations,
    AddChannel,
    AsDiscrete,
    Compose,
    LoadImage,
    RandSpatialCrop,
    Resize,
    ScaleIntensity,
    EnsureType,
)
from monai.utils import first

import ignite
import torch

print_config()

 

データディレクトリのセットアップ

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

 

ロギングのセットアップ

logging.basicConfig(stream=sys.stdout, level=logging.INFO)

 

デモデータのセットアップ

for i in range(40):
    im, seg = create_test_image_3d(128, 128, 128, num_seg_classes=1)

    n = nib.Nifti1Image(im, np.eye(4))
    nib.save(n, os.path.join(root_dir, f"im{i}.nii.gz"))

    n = nib.Nifti1Image(seg, np.eye(4))
    nib.save(n, os.path.join(root_dir, f"seg{i}.nii.gz"))

images = sorted(glob.glob(os.path.join(root_dir, "im*.nii.gz")))
segs = sorted(glob.glob(os.path.join(root_dir, "seg*.nii.gz")))

 

変換, データセットのセットアップ

# Define transforms for image and segmentation
imtrans = Compose(
    [
        LoadImage(image_only=True),
        ScaleIntensity(),
        AddChannel(),
        RandSpatialCrop((96, 96, 96), random_size=False),
        EnsureType(),
    ]
)
segtrans = Compose(
    [
        LoadImage(image_only=True),
        AddChannel(),
        RandSpatialCrop((96, 96, 96), random_size=False),
        EnsureType(),
    ]
)

# Define nifti dataset, dataloader
ds = ArrayDataset(images, imtrans, segs, segtrans)
loader = torch.utils.data.DataLoader(
    ds, batch_size=10, num_workers=2, pin_memory=torch.cuda.is_available()
)
im, seg = first(loader)
print(im.shape, seg.shape)
torch.Size([10, 1, 96, 96, 96]) torch.Size([10, 1, 96, 96, 96])

 

モデル, 損失, Optimizer を作成する

# Create UNet, DiceLoss and Adam optimizer
device = torch.device("cuda:0")
net = UNet(
    spatial_dims=3,
    in_channels=1,
    out_channels=1,
    channels=(16, 32, 64, 128, 256),
    strides=(2, 2, 2, 2),
    num_res_units=2,
).to(device)

loss = DiceLoss(sigmoid=True)
lr = 1e-3
opt = torch.optim.Adam(net.parameters(), lr)

 

ignite を使用して supervised_trainer を作成する

# Create trainer
trainer = ignite.engine.create_supervised_trainer(
    net, opt, loss, device, False
)

 

チェックポインティングとロギングのためのイベントハンドラのセットアップ

# optional section for checkpoint and tensorboard logging
# adding checkpoint handler to save models (network
# params and optimizer stats) during training
log_dir = os.path.join(root_dir, "logs")
checkpoint_handler = ignite.handlers.ModelCheckpoint(
    log_dir, "net", n_saved=10, require_empty=False
)
trainer.add_event_handler(
    event_name=ignite.engine.Events.EPOCH_COMPLETED,
    handler=checkpoint_handler,
    to_save={"net": net, "opt": opt},
)

# StatsHandler prints loss at every iteration
# user can also customize print functions and can use output_transform to convert
# engine.state.output if it's not a loss value
train_stats_handler = StatsHandler(name="trainer", output_transform=lambda x: x)
train_stats_handler.attach(trainer)

# TensorBoardStatsHandler plots loss at every iteration
train_tensorboard_stats_handler = TensorBoardStatsHandler(log_dir=log_dir, output_transform=lambda x: x)
train_tensorboard_stats_handler.attach(trainer)

# MLFlowHandler plots loss at every iteration on MLFlow web UI
mlflow_dir = os.path.join(log_dir, "mlruns")
train_mlflow_handler = MLFlowHandler(tracking_uri=Path(mlflow_dir).as_uri(), output_transform=lambda x: x)
train_mlflow_handler.attach(trainer)

 

N エポック毎の検証の追加

# optional section for model validation during training
validation_every_n_epochs = 1
# Set parameters for validation
metric_name = "Mean_Dice"
# add evaluation metric to the evaluator engine
val_metrics = {metric_name: MeanDice()}
post_pred = Compose(
    [EnsureType(), Activations(sigmoid=True), AsDiscrete(threshold_values=True)]
)
post_label = Compose([EnsureType(), AsDiscrete(threshold_values=True)])
# Ignite evaluator expects batch=(img, seg) and
# returns output=(y_pred, y) at every iteration,
# user can add output_transform to return other values
evaluator = ignite.engine.create_supervised_evaluator(
    net,
    val_metrics,
    device,
    True,
    output_transform=lambda x, y, y_pred: (
        [post_pred(i) for i in decollate_batch(y_pred)],
        [post_label(i) for i in decollate_batch(y)]
    ),
)

# create a validation data loader
val_imtrans = Compose(
    [
        LoadImage(image_only=True),
        ScaleIntensity(),
        AddChannel(),
        Resize((96, 96, 96)),
        EnsureType(),
    ]
)
val_segtrans = Compose(
    [
        LoadImage(image_only=True),
        AddChannel(),
        Resize((96, 96, 96)),
        EnsureType(),
    ]
)
val_ds = ArrayDataset(images[21:], val_imtrans, segs[21:], val_segtrans)
val_loader = torch.utils.data.DataLoader(
    val_ds, batch_size=5, num_workers=8, pin_memory=torch.cuda.is_available()
)


@trainer.on(
    ignite.engine.Events.EPOCH_COMPLETED(every=validation_every_n_epochs)
)
def run_validation(engine):
    evaluator.run(val_loader)


# Add stats event handler to print validation stats via evaluator
val_stats_handler = StatsHandler(
    name="evaluator",
    # no need to print loss value, so disable per iteration output
    output_transform=lambda x: None,
    # fetch global epoch number from trainer
    global_epoch_transform=lambda x: trainer.state.epoch,
)
val_stats_handler.attach(evaluator)

# add handler to record metrics to TensorBoard at every validation epoch
val_tensorboard_stats_handler = TensorBoardStatsHandler(
    log_dir=log_dir,
    # no need to plot loss value, so disable per iteration output
    output_transform=lambda x: None,
    # fetch global epoch number from trainer
    global_epoch_transform=lambda x: trainer.state.epoch,
)
val_tensorboard_stats_handler.attach(evaluator)

# add handler to record metrics to MLFlow at every validation epoch
val_mlflow_handler = MLFlowHandler(
    tracking_uri=Path(mlflow_dir).as_uri(),
    # no need to plot loss value, so disable per iteration output
    output_transform=lambda x: None,
    # fetch global epoch number from trainer
    global_epoch_transform=lambda x: trainer.state.epoch,
)
val_mlflow_handler.attach(evaluator)

# add handler to draw the first image and the corresponding
# label and model output in the last batch
# here we draw the 3D output as GIF format along Depth
# axis, at every validation epoch
val_tensorboard_image_handler = TensorBoardImageHandler(
    log_dir=log_dir,
    batch_transform=lambda batch: (batch[0], batch[1]),
    output_transform=lambda output: output[0],
    global_iter_transform=lambda x: trainer.state.epoch,
)
evaluator.add_event_handler(
    event_name=ignite.engine.Events.EPOCH_COMPLETED,
    handler=val_tensorboard_image_handler,
)

 

訓練ループの実行

# create a training data loader
train_ds = ArrayDataset(images[:20], imtrans, segs[:20], segtrans)
train_loader = torch.utils.data.DataLoader(
    train_ds,
    batch_size=5,
    shuffle=True,
    num_workers=8,
    pin_memory=torch.cuda.is_available(),
)

max_epochs = 10
state = trainer.run(train_loader, max_epochs)

 

Tensorboard ログの可視化

%load_ext tensorboard
%tensorboard --logdir=log_dir

 

 

MLFlow で訓練ステータスを可視化する

mlflow は IPython コンポーネントではないので、log_dir に切り替えて MLFlow UI を起動するためにコマンド mlflow ui を実行してください。

MLFlow UI で予想される訓練曲線です :

 

データディレクトリのクリーンアップ

一時ディレクトリが使用された場合ディレクトリを削除します。

if directory is None:
    shutil.rmtree(root_dir)
 

以上



MONAI 0.7 : チュートリアル

MONAI 0.7 : チュートリアル

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/09/2021 (0.7.0)
更新日時 : 11/07/2021

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

MONAI 0.7 : チュートリアル

2D 分類

 

2D セグメンテーション

 

3D 分類

 

3D セグメンテーション

 

2D レジストレーション

 

3D レジストレーション

  • (3D registration using paired lung CT)

 

deepgrow

  • (Deepgrow)

 

配備

 

連合学習

  • (NVFlare)
  • (Substra)

 

デジタルパソロジー

  • (Whole Slide Tumor Detection)
  • (Profiling Whole Slide Tumor Detection)

 

高速化

  • (fast_model_training_guide)
  • (distributed_training)
  • (automatic_mixed_precision)
  • (dataset_type_performance)
  • MONAI 機能による高速訓練 (fast_training_tutorial) (10/15/2021)
  • (multi_gpu_test)
  • (threadbuffer_performance)
  • (transform_speed)

 

モジュール

 

以上



MONAI 0.7 : tutorials : モジュール – 公開データセットと新しいデータセットのクイックスタート

MONAI 0.7 : tutorials : モジュール – 公開データセットと新しいデータセットのクイックスタート (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 11/05/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

 

MONAI 0.7 : tutorials : モジュール – 公開データセットと新しいデータセットのクイックスタート

このノートブックは MedNISTDataset と DecathlonDataset に基づいた訓練ワークフローを素早くセットアップする方法と、新しいデータセットを作成する方法を示します。

このチュートリアルでは、MONAI 公開データセットでワークフローを素早くセットアップする方法と新しいデータセットを追加する方法を紹介します。現在、MONAI は MedNISTDataset と DecathlonDataset を提供していて、MedNIST と Decathlon データセットを自動的にダウンロードして抽出し、そして訓練/検証/テストデータを生成する PyTorch データセットとして機能します。

このチュートリアルでは以下のトピックをカバーします :

  • MedNISTDataset による訓練実験とワークフローを作成する
  • DecathlonDataset による訓練実験とワークフローを作成する
  • 他の公開データを共有して MONAI でデータセットを追加する

 

環境のセットアップ

!python -c "import monai" || pip install -q "monai-weekly[nibabel, pillow, ignite, tqdm]"
!python -c "import matplotlib" || pip install -q matplotlib
%matplotlib inline

from monai.transforms import (
    AddChanneld,
    AsDiscreted,
    Compose,
    LoadImaged,
    Orientationd,
    Randomizable,
    Resized,
    ScaleIntensityd,
    Spacingd,
    EnsureTyped,
)
from monai.networks.nets import UNet, DenseNet121
from monai.networks.layers import Norm
from monai.losses import DiceLoss
from monai.inferers import SimpleInferer
from monai.handlers import MeanDice, StatsHandler, from_engine
from monai.engines import SupervisedTrainer
from monai.data import CacheDataset, DataLoader
from monai.config import print_config
from monai.apps import DecathlonDataset, MedNISTDataset, download_and_extract
import torch
import matplotlib.pyplot as plt
import ignite
import tempfile
import sys
import shutil
import os
import logging

 

インポートのセットアップ

# 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.


print_config()
MONAI version: 0.6.0rc1+23.gc6793fd0
Numpy version: 1.20.3
Pytorch version: 1.9.0a0+c3d40fd
MONAI flags: HAS_EXT = True, USE_COMPILED = False
MONAI rev id: c6793fd0f316a448778d0047664aaf8c1895fe1c

Optional dependencies:
Pytorch Ignite version: 0.4.5
Nibabel version: 3.2.1
scikit-image version: 0.15.0
Pillow version: 7.0.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

 

ロギングのセットアップ

logging.basicConfig(stream=sys.stdout, level=logging.INFO)

 

MedNISTDataset による訓練実験とワークフローを作成する

MedMNIST データセットは TCIA, RSNA Bone Age チャレンジNIH Chest X-ray データセット からの様々なセットから集められました。

 

前処理変換のセットアップ

transform = Compose(
    [
        LoadImaged(keys="image"),
        AddChanneld(keys="image"),
        ScaleIntensityd(keys="image"),
        EnsureTyped(keys="image"),
    ]
)

 

訓練のために MedNISTDataset を作成する

MedNISTDataset は MONAI CacheDataset から継承して期待する動作を実現するために豊富なパラメータを提供しています :

  1. root_dir: MedNIST データセットをダウンロードしてロードするターゲットディレクトリ。
  2. section: 想定されるデータ・セクション、以下のいずれかです : training, validation or test.
  3. transform: 入力データ上で操作を実行する変換。デフォルト変換は LoadPNGd と AddChanneld から成り、これはデータを [C, H, W] shape を持つ numpy 配列にロードできます。
  4. download: リソース・リンクから MedNIST をダウンロードして抽出するか否か、デフォルトは False です。想定されるファイルが既に存在していれば、それが True に設定されていてもダウンロードはスキップします。ユーザは MedNIST.tar.gz ファイルか MedNIST フォルダをルートディレクトリに手動でコピーできます。
  5. seed: 訓練、検証とテストデータセットをランダムに分割するためのランダムシード、デフォルトは 0 です。
  6. val_frac: データセット全体の検証比率のパーセンテージ、デフォルトは 0.1 です。
  7. test_frac: データセット全体のテスト比率のパーセンテージ、デフォルトは 0.1 です。
  8. cache_num: キャッシュされる項目の数。デフォルトは sys.maxsize です。(cache_num, data_length x cache_rate, data_length) の最小値を取ります。
  9. cache_rate: トータルでキャッシュされるデータのパーセンテージで、デフォルトは 1.0 (cache all) です。(cache_num, data_length x cache_rate, data_length) の最小値を取ります。
  10. num_workers: 使用するワーカースレッドの数です。0 であればシングルスレッドが使用されます。デフォルトは 0 です。

“tar フアイル” は最初にダウンロードした後でキャッシュされることに注意してください。self.__getitem__() API は、self.__len__() 内の指定されたインデックスに従って 1 {“image”: XXX, “label”: XXX} 辞書を生成します。

train_ds = MedNISTDataset(
    root_dir=root_dir, transform=transform, section="training", download=True)
# the dataset can work seamlessly with the pytorch native dataset loader,
# but using monai.data.DataLoader has additional benefits of mutli-process
# random seeds handling, and the customized collate functions
train_loader = DataLoader(train_ds, batch_size=300,
                          shuffle=True, num_workers=10)
Verified 'MedNIST.tar.gz', md5: 0bc7306e7427e00ad1c5526a6677552d.
file /workspace/data/medical/MedNIST.tar.gz exists, skip downloading.
extracted file /workspace/data/medical/MedNIST exists, skip extracting.
100%|██████████| 46946/46946 [00:27<00:00, 1684.89it/s]

 

可視化して確認するために MedNISTDataset から画像をピックアップする

plt.subplots(3, 3, figsize=(8, 8))
for i in range(9):
    plt.subplot(3, 3, i + 1)
    plt.imshow(train_ds[i * 5000]["image"][0].detach().cpu(), cmap="gray")
plt.tight_layout()
plt.show()

 

訓練コンポーネントの作成

device = torch.device("cuda:0")
net = DenseNet121(spatial_dims=2, in_channels=1, out_channels=6).to(device)
loss = torch.nn.CrossEntropyLoss()
opt = torch.optim.Adam(net.parameters(), 1e-5)

 

最も簡単な訓練ワークフローを定義して実行する

訓練ワークフローを素早くセットアップするために MONAI SupervisedTrainer ハンドラを使用します。

trainer = SupervisedTrainer(
    device=device,
    max_epochs=5,
    train_data_loader=train_loader,
    network=net,
    optimizer=opt,
    loss_function=loss,
    inferer=SimpleInferer(),
    key_train_metric={
        "train_acc": ignite.metrics.Accuracy(
            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 5 epochs
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 1/157 -- train_loss: 1.8252 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 2/157 -- train_loss: 1.7637 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 3/157 -- train_loss: 1.7338 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 4/157 -- train_loss: 1.7239 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 5/157 -- train_loss: 1.6950 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 6/157 -- train_loss: 1.6414 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 7/157 -- train_loss: 1.6280 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 8/157 -- train_loss: 1.6190 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 9/157 -- train_loss: 1.5820 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 10/157 -- train_loss: 1.5858 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 11/157 -- train_loss: 1.5342 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 12/157 -- train_loss: 1.4917 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 13/157 -- train_loss: 1.4970 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 14/157 -- train_loss: 1.4540 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 15/157 -- train_loss: 1.4422 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 16/157 -- train_loss: 1.4415 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 17/157 -- train_loss: 1.4168 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 18/157 -- train_loss: 1.4373 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 19/157 -- train_loss: 1.3618 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 20/157 -- train_loss: 1.3188 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 21/157 -- train_loss: 1.3052 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 22/157 -- train_loss: 1.3105 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 23/157 -- train_loss: 1.2936 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 24/157 -- train_loss: 1.2629 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 25/157 -- train_loss: 1.2414 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 26/157 -- train_loss: 1.2488 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 27/157 -- train_loss: 1.1862 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 28/157 -- train_loss: 1.1873 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 29/157 -- train_loss: 1.1685 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 30/157 -- train_loss: 1.1491 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 31/157 -- train_loss: 1.1658 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 32/157 -- train_loss: 1.1465 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 33/157 -- train_loss: 1.1273 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 34/157 -- train_loss: 1.1121 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 35/157 -- train_loss: 1.1016 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 36/157 -- train_loss: 1.0937 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 37/157 -- train_loss: 1.0664 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 38/157 -- train_loss: 1.0472 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 39/157 -- train_loss: 0.9981 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 40/157 -- train_loss: 0.9918 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 41/157 -- train_loss: 0.9644 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 42/157 -- train_loss: 0.9875 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 43/157 -- train_loss: 0.9691 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 44/157 -- train_loss: 0.9285 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 45/157 -- train_loss: 0.9872 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 46/157 -- train_loss: 0.9350 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 47/157 -- train_loss: 0.8944 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 48/157 -- train_loss: 0.9034 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 49/157 -- train_loss: 0.8550 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 50/157 -- train_loss: 0.8690 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 51/157 -- train_loss: 0.8494 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 52/157 -- train_loss: 0.8600 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 53/157 -- train_loss: 0.7888 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 54/157 -- train_loss: 0.8017 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 55/157 -- train_loss: 0.8211 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 56/157 -- train_loss: 0.8050 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 57/157 -- train_loss: 0.7900 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 58/157 -- train_loss: 0.7971 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 59/157 -- train_loss: 0.7693 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 60/157 -- train_loss: 0.7425 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 61/157 -- train_loss: 0.7386 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 62/157 -- train_loss: 0.7208 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 63/157 -- train_loss: 0.7203 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 64/157 -- train_loss: 0.7036 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 65/157 -- train_loss: 0.6863 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 66/157 -- train_loss: 0.6678 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 67/157 -- train_loss: 0.6729 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 68/157 -- train_loss: 0.6435 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 69/157 -- train_loss: 0.6373 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 70/157 -- train_loss: 0.6616 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 71/157 -- train_loss: 0.6325 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 72/157 -- train_loss: 0.6357 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 73/157 -- train_loss: 0.6333 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 74/157 -- train_loss: 0.5840 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 75/157 -- train_loss: 0.6075 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 76/157 -- train_loss: 0.5632 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 77/157 -- train_loss: 0.5624 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 78/157 -- train_loss: 0.5698 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 79/157 -- train_loss: 0.5504 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 80/157 -- train_loss: 0.5456 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 81/157 -- train_loss: 0.5512 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 82/157 -- train_loss: 0.5329 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 83/157 -- train_loss: 0.5306 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 84/157 -- train_loss: 0.5312 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 85/157 -- train_loss: 0.5226 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 86/157 -- train_loss: 0.5166 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 87/157 -- train_loss: 0.5152 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 88/157 -- train_loss: 0.4779 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 89/157 -- train_loss: 0.5044 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 90/157 -- train_loss: 0.5009 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 91/157 -- train_loss: 0.4685 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 92/157 -- train_loss: 0.4510 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 93/157 -- train_loss: 0.4815 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 94/157 -- train_loss: 0.4358 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 95/157 -- train_loss: 0.4570 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 96/157 -- train_loss: 0.4495 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 97/157 -- train_loss: 0.4120 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 98/157 -- train_loss: 0.4414 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 99/157 -- train_loss: 0.4252 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 100/157 -- train_loss: 0.4197 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 101/157 -- train_loss: 0.4312 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 102/157 -- train_loss: 0.4120 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 103/157 -- train_loss: 0.4054 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 104/157 -- train_loss: 0.4341 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 105/157 -- train_loss: 0.3731 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 106/157 -- train_loss: 0.3637 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 107/157 -- train_loss: 0.3850 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 108/157 -- train_loss: 0.3813 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 109/157 -- train_loss: 0.3464 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 110/157 -- train_loss: 0.3810 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 111/157 -- train_loss: 0.3641 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 112/157 -- train_loss: 0.3643 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 113/157 -- train_loss: 0.3592 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 114/157 -- train_loss: 0.3635 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 115/157 -- train_loss: 0.3190 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 116/157 -- train_loss: 0.3745 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 117/157 -- train_loss: 0.3255 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 118/157 -- train_loss: 0.3126 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 119/157 -- train_loss: 0.3331 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 120/157 -- train_loss: 0.3332 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 121/157 -- train_loss: 0.3412 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 122/157 -- train_loss: 0.2994 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 123/157 -- train_loss: 0.3147 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 124/157 -- train_loss: 0.3394 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 125/157 -- train_loss: 0.3133 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 126/157 -- train_loss: 0.3016 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 127/157 -- train_loss: 0.2861 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 128/157 -- train_loss: 0.2973 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 129/157 -- train_loss: 0.2843 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 130/157 -- train_loss: 0.2936 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 131/157 -- train_loss: 0.2902 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 132/157 -- train_loss: 0.2588 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 133/157 -- train_loss: 0.2815 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 134/157 -- train_loss: 0.2529 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 135/157 -- train_loss: 0.2647 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 136/157 -- train_loss: 0.2909 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 137/157 -- train_loss: 0.2883 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 138/157 -- train_loss: 0.3009 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 139/157 -- train_loss: 0.2295 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 140/157 -- train_loss: 0.2391 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 141/157 -- train_loss: 0.2902 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 142/157 -- train_loss: 0.2217 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 143/157 -- train_loss: 0.2387 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 144/157 -- train_loss: 0.2454 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 145/157 -- train_loss: 0.2214 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 146/157 -- train_loss: 0.2477 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 147/157 -- train_loss: 0.2534 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 148/157 -- train_loss: 0.2287 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 149/157 -- train_loss: 0.2381 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 150/157 -- train_loss: 0.2240 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 151/157 -- train_loss: 0.2288 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 152/157 -- train_loss: 0.2337 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 153/157 -- train_loss: 0.2109 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 154/157 -- train_loss: 0.2132 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 155/157 -- train_loss: 0.1772 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 156/157 -- train_loss: 0.2177 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 157/157 -- train_loss: 0.1833 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_acc: 0.8910450304605291
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[1] Metrics -- train_acc: 0.8910 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_acc best value: 0.8910450304605291 at epoch: 1
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[1] Complete. Time taken: 00:00:22
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 1/157 -- train_loss: 0.2187 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 2/157 -- train_loss: 0.1953 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 3/157 -- train_loss: 0.2099 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 4/157 -- train_loss: 0.1911 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 5/157 -- train_loss: 0.1970 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 6/157 -- train_loss: 0.1962 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 7/157 -- train_loss: 0.1935 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 8/157 -- train_loss: 0.2117 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 9/157 -- train_loss: 0.1942 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 10/157 -- train_loss: 0.2168 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 11/157 -- train_loss: 0.1968 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 12/157 -- train_loss: 0.1700 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 13/157 -- train_loss: 0.2183 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 14/157 -- train_loss: 0.2052 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 15/157 -- train_loss: 0.1826 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 16/157 -- train_loss: 0.1790 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 17/157 -- train_loss: 0.2115 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 18/157 -- train_loss: 0.1955 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 19/157 -- train_loss: 0.1888 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 20/157 -- train_loss: 0.1706 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 21/157 -- train_loss: 0.1812 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 22/157 -- train_loss: 0.1542 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 23/157 -- train_loss: 0.1554 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 24/157 -- train_loss: 0.1728 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 25/157 -- train_loss: 0.1681 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 26/157 -- train_loss: 0.1579 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 27/157 -- train_loss: 0.1803 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 28/157 -- train_loss: 0.1819 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 29/157 -- train_loss: 0.1789 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 30/157 -- train_loss: 0.1591 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 31/157 -- train_loss: 0.1464 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 32/157 -- train_loss: 0.1687 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 33/157 -- train_loss: 0.1740 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 34/157 -- train_loss: 0.1438 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 35/157 -- train_loss: 0.1432 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 36/157 -- train_loss: 0.1790 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 37/157 -- train_loss: 0.1615 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 38/157 -- train_loss: 0.1457 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 39/157 -- train_loss: 0.1639 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 40/157 -- train_loss: 0.1887 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 41/157 -- train_loss: 0.1642 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 42/157 -- train_loss: 0.1487 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 43/157 -- train_loss: 0.1519 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 44/157 -- train_loss: 0.1506 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 45/157 -- train_loss: 0.1562 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 46/157 -- train_loss: 0.1436 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 47/157 -- train_loss: 0.1527 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 48/157 -- train_loss: 0.1184 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 49/157 -- train_loss: 0.1562 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 50/157 -- train_loss: 0.1344 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 51/157 -- train_loss: 0.1734 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 52/157 -- train_loss: 0.1416 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 53/157 -- train_loss: 0.1601 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 54/157 -- train_loss: 0.1302 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 55/157 -- train_loss: 0.1560 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 56/157 -- train_loss: 0.1393 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 57/157 -- train_loss: 0.1624 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 58/157 -- train_loss: 0.1227 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 59/157 -- train_loss: 0.1354 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 60/157 -- train_loss: 0.1270 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 61/157 -- train_loss: 0.1595 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 62/157 -- train_loss: 0.1158 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 63/157 -- train_loss: 0.1426 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 64/157 -- train_loss: 0.1158 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 65/157 -- train_loss: 0.1218 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 66/157 -- train_loss: 0.1408 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 67/157 -- train_loss: 0.1318 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 68/157 -- train_loss: 0.1169 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 69/157 -- train_loss: 0.1218 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 70/157 -- train_loss: 0.1448 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 71/157 -- train_loss: 0.1177 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 72/157 -- train_loss: 0.1105 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 73/157 -- train_loss: 0.1308 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 74/157 -- train_loss: 0.1065 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 75/157 -- train_loss: 0.1464 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 76/157 -- train_loss: 0.1296 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 77/157 -- train_loss: 0.1276 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 78/157 -- train_loss: 0.1239 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 79/157 -- train_loss: 0.1269 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 80/157 -- train_loss: 0.1382 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 81/157 -- train_loss: 0.1123 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 82/157 -- train_loss: 0.1223 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 83/157 -- train_loss: 0.1120 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 84/157 -- train_loss: 0.1225 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 85/157 -- train_loss: 0.1137 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 86/157 -- train_loss: 0.1216 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 87/157 -- train_loss: 0.1397 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 88/157 -- train_loss: 0.1087 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 89/157 -- train_loss: 0.1158 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 90/157 -- train_loss: 0.1171 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 91/157 -- train_loss: 0.1165 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 92/157 -- train_loss: 0.1073 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 93/157 -- train_loss: 0.1082 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 94/157 -- train_loss: 0.1055 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 95/157 -- train_loss: 0.1054 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 96/157 -- train_loss: 0.0869 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 97/157 -- train_loss: 0.1184 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 98/157 -- train_loss: 0.1490 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 99/157 -- train_loss: 0.1033 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 100/157 -- train_loss: 0.0991 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 101/157 -- train_loss: 0.1009 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 102/157 -- train_loss: 0.1224 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 103/157 -- train_loss: 0.1098 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 104/157 -- train_loss: 0.0965 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 105/157 -- train_loss: 0.1097 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 106/157 -- train_loss: 0.1287 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 107/157 -- train_loss: 0.1126 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 108/157 -- train_loss: 0.1096 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 109/157 -- train_loss: 0.1235 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 110/157 -- train_loss: 0.0929 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 111/157 -- train_loss: 0.0996 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 112/157 -- train_loss: 0.0982 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 113/157 -- train_loss: 0.0942 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 114/157 -- train_loss: 0.1076 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 115/157 -- train_loss: 0.0978 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 116/157 -- train_loss: 0.1017 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 117/157 -- train_loss: 0.0882 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 118/157 -- train_loss: 0.1133 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 119/157 -- train_loss: 0.0938 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 120/157 -- train_loss: 0.0902 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 121/157 -- train_loss: 0.1098 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 122/157 -- train_loss: 0.0852 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 123/157 -- train_loss: 0.0835 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 124/157 -- train_loss: 0.0857 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 125/157 -- train_loss: 0.0822 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 126/157 -- train_loss: 0.0956 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 127/157 -- train_loss: 0.0966 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 128/157 -- train_loss: 0.1105 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 129/157 -- train_loss: 0.0925 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 130/157 -- train_loss: 0.0875 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 131/157 -- train_loss: 0.0856 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 132/157 -- train_loss: 0.0854 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 133/157 -- train_loss: 0.0728 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 134/157 -- train_loss: 0.0928 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 135/157 -- train_loss: 0.0884 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 136/157 -- train_loss: 0.1160 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 137/157 -- train_loss: 0.0679 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 138/157 -- train_loss: 0.1008 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 139/157 -- train_loss: 0.0959 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 140/157 -- train_loss: 0.0868 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 141/157 -- train_loss: 0.0797 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 142/157 -- train_loss: 0.0869 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 143/157 -- train_loss: 0.0884 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 144/157 -- train_loss: 0.0675 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 145/157 -- train_loss: 0.0856 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 146/157 -- train_loss: 0.1024 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 147/157 -- train_loss: 0.0965 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 148/157 -- train_loss: 0.0864 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 149/157 -- train_loss: 0.0700 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 150/157 -- train_loss: 0.0698 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 151/157 -- train_loss: 0.0871 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 152/157 -- train_loss: 0.0680 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 153/157 -- train_loss: 0.0719 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 154/157 -- train_loss: 0.0706 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 155/157 -- train_loss: 0.0620 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 156/157 -- train_loss: 0.0814 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 157/157 -- train_loss: 0.0689 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_acc: 0.9833425637967026
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[2] Metrics -- train_acc: 0.9833 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_acc best value: 0.9833425637967026 at epoch: 2
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[2] Complete. Time taken: 00:00:23
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 1/157 -- train_loss: 0.0757 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 2/157 -- train_loss: 0.0663 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 3/157 -- train_loss: 0.0792 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 4/157 -- train_loss: 0.0586 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 5/157 -- train_loss: 0.0749 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 6/157 -- train_loss: 0.0906 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 7/157 -- train_loss: 0.0684 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 8/157 -- train_loss: 0.0677 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 9/157 -- train_loss: 0.0870 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 10/157 -- train_loss: 0.0835 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 11/157 -- train_loss: 0.0652 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 12/157 -- train_loss: 0.0805 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 13/157 -- train_loss: 0.0663 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 14/157 -- train_loss: 0.0744 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 15/157 -- train_loss: 0.0653 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 16/157 -- train_loss: 0.0717 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 17/157 -- train_loss: 0.0520 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 18/157 -- train_loss: 0.0743 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 19/157 -- train_loss: 0.0975 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 20/157 -- train_loss: 0.0981 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 21/157 -- train_loss: 0.0632 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 22/157 -- train_loss: 0.0904 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 23/157 -- train_loss: 0.0762 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 24/157 -- train_loss: 0.0700 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 25/157 -- train_loss: 0.0915 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 26/157 -- train_loss: 0.1116 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 27/157 -- train_loss: 0.0731 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 28/157 -- train_loss: 0.0694 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 29/157 -- train_loss: 0.0657 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 30/157 -- train_loss: 0.0826 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 31/157 -- train_loss: 0.0822 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 32/157 -- train_loss: 0.0687 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 33/157 -- train_loss: 0.0553 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 34/157 -- train_loss: 0.0591 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 35/157 -- train_loss: 0.0676 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 36/157 -- train_loss: 0.0588 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 37/157 -- train_loss: 0.0668 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 38/157 -- train_loss: 0.0736 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 39/157 -- train_loss: 0.0560 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 40/157 -- train_loss: 0.0557 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 41/157 -- train_loss: 0.0574 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 42/157 -- train_loss: 0.0946 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 43/157 -- train_loss: 0.0600 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 44/157 -- train_loss: 0.0700 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 45/157 -- train_loss: 0.0600 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 46/157 -- train_loss: 0.0573 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 47/157 -- train_loss: 0.0596 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 48/157 -- train_loss: 0.0803 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 49/157 -- train_loss: 0.0676 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 50/157 -- train_loss: 0.0669 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 51/157 -- train_loss: 0.0731 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 52/157 -- train_loss: 0.0735 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 53/157 -- train_loss: 0.0578 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 54/157 -- train_loss: 0.0675 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 55/157 -- train_loss: 0.0642 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 56/157 -- train_loss: 0.0646 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 57/157 -- train_loss: 0.0613 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 58/157 -- train_loss: 0.0472 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 59/157 -- train_loss: 0.0723 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 60/157 -- train_loss: 0.0661 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 61/157 -- train_loss: 0.0651 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 62/157 -- train_loss: 0.0490 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 63/157 -- train_loss: 0.0557 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 64/157 -- train_loss: 0.0714 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 65/157 -- train_loss: 0.0462 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 66/157 -- train_loss: 0.0475 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 67/157 -- train_loss: 0.0600 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 68/157 -- train_loss: 0.0479 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 69/157 -- train_loss: 0.0484 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 70/157 -- train_loss: 0.0610 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 71/157 -- train_loss: 0.0740 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 72/157 -- train_loss: 0.0574 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 73/157 -- train_loss: 0.0637 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 74/157 -- train_loss: 0.0448 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 75/157 -- train_loss: 0.0600 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 76/157 -- train_loss: 0.0663 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 77/157 -- train_loss: 0.0511 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 78/157 -- train_loss: 0.0641 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 79/157 -- train_loss: 0.0644 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 80/157 -- train_loss: 0.0644 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 81/157 -- train_loss: 0.0608 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 82/157 -- train_loss: 0.0516 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 83/157 -- train_loss: 0.0659 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 84/157 -- train_loss: 0.0429 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 85/157 -- train_loss: 0.0508 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 86/157 -- train_loss: 0.0713 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 87/157 -- train_loss: 0.0608 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 88/157 -- train_loss: 0.0534 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 89/157 -- train_loss: 0.0461 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 90/157 -- train_loss: 0.0522 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 91/157 -- train_loss: 0.0565 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 92/157 -- train_loss: 0.0464 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 93/157 -- train_loss: 0.0716 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 94/157 -- train_loss: 0.0456 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 95/157 -- train_loss: 0.0469 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 96/157 -- train_loss: 0.0645 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 97/157 -- train_loss: 0.0618 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 98/157 -- train_loss: 0.0767 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 99/157 -- train_loss: 0.0418 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 100/157 -- train_loss: 0.0559 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 101/157 -- train_loss: 0.0430 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 102/157 -- train_loss: 0.0373 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 103/157 -- train_loss: 0.0594 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 104/157 -- train_loss: 0.0677 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 105/157 -- train_loss: 0.0366 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 106/157 -- train_loss: 0.0457 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 107/157 -- train_loss: 0.0385 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 108/157 -- train_loss: 0.0568 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 109/157 -- train_loss: 0.0623 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 110/157 -- train_loss: 0.0580 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 111/157 -- train_loss: 0.0548 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 112/157 -- train_loss: 0.0379 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 113/157 -- train_loss: 0.0395 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 114/157 -- train_loss: 0.0444 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 115/157 -- train_loss: 0.0362 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 116/157 -- train_loss: 0.0416 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 117/157 -- train_loss: 0.0429 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 118/157 -- train_loss: 0.0332 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 119/157 -- train_loss: 0.0452 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 120/157 -- train_loss: 0.0638 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 121/157 -- train_loss: 0.0389 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 122/157 -- train_loss: 0.0532 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 123/157 -- train_loss: 0.0561 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 124/157 -- train_loss: 0.0622 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 125/157 -- train_loss: 0.0387 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 126/157 -- train_loss: 0.0620 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 127/157 -- train_loss: 0.0426 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 128/157 -- train_loss: 0.0361 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 129/157 -- train_loss: 0.0439 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 130/157 -- train_loss: 0.0472 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 131/157 -- train_loss: 0.0363 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 132/157 -- train_loss: 0.0461 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 133/157 -- train_loss: 0.0365 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 134/157 -- train_loss: 0.0414 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 135/157 -- train_loss: 0.0546 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 136/157 -- train_loss: 0.0396 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 137/157 -- train_loss: 0.0347 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 138/157 -- train_loss: 0.0411 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 139/157 -- train_loss: 0.0563 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 140/157 -- train_loss: 0.0579 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 141/157 -- train_loss: 0.0415 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 142/157 -- train_loss: 0.0435 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 143/157 -- train_loss: 0.0674 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 144/157 -- train_loss: 0.0372 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 145/157 -- train_loss: 0.0447 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 146/157 -- train_loss: 0.0427 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 147/157 -- train_loss: 0.0406 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 148/157 -- train_loss: 0.0423 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 149/157 -- train_loss: 0.0391 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 150/157 -- train_loss: 0.0345 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 151/157 -- train_loss: 0.0534 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 152/157 -- train_loss: 0.0304 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 153/157 -- train_loss: 0.0364 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 154/157 -- train_loss: 0.0612 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 155/157 -- train_loss: 0.0383 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 156/157 -- train_loss: 0.0389 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 157/157 -- train_loss: 0.0441 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_acc: 0.9922464107698207
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[3] Metrics -- train_acc: 0.9922 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_acc best value: 0.9922464107698207 at epoch: 3
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[3] Complete. Time taken: 00:00:23
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 1/157 -- train_loss: 0.0391 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 2/157 -- train_loss: 0.0445 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 3/157 -- train_loss: 0.0479 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 4/157 -- train_loss: 0.0516 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 5/157 -- train_loss: 0.0459 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 6/157 -- train_loss: 0.0306 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 7/157 -- train_loss: 0.0654 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 8/157 -- train_loss: 0.0536 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 9/157 -- train_loss: 0.0547 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 10/157 -- train_loss: 0.0461 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 11/157 -- train_loss: 0.0283 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 12/157 -- train_loss: 0.0377 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 13/157 -- train_loss: 0.0543 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 14/157 -- train_loss: 0.0476 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 15/157 -- train_loss: 0.0265 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 16/157 -- train_loss: 0.0320 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 17/157 -- train_loss: 0.0531 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 18/157 -- train_loss: 0.0324 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 19/157 -- train_loss: 0.0416 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 20/157 -- train_loss: 0.0318 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 21/157 -- train_loss: 0.0399 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 22/157 -- train_loss: 0.0348 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 23/157 -- train_loss: 0.0313 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 24/157 -- train_loss: 0.0442 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 25/157 -- train_loss: 0.0339 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 26/157 -- train_loss: 0.0383 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 27/157 -- train_loss: 0.0463 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 28/157 -- train_loss: 0.0483 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 29/157 -- train_loss: 0.0471 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 30/157 -- train_loss: 0.0477 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 31/157 -- train_loss: 0.0327 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 32/157 -- train_loss: 0.0444 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 33/157 -- train_loss: 0.0424 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 34/157 -- train_loss: 0.0361 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 35/157 -- train_loss: 0.0399 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 36/157 -- train_loss: 0.0337 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 37/157 -- train_loss: 0.0505 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 38/157 -- train_loss: 0.0297 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 39/157 -- train_loss: 0.0241 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 40/157 -- train_loss: 0.0298 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 41/157 -- train_loss: 0.0579 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 42/157 -- train_loss: 0.0244 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 43/157 -- train_loss: 0.0372 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 44/157 -- train_loss: 0.0493 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 45/157 -- train_loss: 0.0465 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 46/157 -- train_loss: 0.0396 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 47/157 -- train_loss: 0.0517 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 48/157 -- train_loss: 0.0388 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 49/157 -- train_loss: 0.0513 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 50/157 -- train_loss: 0.0411 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 51/157 -- train_loss: 0.0274 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 52/157 -- train_loss: 0.0413 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 53/157 -- train_loss: 0.0366 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 54/157 -- train_loss: 0.0321 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 55/157 -- train_loss: 0.0336 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 56/157 -- train_loss: 0.0469 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 57/157 -- train_loss: 0.0430 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 58/157 -- train_loss: 0.0381 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 59/157 -- train_loss: 0.0321 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 60/157 -- train_loss: 0.0414 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 61/157 -- train_loss: 0.0393 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 62/157 -- train_loss: 0.0410 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 63/157 -- train_loss: 0.0292 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 64/157 -- train_loss: 0.0327 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 65/157 -- train_loss: 0.0270 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 66/157 -- train_loss: 0.0320 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 67/157 -- train_loss: 0.0384 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 68/157 -- train_loss: 0.0270 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 69/157 -- train_loss: 0.0411 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 70/157 -- train_loss: 0.0295 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 71/157 -- train_loss: 0.0388 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 72/157 -- train_loss: 0.0290 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 73/157 -- train_loss: 0.0374 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 74/157 -- train_loss: 0.0511 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 75/157 -- train_loss: 0.0455 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 76/157 -- train_loss: 0.0369 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 77/157 -- train_loss: 0.0359 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 78/157 -- train_loss: 0.0416 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 79/157 -- train_loss: 0.0287 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 80/157 -- train_loss: 0.0357 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 81/157 -- train_loss: 0.0333 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 82/157 -- train_loss: 0.0307 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 83/157 -- train_loss: 0.0355 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 84/157 -- train_loss: 0.0364 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 85/157 -- train_loss: 0.0355 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 86/157 -- train_loss: 0.0336 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 87/157 -- train_loss: 0.0302 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 88/157 -- train_loss: 0.0312 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 89/157 -- train_loss: 0.0238 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 90/157 -- train_loss: 0.0235 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 91/157 -- train_loss: 0.0381 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 92/157 -- train_loss: 0.0218 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 93/157 -- train_loss: 0.0404 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 94/157 -- train_loss: 0.0338 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 95/157 -- train_loss: 0.0236 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 96/157 -- train_loss: 0.0356 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 97/157 -- train_loss: 0.0354 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 98/157 -- train_loss: 0.0321 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 99/157 -- train_loss: 0.0340 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 100/157 -- train_loss: 0.0281 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 101/157 -- train_loss: 0.0402 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 102/157 -- train_loss: 0.0439 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 103/157 -- train_loss: 0.0291 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 104/157 -- train_loss: 0.0262 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 105/157 -- train_loss: 0.0255 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 106/157 -- train_loss: 0.0483 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 107/157 -- train_loss: 0.0235 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 108/157 -- train_loss: 0.0342 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 109/157 -- train_loss: 0.0294 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 110/157 -- train_loss: 0.0316 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 111/157 -- train_loss: 0.0318 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 112/157 -- train_loss: 0.0307 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 113/157 -- train_loss: 0.0303 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 114/157 -- train_loss: 0.0298 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 115/157 -- train_loss: 0.0254 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 116/157 -- train_loss: 0.0207 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 117/157 -- train_loss: 0.0212 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 118/157 -- train_loss: 0.0233 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 119/157 -- train_loss: 0.0296 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 120/157 -- train_loss: 0.0286 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 121/157 -- train_loss: 0.0424 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 122/157 -- train_loss: 0.0263 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 123/157 -- train_loss: 0.0291 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 124/157 -- train_loss: 0.0218 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 125/157 -- train_loss: 0.0293 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 126/157 -- train_loss: 0.0395 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 127/157 -- train_loss: 0.0274 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 128/157 -- train_loss: 0.0302 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 129/157 -- train_loss: 0.0240 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 130/157 -- train_loss: 0.0281 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 131/157 -- train_loss: 0.0172 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 132/157 -- train_loss: 0.0321 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 133/157 -- train_loss: 0.0272 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 134/157 -- train_loss: 0.0163 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 135/157 -- train_loss: 0.0419 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 136/157 -- train_loss: 0.0296 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 137/157 -- train_loss: 0.0374 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 138/157 -- train_loss: 0.0451 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 139/157 -- train_loss: 0.0190 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 140/157 -- train_loss: 0.0241 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 141/157 -- train_loss: 0.0219 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 142/157 -- train_loss: 0.0354 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 143/157 -- train_loss: 0.0297 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 144/157 -- train_loss: 0.0222 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 145/157 -- train_loss: 0.0282 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 146/157 -- train_loss: 0.0288 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 147/157 -- train_loss: 0.0236 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 148/157 -- train_loss: 0.0301 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 149/157 -- train_loss: 0.0240 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 150/157 -- train_loss: 0.0291 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 151/157 -- train_loss: 0.0379 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 152/157 -- train_loss: 0.0239 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 153/157 -- train_loss: 0.0225 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 154/157 -- train_loss: 0.0254 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 155/157 -- train_loss: 0.0185 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 156/157 -- train_loss: 0.0252 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 157/157 -- train_loss: 0.0317 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_acc: 0.9951433561964811
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[4] Metrics -- train_acc: 0.9951 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_acc best value: 0.9951433561964811 at epoch: 4
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[4] Complete. Time taken: 00:00:23
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 1/157 -- train_loss: 0.0224 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 2/157 -- train_loss: 0.0260 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 3/157 -- train_loss: 0.0490 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 4/157 -- train_loss: 0.0172 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 5/157 -- train_loss: 0.0202 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 6/157 -- train_loss: 0.0324 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 7/157 -- train_loss: 0.0305 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 8/157 -- train_loss: 0.0186 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 9/157 -- train_loss: 0.0262 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 10/157 -- train_loss: 0.0171 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 11/157 -- train_loss: 0.0207 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 12/157 -- train_loss: 0.0129 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 13/157 -- train_loss: 0.0281 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 14/157 -- train_loss: 0.0236 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 15/157 -- train_loss: 0.0233 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 16/157 -- train_loss: 0.0265 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 17/157 -- train_loss: 0.0257 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 18/157 -- train_loss: 0.0246 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 19/157 -- train_loss: 0.0229 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 20/157 -- train_loss: 0.0194 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 21/157 -- train_loss: 0.0141 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 22/157 -- train_loss: 0.0279 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 23/157 -- train_loss: 0.0380 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 24/157 -- train_loss: 0.0220 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 25/157 -- train_loss: 0.0164 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 26/157 -- train_loss: 0.0230 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 27/157 -- train_loss: 0.0185 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 28/157 -- train_loss: 0.0323 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 29/157 -- train_loss: 0.0307 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 30/157 -- train_loss: 0.0435 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 31/157 -- train_loss: 0.0355 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 32/157 -- train_loss: 0.0288 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 33/157 -- train_loss: 0.0358 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 34/157 -- train_loss: 0.0286 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 35/157 -- train_loss: 0.0164 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 36/157 -- train_loss: 0.0358 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 37/157 -- train_loss: 0.0260 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 38/157 -- train_loss: 0.0189 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 39/157 -- train_loss: 0.0420 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 40/157 -- train_loss: 0.0239 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 41/157 -- train_loss: 0.0363 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 42/157 -- train_loss: 0.0280 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 43/157 -- train_loss: 0.0262 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 44/157 -- train_loss: 0.0288 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 45/157 -- train_loss: 0.0512 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 46/157 -- train_loss: 0.0249 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 47/157 -- train_loss: 0.0244 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 48/157 -- train_loss: 0.0218 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 49/157 -- train_loss: 0.0194 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 50/157 -- train_loss: 0.0209 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 51/157 -- train_loss: 0.0280 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 52/157 -- train_loss: 0.0287 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 53/157 -- train_loss: 0.0250 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 54/157 -- train_loss: 0.0183 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 55/157 -- train_loss: 0.0156 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 56/157 -- train_loss: 0.0171 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 57/157 -- train_loss: 0.0230 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 58/157 -- train_loss: 0.0166 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 59/157 -- train_loss: 0.0224 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 60/157 -- train_loss: 0.0192 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 61/157 -- train_loss: 0.0333 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 62/157 -- train_loss: 0.0315 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 63/157 -- train_loss: 0.0229 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 64/157 -- train_loss: 0.0155 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 65/157 -- train_loss: 0.0307 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 66/157 -- train_loss: 0.0289 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 67/157 -- train_loss: 0.0233 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 68/157 -- train_loss: 0.0293 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 69/157 -- train_loss: 0.0194 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 70/157 -- train_loss: 0.0206 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 71/157 -- train_loss: 0.0259 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 72/157 -- train_loss: 0.0241 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 73/157 -- train_loss: 0.0561 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 74/157 -- train_loss: 0.0294 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 75/157 -- train_loss: 0.0353 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 76/157 -- train_loss: 0.0126 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 77/157 -- train_loss: 0.0128 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 78/157 -- train_loss: 0.0187 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 79/157 -- train_loss: 0.0310 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 80/157 -- train_loss: 0.0166 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 81/157 -- train_loss: 0.0184 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 82/157 -- train_loss: 0.0288 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 83/157 -- train_loss: 0.0189 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 84/157 -- train_loss: 0.0292 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 85/157 -- train_loss: 0.0161 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 86/157 -- train_loss: 0.0167 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 87/157 -- train_loss: 0.0239 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 88/157 -- train_loss: 0.0185 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 89/157 -- train_loss: 0.0161 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 90/157 -- train_loss: 0.0214 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 91/157 -- train_loss: 0.0251 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 92/157 -- train_loss: 0.0332 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 93/157 -- train_loss: 0.0324 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 94/157 -- train_loss: 0.0172 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 95/157 -- train_loss: 0.0178 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 96/157 -- train_loss: 0.0195 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 97/157 -- train_loss: 0.0441 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 98/157 -- train_loss: 0.0202 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 99/157 -- train_loss: 0.0158 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 100/157 -- train_loss: 0.0134 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 101/157 -- train_loss: 0.0196 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 102/157 -- train_loss: 0.0286 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 103/157 -- train_loss: 0.0247 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 104/157 -- train_loss: 0.0245 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 105/157 -- train_loss: 0.0146 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 106/157 -- train_loss: 0.0165 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 107/157 -- train_loss: 0.0156 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 108/157 -- train_loss: 0.0221 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 109/157 -- train_loss: 0.0239 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 110/157 -- train_loss: 0.0198 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 111/157 -- train_loss: 0.0227 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 112/157 -- train_loss: 0.0125 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 113/157 -- train_loss: 0.0236 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 114/157 -- train_loss: 0.0132 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 115/157 -- train_loss: 0.0209 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 116/157 -- train_loss: 0.0190 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 117/157 -- train_loss: 0.0330 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 118/157 -- train_loss: 0.0175 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 119/157 -- train_loss: 0.0316 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 120/157 -- train_loss: 0.0182 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 121/157 -- train_loss: 0.0197 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 122/157 -- train_loss: 0.0214 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 123/157 -- train_loss: 0.0177 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 124/157 -- train_loss: 0.0173 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 125/157 -- train_loss: 0.0298 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 126/157 -- train_loss: 0.0126 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 127/157 -- train_loss: 0.0141 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 128/157 -- train_loss: 0.0275 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 129/157 -- train_loss: 0.0158 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 130/157 -- train_loss: 0.0203 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 131/157 -- train_loss: 0.0123 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 132/157 -- train_loss: 0.0263 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 133/157 -- train_loss: 0.0141 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 134/157 -- train_loss: 0.0117 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 135/157 -- train_loss: 0.0192 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 136/157 -- train_loss: 0.0240 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 137/157 -- train_loss: 0.0187 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 138/157 -- train_loss: 0.0209 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 139/157 -- train_loss: 0.0224 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 140/157 -- train_loss: 0.0154 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 141/157 -- train_loss: 0.0277 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 142/157 -- train_loss: 0.0274 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 143/157 -- train_loss: 0.0243 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 144/157 -- train_loss: 0.0132 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 145/157 -- train_loss: 0.0158 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 146/157 -- train_loss: 0.0138 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 147/157 -- train_loss: 0.0167 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 148/157 -- train_loss: 0.0135 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 149/157 -- train_loss: 0.0240 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 150/157 -- train_loss: 0.0194 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 151/157 -- train_loss: 0.0225 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 152/157 -- train_loss: 0.0229 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 153/157 -- train_loss: 0.0226 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 154/157 -- train_loss: 0.0224 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 155/157 -- train_loss: 0.0127 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 156/157 -- train_loss: 0.0165 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 157/157 -- train_loss: 0.0191 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_acc: 0.9965918289098112
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[5] Metrics -- train_acc: 0.9966 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_acc best value: 0.9965918289098112 at epoch: 5
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[5] Complete. Time taken: 00:00:22
INFO:ignite.engine.engine.SupervisedTrainer:Engine run complete. Time taken: 00:01:54

 

DecathlonDataset による訓練実験とワークフロー

Decathlon データセットは Medical Segmentation Decathlon AI challenge に由来します。

 

前処理変換のセットアップ

transform = Compose(
    [
        LoadImaged(keys=["image", "label"]),
        AddChanneld(keys=["image", "label"]),
        Spacingd(keys=["image", "label"], pixdim=(
            1.0, 1.0, 1.0), mode=("bilinear", "nearest")),
        Orientationd(keys=["image", "label"], axcodes="RAS"),
        ScaleIntensityd(keys="image"),
        Resized(keys=["image", "label"], spatial_size=(
            32, 64, 32), mode=("trilinear", "nearest")),
        EnsureTyped(keys=["image", "label"]),
    ]
)

 

訓練のために DeccathlonDataset を作成する

DecathlonDataset は MONAI CacheDataset から継承して期待する動作を実現するために豊富なパラメータを提供しています :

  1. root_dir: MSD データセットをキャッシュしてロードするためのユーザのローカルディレクトリ。
  2. task: どのタスクをダウンロードして実行するか : 次のリストの一つです (“Task01_BrainTumour”, “Task02_Heart”, “Task03_Liver”, “Task04_Hippocampus”, “Task05_Prostate”, “Task06_Lung”, “Task07_Pancreas”, “Task08_HepaticVessel”, “Task09_Spleen”, “Task10_Colon”).
  3. section: 想定されるデータ・セクション、以下のいずれかです : training, validation or test.
  4. transform: 入力データ上で操作を実行する変換。デフォルト変換は LoadPNGd と AddChanneld から成り、これはデータを [C, H, W, D] shape を持つ numpy 配列にロードできます。
  5. download: リソース・リンクから Decathlon をダウンロードして抽出するか否か、デフォルトは False です。想定されるファイルが既に存在していれば、それが True に設定されていてもダウンロードはスキップします。ユーザは tar ファイルか dataset フォルダをルートディレクトリに手動でコピーできます。
  6. seed: 訓練、検証とテストデータセットをランダムに分割するためのランダムシード、デフォルトは 0 です。
  7. val_frac: 訓練セクションからの検証比率のパーセンテージで、デフォルトは 0.2 です。Decathlon データはラベルを持つ訓練セクションとラベルなしのテストセクションだけを含みますので、検証セクションとして訓練セクションからランダムに一部を選択します。
  8. cache_num: キャッシュされる項目の数。デフォルトは sys.maxsize です。(cache_num, data_length x cache_rate, data_length) の最小値を取ります。
  9. cache_rate: トータルでキャッシュされるデータのパーセンテージで、デフォルトは 1.0 (cache all) です。(cache_num, data_length x cache_rate, data_length) の最小値を取ります。
  10. num_workers: 使用するワーカースレッドの数です。0 であればシングルスレッドが使用されます。デフォルトは 0 です。

“tar フアイル” は最初にダウンロードした後でキャッシュされることに注意してください。self.__getitem__() API は、self.__len__() 内の指定されたインデックスに従って 1 {“image”: XXX, “label”: XXX} 辞書を生成します。


train_ds = DecathlonDataset(
    root_dir=root_dir,
    task="Task04_Hippocampus",
    transform=transform,
    section="training",
    download=True,
)
# the dataset can work seamlessly with the pytorch native dataset loader,
# but using monai.data.DataLoader has additional benefits of mutli-process
# random seeds handling, and the customized collate functions
train_loader = DataLoader(train_ds, batch_size=32,
                          shuffle=True, num_workers=16)
Task04_Hippocampus.tar: 100%|██████████| 27.1M/27.1M [01:15<00:00, 377kB/s]
Verified 'Task04_Hippocampus.tar.part', md5: 9d24dba78a72977dbd1d2e110310f31b.
Verified 'Task04_Hippocampus.tar', md5: 9d24dba78a72977dbd1d2e110310f31b.
Verified 'Task04_Hippocampus.tar', md5: 9d24dba78a72977dbd1d2e110310f31b.
  0%|          | 0/208 [00:00<?, ?it/s]Default upsampling behavior when mode=trilinear is changed to align_corners=False since 0.4.0. Please specify align_corners=True if the old behavior is desired. See the documentation of nn.Upsample for details.
100%|██████████| 208/208 [00:34<00:00,  6.03it/s]

 

可視化して確認するために DecathlonDataset から画像をピックアップする

plt.subplots(3, 3, figsize=(8, 8))
for i in range(9):
    plt.subplot(3, 3, i + 1)
    plt.imshow(train_ds[i * 20]["image"]
               [0, :, :, 10].detach().cpu(), cmap="gray")
plt.tight_layout()
plt.show()

 

訓練コンポーネントの作成


device = torch.device("cuda:0")
net = UNet(
    spatial_dims=3,
    in_channels=1,
    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)

 

最も簡単な訓練ワークフローを定義して実行する

訓練ワークフローを素早くセットアップするために MONAI SupervisedTrainer ハンドラを使用します。

trainer = SupervisedTrainer(
    device=device,
    max_epochs=5,
    train_data_loader=train_loader,
    network=net,
    optimizer=opt,
    loss_function=loss,
    inferer=SimpleInferer(),
    postprocessing=AsDiscreted(
        keys=["pred", "label"], argmax=(True, False),
        to_onehot=True, num_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 5 epochs
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 1/7 -- train_loss: 0.7959 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 2/7 -- train_loss: 0.7505 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 3/7 -- train_loss: 0.7073 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 4/7 -- train_loss: 0.6903 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 5/7 -- train_loss: 0.6436 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 6/7 -- train_loss: 0.5983 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 1/5, Iter: 7/7 -- train_loss: 0.5609 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_meandice: 0.3706986674895653
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[1] Metrics -- train_meandice: 0.3707 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_meandice best value: 0.3706986674895653 at epoch: 1
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[1] Complete. Time taken: 00:00:01
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 1/7 -- train_loss: 0.5261 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 2/7 -- train_loss: 0.5211 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 3/7 -- train_loss: 0.5054 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 4/7 -- train_loss: 0.4820 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 5/7 -- train_loss: 0.4693 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 6/7 -- train_loss: 0.4541 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 2/5, Iter: 7/7 -- train_loss: 0.4388 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_meandice: 0.5458252521661612
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[2] Metrics -- train_meandice: 0.5458 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_meandice best value: 0.5458252521661612 at epoch: 2
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[2] Complete. Time taken: 00:00:03
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 1/7 -- train_loss: 0.4413 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 2/7 -- train_loss: 0.4305 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 3/7 -- train_loss: 0.4200 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 4/7 -- train_loss: 0.4210 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 5/7 -- train_loss: 0.4044 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 6/7 -- train_loss: 0.3963 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 3/5, Iter: 7/7 -- train_loss: 0.3781 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_meandice: 0.5662448773017297
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[3] Metrics -- train_meandice: 0.5662 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_meandice best value: 0.5662448773017297 at epoch: 3
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[3] Complete. Time taken: 00:00:03
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 1/7 -- train_loss: 0.3717 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 2/7 -- train_loss: 0.3557 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 3/7 -- train_loss: 0.3526 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 4/7 -- train_loss: 0.3365 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 5/7 -- train_loss: 0.3163 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 6/7 -- train_loss: 0.3026 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 4/5, Iter: 7/7 -- train_loss: 0.2737 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_meandice: 0.6949328046578628
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[4] Metrics -- train_meandice: 0.6949 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_meandice best value: 0.6949328046578628 at epoch: 4
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[4] Complete. Time taken: 00:00:03
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 1/7 -- train_loss: 0.2623 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 2/7 -- train_loss: 0.2445 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 3/7 -- train_loss: 0.2299 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 4/7 -- train_loss: 0.2190 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 5/7 -- train_loss: 0.2207 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 6/7 -- train_loss: 0.2051 
INFO:ignite.engine.engine.SupervisedTrainer:Epoch: 5/5, Iter: 7/7 -- train_loss: 0.1910 
INFO:ignite.engine.engine.SupervisedTrainer:Got new best metric of train_meandice: 0.7996270152238699
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[5] Metrics -- train_meandice: 0.7996 
INFO:ignite.engine.engine.SupervisedTrainer:Key metric: train_meandice best value: 0.7996270152238699 at epoch: 5
INFO:ignite.engine.engine.SupervisedTrainer:Epoch[5] Complete. Time taken: 00:00:03
INFO:ignite.engine.engine.SupervisedTrainer:Engine run complete. Time taken: 00:00:15

 

他の公開データを共有して MONAI にデータセットを追加する

MedNISTDataset or DecathlonDataset を参考にして、他の公開データのための新しいデータセットを作成することは簡単です。主として以下のステップを含みます :

  1. MONAI CacheDataset を継承して、訓練を高速化するためにキャッシング機構を利用します。
  2. データセットのライセンスが公開アクセスと共有を許容していることを確認してください。
  3. データセットでデータをダウンロードして抽出するために monai.apps.download_and_extract を使用します。
  4. 訓練、検証とテストセクションをランダムに分割するロジックを定義します。
  5. 辞書項目でデータリストを構築します :
    [
     {'image': image1_path, 'label': label1_path},
     {'image': image2_path, 'label': label2_path},
     {'image': image3_path, 'label': label3_path},
     ... ...
    ]
    
  6. データセット固有のロジックを定義します。

 

例として IXIDataset を定義する

ここでは新しい IXIDataset を作成する方法を示すために例として IXI データセット を使用します。

class IXIDataset(Randomizable, CacheDataset):
    resource = "http://biomedic.doc.ic.ac.uk/" \
        + "brain-development/downloads/IXI/IXI-T1.tar"
    md5 = "34901a0593b41dd19c1a1f746eac2d58"

    def __init__(
        self,
        root_dir,
        section,
        transform,
        download=False,
        seed=0,
        val_frac=0.2,
        test_frac=0.2,
        cache_num=sys.maxsize,
        cache_rate=1.0,
        num_workers=0,
    ):
        if not os.path.isdir(root_dir):
            raise ValueError("Root directory root_dir must be a directory.")
        self.section = section
        self.val_frac = val_frac
        self.test_frac = test_frac
        self.set_random_state(seed=seed)
        dataset_dir = os.path.join(root_dir, "ixi")
        tarfile_name = f"{dataset_dir}.tar"
        if download:
            download_and_extract(
                self.resource, tarfile_name, dataset_dir, self.md5)
        # as a quick demo, we just use 10 images to show

        self.datalist = [
            {"image": os.path.join(
                dataset_dir, "IXI314-IOP-0889-T1.nii.gz"), "label": 0},
            {"image": os.path.join(
                dataset_dir, "IXI249-Guys-1072-T1.nii.gz"), "label": 0},
            {"image": os.path.join(
                dataset_dir, "IXI609-HH-2600-T1.nii.gz"), "label": 0},
            {"image": os.path.join(
                dataset_dir, "IXI173-HH-1590-T1.nii.gz"), "label": 1},
            {"image": os.path.join(
                dataset_dir, "IXI020-Guys-0700-T1.nii.gz"), "label": 0},
            {"image": os.path.join(
                dataset_dir, "IXI342-Guys-0909-T1.nii.gz"), "label": 0},
            {"image": os.path.join(
                dataset_dir, "IXI134-Guys-0780-T1.nii.gz"), "label": 0},
            {"image": os.path.join(
                dataset_dir, "IXI577-HH-2661-T1.nii.gz"), "label": 1},
            {"image": os.path.join(
                dataset_dir, "IXI066-Guys-0731-T1.nii.gz"), "label": 1},
            {"image": os.path.join(
                dataset_dir, "IXI130-HH-1528-T1.nii.gz"), "label": 0},
        ]
        data = self._generate_data_list()
        super().__init__(
            data, transform, cache_num=cache_num,
            cache_rate=cache_rate, num_workers=num_workers,
        )

    def randomize(self, data=None):
        self.rann = self.R.random()

    def _generate_data_list(self):
        data = []
        for d in self.datalist:
            self.randomize()
            if self.section == "training":
                if self.rann < self.val_frac + self.test_frac:
                    continue
            elif self.section == "validation":
                if self.rann >= self.val_frac:
                    continue
            elif self.section == "test":
                if self.rann < self.val_frac or \
                        self.rann >= self.val_frac + self.test_frac:
                    continue
            else:
                raise ValueError(
                    f"Unsupported section: {self.section}, "
                    "available options are ['training', 'validation', 'test']."
                )
            data.append(d)
        return data

 

可視化して確認するために IXIDataset から画像をピックアップする

train_ds = IXIDataset(
    root_dir=root_dir,
    section="training",
    transform=Compose([LoadImaged("image"), EnsureTyped("image")]),
    download=True,
)
plt.figure("check", (18, 6))
for i in range(3):
    plt.subplot(1, 3, i + 1)
    plt.imshow(train_ds[i]["image"][:, :, 80].detach().cpu(), cmap="gray")
plt.show()
Verified 'ixi.tar', md5: 34901a0593b41dd19c1a1f746eac2d58.
file /workspace/data/medical/ixi.tar exists, skip downloading.
Verified 'ixi.tar', md5: 34901a0593b41dd19c1a1f746eac2d58.
100%|██████████| 9/9 [00:02<00:00,  3.51it/s]

 

データディレクトリのクリーンアップ

一時ディレクトリが使用された場合にはディレクトリを削除します。

if directory is None:
    shutil.rmtree(root_dir)
 

以上



MONAI 0.7 : モジュール概要 (4) 研究, パフォーマンス最適化と GPU 高速化, アプリケーション

MONAI 0.7 : モジュール概要 (4) 研究, パフォーマンス最適化と GPU 高速化, アプリケーション (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 11/04/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

 

MONAI 0.7 : モジュール概要 (4) 研究, パフォーマンス最適化と GPU 高速化, アプリケーション

研究

MONAI には、高位な研究課題に取り組む最近公開された論文に対応する、幾つかの研究プロトタイプがあります。私達はコメント、提案そしてコード実装の形式での貢献をいつでも歓迎しています。

研究プロトタイプから特定される一般的なパターン/モジュールは MONAI コア機能に統合されます。

 

1. COVID-19 肺炎病変セグメンテーションのための COPLE-Net

次により元々は提案された COPLE-Net の 再実装 :

G. Wang, X. Liu, C. Li, Z. Xu, J. Ruan, H. Zhu, T. Meng, K. Li, N. Huang, S. Zhang. (2020) “A Noise-robust Framework for Automatic Segmentation of COVID-19 Pneumonia Lesions from CT Images.” IEEE Transactions on Medical Imaging. 2020. DOI: 10.1109/TMI.2020.3000314

 

2. LAMP : 画像セグメンテーションのための自動モデル並列化による Large Deep Net

次により元々は提案された LAMP の 再実装 :

Wentao Zhu, Can Zhao, Wenqi Li, Holger Roth, Ziyue Xu, and Daguang Xu (2020) “LAMP: Large Deep Nets with Automated Model Parallelism for Image Segmentation.” MICCAI 2020 (Early Accept, paper link: https://arxiv.org/abs/2006.12575)

 

パフォーマンス最適化と GPU アクセラレーション

典型的には、モデル訓練は深層学習開発の間の時間を消費するステップです、特に医用画像アプリケーションでは。ボリュメトリックな医用画像は通常は (多次元配列として) 大きくそしてモデル訓練プロセスは複雑である可能性があります。強力なハードウェア (大きな RAM を持つ CPU/GPU) を使用してさえも、高いパフォーマンスを得るためにそれらを活用することは簡単ではありません。MONAI はベスト・パフォーマンスを得るための高速訓練ガイドを提供しています : https://github.com/Project-MONAI/tutorials/blob/master/acceleration/fast_model_training_guide.md

NVIDIA GPU は深層学習と評価の多くの分野で広く利用されていて、CUDA 並列計算は従来の計算方法と比較したとき明らかな高速化を示します。GPU 機能を完全に活用するため、自動混合精度 (AMP), 分散データ並列 等のような、多くのポピュラーなメカニズムが提示されました。MONAI はこれらの機能をサポートできて、豊富なサンプルを提供しています。

 

1. パイプラインのプロファイル

最初に、MONAI はパフォーマンス・ボトルネックを特定するためにプログラムを分析する DLProf, Nsight, NVTX と NVML に基づく幾つかの方法をユーザに提供します。分析はモデル訓練の間の演算ベースの GPU アクティビティと GPU 全体のアクティビティです。それらはユーザが計算ボトルネックを管理するのに非常に役立ち、そしてより良い計算効率のために改良されるべき領域のための洞察を与えます。詳細なサンプルは パフォーマンス・プロファイリング・チュートリアル で示されます

 

2. 自動混合精度 (AMP)

2017 年に、NVIDIA 研究者は混合精度訓練のための手法を開発しました、これはネットワークを訓練するとき、単精度 (FP32) を半精度 (e.g. FP16) 形式と組合せ、そして同じハイパーパラメータを使用する FP32 訓練と同じ精度を獲得するものです。

PyTorch 1.6 リリースについて、NVIDIA と Facebook の開発者は混合精度機能を PyTorch コアに AMP パッケージ, torch.cuda.amp として移しました。

MONAI ワークフローは AMP を有効/無効にするために訓練の間に SupervisedTrainer or SupervisedEvaluator で amp=True/False を簡単に設定できます。そして CUDA 11 と PyTorch 1.6 を使用して NVIDIA V100 上で AMP ON/OFF で訓練スピードを比較することを試し、幾つかのベンチマーク結果を得ました :

同じソフトウェア環境で同じテストプログラムを NVIDIA A100 GPU 上で実行もしました、より高速な結果を得ました :

詳細は AMP 訓練チュートリアル で利用可能です。AMP をまた、MONAI で高速訓練を獲得するために CacheDataset, GPU キャッシュ, GPU 変換, ThreadDataLoader, DiceCE 損失関数と Novograd optimizer と組合せてもみました。訓練が 0.95 の検証平均 dice で収束するとき PyTorch ネイティブ実装と比較しておよそ 200x のスピードアップを得られました。参考のためのベンチマークです :

詳細は 高速訓練チュートリアル で利用可能です。

 

3. 分散データ並列

分散データ並列は、モデルを訓練または評価するためにシングル or マルチノード上で複数の GPU デバイスに接続するための PyTorch の重要な機能です。MONAI の分散データ並列 API はネイティブ PyTorch 分散モジュール、pytorch-ignite 分散モジュール、Horovod、XLA そして SLURM プラットフォームと互換です。MONAI は参考のためのデモを提供しています : PyTorch DDP による訓練/評価、Horovod による訓練/評価、Ignite DDP による訓練/評価、SmartCacheDataset によるデータセットの分割と訓練、そして Decathlon チャンレンジ Task01 に基づく現実世界の訓練サンプル – 脳腫瘍セグメンテーション 等です。チュートリアル は分散キャッシング、訓練と検証を含みます。参考のためにパフォーマンス・ベンチマークを取得しました (PyTorch 1.9.1, CUDA 11.4, NVIDIA V100 GPU に基づいています。最適化は、より多くの GPU リソースにより、データを分割し GPU メモリにキャッシュして GPU 変換を直接実行できるという意味です)。

 

4. C++/CUDA 最適化モジュール

ワークフローのドメイン固有のルーチンを更に高速化するため、MONAI C++/CUDA 実装が PyTorch ネイティブ実装の拡張として導入されました。MONAI は PyTorch から C++ 拡張を構築する 2 つの方法 を使用してモジュールを提供します。

  • Resampler, Conditional random field (CRF), permutohedral 格子を使用する Fast bilateral フィルタリングを含むモジュールについては、setuptools を通して。

  • Gaussian mixtures (ガウス混合) モジュールについては、just-in-time (JIT) コンパイルを通しています。このアプローチはユーザが指定したパラメータとローカルシステム環境に従って動的最適化を可能にします。次の図は、組織と手術器具のセグメンテーションに適用された MONAI のガウス混合モデルの結果を示しています :

 

5. Cache IO and transforms data to GPU memory

CacheDataset を使用してさえも、通常はエポック毎に GPU ランダム変換やネットワーク計算のために同じデータを GPU メモリにコピーする必要があります。効率的なアプローチはデータを GPU メモリに直接キャッシュすれば、総てのエポックで GPU 計算を直ちに始められます。

例えば :

train_transforms = [
    LoadImaged(...),
    AddChanneld(...),
    Spacingd(...),
    Orientationd(...),
    ScaleIntensityRanged(...),
    EnsureTyped(..., data_type="tensor"),
    ToDeviced(..., device="cuda:0"),
    RandCropByPosNegLabeld(...),
]
dataset = CacheDataset(..., transform=train_trans)

ここでは EnsureTyped 変換で PyTorch テンソルに変換して、ToDeviced 変換でデータを GPU に移しています。CacheDataset が変換結果を ToDeviced までキャッシュしますので、それは GPU メモリ内にあります。そしてエポック毎に、プログラムは GPU メモリからキャッシュされたデータを取得して GPU 上でランダム変換 RandCropByPosNegLabeld だけを直接実行します。GPU キャッシング・サンプルは 脾臓高速訓練チュートリアル で利用可能です。

 

アプリケーション

医用画像深層学習の研究エリアは急速に拡大しています。最新の成果をアプリケーションに応用するため、MONAI は、他の類似のユースケースのために end-to-end なソリューションやプロトタイプを構築するために多くのアプリケーション・コンポーネントを含みます。

 

1. 対話的セグメンテーションのための DeepGrow モジュール

DeepGrow コンポーネントの再実装です、これは深層学習ベースの半自動のセグメンテーション・アプローチで、医用画像の関心領域描写のための「スマートな」対話的ツールを目的としていて、元は次により提案されました :

Sakinis, Tomas, et al. “Interactive segmentation of medical images through fully convolutional neural networks.” arXiv preprint arXiv:1903.08205 (2019).

 

2. デジタルパソロジーの病変検出

パソロジー検出コンポーネントの 実装 で、NVIDIA cuCIM ライブラリと SmartCache メカニズムによる効率的なスライド全体の画像 IO とサンプリング、病変の FROC 測定、そして病変検出のための確率的後処理を含みます。

 

3. 学習ベースの画像レジストレーション

v0.5.0 から、MONAI は学習ベースの 2D/3D レジストレーション・ワークフローを構築するための実験的な機能を提供しています。これらは損失関数として画像類似尺度、モデル正則化として曲げエネルギー (= bending energy)、ネットワーク・アーキテクチャ、ワーピング・モジュールを含みます。コンポーネントは主要な教師なし、弱 (= weakly) 教師ありアルゴリズムを構築するために使用できます。

以下の図は、MONAI を使用して単一の患者の異なる時間点で得られた CT 画像のレジストレーションを示します :

 

4. 最先端の Kaggle コンペティション・ソリューションの再現

RANZCR CLiP – カテーテルと Line Position チャレンジ in Kaggle: https://www.kaggle.com/c/ranzcr-clip-catheter-line-classification の 4 位のソリューションの 再実装 です。

元のソリューションは Team Watercooled により作成され、そして作者は Dieter (https://www.kaggle.com/christofhenkel) と Psi (https://www.kaggle.com/philippsinger) です。

 

以上



MONAI 0.7 : モジュール概要 (3) ネットワーク, 評価, ワークフロー 等

MONAI 0.7 : モジュール概要 (3) ネットワーク, 評価, ワークフロー 等 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 11/01/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

 

MONAI 0.7 : モジュール概要 (3) ネットワーク, 評価, ワークフロー 等

損失

医用画像の研究では、一般的なコンピュータビジョン・タスクでは通常は使用されない、ドメイン固有の損失関数があります。MONAI の重要なモジュールとして、DiceLoss, GeneralizedDiceLoss, MaskedDiceLoss, TverskyLoss, FocalLoss, DiceCELoss と DiceFocalLoss 等のような、これらの損失関数は PyTorch で実装されています。

 

Optimizers

MONAI は訓練は再調整の進捗を高速化する手助けをするために optimizer で幾つかの高度な機能を提供しています。例えば、Novograd optimizer は従来の optimizer よりも高速に収束させるために使用できます。そしてユーザは generate_param_groups ユティリティ API に基づいて、モデル層のために異なる学習率を簡単に定義することができます。

もう一つの重要な機能は LearningRateFinder です。学習率の範囲テストは 2 つの境界の間で事前訓練実行の学習率を線形または指数関数的な方法で増加させます。それはネットワークが学習率の範囲でどのくらい上手く訓練できるか、そして最適な学習率が何かについての有益な情報を提供します。LearningRateFinder チュートリアル は API 使用方法のサンプルを示します。

 

ネットワーク・アーキテクチャ

幾つかの深層ニューラルネットワーク・アーキテクチャが医用画像解析タスクに特に効果的であることを示しています。MONAI は柔軟性とコード可読性の両方を目的とするリファレンス・ネットワークを実装しています。

 

1. 事前定義された層とブロック

一般的なネットワーク層とブロックを活用するため、MONAI は幾つかの事前定義された層とブロックを提供しています、これらは 1D, 2D と 3D ネットワークと互換です。ユーザは層ファクトリをカスタマイズされたネットワークに簡単に統合できます。

例えば :

# import MONAI’s layer factory
from monai.networks.layers import Conv

# adds a transposed convolution layer to the network
# which is compatible with different spatial dimensions.
name, dimension = Conv.CONVTRANS, 3
conv_type = Conv[name, dimension]
add_module('conv1', conv_type(in_channels, out_channels, kernel_size=1, bias=False))

 

2. 一般的な 2D/3D ネットワークの実装

そして、UNet, DynUNet, DenseNet, GAN, AHNet, VNet, SENet(と SEResNet, SEResNeXt), SegResNet, EfficientNet, Attention ベースのトランスフォーマー・ネットワークのような、中間的なブロックと一般的なネットワークの幾つかの 1D/2D/3D 互換な実装もあります、総てのネットワークは torch.jit.script に基づいた PyTorch シリアライゼーション・パイプラインをサポートできます。

 

3. 最終層を再調整するためのネットワーク・アダプター

スクラッチから訓練する代わりに、新しい学習タスクのために既存のモデルを活用して、ネットワークの最終層を再調整する場合が良くあります。MONAI はモデルの最終層を畳込み層や完全結合層で簡単に置き換えられる NetAdapter を提供しています。典型的な使用例は ImageNet で訓練された Torchvision モデル を他の学習タスクに適応させることです。

 

評価

モデル推論を実行してモデル品質を評価するために、MONAI は広く使用されている関連アプローチのためのリファレンス実装を提供しています。現在、幾つかのポピュラーな評価メトリクスと推論パターンが含まれています :

 

1. スライディング・ウィンドウ推論

大きなボリューム上のモデル推論のためには、スライディングウィンドウ・アプローチは、柔軟なメモリ要件を持ちながら、高い性能を獲得するためのポピュラーな選択です (代わりに、MONAI を使用する モデル並列訓練 についての最新の研究もチェックしてください)。それはまたより良い性能のためにオーバーラップされたウィンドウを処理するために overlap と blending_mode configuration もサポートします。

典型的なプロセスは :

  1. 元の画像上で連続するウィンドウを選択する。
  2. 総てのウィンドウが解析されるまでバッチ処理されたウィンドウ推論を反復的に実行する。
  3. 推論出力を単一のセグメンテーション・マップに集約する。
  4. 結果をファイルに保存するか評価メトリクスを計算する。

脾臓 3D セグメンテーション・チュートリアル は検証のために SlidingWindow 推論を利用しています。

 

2. 医療タスクのためのメトリクス

医用画像固有のモデルの品質を測定するために様々な有用な評価メトリクスが使用されています。MONAI は既に多くの医療ドメイン固有のメトリクスを実装しています、次のようなものです : 平均 Dice, ROCAUC, 混同行列, ハウスドルフ距離, サーフェス距離, オクルージョン感度。

例えば、セグメンテーション・タスクのために平均 Dice スコアが、分類タスクのために ROC 曲線の下の面積 (ROCAUC) が使用できます。より多くのオプションを統合し続けます。

  1. MONAI はメトリクスのための柔軟な基底 API を提供しています。MONAI メトリクスの基底クラスは反復とエポックベースのメトリクスの両方のための基本計算ロジックを実装しています。それらはカスタマイズされたメトリクスのための良い開始点です。

  2. 総てのメトリクスはデータ並列計算をサポートします。Cumulative 基底クラスでは、中間的なメトリックの結果を自動的にバッファリングし、累積し、分散プロセスに渡り同期し、そして最終結果のために集約できます。マルチプロセス計算サンプル は、マルチプロセス環境で保存された予測とラベルに基づいてメトリクスを計算する方法を示します。

  3. 総てのメトリクスモジュールはバッチ first テンソルとチャネル first テンソルのリストを扱うことができます。

 

3. メトリクス・レポート生成

評価の間、ユーザは通常は総ての入力画像のメトリクスを保存してから、深層学習パイプラインを改良するために悪いケースを分析します。
メトリクスの詳細情報をセーブするため、MONAI はハンドラ MetricsSaver を提供しました、これは最終的なメトリック値、総ての入力画像の総てのモデル出力チャネルの raw メトリック、(平均, 中央値, max, min <int>パーセンタイル, std 等の) 演算のメトリクス要約レポートをセーブすることができます。前立腺データセットによる検証の MeanDice レポートは以下のようなものです :

 

視覚化

単純な点と曲線プロットとは別に、MONAI は多次元データを TensorBoard でGIF アニメとして可視化するために直感的なインターフェイスを提供します。これは、例えば、ボリュメトリック入力、セグメンテーションマップと中間的な特徴マップを可視化することによりモデルの素早い定性的な評価を提供できるでしょう。可視化の実行可能なサンプルは UNet 訓練サンプル で利用可能です。

そして訓練済みの分類モデルのためのクラス活性マッピングを可視化するため、MONAI は 2D と 3D モデルの両方のための CAM, GradCAM, GradCAM++ API を提供します :

上のサンプルは、肺 CT 病変分類モデルから GradCAM/GradCAM++ を計算することにより生成されます。

 

結果の書き出し

現在、MONAI はモデル出力をセグメンテーション・タスクのためには NIfTI ファイルや PNG ファイル、そして分類タスクのためには CSV ファイルとして書き出すことをサポートしています。そして writer は入力画像の original_shape or original_affine 情報に従ってデータ spacing, 向きや shape を復元することができます。

形式の豊富なセットもまた、出力から自動的に計算される関連する統計情報と評価メトリクスと一緒に間もなくサポートされます。

 

ワークフロー

訓練と評価実験を素早くセットアップするため、MONAI はモジュールを大幅に単純化して高速なプロトタイピングを可能にするワークフローのセットを提供します。

これらの機能はドメイン固有のコンポーネントと一般的な機械学習プロセスを切り離します。それらはまた (AutoML, 連合学習のような) 高位アプリケーションのための unify API のセットも提供します。ワークフローの trainer と evaluator は pytorch-ignite エンジンとイベントハンドラ・メカニズムと互換です。MONAI には独立に trainer や evaluator に装着する豊富なイベントハンドラがあり、ユーザはワークフローに追加のカスタムイベントを登録できます。

 

1. 一般的なワークフロー・パイプライン

ワークフローと MONAI イベントハンドラの幾つかは以下で示されます :

end-to-end な訓練と評価サンプルは Workflow サンプル で利用可能です。

 

2. EnsembleEvaluator

モデル・アンサンブルはより正確でより安定した出力を獲得するために機械学習と深層学習領域でポピュラーなストラテジーです。典型的な実践は :

  1. 総ての訓練データセットを K folds に分割します。
  2. 総ての K-1 folds データで K 個のモデルを訓練します。
  3. 総ての K 個のモデルでテストデータ上の推論を実行します。
  4. 最終結果として重み付けて平均値を計算するか、最も一般的な値を投票で決定します。

     

    実践の詳細は モデルアンサンブル・チュートリアル にあります。

     

    異なる入力/出力クラスのための転移学習

    転移学習は一般的で効率的な訓練アプローチで、特に訓練のための大規模なデータセットを得ることが困難である可能性がある医療固有ドメインで。従って事前訓練済みのチェックポイントからの転移学習はモデルメトリクスを大幅に改善して訓練時間を短縮できます。

    MONAI は訓練の前のワークフローのためにチェックポイントをロードする CheckpointLoader を提供しました、そしてそれは現在のネットワークの幾つかの層名がチェックポイントと一致しなかったり、幾つかの層 shape がチェックポイントに一致しないことを許容します、それは現在のタスクが異なる画像クラスや出力クラスを持つ場合に有用である可能性があります。

     

    4. NVIDIA Clara MMAR に基づく転移学習

    MMAR (医療モデル ARchive) はモデル開発ライフサイクルの間に生成される総てのアーティファクトを体系化するためのデータ構造を定義します。NVIDIA Clara は医療ドメイン固有のモデルの豊富な既存の MMAR を提供しています。そしてこれらの MMAR は、総ての開発タスクを実行するワークスペースを提供する configuration とスクリプトを含む、モデルについての総ての情報を含みます。Nvidia GPU クラウド上でリリースされた事前訓練済みの MMAR をより良く利用するために、MONAI は MMAR にアクセスするために pythonic API を提供しています。

    以下の図は損失曲線と検証スコアを訓練エポック数に従って、次のために比較しています : (1) スクラッチからの訓練 (緑色のライン), (2) 事前訓練済みのモデルの適用 (マゼンタ色のライン), (3) 事前訓練済みモデルからの訓練 (青色のライン) (チュートリアルは transfer_mmar で利用可能です) :

     

    5. 柔軟な後処理のためにバッチデータを分離する (= Decollate)

    decollate batch が MONAI v0.6 で導入されました、これは後処理変換を単純化して、様々なデータ shape のデータのバッチ上で柔軟な後に続く演算を提供します。それはバッチ化データをテンソルのリストに分離できます、以下のようなメリットのためにです :

    1. 各項目に対して独立に後処理変換を可能にします – ランダム化された変換がバッチの各予測された項目のために異なって適用できます。

    2. 変換 API を単純化して入力検証の負荷を軽減します、何故なら今では前処理と後処理変換は「チャネル first」入力形式をサポートする必要があるだけだからです。

    3. 予測のための Invertd と異なる shape を持つ反転したデータを可能にします、データ項目がリストにあり単一のテンソルにスタックされていないからです。

    4. 柔軟なメトリック計算でバッチ first テンソルとチャネル first テンソルのリストの両方を可能にします。

     
    decollate batch の典型的なプロセスは以下のように図示されます (例として batch_size=N モデル予測とラベルによる) :

    decollate batch チュートリアル は PyTorch ネイティブ・ワークフローに基づく詳細な使用例を示します。

     

    6. ポピュラーなワークフローへの統合が簡単

    pytorch-ignite ベースの monai.engines を除いて、MONAI モジュールの殆どは独立に使用できて他のソフトウェア・パッケージと組み合わせることもできます。例えば、MONAI は PyTorch-Lightning と Catalyst のようなポピュラーなフレームワークに容易に統合できます : Lightning セグメンテーションLightning + TorchIO チュートリアルは MONAI モジュールを使用する PyTorch Lightning を示し、そして Catalyst セグメンテーション は MONAI モジュールを使用する Catalyst プログラムを示します。

     

    以上



MONAI 0.7 : tutorials : 3D セグメンテーション – MONAI と Catalyst による 3D セグメンテーション

MONAI 0.7 : tutorials : 3D セグメンテーション – MONAI と Catalyst による 3D セグメンテーション (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/22/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

 

MONAI 0.7 : tutorials : 3D セグメンテーション – MONAI と Catalyst による 3D セグメンテーション

このノートブックは MONAI が Catalyst フレームワークと連携して使用される場合の方法を示します。

このチュートリアルは、3D セグメンテーション・タスクのために MONAI を Catalyst フレームワークと共に使用できる方法を実演します。そして以下の機能を簡単に利用できます :

  • 合成データを準備する。
  • メタデータと一緒に Nifti 画像をロードする。
  • 辞書形式データのための変換。
  • チャネル次元がない場合、データにチャネル dim を追加する。
  • 医療画像強度を想定される範囲でスケールする。
  • ポジティブ / ネガティブ・ラベル比率に基づいてバランスの取れた画像のバッチをクロップする。
  • 3D セグメンテーション・タスクのための 3D UNet モデル、Dice 損失関数、Mean Dice メトリック。
  • スライディング・ウィンドウ推論法。
  • 再現性のための決定論的訓練。

このチュートリアルは unet_training_dict.pyspleen_segmentation_3d.ipynb に基づいています。

 

環境のセットアップ

!python -c "import monai" || pip install -q "monai-weekly[nibabel, tensorboard]"
!python -c "import matplotlib" || pip install -q matplotlib
!python -c "import catalyst" || pip install -q catalyst==20.07
%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 glob
import logging
import os
import shutil
import sys
import tempfile

import catalyst.dl
import matplotlib.pyplot as plt
import nibabel as nib
import numpy as np
from monai.config import print_config
from monai.data import Dataset, create_test_image_3d, list_data_collate, decollate_batch
from monai.inferers import sliding_window_inference
from monai.losses import DiceLoss
from monai.metrics import DiceMetric
from monai.networks.nets import UNet
from monai.transforms import (
    Activations,
    AsChannelFirstd,
    AsDiscrete,
    Compose,
    LoadImaged,
    RandCropByPosNegLabeld,
    RandRotate90d,
    ScaleIntensityd,
    EnsureTyped,
    EnsureType,
)
from monai.utils import first

import torch

print_config()
MONAI version: 0.6.0rc1+2.g50d83912
Numpy version: 1.20.1
Pytorch version: 1.9.0a0+2ecb2c7
MONAI flags: HAS_EXT = True, USE_COMPILED = False
MONAI rev id: 50d83912536c5579506cdf6920c47ba65ea66e49

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: 1.15.0+nv
gdown version: 3.13.0
TorchVision version: 0.9.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

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

 

ロギングのセットアップ

logging.basicConfig(stream=sys.stdout, level=logging.INFO)

 

MONAI コンポーネント

合成データの準備

for i in range(40):
    im, seg = create_test_image_3d(
        128, 128, 128, num_seg_classes=1, channel_dim=-1
    )

    n = nib.Nifti1Image(im, np.eye(4))
    nib.save(n, os.path.join(root_dir, f"img{i}.nii.gz"))

    n = nib.Nifti1Image(seg, np.eye(4))
    nib.save(n, os.path.join(root_dir, f"seg{i}.nii.gz"))

images = sorted(glob.glob(os.path.join(root_dir, "img*.nii.gz")))
segs = sorted(glob.glob(os.path.join(root_dir, "seg*.nii.gz")))

 

変換とデータセットの準備

train_files = [
    {"img": img, "seg": seg} for img, seg in zip(images[:20], segs[:20])
]
val_files = [
    {"img": img, "seg": seg} for img, seg in zip(images[-20:], segs[-20:])
]

# define transforms for image and segmentation
train_transforms = Compose(
    [
        LoadImaged(keys=["img", "seg"]),
        AsChannelFirstd(keys=["img", "seg"], channel_dim=-1),
        ScaleIntensityd(keys=["img", "seg"]),
        RandCropByPosNegLabeld(
            keys=["img", "seg"],
            label_key="seg",
            spatial_size=[96, 96, 96],
            pos=1,
            neg=1,
            num_samples=4,
        ),
        RandRotate90d(keys=["img", "seg"], prob=0.5, spatial_axes=[0, 2]),
        EnsureTyped(keys=["img", "seg"]),
    ]
)
val_transforms = Compose(
    [
        LoadImaged(keys=["img", "seg"]),
        AsChannelFirstd(keys=["img", "seg"], channel_dim=-1),
        ScaleIntensityd(keys=["img", "seg"]),
        EnsureTyped(keys=["img", "seg"]),
    ]
)

# define dataset, data loader
check_ds = Dataset(data=train_files, transform=train_transforms)
# use batch_size=2 to load images and use RandCropByPosNegLabeld to generate 2 x 4 images for network training
check_loader = torch.utils.data.DataLoader(
    check_ds, batch_size=2, num_workers=4, collate_fn=list_data_collate
)
check_data = first(check_loader)
print(check_data["img"].shape, check_data["seg"].shape)

# create a training data loader
train_ds = Dataset(data=train_files, transform=train_transforms)
# use batch_size=2 to load images and use RandCropByPosNegLabeld to generate 2 x 4 images for network training
train_loader = torch.utils.data.DataLoader(
    train_ds,
    batch_size=2,
    shuffle=True,
    num_workers=4,
    collate_fn=list_data_collate,
    pin_memory=torch.cuda.is_available(),
)
# create a validation data loader
val_ds = Dataset(data=val_files, transform=val_transforms)
val_loader = torch.utils.data.DataLoader(
    val_ds, batch_size=1, num_workers=4, collate_fn=list_data_collate
)

 

モデル, optimizer とメトリクスの準備

# create UNet, DiceLoss and Adam optimizer
# device = torch.device("cuda:0")  # you don't need device, because Catalyst uses autoscaling
model = UNet(
    spatial_dims=3,
    in_channels=1,
    out_channels=1,
    channels=(16, 32, 64, 128, 256),
    strides=(2, 2, 2, 2),
    num_res_units=2,
)
loss_function = DiceLoss(sigmoid=True)
optimizer = torch.optim.Adam(model.parameters(), 1e-3)

dice_metric = DiceMetric(include_background=True, reduction="mean")
post_trans = Compose(
    [EnsureType(), Activations(sigmoid=True), AsDiscrete(threshold_values=True)]
)

 

Catalyst experiment

Runner のセットアップ


class MonaiSupervisedRunner(catalyst.dl.SupervisedRunner):
    def forward(self, batch):
        if self.is_train_loader:
            output = {self.output_key: self.model(batch[self.input_key])}
        elif self.is_valid_loader:
            roi_size = (96, 96, 96)
            sw_batch_size = 4
            output = {
                self.output_key: sliding_window_inference(
                    batch[self.input_key], roi_size, sw_batch_size, self.model
                )
            }
        elif self.is_infer_loader:
            roi_size = (96, 96, 96)
            sw_batch_size = 4
            batch = self._batch2device(batch, self.device)
            output = {
                self.output_key: sliding_window_inference(
                    batch[self.input_key], roi_size, sw_batch_size, self.model
                )
            }
            output = {**output, **batch}
        return output

 

実験の実行


# define metric function to match MONAI API
def get_metric(y_pred, y):
    y_pred = [post_trans(i) for i in decollate_batch(y_pred)]
    dice_metric(y_pred=y_pred, y=y)
    metric = dice_metric.aggregate().item()
    dice_metric.reset()
    return metric
max_epochs = 50
val_interval = 2
log_dir = os.path.join(root_dir, "logs")
runner = MonaiSupervisedRunner(
    input_key="img", input_target_key="seg", output_key="logits"
)  # you can also specify `device` here
runner.train(
    loaders={"train": train_loader, "valid": val_loader},
    model=model,
    criterion=loss_function,
    optimizer=optimizer,
    num_epochs=max_epochs,
    logdir=log_dir,
    main_metric="dice_metric",
    minimize_metric=False,
    verbose=False,
    timeit=True,  # let's use minimal logs, but with time checkers
    callbacks={
        "loss": catalyst.dl.CriterionCallback(
            input_key="seg", output_key="logits"
        ),
        "periodic_valid": catalyst.dl.PeriodicLoaderCallback(
            valid=val_interval
        ),
        "dice_metric": catalyst.dl.MetricCallback(
            prefix="dice_metric",
            metric_fn=lambda y_pred, y: get_metric(y_pred, y),
            input_key="seg",
            output_key="logits",
        ),
    },
    load_best_on_end=True,  # user-friendly API :)
)

 

Tensorboard ログ

%load_ext tensorboard
%tensorboard --logdir=log_dir

 

ベストモデル・パフォーマンス可視化


for i, valid_output in enumerate(runner.predict_loader(loader=val_loader)):
    if i > 4:
        break
    plt.figure("check", (9, 3))
    plt.subplot(1, 3, 1)
    plt.title("image " + str(i))
    plt.imshow(valid_output["img"].detach().cpu()[0, 0, :, :, 48], cmap="gray")
    plt.subplot(1, 3, 2)
    plt.title("label " + str(i))
    plt.imshow(valid_output["seg"].detach().cpu()[0, 0, :, :, 48])
    plt.subplot(1, 3, 3)
    plt.title("output " + str(i))
    logits = valid_output["logits"]
    plt.imshow((logits[0] > 0.5).float().detach().cpu()[0, :, :, 48])
    plt.show()

 

データディレクトリのクリーンアップ

Remove directory if a temporary was used.

if directory is None:
    shutil.rmtree(root_dir)
 

以上



MONAI 0.7 : tutorials : モジュール – 医用画像のロード

MONAI 0.7 : tutorials : モジュール – 医用画像のロード (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/21/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

MONAI 0.7 : tutorials : モジュール – 医用画像のロード

このノートブックは MONAI で医用画像の様々な形式を簡単にロードして多くの追加の操作を実行する方法を紹介します。

このノートブックは MONAI で医用画像の様々な形式を簡単にロードして多くの追加の操作を実行する方法を説明します。

 

環境のセットアップ

!python -c "import monai" || pip install -q "monai-weekly[itk, pillow]"

 

インポートのセットアップ

# 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.

# 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 numpy as np
import itk
from PIL import Image
import tempfile
from monai.data import ITKReader, PILReader
from monai.transforms import (
    LoadImage, LoadImaged, EnsureChannelFirstd,
    Resized, EnsureTyped, Compose
)
from monai.config import print_config

print_config()
MONAI version: 0.6.0+22.g027947bf.dirty
Numpy version: 1.21.0
Pytorch version: 1.9.0
MONAI flags: HAS_EXT = False, USE_COMPILED = False
MONAI rev id: 027947bf91ff0dfac94f472ed1855cd49e3feb8d

Optional dependencies:
Pytorch Ignite version: 0.4.5
Nibabel version: 3.2.1
scikit-image version: 0.18.2
Pillow version: 8.2.0
Tensorboard version: 2.4.1
gdown version: 3.13.0
TorchVision version: 0.10.0
tqdm version: 4.61.1
lmdb version: 1.2.1
psutil version: 5.8.0
pandas version: 1.1.5
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

 

デフォルトの画像リーダーで Nifti 画像をロードする

MONAI はサポートされる suffix と下の順序に基づいてリーダーを自動的に選択します :

  • このローダを呼び出すとき実行時にユーザ指定されたリーダー。
  • リストの最新のものから最初のものへ登録されたリーダー。
  • デフォルトのリーダー : (nii, nii.gz -> NibabelReader), (png, jpg, bmp -> PILReader), (npz, npy -> NumpyReader), (others -> ITKReader).

 

サンプル画像を生成する

# generate 3D test images
tempdir = tempfile.mkdtemp()
test_image = np.random.rand(64, 128, 96)
filename = os.path.join(tempdir, "test_image.nii.gz")
itk_np_view = itk.image_view_from_array(test_image)
itk.imwrite(itk_np_view, filename)

 

画像ファイルをロードする

data, meta = LoadImage()(filename)
print(f"image data shape:{data.shape}")
print(f"meta data:{meta}")
image data shape:(96, 128, 64)
meta data:{'sizeof_hdr': array(348, dtype=int32), 'extents': array(0, dtype=int32), 'session_error': array(0, dtype=int16), 'dim_info': array(0, dtype=uint8), 'dim': array([  3,  96, 128,  64,   1,   1,   1,   1], dtype=int16), 'intent_p1': array(0., dtype=float32), 'intent_p2': array(0., dtype=float32), 'intent_p3': array(0., dtype=float32), 'intent_code': array(0, dtype=int16), 'datatype': array(64, dtype=int16), 'bitpix': array(64, dtype=int16), 'slice_start': array(0, dtype=int16), 'pixdim': array([1., 1., 1., 1., 0., 0., 0., 0.], dtype=float32), 'vox_offset': array(0., dtype=float32), 'scl_slope': array(nan, dtype=float32), 'scl_inter': array(nan, dtype=float32), 'slice_end': array(0, dtype=int16), 'slice_code': array(0, dtype=uint8), 'xyzt_units': array(2, dtype=uint8), 'cal_max': array(0., dtype=float32), 'cal_min': array(0., dtype=float32), 'slice_duration': array(0., dtype=float32), 'toffset': array(0., dtype=float32), 'glmax': array(0, dtype=int32), 'glmin': array(0, dtype=int32), 'qform_code': array(1, dtype=int16), 'sform_code': array(1, dtype=int16), 'quatern_b': array(0., dtype=float32), 'quatern_c': array(0., dtype=float32), 'quatern_d': array(1., dtype=float32), 'qoffset_x': array(-0., dtype=float32), 'qoffset_y': array(-0., dtype=float32), 'qoffset_z': array(0., dtype=float32), 'srow_x': array([-1.,  0.,  0., -0.], dtype=float32), 'srow_y': array([ 0., -1.,  0., -0.], dtype=float32), 'srow_z': array([0., 0., 1., 0.], dtype=float32), 'affine': array([[-1.,  0.,  0., -0.],
       [ 0., -1.,  0., -0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]), 'original_affine': array([[-1.,  0.,  0., -0.],
       [ 0., -1.,  0., -0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]), 'as_closest_canonical': False, 'spatial_shape': array([ 96, 128,  64], dtype=int16), 'original_channel_dim': 'no_channel', 'filename_or_obj': '/var/folders/6f/fdkl7m0x7sz3nj_t7p3ccgz00000gp/T/tmpq2arvyex/test_image.nii.gz'}

 

Nifti 画像のリストをロードしてそれらをマルチチャネル画像としてスタックする

ファイルのリストをロードし、それらを一緒にスタックして最初の次元として新しい次元を追加します。

そしてスタックされた結果を表わすために最初の画像のメタデータを使用します。

 

幾つかの画像サンプルを生成する

filenames = ["test_image.nii.gz", "test_image2.nii.gz", "test_image3.nii.gz"]
for i, name in enumerate(filenames):
    filenames[i] = os.path.join(tempdir, name)
    itk_np_view = itk.image_view_from_array(test_image)
    itk.imwrite(itk_np_view, filenames[i])

 

画像をロードする

出力データ shape は (3, 96, 128, 64) であることに注意してください、3 チャネル画像を示しています。

data, meta = LoadImage()(filenames)

print(f"image data shape:{data.shape}")
print(f"meta data:{meta}")
image data shape:(3, 96, 128, 64)
meta data:{'sizeof_hdr': array(348, dtype=int32), 'extents': array(0, dtype=int32), 'session_error': array(0, dtype=int16), 'dim_info': array(0, dtype=uint8), 'dim': array([  3,  96, 128,  64,   1,   1,   1,   1], dtype=int16), 'intent_p1': array(0., dtype=float32), 'intent_p2': array(0., dtype=float32), 'intent_p3': array(0., dtype=float32), 'intent_code': array(0, dtype=int16), 'datatype': array(64, dtype=int16), 'bitpix': array(64, dtype=int16), 'slice_start': array(0, dtype=int16), 'pixdim': array([1., 1., 1., 1., 0., 0., 0., 0.], dtype=float32), 'vox_offset': array(0., dtype=float32), 'scl_slope': array(nan, dtype=float32), 'scl_inter': array(nan, dtype=float32), 'slice_end': array(0, dtype=int16), 'slice_code': array(0, dtype=uint8), 'xyzt_units': array(2, dtype=uint8), 'cal_max': array(0., dtype=float32), 'cal_min': array(0., dtype=float32), 'slice_duration': array(0., dtype=float32), 'toffset': array(0., dtype=float32), 'glmax': array(0, dtype=int32), 'glmin': array(0, dtype=int32), 'qform_code': array(1, dtype=int16), 'sform_code': array(1, dtype=int16), 'quatern_b': array(0., dtype=float32), 'quatern_c': array(0., dtype=float32), 'quatern_d': array(1., dtype=float32), 'qoffset_x': array(-0., dtype=float32), 'qoffset_y': array(-0., dtype=float32), 'qoffset_z': array(0., dtype=float32), 'srow_x': array([-1.,  0.,  0., -0.], dtype=float32), 'srow_y': array([ 0., -1.,  0., -0.], dtype=float32), 'srow_z': array([0., 0., 1., 0.], dtype=float32), 'affine': array([[-1.,  0.,  0., -0.],
       [ 0., -1.,  0., -0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]), 'original_affine': array([[-1.,  0.,  0., -0.],
       [ 0., -1.,  0., -0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]), 'as_closest_canonical': False, 'spatial_shape': array([ 96, 128,  64], dtype=int16), 'original_channel_dim': 0, 'filename_or_obj': '/var/folders/6f/fdkl7m0x7sz3nj_t7p3ccgz00000gp/T/tmpq2arvyex/test_image.nii.gz'}

 

DICOM 形式の 3D 画像のロード

サンプル画像を生成する

filename = os.path.join(tempdir, "test_image.dcm")
dcm_image = np.random.randint(256, size=(64, 128, 96)).astype(np.uint8)
itk_np_view = itk.image_view_from_array(dcm_image)
itk.imwrite(itk_np_view, filename)

Ref.

!pip install pydicom
from pydicom import dcmread
from pydicom.data import get_testdata_file
ds = dcmread(filename)
 print(type(ds.PixelData), len(ds.PixelData), ds.PixelData[:2])
<class 'bytes'> 786432 b'\x97\xb3'
arr = ds.pixel_array
print(type(arr), arr.shape, arr.dtype)
<class 'numpy.ndarray'> (64, 128, 96) uint8
plt.imshow(arr[:,:,0])

 

画像のロード

data, meta = LoadImage()(filename)

print(f"image data shape:{data.shape}")
print(f"meta data:{meta}")
image data shape:(96, 128, 64)
meta data:{'0008|0016': '1.2.840.10008.5.1.4.1.1.7.2', '0008|0018': '1.2.826.0.1.3680043.2.1125.1.49144329026051408197861589261117151', '0008|0020': '20210722', '0008|0030': '170636.794924 ', '0008|0050': '', '0008|0060': 'OT', '0008|0090': '', '0010|0010': '', '0010|0020': '', '0010|0030': '', '0010|0040': '', '0020|000d': '1.2.826.0.1.3680043.2.1125.1.55082693700512159103862591206822067', '0020|000e': '1.2.826.0.1.3680043.2.1125.1.88286845929415088271370520342732963', '0020|0010': '', '0020|0011': '', '0020|0013': '', '0020|0052': '1.2.826.0.1.3680043.2.1125.1.54872246537810654209027218359324264', '0028|0002': '1', '0028|0004': 'MONOCHROME2 ', '0028|0008': '64', '0028|0009': '(5200,9230)', '0028|0010': '128', '0028|0011': '96', '0028|0100': '8', '0028|0101': '8', '0028|0102': '7', '0028|0103': '0', '0028|1052': '0 ', '0028|1053': '1 ', '0028|1054': 'US', 'spacing': array([1., 1., 1.]), 'original_affine': array([[-1.,  0.,  0.,  0.],
       [ 0., -1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]), 'affine': array([[-1.,  0.,  0.,  0.],
       [ 0., -1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]), 'spatial_shape': array([ 96, 128,  64]), 'original_channel_dim': 'no_channel', 'filename_or_obj': '/var/folders/6f/fdkl7m0x7sz3nj_t7p3ccgz00000gp/T/tmpq2arvyex/test_image.dcm'}

 

DICOM 画像のリストをロードしてそれらをマルチチャネル画像としてスタックする

ファイルのリストをロードし、それらを一緒にスタックして最初の次元として新しい次元を追加します。

そしてスタックされた結果を表わすために最初の画像のメタデータを使用します。

 

幾つかの画像サンプルを生成する

filenames = ["test_image-1.dcm", "test_image-2.dcm", "test_image-3.dcm"]
for i, name in enumerate(filenames):
    filenames[i] = os.path.join(tempdir, name)
    dcm_image = np.random.randint(256, size=(64, 128, 96)).astype(np.uint8)
    itk_np_view = itk.image_view_from_array(dcm_image)
    itk.imwrite(itk_np_view, filenames[i])

 

画像をロードする

data, meta = LoadImage()(filenames)

print(f"image data shape:{data.shape}")
print(f"meta data:{meta}")
image data shape:(3, 96, 128, 64)
meta data:{'0008|0016': '1.2.840.10008.5.1.4.1.1.7.2', '0008|0018': '1.2.826.0.1.3680043.2.1125.1.70459687821230247148357643462536357', '0008|0020': '20210722', '0008|0030': '170636.830318 ', '0008|0050': '', '0008|0060': 'OT', '0008|0090': '', '0010|0010': '', '0010|0020': '', '0010|0030': '', '0010|0040': '', '0020|000d': '1.2.826.0.1.3680043.2.1125.1.29026801319907695346385092515779097', '0020|000e': '1.2.826.0.1.3680043.2.1125.1.48166663359438709592920991059259631', '0020|0010': '', '0020|0011': '', '0020|0013': '', '0020|0052': '1.2.826.0.1.3680043.2.1125.1.52318595437965660783667062205792724', '0028|0002': '1', '0028|0004': 'MONOCHROME2 ', '0028|0008': '64', '0028|0009': '(5200,9230)', '0028|0010': '128', '0028|0011': '96', '0028|0100': '8', '0028|0101': '8', '0028|0102': '7', '0028|0103': '0', '0028|1052': '0 ', '0028|1053': '1 ', '0028|1054': 'US', 'spacing': array([1., 1., 1.]), 'original_affine': array([[-1.,  0.,  0.,  0.],
       [ 0., -1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]), 'affine': array([[-1.,  0.,  0.,  0.],
       [ 0., -1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]), 'spatial_shape': array([ 96, 128,  64]), 'original_channel_dim': 0, 'filename_or_obj': '/var/folders/6f/fdkl7m0x7sz3nj_t7p3ccgz00000gp/T/tmpq2arvyex/test_image-1.dcm'}

 

PNG 形式で 2D 画像をロードする

画像を生成する

test_image = np.random.randint(0, 256, size=[128, 256])
filename = os.path.join(tempdir, "test_image.png")
Image.fromarray(test_image.astype("uint8")).save(filename)

 

画像をロードする

data, meta = LoadImage()(filename)

print(f"image data shape:{data.shape}")
print(f"meta data:{meta}")
image data shape:(256, 128)
meta data:{'format': 'PNG', 'mode': 'L', 'width': 256, 'height': 128, 'spatial_shape': array([256, 128]), 'original_channel_dim': 'no_channel', 'filename_or_obj': '/var/folders/6f/fdkl7m0x7sz3nj_t7p3ccgz00000gp/T/tmpq2arvyex/test_image.png'}

 

指定した画像リーダで画像をロードする

そして画像リーダーのための追加パラメータを設定できます、例えば、ITKReader のために c_order_axis_indexing=True を設定すると、このパラメータは後で ITK read() 関数に渡されます。

loader = LoadImage()
loader.register(ITKReader())
data, meta = loader(filename)

print(f"image data shape:{data.shape}")
print(f"meta data:{meta}")
image data shape:(256, 128)
meta data:{'spacing': array([1., 1.]), 'original_affine': array([[-1.,  0.,  0.],
       [ 0., -1.,  0.],
       [ 0.,  0.,  1.]]), 'affine': array([[-1.,  0.,  0.],
       [ 0., -1.,  0.],
       [ 0.,  0.,  1.]]), 'spatial_shape': array([256, 128]), 'original_channel_dim': 'no_channel', 'filename_or_obj': '/var/folders/6f/fdkl7m0x7sz3nj_t7p3ccgz00000gp/T/tmpq2arvyex/test_image.png'}

 

画像をロードして追加の操作を実行する

幾つかの画像リーダーはファイルから画像を読んだ後の追加の操作をサポートできます。

例えば、PILReader のためにコンバータを設定できます : PILReader(converter=lambda image: image.convert(“LA”))

loader = LoadImage(PILReader(converter=lambda image: image.convert("LA")))
data, meta = loader(filename)

print(f"image data shape:{data.shape}")
print(f"meta data:{meta}")
image data shape:(256, 128, 2)
meta data:{'format': None, 'mode': 'LA', 'width': 256, 'height': 128, 'spatial_shape': array([256, 128]), 'original_channel_dim': -1, 'filename_or_obj': '/var/folders/6f/fdkl7m0x7sz3nj_t7p3ccgz00000gp/T/tmpq2arvyex/test_image.png'}

 

LoadImage を他の変換と組み合わせる

変換チェインを構築するために LoadImage を他の変換と接続することは非常に簡単です。

transform = Compose([
    LoadImaged(keys="image"),
    EnsureChannelFirstd(keys="image"),
    Resized(keys="image", spatial_size=[64, 64]),
    EnsureTyped("image"),
])
test_data = {"image": filename}
result = transform(test_data)
print(f"image data shape:{result['image'].shape}")
print(f"meta data:{result['image_meta_dict']}")
image data shape:torch.Size([1, 64, 64])
meta data:{'format': 'PNG', 'mode': 'L', 'width': 256, 'height': 128, 'spatial_shape': array([256, 128]), 'original_channel_dim': 'no_channel', 'filename_or_obj': '/var/folders/6f/fdkl7m0x7sz3nj_t7p3ccgz00000gp/T/tmpq2arvyex/test_image.png'}

 

データディレクトリのクリーンアップ

一時ディレクトリが使用された場合にはディレクトリを削除します。

shutil.rmtree(tempdir)
 

以上



MONAI 0.7 : tutorials : モジュール – Nifti 読み込み例

MONAI 0.7 : tutorials : モジュール – Nifti 読み込み例 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/21/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

MONAI 0.7 : tutorials : モジュール – Nifti 読み込み例

NIfTI ファイルを読みそしてそれらからロードされたボリュームの画像パッチに渡る反復を例示して説明します。

このノートブックの目的は、NIfTI ファイルを読みそしてそれらからロードされたボリュームの画像パッチに渡る反復を例示して説明します。

 

環境のセットアップ

!python -c "import monai" || pip install -q "monai-weekly[nibabel]"

 

インポートのセットアップ

# 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 glob
import os
import shutil
import tempfile

import nibabel as nib
import numpy as np
import torch

from monai.config import print_config
from monai.data import (
    ArrayDataset, GridPatchDataset, create_test_image_3d, PatchIter)
from monai.transforms import (
    AddChannel,
    Compose,
    LoadImage,
    RandSpatialCrop,
    ScaleIntensity,
    EnsureType,
)
from monai.utils import first

print_config()
MONAI version: 0.6.0rc1+23.gc6793fd0
Numpy version: 1.20.3
Pytorch version: 1.9.0a0+c3d40fd
MONAI flags: HAS_EXT = True, USE_COMPILED = False
MONAI rev id: c6793fd0f316a448778d0047664aaf8c1895fe1c

Optional dependencies:
Pytorch Ignite version: 0.4.5
Nibabel version: 3.2.1
scikit-image version: 0.15.0
Pillow version: 7.0.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)
/tmp/tmp3y4h4i5o

幾つかのテスト Nifti ファイルを作成します :

for i in range(5):
    im, seg = create_test_image_3d(128, 128, 128)

    n = nib.Nifti1Image(im, np.eye(4))
    nib.save(n, os.path.join(root_dir, f"im{i}.nii.gz"))

    n = nib.Nifti1Image(seg, np.eye(4))
    nib.save(n, os.path.join(root_dir, f"seg{i}.nii.gz"))

Ref.

test_file = root_dir + "/im0.nii.gz" 
img_test = nib.load(test_file)
print(type(img_test), img_test.shape)

img_ary = img_test.get_fdata()[:, :, 64]
print(type(img_ary), img_ary.shape, img_ary.dtype)

plt.imshow(img_ary)
<class 'nibabel.nifti1.Nifti1Image'> (128, 128, 128)
<class 'numpy.ndarray'> (128, 128) float64

plt.subplots(4, 3, figsize=(128, 128))
for i in range(12):
    img_ary = img_test.get_fdata()[:, :, i*10]
    plt.subplot(4, 3, i + 1)
    plt.imshow(img_ary, cmap="gray")
plt.tight_layout()
plt.show()

 
ロードされた Nifti ファイルから一様なランダムパッチを生成するデータローダを作成します :

images = sorted(glob.glob(os.path.join(root_dir, "im*.nii.gz")))
segs = sorted(glob.glob(os.path.join(root_dir, "seg*.nii.gz")))

imtrans = Compose(
    [
        LoadImage(image_only=True),
        ScaleIntensity(),
        AddChannel(),
        RandSpatialCrop((64, 64, 64), random_size=False),
        EnsureType(),
    ]
)

segtrans = Compose(
    [
        LoadImage(image_only=True),
        AddChannel(),
        RandSpatialCrop((64, 64, 64), random_size=False),
        EnsureType(),
    ]
)

ds = ArrayDataset(images, imtrans, segs, segtrans)

loader = torch.utils.data.DataLoader(
    ds, batch_size=10, num_workers=2, pin_memory=torch.cuda.is_available()
)
im, seg = first(loader)
print(im.shape, seg.shape)
torch.Size([5, 1, 64, 64, 64]) torch.Size([5, 1, 64, 64, 64])

あるいは、ロードされた画像から規則的なグリッド順でパッチを生成するデータローダを作成します :

imtrans = Compose([LoadImage(image_only=True),
                   ScaleIntensity(), AddChannel(), EnsureType()])

segtrans = Compose([LoadImage(image_only=True), AddChannel(), EnsureType()])

ds = ArrayDataset(images, imtrans, segs, segtrans)
patch_iter = PatchIter(patch_size=(64, 64, 64), start_pos=(0, 0, 0))


def img_seg_iter(x):
    return (zip(patch_iter(x[0]), patch_iter(x[1])),)


ds = GridPatchDataset(ds, img_seg_iter, with_coordinates=False)

loader = torch.utils.data.DataLoader(
    ds, batch_size=10, num_workers=2, pin_memory=torch.cuda.is_available()
)
im, seg = first(loader)
print("image shapes:", im[0].shape, seg[0].shape)
print("coordinates shapes:", im[1].shape, seg[1].shape)
image shapes: torch.Size([3, 1, 64, 64, 64]) torch.Size([3, 1, 64, 64, 64])
coordinates shapes: torch.Size([3, 4, 2]) torch.Size([3, 4, 2])

 

データディレクトリのクリーンアップ

一時ディレクトリが使用された場合にはディレクトリを削除します。

if directory is None:
    shutil.rmtree(root_dir)
 

以上



MONAI 0.7 : tutorials : モジュール – ImageDataset

MONAI 0.7 : tutorials : モジュール – ImageDataset (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/20/2021 (0.7.0)

* 本ページは、MONAI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス 無料 Web セミナー開催中

◆ クラスキャットは人工知能・テレワークに関する各種サービスを提供しております。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

MONAI 0.7 : tutorials : モジュール – ImageDataset

ノートブックは monai.data.ImageDataset モジュールの基本的な使い方を紹介します。

このノートブックは monai.data.ImageDataset の基本的な使い方を紹介します。

 

環境のセットアップ

!python -c "import monai" || pip install -q "monai-weekly[itk, pillow]"

 

インポートのセットアップ

# Copyright 2020 - 2021 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.

# 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 tempfile
import shutil

import nibabel as nib
import numpy as np

from monai.data import ImageDataset
from monai.transforms import Compose, EnsureChannelFirst, RandAdjustContrast, Spacing
from monai.config import print_config

print_config()
MONAI version: 0.6.0rc1+23.gc6793fd0
Numpy version: 1.20.3
Pytorch version: 1.9.0a0+c3d40fd
MONAI flags: HAS_EXT = True, USE_COMPILED = False
MONAI rev id: c6793fd0f316a448778d0047664aaf8c1895fe1c

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
# Generate some image data
tempdir = tempfile.mkdtemp()
img_ = nib.Nifti1Image(np.random.randint(0, 2, size=(20, 20, 20)), np.eye(4))
seg_ = nib.Nifti1Image(np.random.randint(0, 2, size=(20, 20, 20)), np.eye(4))
img_name = os.path.join(tempdir, "img.nii.gz")
seg_name = os.path.join(tempdir, "seg.nii.gz")
nib.save(img_, img_name)
nib.save(seg_, seg_name)
img_list = [img_name]
seg_list = [seg_name]

 

変換のカスタマイズされたチェインを構築する

TestCompose は前処理パイプラインの一部として追加のメタデータを処理するために使用されます。

class TestCompose(Compose):
    def __call__(self, data, meta):
        data = self.transforms[0](data, meta)  # ensure channel first
        data, _, meta["affine"] = self.transforms[1](data, meta["affine"])  # spacing
        if len(self.transforms) == 3:
            return self.transforms[2](data), meta  # image contrast
        return data, meta


img_xform = TestCompose([EnsureChannelFirst(), Spacing(pixdim=(1.5, 1.5, 3.0)), RandAdjustContrast()])
seg_xform = TestCompose([EnsureChannelFirst(), Spacing(pixdim=(1.5, 1.5, 3.0), mode="nearest")])
img_dataset = ImageDataset(
    image_files=img_list,
    seg_files=seg_list,
    transform=img_xform,
    seg_transform=seg_xform,
    image_only=False,
    transform_with_metadata=True,
)
print("image shape:", img_dataset[0][0].shape)
print("seg. shape:", img_dataset[0][1].shape)

image shape: (1, 14, 14, 7)
seg. shape: (1, 14, 14, 7)

 

ディレクトリのクリーンアップ

shutil.rmtree(tempdir)
 

以上



ClassCat® Chatbot

人工知能開発支援

◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com

カテゴリー