[医療×生成系AI :P3/G2.3] Pythonと深層学習入門(ニューラルネットを構築しよう)

難易度:★★☆

💡この第3章では、第1・2章で学んだ知識を活かし、実際にニューラルネットワークを構築してMNIST手書き数字データを分類してみましょう。モデルの定義から訓練、精度の評価、そして誤認識の可視化まで、ディープラーニングの基本サイクルを一通り実装します。

実際に手を動かしてみることで、「学習とは何か?」「誤差逆伝播がどう使われているか?」といった概念が具体的に理解できるはずです。生成系AIの本格的なモデル実装に入る前に、シンプルなニューラルネットで学習の原理を確かめておきましょう。

深層学習の一連のプロセスを概念的に理解・おさらいしておきたい方は、過去の回「【医療AI教室:Vol.7】誤差を逆さにたどる!? “深層学習”の学習プロセス」を一読されることをお勧めします!

目次

1. MNISTデータセットとは?

MNISTは、米国商務省配下の研究所が構築した、28×28ピクセルの手書き数字(0~9)画像が7万枚(学習用6万枚 + テスト用1万枚)含まれる有名なベンチマークデータセットです。

Wikipedia
  • モノクロ1チャネル画像
  • ピクセル値を 0~255 → 0~1 や -1~1 の範囲に正規化
  • 「機械学習初心者が最初に試す定番データセット」として広く利用される

PyTorchでは torchvision.datasets.MNIST を使って自動ダウンロード&簡単に扱えます。ニューラルネットの構造を理解する上で非常に取り組みやすい例です。


2. Google Colab で試すための手順

  1. Google Colab にアクセスし、新しいノートブックを作成します。
  2. 上部メニューの「ランタイム」→「ランタイムのタイプを変更」→「ハードウェアアクセラレータ」を GPU に変更(CPUでも動作しますがGPUが速い)。
  3. 以下のコードブロックをすべて同じノートブックに貼り付け、上から順に実行してください。

3. 学習用コード例

ここでは、MNISTを使ったニューラルネットによる多クラス分類を実装します。

  • データの準備
  • サンプル画像の表示
  • モデルの定義
  • 学習ループ(損失推移グラフつき)
  • テスト評価(誤認識表示、混同行列)

各セルのコードを順番にGoogle Colab のノートブックにコピペしていき、実行し、出力を確認してみましょう。

(1) ライブラリのインストール & インポート

# --- ライブラリとは? ---
# プログラミングでよく使う便利な機能(たとえば数学の計算、画像の表示、AIの学習など)を、
# あらかじめまとめて用意してくれている“道具箱”のようなものです。
# 自分でゼロから作らずに済むので、効率よく開発ができます。

# 1) ライブラリのインストール (Google Colab用)
!pip install torch torchvision scikit-learn seaborn
# ↑ AI・画像処理・機械学習・可視化に必要な4つのライブラリをまとめてインストールします。
# - torch:PyTorchというディープラーニングライブラリの本体
# - torchvision:画像データの読み込みや変換を助けるライブラリ
# - scikit-learn:機械学習の評価や分類などに便利な関数群
# - seaborn:グラフや図をきれいに表示するための可視化ライブラリ

# 2) 必要なライブラリをインポート
import torch
# ↑ PyTorchの基本機能(テンソル計算、自動微分など)を使うために読み込みます。

import torch.nn as nn
# ↑ ニューラルネットワークを構成するためのモジュール(レイヤーなど)を提供。

import torch.nn.functional as F
# ↑ 活性化関数(ReLUなど)や損失関数(CrossEntropyなど)が含まれています。

import torch.optim as optim
# ↑ 最適化アルゴリズム(例:SGDやAdam)を使うためのモジュールです。

import torchvision
# ↑ 画像データセット(MNISTやCIFARなど)や、画像処理のユーティリティが含まれています。

import torchvision.transforms as transforms
# ↑ 画像の前処理(リサイズ、正規化など)を簡単に行うためのツール群。

import matplotlib.pyplot as plt
# ↑ 画像やグラフの描画に使うライブラリ。Matplotlibの基本機能です。

import numpy as np
# ↑ 配列や行列などの数値計算を高速で処理できるライブラリです。

import seaborn as sns  # 混同行列可視化に利用
# ↑ データの可視化に特化したライブラリ。特にヒートマップ表示が得意です。

from sklearn.metrics import confusion_matrix
# ↑ モデルの分類結果を評価する「混同行列」を作る関数が入っています。

# PyTorchでGPUが使えるかどうかチェックし、利用可能ならGPUを使用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# ↑ CUDAというNVIDIA製GPUが使える場合はGPU、なければCPUを選択する仕組みです。

print("使用デバイス:", device)
# ↑ 実際に使われるデバイス(CPU or GPU)を出力して確認します。


(2) データセットとDataLoaderの準備

graph TD
    subgraph "Step 1: 変換ルールの定義 (transform)"
        A["画像データを変換する「レシピ」を定義

モデルが学習しやすい数値データに整えるため、
一連の変換処理を準備します。

1. ToTensor: 画像を数値の塊 (テンソル) に変換
2. Normalize: 数値の範囲を調整 (-1〜1)"] end subgraph "Step 2: データセットの準備 (Dataset)" B["元データと「レシピ」を組み合わせる

ダウンロードしたMNISTの全画像データに、
Step 1で定義した変換レシピを適用する設定を行います。"] end subgraph "Step 3: データの供給装置を作成 (DataLoader)" C["データを学習単位に分割・整理

データセット全体を効率的に学習させるため、
小さな塊 (ミニバッチ) に分割する装置を作成します。

バッチサイズ: 一度にモデルへ渡すデータ数 (例: 64)
シャッフル: データの供給順を毎回ランダム化"] end subgraph "最終出力" D["学習用ミニバッチ

モデルが一つずつ学習していくための、
準備が整ったデータ"] end A -- "変換レシピとして" --> B B -- "データセット全体を" --> C C -- "一つずつ生成" --> D
# 3) データ前処理のTransform定義
transform = transforms.Compose([
    transforms.ToTensor(),                      # 画像をTensor(PyTorch用の数値配列)に変換(0〜1の範囲に正規化)
    transforms.Normalize((0.5,), (0.5,))        # 平均0.5、標準偏差0.5でさらに正規化(-1〜1の範囲にスケーリング)
])
# ↑ ディープラーニングでは、画像データをそのまま使うのではなく、
#    モデルに合った形式(テンソル)に変換し、学習しやすいように「正規化」します。
#    transforms.Compose は、複数の前処理を順番にまとめて適用できる便利な仕組みです。

# 4) MNIST学習データセットの作成
train_dataset = torchvision.datasets.MNIST(
    root='./data',                # データの保存先フォルダ(なければ自動で作られます)
    train=True,                   # 訓練用データ(True)か、テスト用データ(False)かを指定
    transform=transform,         # 上で定義した画像の前処理を適用
    download=True                # データがなければ自動でインターネットからダウンロード
)
# ↑ torchvisionに含まれるMNIST(手書き数字画像)のデータセットを準備します。
#    画像は28x28ピクセルで、0〜9の数字がラベルとして付いています。

# 5) バッチサイズを設定し、DataLoaderを作成
train_loader = torch.utils.data.DataLoader(
    train_dataset,               # 上で作成したデータセットを使用
    batch_size=64,               # 1回の学習で使用するデータの数(バッチサイズ)
    shuffle=True                 # 毎回データの順番をシャッフルして、学習の偏りを防ぐ
)
# ↑ DataLoaderは、データを小分けにしてモデルに渡すための仕組みです。
#    バッチ学習と呼ばれ、効率的に学習できるようになります。

print("学習用データ数:", len(train_dataset))
# ↑ ダウンロードした学習データの総数(60,000件)を表示して確認します。

(3) サンプル画像の可視化

graph TD
    A["入力: DataLoader
前工程で作成した
データの供給装置"] subgraph "Step 1: データを取り出す準備" B["蛇口を取り付ける (iter)

供給装置からデータを
1セットずつ取り出せるようにする
「イテレータ」を準備する。"] C["最初の1杯分を注ぐ (next)

イテレータから最初のデータ塊
(ミニバッチ)を実際に取り出す。

・画像データ (images)
・正解ラベル (labels)"] end subgraph "Step 2: 表示のためのデータ加工" D["形式を翻訳する (.numpy)

PyTorch専用のTensor形式から、
画像表示ライブラリが扱える
汎用的な数値配列(NumPy)に変換する。"] end subgraph "Step 3: 描画処理" E["キャンバスと枠を準備する

・描画する大きな紙 (Figure) を用意
・画像を並べる3x3のマス目 (Subplot) を作成"] F["マス目に画像を配置 (ループ処理)

バッチの中から9枚の画像を選び、
1枚ずつマス目に描画していく。

・画像とラベルを表示
・余計な枠線は消す"] end G["最終成果物: サンプル画像の表示

完成した図を画面に出力し、
データが正しく準備できたかを目で見て確認する。"] A --> B B --> C C --> D D --> E E --> F F --> G
# 6) DataLoaderから最初のバッチを取り出し、画像を表示

data_iter = iter(train_loader)  # イテレータを取得
# ↑ DataLoaderからデータを1バッチずつ取り出せる「イテレータ」という仕組みを取得します。
#    Pythonの「for文」で使う仕組みの裏側です。

images, labels = next(data_iter)  # 最初のバッチ(64枚)
# ↑ イテレータから最初のバッチを取り出します。
#    images: 画像データ(64枚分のテンソル)/ labels: 各画像に対応する正解の数字ラベル

images_np = images.numpy()
# ↑ PyTorchのTensor形式を、NumPy形式(Pythonで一般的な数値配列)に変換します。
#    画像表示のときはNumPyに変換すると便利です。
# ※GPU上のTensorだと .numpy() はエラーになります。GPU使用時は .cpu().numpy() が必要。

fig = plt.figure(figsize=(8, 8))
# ↑ 描画用の図(Figure)を作成。サイズは8x8インチ。

for i in range(9):
    ax = fig.add_subplot(3, 3, i+1)
    # ↑ 3行×3列のグリッドに、画像を1枚ずつ並べる準備をします。

    ax.imshow(np.squeeze(images_np[i]), cmap='gray_r')
    # ↑ 画像を表示します。
    # - np.squeeze():画像の余計な次元(例:1チャンネル)を取り除きます。
    # - cmap='gray_r':白黒(反転グレースケール)で表示します。

    ax.set_title(f"Label: {labels[i].item()}")
    # ↑ 画像の上に「正解ラベル(数字)」をタイトルとして表示。

    ax.axis('off')
    # ↑ 画像の周りの軸(枠)を非表示にします。

plt.suptitle("MNISTサンプルイメージ", fontsize=16)
# ↑ 図全体にタイトルを付けます。

plt.show()
# ↑ 表示用のウィンドウにグラフ(ここでは画像)を出力します。

(4) ニューラルネット定義

ニューラルネットワーク(SimpleNet)の構造定義 ネットワーク構造 入力画像 (28×28) Flatten 28×28 → 784 fc1: Linear(784 → 128) 全結合層 ReLU 活性化関数 fc2: Linear(128 → 10) 出力層 出力(logits) 10クラス(0~9) SimpleNetクラスの構造 __init__メソッド(初期化) • nn.Moduleを継承 • fc1 = Linear(784, 128) • fc2 = Linear(128, 10) • レイヤーの定義を行う forwardメソッド(順伝播) 1. x = x.view(-1, 28*28) → 画像を1次元に変換 2. x = F.relu(self.fc1(x)) → 第1層 + ReLU活性化 3. x = self.fc2(x) → 第2層(出力層) 4. return x → logitsを返す モデルの作成と初期化 model = SimpleNet().to(device) → インスタンス化してGPU/CPUに配置 重要なポイント nn.Module継承 PyTorchでネットワークを作る基本パターン __init__でレイヤー定義 使用する層(Linear、Conv2dなど)を宣言 forwardで処理の流れ 入力から出力への変換処理を記述 ReLU活性化関数 0以下を0に、0より大きい値はそのまま通す 全結合層(Linear) すべての入力と出力が結合された層 logits出力 各クラスの未正規化スコア(損失関数に渡す) データの流れ: 画像(28×28) → Flatten(784) → fc1(128) → ReLU → fc2(10) → logits
# 7) ニューラルネットワークの定義

# ======================================
# ネットワーク構造(テキストベース図)
# ======================================
#
# 入力画像 (28x28)
#       │
#       ▼
#   [ Flatten ]         ← 画像を1次元(784)に変換
#       │
#       ▼
#   [ fc1: Linear(784 → 128) ]
#       │
#       ▼
#   [ ReLU ]            ← 活性化関数(非線形変換)
#       │
#       ▼
#   [ fc2: Linear(128 → 10) ]
#       │
#       ▼
#   出力(logits)      ← 各クラス(0〜9)のスコア
#
# ======================================

class SimpleNet(nn.Module):
    # ↑ PyTorchのnn.Moduleを継承して、自作のネットワーク「SimpleNet」を定義します。
    #    nn.Moduleは、ニューラルネットワークを作るための“ひな形”のような存在です。

    def __init__(self):
        super(SimpleNet, self).__init__()
        # ↑ 親クラス(nn.Module)の初期化を呼び出します。これがないと正しく動きません。

        self.fc1 = nn.Linear(28*28, 128)  # 入力784 → 出力128
        # ↑ 入力画像(28×28 = 784ピクセル)を128次元のベクトルに変換する「全結合層(全てのノードが接続)」

        self.fc2 = nn.Linear(128, 10)     # 出力10クラス (0~9)
        # ↑ 128次元の特徴量を、0〜9の「10クラス」に分類する出力層です。

    def forward(self, x):
        # ↑ モデルにデータを渡したとき、どのように処理されるかを定義する関数です。
        #    これは「順伝播(forward pass)」と呼ばれ、入力から出力への流れを意味します。

        x = x.view(-1, 28*28)  # 2次元画像を1次元に
        # ↑ 画像は (1, 28, 28) のような形ですが、全結合層に入れるために (784,) に変形します。
        #    -1は「バッチサイズは自動で合わせて」という意味。

        x = F.relu(self.fc1(x))
        # ↑ 第1層(fc1)に入力を通し、活性化関数ReLUで非線形変換します。
        #    ReLU(Rectified Linear Unit)は、0以下を切り捨て、0より大きい値だけを通します。

        x = self.fc2(x)
        # ↑ 第2層(fc2)に通して、最終的なクラスごとのスコア(logits)を出力します。

        return x
        # ↑ 出力(logits)は、CrossEntropyLossなどの損失関数にそのまま渡せます。


model = SimpleNet().to(device)
# ↑ 上で定義したモデルをインスタンス化し、CPUまたはGPUに移動します(.to(device))。
#    こうすることで、モデルとデータの両方が同じデバイス上で計算されるようになります。

print(model)
# ↑ モデルの構造(レイヤー構成など)を出力して確認します。


(5) 損失関数 & Optimizer

# 8) 損失関数 & 最適化手法

criterion = nn.CrossEntropyLoss()
# ↑ 「クロスエントロピー損失関数」を定義します。
#    これは分類問題(0〜9などのカテゴリ分類)でよく使われる損失関数です。
#    モデルの出力(logits)と、正解ラベルとの“ズレ”を数値化してくれます。
#    ズレが大きいほど損失も大きくなり、学習によってこの損失を最小化していきます。

optimizer = optim.Adam(model.parameters(), lr=0.001)
# ↑ 「Adam(アダム)最適化アルゴリズム」を使って学習を行う設定です。
#    model.parameters() は、学習すべきモデル内の全パラメータ(重みやバイアス)を指定します。
#    lr=0.001 は「学習率(learning rate)」と呼ばれ、どのくらいのスピードで学習するかを調整する重要な値です。

# 💡補足
# - 損失関数(criterion)は「どれくらい間違っているか?」を測るもの。
# - 最適化手法(optimizer)は「どうやってパラメータを直すか?」を決めるものです。
💡クロスエントロピー損失とは?

「正解をどれだけ自信を持って予測できたか?」を評価する指標です。

たとえば、正解が「3」の画像に対して、モデルが「3」と予測し、その確率が高ければ損失は小さく、逆に外れていれば損失は大きくなります。

数式でいうと:

損失 = -log(正解クラスの確率)

つまり、正解データについて、正解と予測した確率が高い=損失が小さいという仕組みです。

PyTorchではこの一行でOK:

criterion = nn.CrossEntropyLoss()

学習では、この損失をもとに「間違った分だけ」モデルが修正されるように工夫されています。


(6) 学習ループと損失推移グラフ

# 9) 学習ループの実行

num_epochs = 5
# ↑ 学習全体の繰り返し回数(エポック数)を指定します。
#    エポックとは、「全データを1周して学習させること」を1回と数えます。

epoch_losses = []
# ↑ 各エポックごとの損失(loss)の平均を保存するためのリストを用意します。

for epoch in range(num_epochs):
    running_loss = 0.0   # 1エポック内での累積損失
    total_batch = 0      # バッチ数のカウント

    for images, labels in train_loader:
        # ↑ データローダーから、画像とラベルを1バッチずつ取り出します。

        images = images.to(device)
        labels = labels.to(device)
        # ↑ 画像とラベルをGPUまたはCPUへ転送(モデルと同じデバイスにする必要があります)。

        optimizer.zero_grad()
        # ↑ 前のバッチで計算された勾配(grad)をリセットします。
        #    勾配は蓄積されるため、毎回0に初期化が必要です。

        outputs = model(images)
        # ↑ モデルに画像を入力し、出力(logits)を取得します。

        loss = criterion(outputs, labels)
        # ↑ 出力と正解ラベルの差(誤差)を計算します(損失関数)。

        loss.backward()
        # ↑ 誤差(loss)を使って、各パラメータの勾配を自動で計算します(逆伝播)。

        optimizer.step()
        # ↑ 勾配をもとに、モデルのパラメータを更新します(学習)。

        running_loss += loss.item()
        # ↑ そのバッチでの損失値を足し合わせます(.item() は純粋な数値に変換するためのもの)。

        total_batch += 1
        # ↑ バッチのカウントを1つ進めます。

    avg_loss = running_loss / total_batch
    # ↑ 1エポック分の平均損失を計算します。

    epoch_losses.append(avg_loss)
    # ↑ 平均損失を記録して、後でグラフに使えるようにします。

    print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {avg_loss:.4f}")
    # ↑ 各エポック終了後に、損失を表示して学習の進み具合を確認します。

print("学習が完了しました!")
# ↑ すべてのエポックが終わったことを表示します。

# 10) 損失の推移をプロット

plt.figure(figsize=(6, 4))
# ↑ グラフ用の図を作成(サイズ指定)。

plt.plot(range(1, num_epochs+1), epoch_losses, marker='o')
# ↑ 各エポックにおける損失の推移を線グラフで表示(丸印をつけて見やすくしています)。

plt.title("Training Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.grid(True)
# ↑ グラフの装飾(タイトル、軸ラベル、グリッド線)

plt.show()
# ↑ グラフを画面に表示します。

  • (a) 勾配リセット → (b) 順伝播 → (c) 損失計算 → (d) 逆伝播 → (e) パラメータ更新
  • 学習が進むと Loss が徐々に減少

(7) テストデータ評価 & 誤認識例の可視化

# 11) テストデータのDataLoaderを作成

test_dataset = torchvision.datasets.MNIST(
    root='./data',               # 学習時と同じフォルダに保存
    train=False,                 # テストデータ(False)を指定
    transform=transform,         # 学習時と同じ前処理(ToTensor+Normalize)を適用
    download=True                # 必要に応じてダウンロード
)
# ↑ テスト用のMNISTデータセット(10,000枚)を用意します。

test_loader = torch.utils.data.DataLoader(
    test_dataset,
    batch_size=64,
    shuffle=False                # テストでは順番をシャッフルしない(再現性のため)
)
# ↑ 学習時と同様、DataLoaderでテストデータを扱いやすくします。

print("テスト用データ数:", len(test_dataset))
# ↑ テストデータが10,000件あることを確認します。

# 12) テストデータを使って正解率を計算

model.eval()
# ↑ モデルを「評価モード」に切り替えます。
#    これはDropoutやBatchNormのような層の振る舞いを学習用から変更するために必要です。

correct = 0
total = 0
# ↑ 正解した数と、全体のサンプル数を数えるためのカウンター。

misclassified_images = []
misclassified_true = []
misclassified_pred = []
# ↑ 間違えた画像と、その正解ラベル/予測ラベルを保存するリスト(最大9件)

with torch.no_grad():
    # ↑ 評価中は勾配計算が不要なので、無効化して処理を軽く・速くします。
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)

        outputs = model(images)
        # ↑ テスト画像をモデルに通して、出力(各クラスのスコア)を取得。

        _, predicted = torch.max(outputs, 1)
        # ↑ 各画像について、最もスコアが高いクラスを予測結果とします。

        total += labels.size(0)
        correct += (predicted == labels).sum().item()
        # ↑ 全体の枚数に加算し、正解だったものだけカウントを増やします。

        # 誤認識を9枚までピックアップ
        for i in range(len(labels)):
            if predicted[i] != labels[i]:
                if len(misclassified_images) < 9:
                    misclassified_images.append(images[i].cpu().numpy())
                    misclassified_true.append(labels[i].cpu().item())
                    misclassified_pred.append(predicted[i].cpu().item())
        # ↑ 間違えた画像・正解・予測をそれぞれ記録。
        #    GPU上のTensorをCPUに移して、NumPy配列や整数として扱えるように変換しています。

accuracy = correct / total
print(f"テストデータでの正解率: {accuracy*100:.2f}%")
# ↑ 全体に対して、どれくらい正解したか(正解率)をパーセントで表示します。

# 13) 誤認識した画像を可視化

if len(misclassified_images) > 0:
    fig = plt.figure(figsize=(8, 8))
    for i in range(len(misclassified_images)):
        ax = fig.add_subplot(3, 3, i+1)
        ax.imshow(np.squeeze(misclassified_images[i]), cmap='gray_r')
        # ↑ 誤認識した画像を白黒表示。squeezeで余分な次元を除去。

        ax.set_title(f"True: {misclassified_true[i]}, Pred: {misclassified_pred[i]}")
        # ↑ タイトルとして、「本当のラベル」と「予測されたラベル」を表示。

        ax.axis('off')
        # ↑ 枠線や目盛りを非表示にして画像を見やすくします。

    plt.suptitle("Misclassified Samples", fontsize=16)
    plt.show()
else:
    print("誤認識がありませんでした。高精度です!")
    # ↑ もし9枚以内に誤認識が見つからなければ、それも結果として表示。

  • model.eval() : 推論モード
  • torch.no_grad() : 勾配追跡を無効化し計算負荷を削減
  • 誤認識例を数枚確認することで、どのように間違えているか理解しやすい

(8) (オプション)混同行列の描画

# 14) 混同行列の可視化

y_true = []
y_pred = []
# ↑ 実際のラベル(正解)と、モデルの予測ラベルを保存するリストを用意します。

model.eval()
# ↑ 評価モードに切り替え(BatchNormやDropoutなどの挙動を固定)

with torch.no_grad():
    # ↑ 評価中は勾配計算が不要なので、処理を高速・軽量化します。
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)

        outputs = model(images)
        # ↑ モデルにテスト画像を入力して、クラスごとのスコアを取得

        _, predicted = torch.max(outputs, 1)
        # ↑ スコアが最も高いクラスを予測結果として取得します。

        y_true.extend(labels.cpu().numpy())
        y_pred.extend(predicted.cpu().numpy())
        # ↑ 正解ラベル(labels)と予測ラベル(predicted)をそれぞれCPUに移し、
        #    NumPy配列としてリストに追加します(extendで複数を一気に追加)。

cm = confusion_matrix(y_true, y_pred)
# ↑ sklearnの関数を使って「混同行列(confusion matrix)」を作成します。
#    行が実際のクラス、列が予測されたクラスを表し、どこで間違えたかがわかります。

plt.figure(figsize=(8,6))
# ↑ 描画サイズを指定して新しい図を作成

sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
# ↑ Seabornライブラリを使って、混同行列をヒートマップ形式で可視化します。
#    - annot=True:各マスに数値を表示
#    - fmt='d':整数形式で表示
#    - cmap='Blues':青系のカラーマップを使用

plt.title("Confusion Matrix (MNIST)")
plt.xlabel("Predicted Label")
plt.ylabel("True Label")
plt.show()
# ↑ グラフを表示します。
  • クラス0~9の誤認識分布が一目でわかる
  • 対角成分が多いほど正しく識別できている

4. 実行結果

セルをすべて実行すると、以下のようなログやグラフ・画像が出力されます。

  1. 学習前のサンプル画像
    • 手書き数字がどんな形でデータ化されているか分かる
  2. 損失表示 & 推移グラフ
    • 各エポックごとに損失が減少していく様子
  3. テストデータでの正解率
    • シンプルな全結合ネットでも5エポックで90~95%超が出やすい
  4. 誤認識例
    • 「True: 9, Pred: 4」など、間違えたケースを可視化
  5. 混同行列(オプション)
    • クラス間の誤分類を俯瞰できる

5. まとめと次回予告

MNISTは手書き数字0~9のモノクロ画像(28×28)。
PyTorchを使い、以下の流れで学習フローを体験しました。

  1. DataLoader でバッチ分割
  2. モデルに入力順伝播
  3. 損失計算
  4. 逆伝播
  5. パラメータ更新

医療画像や他分野のデータでも、基本構造は同じです。

医療AIへの応用イメージ

  • レントゲンやCT、病理画像などは、さらに大きなモデル(CNN/Transformer)転移学習が有効。
  • データ量やチャネル数は異なっても、学習ループの仕組みは同じ
  • 実運用では、患者情報の保護倫理審査などの面が非常に重要。

次回予告: 「データ準備と前処理の基礎(医療データの扱い方)」

  • テキスト・画像・音声のクリーニング、フォーマット変換
  • 患者データの匿名化、倫理審査、個人情報保護法やHIPAAなどの法令遵守
  • データ分割と過学習対策(Train/Validation/Test)

医療AIプロジェクトでは「データの質」が成果を大きく左右します。どうぞお楽しみに!

次章予告: もっとPythonと深層学習中級編

前章で触れた「計算グラフ」や「損失関数」、「誤差逆伝播」など、Pythonと深層学習中級編を、第2回の4章以降で、技術的な内容に触れていければと思います。


参考リンク


注意

  • 本記事の内容は執筆時点のものです。環境やバージョンによって変更の可能性があります。
  • 実際に患者情報を扱う際は、プライバシー保護と法令遵守を徹底してください。
  • 特に患者画像やカルテ情報は、組織ガイドラインや倫理審査(IRB)手続きを踏んだうえで適切に扱いましょう。

これで「MNISTを用いた簡単なニューラルネットの構築」の解説は終了です。
ぜひColab等で動かし、学習過程や誤認識を可視化しながら、ニューラルネットの理解を深めてください。



ご利用規約(免責事項)

当サイト(以下「本サイト」といいます)をご利用になる前に、本ご利用規約(以下「本規約」といいます)をよくお読みください。本サイトを利用された時点で、利用者は本規約の全ての条項に同意したものとみなします。

第1条(目的と情報の性質)

  1. 本サイトは、医療分野におけるAI技術に関する一般的な情報提供および技術的な学習機会の提供を唯一の目的とします。
  2. 本サイトで提供されるすべてのコンテンツ(文章、図表、コード、データセットの紹介等を含みますが、これらに限定されません)は、一般的な学習参考用であり、いかなる場合も医学的な助言、診断、治療、またはこれらに準ずる行為(以下「医行為等」といいます)を提供するものではありません。
  3. 本サイトのコンテンツは、特定の製品、技術、または治療法の有効性、安全性を保証、推奨、または広告・販売促進するものではありません。紹介する技術には研究開発段階のものが含まれており、その臨床応用には、さらなる研究と国内外の規制当局による正式な承認が別途必要です。
  4. 本サイトは、情報提供を目的としたものであり、特定の治療法を推奨するものではありません。健康に関するご懸念やご相談は、必ず専門の医療機関にご相談ください。

第2条(法令等の遵守)
利用者は、本サイトの利用にあたり、医師法、医薬品、医療機器等の品質、有効性及び安全性の確保等に関する法律(薬機法)、個人情報の保護に関する法律、医療法、医療広告ガイドライン、その他関連する国内外の全ての法令、条例、規則、および各省庁・学会等が定める最新のガイドライン等を、自らの責任において遵守するものとします。これらの適用判断についても、利用者が自ら関係各所に確認するものとし、本サイトは一切の責任を負いません。

第3条(医療行為における責任)

  1. 本サイトで紹介するAI技術・手法は、あくまで研究段階の技術的解説であり、実際の臨床現場での診断・治療を代替、補助、または推奨するものでは一切ありません。
  2. 医行為等に関する最終的な判断、決定、およびそれに伴う一切の責任は、必ず法律上その資格を認められた医療専門家(医師、歯科医師等)が負うものとします。AIによる出力を、資格を有する専門家による独立した検証および判断を経ずに利用することを固く禁じます。
  3. 本サイトの情報に基づくいかなる行為によって利用者または第三者に損害が生じた場合も、本サイト運営者は一切の責任を負いません。実際の臨床判断に際しては、必ず担当の医療専門家にご相談ください。本サイトの利用によって、利用者と本サイト運営者の間に、医師と患者の関係、またはその他いかなる専門的な関係も成立するものではありません。

第4条(情報の正確性・完全性・有用性)

  1. 本サイトは、掲載する情報(数値、事例、ソースコード、ライブラリのバージョン等)の正確性、完全性、網羅性、有用性、特定目的への適合性、その他一切の事項について、何ら保証するものではありません。
  2. 掲載情報は執筆時点のものであり、予告なく変更または削除されることがあります。また、技術の進展、ライブラリの更新等により、情報は古くなる可能性があります。利用者は、必ず自身で公式ドキュメント等の最新情報を確認し、自らの責任で情報を利用するものとします。

第5条(AI生成コンテンツに関する注意事項)
本サイトのコンテンツには、AIによる提案を基に作成された部分が含まれる場合がありますが、公開にあたっては人間による監修・編集を経ています。利用者が生成AI等を用いる際は、ハルシネーション(事実に基づかない情報の生成)やバイアスのリスクが内在することを十分に理解し、その出力を鵜呑みにすることなく、必ず専門家による検証を行うものとします。

第6条(知的財産権)

  1. 本サイトを構成するすべてのコンテンツに関する著作権、商標権、その他一切の知的財産権は、本サイト運営者または正当な権利を有する第三者に帰属します。
  2. 本サイトのコンテンツを引用、転載、複製、改変、その他の二次利用を行う場合は、著作権法その他関連法規を遵守し、必ず出典を明記するとともに、権利者の許諾を得るなど、適切な手続きを自らの責任で行うものとします。

第7条(プライバシー・倫理)
本サイトで紹介または言及されるデータセット等を利用する場合、利用者は当該データセットに付随するライセンス条件および研究倫理指針を厳格に遵守し、個人情報の匿名化や同意取得の確認など、適用される法規制に基づき必要とされるすべての措置を、自らの責任において講じるものとします。

第8条(利用環境)
本サイトで紹介するソースコードやライブラリは、執筆時点で特定のバージョンおよび実行環境(OS、ハードウェア、依存パッケージ等)を前提としています。利用者の環境における動作を保証するものではなく、互換性の問題等に起因するいかなる不利益・損害についても、本サイト運営者は責任を負いません。

第9条(免責事項)

  1. 本サイト運営者は、利用者が本サイトを利用したこと、または利用できなかったことによって生じる一切の損害(直接損害、間接損害、付随的損害、特別損害、懲罰的損害、逸失利益、データの消失、プログラムの毀損等を含みますが、これらに限定されません)について、その原因の如何を問わず、一切の法的責任を負わないものとします。
  2. 本サイトの利用は、学習および研究目的に限定されるものとし、それ以外の目的での利用はご遠慮ください。
  3. 本サイトの利用に関連して、利用者と第三者との間で紛争が生じた場合、利用者は自らの費用と責任においてこれを解決するものとし、本サイト運営者に一切の迷惑または損害を与えないものとします。
  4. 本サイト運営者は、いつでも予告なく本サイトの運営を中断、中止、または内容を変更できるものとし、これによって利用者に生じたいかなる損害についても責任を負いません。

第10条(規約の変更)
本サイト運営者は、必要と判断した場合、利用者の承諾を得ることなく、いつでも本規約を変更することができます。変更後の規約は、本サイト上に掲載された時点で効力を生じるものとし、利用者は変更後の規約に拘束されるものとします。

第11条(準拠法および合意管轄)
本規約の解釈にあたっては、日本法を準拠法とします。本サイトの利用および本規約に関連して生じる一切の紛争については、東京地方裁判所を第一審の専属的合意管轄裁判所とします。


For J³, may joy follow you.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

医師・医学博士・AI研究者・連続起業家
元厚生労働省幹部・ハーバード大学理学修士・ケンブリッジ大学MBA・コロンビア大学行政修士(経済)
岡山大学医学部卒業後、内科・地域医療に従事。厚生労働省で複数室長(医療情報・救急災害・国際展開等)を歴任し、内閣官房・内閣府・文部科学省でも医療政策に携わる。
退官後は、日本大手IT企業や英国VCで新規事業開発・投資を担当し、複数の医療スタートアップを創業。現在は医療AI・デジタル医療機器の開発に取り組むとともに、東京都港区で内科クリニックを開業。
複数大学で教授として教育・研究活動に従事し、医療関係者向け医療AIラボ「Medical AI Nexus」、医療メディア「The Health Choice | 健康の選択」を主宰。
ケンブリッジ大学Associate・社会医学系指導医・専門医・The Royal Society of Medicine Fellow

コメント

コメントする

目次