Traffine I/O

日本語

2022-10-23

バックプロパゲーション

バックプロパゲーションとは

バックプロパゲーションは、ニューラルネットワークの重みとバイアスを更新するために必要な勾配を効率的に計算することができるため、ディープラーニングモデルのトレーニングプロセスにおいて重要な役割を果たします。予測された出力と実際の出力との誤差を最小化することにより、バックプロパゲーションはニューラルネットワークが新しいデータに学習し適応することを可能にし、最終的に性能を向上させます。

バックプロパゲーションのアルゴリズム

この章では、バックプロパゲーションアルゴリズムとそのディープニューラルネットワークのトレーニングにおける役割について詳しく説明します。連瑣律や勾配降下法などの基本的な数学的概念を説明した後、アルゴリズムを詳しく説明し、その実装のための疑似コードを提供します。

微積分の連鎖律

連瑣律は微積分の基本的な概念の一つであり、合成関数の微分を計算することができます。バックプロパゲーションでは、この連瑣律を使用して、ネットワークの重みとバイアスに関する損失関数の勾配を計算するのに役立ちます。

\frac{dy}{dx} = \frac{dy}{dg(x)} \cdot \frac{dg(x)}{dx}

合成関数 y = f(g(x)) の場合、連瑣律は、yx に関する微分は、fg(x) に関する微分と g(x)x に関する微分の積として表されます。

損失関数

損失関数は、ニューラルネットワークの予測された出力と実際の出力(ターゲット)の差を定量化する関数であり、ディープラーニングにおいて非常に重要です。回帰タスクには平均二乗誤差(MSE)、分類タスクにはクロスエントロピーなどが一般的に使用されます。

例えば、平均二乗誤差は以下のように定義されます。

L = \frac{1}{N}\sum_{i=1}^{N}(y_i - \hat{y}_i)^2

ここで、N はサンプル数、y_i は実際の出力、\hat{y}_i は予測された出力です。

勾配降下法

勾配降下法は、損失関数を最小化するために使用される最適化アルゴリズムであり、ネットワークの重みとバイアスを反復的に更新することで実現されます。基本的なアイデアは、パラメータの勾配を計算し、勾配の負の比例でパラメータを更新することです。

勾配降下法の一般的な更新ルールは以下のとおりです。

w_{t+1} = w_t - \eta \frac{\partial L}{\partial w_t}

ここで、w_t は現在の重み、w_{t+1} は更新された重み、\eta は学習率、\frac{\partial L}{\partial w_t} は重みに関する損失関数の勾配です。

アルゴリズムの詳細

バックプロパゲーションアルゴリズムには、フォワードパスとバックワードパスの2つの主要なステップがあります。

  • フォワードパス
    フォワードパスでは、入力データがネットワークを通過して予測された出力を計算します。これには、各ニューロンの入力とバイアスの加重和を計算し、活性化関数を適用してニューロンの出力を生成することが含まれます。

  • バックワードパス
    バックワードパスでは、連瑣律を使用して、ネットワークの重みとバイアスに関する損失関数の勾配を計算します。これらの勾配を使用して、勾配降下法を使用して重みとバイアスを更新します。

バックプロパゲーションアルゴリズムは、以下のように要約することができます。

  1. フォワードパスを実行して予測された出力を計算
  2. 損失関数を使用して損失を計算
  3. 出力層の活性化に関する損失関数の勾配を計算
  4. 連瑣律を使用して、ネットワーク内の重みとバイアスに関する損失関数の勾配を計算
  5. 勾配降下法を使用して重みとバイアスを更新

バックプロパゲーションの導出

この章では、連瑣律と勾配降下法の最適化方法を使用して、バックプロパゲーションアルゴリズムをステップバイステップで導出します。まず、必要な記号を定義し、ネットワークの重みとバイアスの更新方程式を導出します。

記号

ニューラルネットワークのために、次の記号を定義します。

  • L: ネットワーク内の層の数
  • N_l: 層lのニューロンの数
  • w^l_{jk}: 層l-1のニューロンkと層lのニューロンjを接続する重み
  • b^l_j: 層lのニューロンjのバイアス
  • a^l_j: 層lのニューロンjの活性化
  • z^l_j: 層lのニューロンjの入力とバイアスの加重和で、z^l_j = \sum_k w^l_{jk} a^{l-1}_k + b^l_j で定義される
  • f^l: 層lのニューロンの活性化関数
  • L(\mathbf{y}, \mathbf{\hat{y}}):損失関数。ここで、\mathbf{y} は実際の出力を表し、\mathbf{\hat{y}} は予測された出力を表す

バックプロパゲーションアルゴリズムの導出

バックプロパゲーションアルゴリズムを導出するために、重みとバイアスに関する損失関数の勾配を計算する必要があります。最初に、出力層の活性化に関する勾配を計算してから、ニューロンの誤差項を計算します。

ステップ1: 出力層の活性化に関する損失関数の勾配を計算

\frac{\partial L}{\partial a^{L}_j}

ステップ:出力層のニューロンの誤差項を計算

Lのニューロンjの誤差項を\delta^L_jと定義します。

\delta^L_j = \frac{\partial L}{\partial z^{L}_j}

連瑣律を使用して、\delta^L_jを以下のように表すことができます。

\delta^L_j = \frac{\partial L}{\partial a^{L}_j} \cdot f'^{L}(z^{L}_j)

ステップ3: 隠れ層のニューロンの誤差項を計算

隠れ層では、次の層(層l+1)の誤差項と連瑣律を使用して、誤差項を計算できます。

\delta^l_j = \frac{\partial L}{\partial z^{l}_j} = \sum_k \frac{\partial L}{\partial z^{l+1}_k} \cdot \frac{\partial z^{l+1}_k}{\partial z^{l}_j} = \sum_k \delta^{l+1}_k \cdot \frac{\partial z^{l+1}_k}{\partial z^{l}_j}

連瑣律を再度適用すると、以下のように表すことができます。

\delta^l_j = \sum_k \delta^{l+1}_k \cdot w^{l+1}_{kj} \cdot f'^{l}(z^{l}_j)

ステップ4: 重みに関する損失関数の勾配を計算

ニューロンの誤差項が全て揃ったら、重みに関する損失関数の勾配を計算できます。連瑣律を使用すると、以下の式が得られます。

\frac{\partial L}{\partial w^l_{jk}} = \delta^l_j \cdot a^{l-1}_k

ステップ5: バイアスに関する損失関数の勾配を計算

同様に、バイアスに関する損失関数の勾配を計算できます。

\frac{\partial L}{\partial b^l_j} = \delta^l_j

ステップ6: 勾配降下法を使用して重みとバイアスを更新

重みとバイアスに関する損失関数の勾配が得られたら、勾配降下法を使用してそれらを更新できます。

w^l_{jk} \leftarrow w^l_{jk} - \eta \delta^l_j \cdot a^{l-1}_k
b^l_j \leftarrow b^l_j - \eta \delta^l_j

これらの更新式をトレーニングプロセス中に反復的に適用することにより、バックプロパゲーションアルゴリズムはニューラルネットワークが入力データに適応し、損失関数を最小化し、学習することを可能にします。

フィードフォワードニューラルネットワークのバックプロパゲーションの例

以下は、PythonとNumpyを使用したシンプルなフィードフォワードニューラルネットワークのバックプロパゲーションの例です。

python
import numpy as np

# Activation function and its derivative
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return sigmoid(x) * (1 - sigmoid(x))

# Initialize network
def initialize_network(input_nodes, hidden_nodes, output_nodes):
    network = {
        "W1": np.random.randn(hidden_nodes, input_nodes) * 0.1,
        "b1": np.zeros((hidden_nodes, 1)),
        "W2": np.random.randn(output_nodes, hidden_nodes) * 0.1,
        "b2": np.zeros((output_nodes, 1))
    }
    return network

# Forward pass
def forward_pass(network, X):
    W1, b1, W2, b2 = network["W1"], network["b1"], network["W2"], network["b2"]
    Z1 = np.dot(W1, X) + b1
    A1 = sigmoid(Z1)
    Z2 = np.dot(W2, A1) + b2
    A2 = sigmoid(Z2)

    return Z1, A1, Z2, A2

# Backward pass
def backward_pass(network, X, y, Z1, A1, Z2, A2, learning_rate):
    m = X.shape[1]
    dZ2 = A2 - y
    dW2 = (1 / m) * np.dot(dZ2, A1.T)
    db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)
    dZ1 = np.dot(network["W2"].T, dZ2) * sigmoid_derivative(Z1)
    dW1 = (1 / m) * np.dot(dZ1, X.T)
    db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True)

    network["W1"] -= learning_rate * dW1
    network["b1"] -= learning_rate * db1
    network["W2"] -= learning_rate * dW2
    network["b2"] -= learning_rate * db2

# Training the network
def train_network(network, X, y, epochs, learning_rate):
    for i in range(epochs):
        Z1, A1, Z2, A2 = forward_pass(network, X)
        backward_pass(network, X, y, Z1, A1, Z2, A2, learning_rate)

# Example
input_nodes = 2
hidden_nodes = 3
output_nodes = 1
network = initialize_network(input_nodes, hidden_nodes, output_nodes)

# Training data (XOR problem)
X = np.array([[0, 0, 1, 1], [0, 1, 0, 1]])
y = np.array([[0, 1, 1, 0]])

epochs = 10000
learning_rate = 0.1

train_network(network, X, y, epochs, learning_rate)

# Testing
Z1, A1, Z2, A2 = forward_pass(network, X)
predictions = (A2 > 0.5).astype(int)
print("Predictions:", predictions)

この実装は、1つの隠れ層を持つシンプルなフィードフォワードニューラルネットワークを示しています。アーキテクチャとトレーニングパラメータを調整することで、このネットワークはより複雑な問題を解決するために適応することができます。

参考

http://karpathy.github.io/neuralnets/
https://towardsdatascience.com/backpropagation-from-scratch-how-neural-networks-really-work-36ee4af202bf
https://www.youtube.com/watch?v=IN2XmBhILt4&ab_channel=StatQuestwithJoshStarmer
https://www.youtube.com/watch?v=Ilg3gGewQ5U&ab_channel=3Blue1Brown
https://www.youtube.com/watch?v=0itH0iDO8BE&ab_channel=予備校のノリで学ぶ「大学の数学・物理」

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!