【医療×生成系AI :P15/G3.2】Pythonと深層学習入門(ディープラーニングの心臓部:誤差逆伝播と自動微分)

難易度:★★★★★(正直、激ムズです!初学者の方は、読み飛ばしても大丈夫です)

学習のポイント

この章では、ニューラルネットワークが「間違い」から学ぶ仕組みである「誤差逆伝播法」と、その計算を自動化するPyTorchの「自動微分」を解説します。順伝播で計算ルートを記録し、逆伝播でそのルートを逆に辿ってパラメータを賢く更新する流れを掴むことが目標です。

誤差逆伝播
モデルが賢くなるプロセス

予測と正解の「誤差」を計算し、その誤差を小さくするため、出力側から入力側へと逆向きに「責任の度合い(勾配)」を計算する手法です。これにより、どのパラメータ (w, b) を修正すれば良いかが分かり、モデルを最適化できます。

自動微分 (Autograd)
PyTorchの魔法の杖

順伝播の計算ルートを「計算グラフ」として自動で記録します。loss.backward()を呼ぶだけで、このグラフを逆に辿って複雑な微分計算を全自動で実行。開発者は数式を意識せずモデル構築に集中できます。

誤差逆伝播と自動微分の仕組み
PyTorchのautogradが実現する学習の心臓部
1. 順伝播 (Forward Pass) 入力から損失を計算し、その過程を「計算グラフ」として記録 入力データ (x) モデル (パラメータ) 重み(w), バイアス(b) 予測値 (y_pred) 損失 (Loss) 予測と正解のズレ 2. 逆伝播 (Backward Pass) 損失から逆向きにたどり、各パラメータの勾配(損失への影響度)を自動計算
勾配 (∇L) を計算
∂L/∂w, ∂L/∂b
パラメータを更新:
wneww – η ⋅ ∂L/∂w
PyTorchの学習ループ (autograd)
(1) 順伝播 y_pred = model(x) (2) 損失計算 loss = loss_fn(y_pred, y_true) (3) 勾配リセット optimizer.zero_grad() (4) 逆伝播 (勾配計算) loss.backward() (5) パラメータ更新 optimizer.step()
この章で学ぶこと
  • 誤差逆伝播法(バックプロパゲーション)の仕組みと、ニューラルネットワークが学習する流れを理解する。
  • PyTorchの自動微分機能 autograd が、計算グラフをどのように利用して勾配を計算するかを把握する。
  • シンプルなコード例を通じて、順伝播から損失計算、逆伝播、パラメータ更新までの一連のプロセスを実装レベルで体感する。
学習の前提となる知識
  • 💡 PyTorchの基本的なセットアップとテンソル操作
    第1章で解説した環境構築や基本的なテンソル作成・操作の知識が必要です。
  • 💡 ニューラルネットワークの順伝播の基本的な概念。
    入力データが層を通過して出力が得られるまでの一連の流れをイメージできること。
  • 💡 微分の基本的な考え方(特に連鎖律)。
    「損失をパラメータで微分する」という概念が重要です。連鎖律は本文中でも解説しますが、事前に知っていると理解がスムーズです。

💡第2章では、第1章で整えた環境と基礎をふまえ、いよいよディープラーニングの心臓部である「誤差逆伝播」と「自動微分」に切り込みます。
ニューラルネットがどのように学習し、どのようにパラメータを更新していくのか?
PyTorchの autograd の仕組みや、計算グラフを通じた勾配の伝播など、生成系AIにも不可欠な内部動作を丁寧に解説していきます。

🔜 次の第3章では、実際にシンプルなニューラルネットワークを構築し、MNIST手書き数字データを分類する一連の学習プロセスを体験します。この章ではディープラーニングの中身を数学的に解説しているため、正直難しいです。読み飛ばしたり、次の第3章で試してみてから戻ってくるのでも大丈夫です。
次の第3章までいくと、実データを用いたモデルの定義・学習・評価を通じて、深層学習の「一通りの流れ」が体感できる実践編です。


目次

4. 誤差逆伝播法(Backpropagation)と自動微分(autograd)

ディープラーニングを支える中心技術の1つが、誤差逆伝播法(バックプロパゲーション)です。
そして、PyTorchなどの深層学習フレームワークでは、計算グラフと
自動微分(autograd)を用いて、この誤差逆伝播の計算を自動化しています。


4.1. 誤差逆伝播とは?

4.1.1. 順伝播と逆伝播

  • 順伝播 (Forward pass)
    入力から出力へ計算を進める工程。例えば、ニューラルネットワークの入力層 → 隠れ層 → 出力層と信号が流れていき、最終的に損失(L)を得ます。
  • 逆伝播 (Backward pass)
    出力側(損失)から逆向きに勾配(微分)を計算し、各層のパラメータ(重み・バイアス)を勾配降下法で更新する工程。\( w \leftarrow w – \eta \,\frac{\partial L}{\partial w} \)
    というの式を用い、学習率ηだけパラメータを修正して誤差を減らしていきます。

4.1.2. 逆伝播フローのイメージ

下図は、誤差逆伝播の概念図(多層ニューラルネットを例に)です。

直感的なイメージ
Hands-on! 誤差逆伝播体験
誤差逆伝播アルゴリズム
ニューラルネットワークの学習過程を可視化し、誤差がどのように逆向きに伝播するかを体験してください
0.10
0.8
誤差逆伝播とは
誤差逆伝播(Backpropagation)は、ニューラルネットワークの学習における中核的なアルゴリズムです。 出力層で計算された誤差を、ネットワークの各層に逆向きに伝播させることで、各重みとバイアスの勾配を効率的に計算します。
上の可視化では、3層のニューラルネットワークにおいて、順伝播(緑色の信号)と逆伝播(赤色の誤差信号)の流れを観察できます。 学習率や目標値を調整して、ネットワークがどのように学習していくかを体験してください。
  1. 順伝播:
    入力を順に変換し、出力を得る。
  2. 損失関数で誤差を計算:
    出力と正解ラベルを比べて、スカラー値の損失(L)を算出。
  3. 誤差逆伝播:
    損失を各層のパラメータに対して微分し、勾配(gradient)を得る。
  4. 勾配降下法:
    勾配に基づき、重みやバイアスを修正 。
  5. 反復:
    データセット全体に対して何度も繰り返すことで、誤差が徐々に減少し、モデルが最適化されていく。

以下では、計算グラフ (Computation Graph)自動微分 (autograd) を、なるべく直感的にイメージしやすいよう補足説明を加えながら解説します。(それでも、めちゃくちゃ難しいので、今後勉強を進めていった後で、戻ってくることをお勧めします。)


4.2. 計算グラフと自動微分 (autograd)

4.2.1. 計算グラフ(Computation Graph)とは?

直感で捉える計算グラフ

  1. 順伝播(forward pass)では、「入力データ(テンソル)」が、いくつもの「中間演算」(行列積、活性化関数など)を順番に通りながら変換されていき、最終的に「損失(Loss)」という評価値にたどり着きます。
  2. 左から右へ: 順伝播は、「入力」から「中間演算」いくつも通って最終的に「損失(Loss)」へ到達する一連の流れです。
  3. パイプラインや地図のよう:
    • イメージとしては、パイプラインが何本も合流・分岐して、最終的に1本の配管(損失)に集約するようなものです。
    • または、「入力から損失までの経路」を道路地図に例えることもできます。どの道(演算)を通って最終地点に至るかをノードとエッジで示します。

実際のディープラーニングでは、例えば「行列積 → 活性化関数 → 行列積 → 活性化関数 → …」といった具合に、層がどんどん重なり合います。これをすべて個別に微分するのは大変ですが、計算グラフを裏で構築しておくことで、後からまとめて「ここはこう微分すればいい」とわかるようになっているのです。


(A) 順伝播時の動き

  • 入力 → 演算 → 演算… → 最後の損失(L)
    各演算が実行されるたび、「どのテンソルを元に、このテンソルが生まれたか」をPyTorchが覚えています。
  • 例えば、 以下の一つ一つのステップを、PyTorchはノード(中間のテンソル)とエッジ(各演算)で関連づけて記録します。
\(y = W \cdot x + b \;\rightarrow\; \text{さらに活性化関数 } \sigma(W \cdot x + b)\)

ここで W は「入力 x を変換するためのルール(線形変換)」として使われます。このように入力ベクトルを別の形に変える仕組みを数学では「写像(しゃぞう)」と呼びますが、かんたんに言えば「x を目的に合わせて変形するフィルター」のようなものです。

W は順伝播の計算中では“その時点では固定された値”として使われますが、モデルの学習においては「損失を減らすために少しずつ変えていく対象」でもあります。つまり、順伝播では「今の W を使って計算」し、逆伝播では「W をより良くするための方向」を勾配により見つけます。

具体例のイメージ

ニューラルネットワーク:順伝播の計算フロー
テキストベース図
     x_data    W       b
       │       │       │
       │       │       ▼
       │       └───▶[ × ]   ← 行列積(W・x)
       │               │
       └────────────▶[ + ]   ← バイアス加算(+ b)
                       │
                    [σ(⋅)]   ← 活性化関数(ReLU, Sigmoidなど)
                       │
                    [ Loss ] ← 損失関数(例:MSE, CrossEntropy)

  • ノード = x_data, W, b, 中間テンソルたち
  • エッジ = 各演算(乗算, 加算, 活性化, …)

(B) 逆伝播時の動き

  • 損失 (Loss) から逆向きにたどる
    • 逆伝播は、「損失関数の出力が、どのパラメータや中間演算にどのように影響されるか(=偏微分)」を、連鎖律(Chain Rule)(以下参照)を用いて順に計算していく工程です。
  • 水路を逆流するイメージ
    • 順伝播では、入力から水を流して最終地点(損失)に到達しました。逆伝播では、その水を逆方向にたどりながら、「どの水路(演算)が損失にどれだけ寄与したか」を追跡するような感覚です。
  • 結果として得られるもの
    • 各パラメータ(重みやバイアス)に対して、損失を小さくするための方向と量を表す勾配(偏微分値)が得られます。
    • PyTorchでは、この勾配が .grad 属性に格納され、次のステップ(パラメータ更新)で「どれだけ、どの方向に変更すれば損失が下がるか」が分かるようになります。
    • つまり逆伝播の目的は、「Wをどれだけ・どの方向に変えれば損失が減るか」を知ることです。
    • そして、順伝播で使われ、逆伝播で調整されるW(重み)こそが、モデルが“学習”によって改善されていく核心です。

具体例のイメージ

ニューラルネットワークの計算グラフ
順伝播 (Forward Propagation) と 逆伝播 (Backward Propagation)
結論:勾配による学習

逆伝播によって、全てのパラメータ(W, b)について「このパラメータをわずかに変化させると、最終的な損失Lがどれだけ変化するか」という感度、すなわち勾配(∂L/∂W, ∂L/∂b)が効率的に計算されます。この勾配情報を利用し、Optimizer(例: SGD, Adam)がパラメータを損失が小さくなる方向へ少しずつ更新していくことで、ニューラルネットワークの学習が進みます。

テキストベース図
     x_data        W            b
       │           │            │
       │           │            ▼
       │           └──────▶[ × ]         ← 【順伝播】z = W・x_data(線形変換:行列積)
       │                         │         z は x_data と W の積(内積ベクトル)
       └──────────────────────▶[ + ]     ← 【順伝播】z = W・x + b(バイアス加算)
                                 ▲         → z はパラメータ W と b の両方の関数
                              [ σ(⋅) ]     ← 【順伝播】a = σ(z)
                                 ▲         → a は活性化関数(ReLUやSigmoidなど)を通した非線形出力
                              [ ŷ ]         ← 【順伝播】ŷ = f(a)
                                 ▲         → モデルの最終出力。クラス分類なら softmax の出力
                              [ Loss ]     ← 【順伝播】L = Loss(ŷ, y_true)
                                           → 真の正解ラベル y_true とのズレ(誤差)を数値化する

──────────────────────────────────────────────
【逆伝播:パラメータに勾配(∂L/∂パラメータ)を伝える流れ】

∂L/∂ŷ       ← 損失関数の出力に対する微分(例:CrossEntropy の場合は ∂L/∂ŷ = ŷ - y_true)

∂L/∂a       = ∂L/∂ŷ × ∂ŷ/∂a
            = ∂L/∂ŷ × σ'(z)
            → a = σ(z) であるため、連鎖律を使って逆伝播する
            → σ'(z) は ReLU なら 0 or 1、Sigmoid なら s(z)(1 - s(z))

∂L/∂z       = ∂L/∂a × ∂a/∂z = ∂L/∂a × 1
            → z = W・x + b なので、z は W・x や b に直接依存している(加算なので係数は1)

∂L/∂W       = ∂L/∂z × ∂z/∂W = ∂L/∂z × x_data^T
            → W は行列として x_data をかけて z を生成するため、入力 x_data が関与

∂L/∂b       = ∂L/∂z × ∂z/∂b = ∂L/∂z
            → b は z にそのまま加えられるため、勾配はそのまま流れる

【結果】
→ すべてのパラメータ(W, b)について、「このパラメータを少し変えたら損失がどれだけ変わるか」
   という勾配が計算され、SGD などの最適化手法で更新される。

各ノードにおける微分の意味:

  • ∂L/∂ŷ: 出力と正解ラベルとの差から得られる損失の微分(損失関数の出力)
  • ∂L/∂a: 活性化関数の入力に対する勾配(σの導関数をかける)
  • ∂L/∂z: 線形和 z = Wx + b に対する勾配
  • ∂L/∂W, ∂L/∂x: 行列積の勾配(連鎖律を使って計算)
連鎖律(Chain Rule)とは + 今回の例では

連鎖律(Chain Rule)は、複数の関数がつながっているときに、入力の変化が出力にどう影響するかを求めるルールです。

例えば、x → u → v → y という関数があるとき、「xが変わるとyはどう変わるか?」は、それぞれの関数の影響を掛け合わせて

\(
\frac{dy}{dx} = \frac{dy}{dv} \cdot \frac{dv}{du} \cdot \frac{du}{dx}
\)

と求めます。

深層学習の逆伝播では、これを使って「損失が各パラメータにどう影響するか」を計算しています。

4.2.2. PyTorchのautograd

(A) requires_grad=True で追跡対象に

  • テンソルw = torch.tensor(1.0, requires_grad=True) のように定義すると、PyTorchは「この w を使う演算はすべて計算グラフの一員だな」とみなします。
  • 勾配は「学習対象(最適化の対象)のパラメータ」だけが持ちます。勾配は、今のパラメータが損失にどれくらい影響を与えやすいか(変化させたときに損失がどれだけ増減するか)を示し、損失を小さくするために、“どのパラメータをどれだけ動かすべきか”を教えてくれます。
    PyTorchでは .requires_grad=True を指定したテンソルだけが、 .grad に勾配を持てます。
  • 順伝播中、「wx の乗算」「バイアス加算」「活性化関数」「最終損失との比較」など、あらゆる演算を繋いで「これが loss に至るルートだ」と内部に記録します。

(B) loss.backward() が逆伝播を自動実行

  • ユーザーが計算式(逆伝播アルゴリズム)を書く必要は一切なし
  • 単に loss.backward() と呼べば、PyTorchが計算グラフを後ろから前へ駆け上がり、自動的に逆伝播を行ってくれます。PyTorch は、順伝播(forward)で構築された「計算グラフ」をもとに、損失(loss)から逆向きに各演算の微分を計算します。これは、「連鎖律(Chain Rule)」という数学的なルールを使って、
  • \(\frac{\partial \mathrm{loss}}{\partial w},\quad \frac{\partial \mathrm{loss}}{\partial b},\quad \ldots\)
  • のように連鎖律で微分を計算し、それぞれのパラメータが損失に与える影響(勾配)を求めていく処理です。 そして、求めた勾配は、各パラメータ(w, b など)の 属性.grad に自動的に格納されます。

(C) 大規模モデルでも実装がシンプル

  • CNN(画像認識などに使われる畳み込みニューラルネットワーク)やRNN(自然言語処理などに使われる再帰型ニューラルネットワーク)、Transformer(ChatGPTなどのLLM(大規模言語モデルなどに使われる))など深層かつ複雑なネットワークを手書きで微分するのは非現実的。
  • autogradなら、どんなに層が多くても「順伝播(モデル定義)+損失計算+loss.backward()」で誤差逆伝播が回るので、実装を大幅に簡略化できるのです。
PyTorch Autograd 可視化デモ
PyTorchのautograd
自動微分による計算グラフと逆伝播の可視化
🔍 autogradの核心概念
PyTorchのautogradは、テンソルにrequires_grad=Trueを設定することで、そのテンソルを使用するすべての演算を計算グラフとして自動追跡し、loss.backward()を呼ぶだけで連鎖律に基づいた逆伝播を自動実行する革新的なシステムです。
準備完了:デモ開始ボタンを押して、autogradの動作を確認してください
📊 計算グラフの構築プロセス
(A) requires_grad=Trueで追跡対象に: テンソルを学習対象として指定すると、PyTorchはそのテンソルを使用するすべての演算を内部の計算グラフに記録します。勾配は損失を最小化するために「どのパラメータをどれだけ動かすべきか」を教えてくれる重要な情報です。
w = torch.tensor(1.0, requires_grad=True) # 追跡開始 x = torch.tensor(2.0) # 入力データ y = w * x + b # 演算が自動記録される
自動逆伝播の実行
(B) loss.backward()が逆伝播を自動実行: ユーザーが複雑な微分計算式を記述する必要は一切ありません。PyTorchが計算グラフを後ろから前へ辿り、連鎖律を用いて各パラメータの勾配を自動計算し、.grad属性に格納します。
loss = (y – target)**2 # 損失計算 loss.backward() # 自動逆伝播実行! print(w.grad) # ∂loss/∂w が自動計算される
🏗️ 大規模モデルでの威力
(C) 大規模モデルでも実装がシンプル: CNN、RNN、Transformerなど、数百万~数十億パラメータを持つ深層学習モデルでも、「順伝播の定義 + 損失計算 + loss.backward()」という3ステップで訓練が可能です。手動で微分を計算する必要がないため、開発効率が劇的に向上します。

4.2.3. さらに直感的なアナロジー

  • 料理のレシピ
    • 順伝播: 食材(パラメータ)を混ぜ合わせ、調理して最終料理(損失)を作る。
    • 逆伝播: 出来上がった料理(損失)を食べ比べし、「塩をもう少し増やした方がいい」「水分を減らすべき」など、各材料(パラメータ)をどう変えれば味(誤差)が良くなるかを逆向きに探る。
    • PyTorchはレシピ(計算グラフ)を裏で記録し、料理を舌で味見(損失評価)してから一気に「どの材料をどう増減すればベストか」まとめて教えてくれるイメージ。
  • 交通地図・道順
    • 順伝播: 「入力(出発点)から出力(目的地=損失)まで何本もの道(演算)を通り、どうルートを選ぶか」を正確に記録している。
    • 逆伝播: 行き止まりにならないよう、地図を逆走しながら「どこで曲がれば最適か」「どの道路が時間をロスしているか」を計算して、最短経路(最小損失に至る勾配)を見つける。

こうしたアナロジーは、あくまでイメージではありますが、計算グラフと自動微分の「順伝播→逆伝播」という2段構えの流れを頭に思い浮かべるのに役立ちます。


4.2.4. まとめ (4.2 節)

  1. 計算グラフ (Computation Graph)
    • ディープラーニングにおける順伝播を、ノード(テンソル)とエッジ(演算)で表した構造。
    • 「入力 → 演算 → 演算 … → 損失」に至るすべての経路を把握し、後で逆向きに微分を計算するのが狙い。
  2. 順伝播時
    • PyTorchが演算の履歴を保存し、どのテンソルがどの演算に使われたかをグラフ化して裏で管理。
    • requires_grad=True のテンソルが関係する演算はすべて追跡対象。
  3. 逆伝播時
    • loss.backward() を呼ぶと、計算グラフを後ろ(損失)から前(各パラメータ)へたどって連鎖律で微分を計算。
    • 各パラメータの .grad という属性の勾配の値が更新され、誤差逆伝播(バックプロパゲーション)が完了する。
  4. PyTorchのautograd
    • 順伝播と損失計算を定義するだけで、大規模ネットワークでも自動的に勾配を計算してくれる仕組み。
    • 手書きで複雑な微分式を書く必要がなく、開発効率を飛躍的に向上。
  5. 直感的アナロジー
    • 料理の味見や交通地図の逆走といったイメージで考えると、「出力(損失)から逆向きにどこをどう調整すれば良いかを教えてくれる」という感覚が掴みやすい。

これが計算グラフと自動微分の本質です。
この仕組みによって、私たちは「順伝播を書く → .backward() で一気に逆伝播」するというシンプルなコードで、大規模かつ複雑なディープラーニングモデルを動かすことができるようになっています。

4.3. コード例: 超シンプルな回帰モデルで見る誤差逆伝播

以下に、y=2x というルールのデータを学習する最小限のサンプルコードを示します。
コード内の各行にコメントを付け、実際にどんな操作が行われるかを丁寧に解説します。

flowchart TD
    Start["学習プロセス開始"] --> Setup

    subgraph "準備フェーズ"
        Setup["1. データ、モデル、損失関数、
Optimizerを準備"] end Setup --> LoopCheck{指定回数
学習したか?} LoopCheck -- No --> Forward subgraph "学習ループ (1サイクルの処理)" Forward["2. 順伝播
モデルで予測値を計算"] Loss["3. 損失計算
予測と正解の誤差を計算"] ZeroGrad["4. 勾配の初期化
(前回の勾配をリセット)"] Backward["5. 逆伝播
誤差から勾配を計算"] Update["6. パラメータ更新
勾配を元に重みを更新"] end Forward --> Loss Loss --> ZeroGrad ZeroGrad --> Backward Backward --> Update Update -- "次のサイクルへ" --> LoopCheck LoopCheck -- Yes --> End["学習完了"]
# -*- coding: utf-8 -*-
# ↑ このファイルをUTF-8エンコーディングとして扱う指定(日本語コメント対応)

# ▼=========================================
# ライブラリのインポート
# ==========================================
import torch                 # PyTorch本体(テンソル計算・自動微分などの機能を提供)
import torch.nn as nn       # ニューラルネットワーク関連の便利モジュール(損失関数など)
import torch.optim as optim # 最適化アルゴリズム(SGDなど)を使うためのモジュール

# ▼=========================================
# 学習対象のパラメータ(重み・バイアス)を定義
# ==========================================
# torch.tensor(..., requires_grad=True) とすることで、
# このテンソルに対して自動微分を行うようPyTorchに指示する。
# つまり、計算グラフにこの変数が登場したら、その演算履歴を記録し、勾配計算できるようになる。
w = torch.tensor(1.0, requires_grad=True)  # 重みw(スカラー: shape=()、初期値1.0)
b = torch.tensor(0.0, requires_grad=True)  # バイアスb(スカラー: shape=()、初期値0.0)

# ▼=========================================
# モデル(順伝播)の定義
# ==========================================
# 単純な線形モデル: y = w * x + b
# PyTorchでは、この関数の中で行われた演算が「ノード」として記録され、
# 自動的に計算グラフが構築される(動的計算グラフ)
def simple_model(x):
    # xはshape=(4,)の1次元テンソル(入力バッチ:データ4つ)
    # wはスカラー、bもスカラーなので、要素ごとに w*x[i] + b を計算する
    return w * x + b  # 出力もshape=(4,)の1次元テンソル

# ▼=========================================
# 損失関数とOptimizerの定義
# ==========================================
# nn.MSELoss():平均二乗誤差(Mean Squared Error)を損失関数として利用。
# 出力と正解の差を2乗して平均した値が返る。 shape=(4,) → スカラーに
loss_fn = nn.MSELoss()

# PyTorchのoptimモジュールからSGD(確率的勾配降下法)を使って、
# パラメータ w と b を更新するように設定します。
# lr(learning rate, 学習率)は 0.01 に指定しています。
# 学習率は、パラメータをどれだけ更新するかの大きさを決める超パラメータです。
optimizer = optim.SGD([w, b], lr=0.01)

# ▼=========================================
# 学習データの作成
# ==========================================
# 入力xと正解yのデータ。y = 2 * x という関係にあるシンプルな直線。
x_data = torch.tensor([1.0, 2.0, 3.0, 4.0])  # shape=(4,) の1次元テンソル(入力4件)
y_data = torch.tensor([2.0, 4.0, 6.0, 8.0])  # shape=(4,) の1次元テンソル(正解)

# ▼=========================================
# 学習ループ
# ==========================================
# エポック:データ全体を何回繰り返して学習するか
num_epochs = 10

# forループで学習を繰り返す
for epoch in range(num_epochs):

    # -----------------------
    # (A) 順伝播 (Forward pass)
    # -----------------------
    # モデルに入力データ(x_data)を入れて予測値(y_pred)を得る
    # y_pred: shape=(4,) の予測値ベクトル
    y_pred = simple_model(x_data)

    # -----------------------
    # (B) 損失計算
    # -----------------------
    # 出力(予測値)と正解ラベルの差を計算し、損失(スカラー)を出す
    loss = loss_fn(y_pred, y_data)

    # -----------------------
    # (C) 勾配の初期化
    # -----------------------
    # optimizer.zero_grad() は、パラメータ w, b に蓄積された勾配 (.grad) をリセットします。
    # なぜ必要かというと、PyTorchではデフォルトで「勾配が加算方式」で記録されていくためです。
    # 前のイテレーション(学習ステップ)での勾配が残ったままだと、意図しない更新になってしまう恐れがあります。
    optimizer.zero_grad()

    # -----------------------
    # (D) 逆伝播 (Backward pass)
    # -----------------------
    # 学習データ(x)をモデルに入力すると、モデルは予測値(y_pred)を出力する。
    # この予測値と正解ラベル(y_true)を比べて、「どれだけ間違っていたか」を数値化したものが Loss(損失)。
    # つまり、Lossは「その学習データに対して、モデルの予測がどれだけズレているか」を表す。
    #
    # loss.backward() を呼ぶと、PyTorch は計算グラフをたどって、
    # 各パラメータが損失にどれだけ影響を与えているか(= ∂Loss/∂パラメータ)を自動で計算する。
    # つまり、「損失を最小化するには、どの方向に各パラメータを更新すべきか」が分かるようになる。
    # 
    # ▶ 勾配の計算結果(∂L/∂w や ∂L/∂b)は、それぞれ w や b の .grad 属性に自動的に格納される。
    # 
    # たとえば:
    #   - w = torch.tensor(1.0, requires_grad=True) は shape=() のスカラーテンソル(単一の値)
    #   - b = torch.tensor(0.0, requires_grad=True) も同様に shape=()
    #
    # → それぞれに対応して、
    #   - w.grad には ∂loss/∂w の計算結果(スカラーテンソル: shape=())が入る
    #   - b.grad には ∂loss/∂b の計算結果(スカラーテンソル: shape=())が入る
    #
    # つまり、w と w.grad は「**同じメモリ空間上にあるペア**」のようなもので、
    # 勾配情報は w 本体の中に「.gradという属性」として保持される。
    #
    # 実際に勾配を確認すると以下のようなイメージになる:
    #   print(w)       → tensor(1.2345, requires_grad=True)
    #   print(w.grad)  → tensor(0.5678)   ← ∂L/∂w の具体的な値
    #
    # 💡注意:
    #   この .grad は累積される仕組みなので、毎回 zero_grad() でリセットが必要。

    loss.backward()

    # loss.backward() は、各パラメータが損失にどれだけ影響しているか(=勾配)を自動で計算する関数です。

    # -----------------------
    # (E) パラメータの更新
    # -----------------------
    # optimizer.step() により、学習率×勾配を使って w, b を更新
    optimizer.step()

    # -----------------------
    # (F) 学習の進捗を表示
    # -----------------------
    print(f"Epoch {epoch+1}/{num_epochs} | Loss={loss.item():.4f} | w={w.item():.4f}, b={b.item():.4f}")

💡補足で図的にまとめると:

w = tensor(1.0, requires_grad=True)
         │
         ├──演算に参加(例: y = w * x + b)
         │
         └──loss.backward() 実行後に…
               ↓
         w.grad = ∂L/∂w  ← 勾配がここに格納される(形状: shape=())

このように、勾配(gradient)は元の変数に紐づいた .grad 属性の中に保持されるので、「wの微分値はw.gradの中にある」と覚えておくと非常に便利です。

コードのポイント

  1. wbrequires_grad=True
    • PyTorchがこれらのテンソルを勾配計算の対象とみなし、順伝播時に計算グラフを構築します。
  2. 順伝播 (simple_model)
    • \(y = w \cdot x + b\) という演算が計算グラフに登録される。
  3. loss.backward()
    • loss (スカラー)を元に逆伝播が実行され、w.gradb.grad に勾配が代入される。
  4. optimizer.step()
    • 勾配をもとにSGDがパラメータを更新。たとえば 、以下など
      \(w \leftarrow w – 0.01 \times \frac{\partial L}{\partial w}\)

初期値では w=1.0 ですが、数エポック学習すると w が2.0付近に収束し、 b も0に近づいていくのが観察できるはずです(理想的には y=2x+0)。


4.4. より深い層では?

実際のニューラルネットワークは、畳み込み層(Conv2d)バッチ正規化(BatchNorm)再帰層(RNN/Transformer) など多くのレイヤーを持ちます。
しかし、このサンプルのように

  1. 順伝播で出力損失を計算
  2. loss.backward() で逆伝播(勾配計算)
  3. optimizer.step() でパラメータ更新

という仕組みは基本的に同じです。


4.5. 誤差逆伝播フロー (図解)

下図は、多層ネットワークでの誤差逆伝播の流れを概念的に描いたものです(入力層→隠れ層→出力層)。

  1. 順伝播:
    入力層から隠れ層を経て出力層まで信号が伝わり、予測結果(クラス確率など)を計算。
  2. 損失計算:
    出力を正解と比較し、スカラー値の誤差(L)を得る。
  3. 逆伝播:
    出力層から隠れ層へ、連鎖律を使って微分値(勾配)を逆方向に伝える。各層の重み(w)やバイアス(b)に対する勾配を算出。
  4. 勾配降下:
    求めた勾配でパラメータを少しずつ修正し、誤差が減る方向へモデルを更新する。
  5. 繰り返し:
    多数の学習サンプルを通して上記工程を反復し、モデルが最適化される。
誤差逆伝播フロー 入力 隠れ層 出力 1. 順伝播 損失 計算 L = 誤差 正解 2. 損失計算 ∇w, ∇b ∇w, ∇b 3. 逆伝播(勾配計算) パラメータ更新 w = w – α∇w b = b – α∇b (α: 学習率) 4. 勾配降下 学習の繰り返し 多数のサンプルで 上記工程を反復 → モデル最適化 5. 繰り返し学習 重要なポイント • 連鎖律で勾配を逆方向に伝播 • 各層の重み・バイアスを更新 • 学習率αで更新幅を調整 • 複数サンプルで反復学習 • 誤差を最小化してモデル改善 凡例 順伝播(入力→出力) 逆伝播(勾配計算) 学習の繰り返し 入力層 隠れ層 出力層 損失計算 損失関数 パラメータ更新 勾配降下

4.6. 医療データへの応用

  • 画像診断(X線、CT、MRIなど):
    畳み込みニューラルネット(CNN)で画像から特徴を抽出し、誤差逆伝播によってフィルタが自動的に学習される。
  • テキスト処理(電子カルテ、文献):
    文字列をベクトル化し、RNNやTransformerを使って時系列処理。誤差逆伝播で単語埋め込みやAttention機構の重みが最適化される。
  • 音声分析(心音、呼吸音):
    音声信号をスペクトログラムなどに変換してCNN/RNNで解析。誤差逆伝播によりモデルが音響的特徴を捉える。

いずれのケースでも自動微分(autograd) が支えており、複雑な誤差逆伝播アルゴリズムをユーザーが手書きしなくても済むため、大規模モデルや大量データにも柔軟に対応できます。


4.7. まとめ

  1. 誤差逆伝播法(Backpropagation)
    • ディープラーニングの学習を支える中核的アルゴリズム。
    • 損失(誤差)を出力層から逆向きに伝えながら、各層の重みに対する勾配を計算・更新。
  2. 自動微分(autograd)と計算グラフ
    • PyTorchは計算グラフを自動構築し、loss.backward() で連鎖律を適用して勾配を求める。
    • 利用者は順伝播(モデル定義と損失計算)を書くのみでOK。
  3. 学習フロー
    1. 順伝播 (forward)
    2. 損失 (loss) 計算
    3. 逆伝播 (loss.backward())
    4. パラメータ更新 (optimizer.step())
    5. 勾配リセット (optimizer.zero_grad())
  4. 実装のシンプルさ
    • フレームワークのおかげで、誤差逆伝播の数式を自分で書く必要がない。
    • 大規模ネットワークでも同じ仕組みで学習できる。
  5. 医療AIへの影響
    • 異種データ(画像, テキスト, 音声等)を扱う複雑なニューラルネットでも短期間で開発可能。
    • 大量の医療データからモデルが特徴を自動学習し、高精度な診断支援や文書要約が実現。

上記のように、誤差逆伝播と自動微分はディープラーニングの核となる要素です。
出力から逆向きに勾配を伝えるというアイデアと、フレームワークが計算グラフを管理して一気に微分するという仕組みが組み合わさり、私たちは複雑なニューラルネットを短いコードで高速に学習させられるわけです。医療を含む幅広い分野での大規模AI活用を支える、まさに基盤技術といえます。

🔜 次の第3章では、実際にシンプルなニューラルネットワークを構築し、MNIST手書き数字データを分類する一連の学習プロセスを体験します。
実データを用いたモデルの定義・学習・評価を通じて、深層学習の「一通りの流れ」が体感できる実践編です。



ご利用規約(免責事項)

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

第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 | 健康の選択」、美・医・食ポータル「Food Connoisseur」を主宰。
ケンブリッジ大学Associate・社会医学系指導医・専門医・The Royal Society of Medicine Fellow

目次