バックプロパゲーションとは
バックプロパゲーションは、ニューラルネットワークの重みとバイアスを更新するために必要な勾配を効率的に計算することができるため、ディープラーニングモデルのトレーニングプロセスにおいて重要な役割を果たします。予測された出力と実際の出力との誤差を最小化することにより、バックプロパゲーションはニューラルネットワークが新しいデータに学習し適応することを可能にし、最終的に性能を向上させます。
バックプロパゲーションのアルゴリズム
この章では、バックプロパゲーションアルゴリズムとそのディープニューラルネットワークのトレーニングにおける役割について詳しく説明します。連瑣律や勾配降下法などの基本的な数学的概念を説明した後、アルゴリズムを詳しく説明し、その実装のための疑似コードを提供します。
微積分の連鎖律
連瑣律は微積分の基本的な概念の一つであり、合成関数の微分を計算することができます。バックプロパゲーションでは、この連瑣律を使用して、ネットワークの重みとバイアスに関する損失関数の勾配を計算するのに役立ちます。
合成関数
損失関数
損失関数は、ニューラルネットワークの予測された出力と実際の出力(ターゲット)の差を定量化する関数であり、ディープラーニングにおいて非常に重要です。回帰タスクには平均二乗誤差(MSE)、分類タスクにはクロスエントロピーなどが一般的に使用されます。
例えば、平均二乗誤差は次のように定義されます。
ここで、
勾配降下法
勾配降下法は、損失関数を最小化するために使用される最適化アルゴリズムであり、ネットワークの重みとバイアスを反復的に更新することで実現されます。基本的なアイデアは、パラメータの勾配を計算し、勾配の負の比例でパラメータを更新することです。
勾配降下法の一般的な更新ルールは次のとおりです。
ここで、
アルゴリズムの詳細
バックプロパゲーションアルゴリズムには、フォワードパスとバックワードパスの2つの主要なステップがあります。
-
フォワードパス
フォワードパスでは、入力データがネットワークを通過して予測された出力を計算します。これには、各ニューロンの入力とバイアスの加重和を計算し、活性化関数を適用してニューロンの出力を生成することが含まれます。 -
バックワードパス
バックワードパスでは、連瑣律を使用して、ネットワークの重みとバイアスに関する損失関数の勾配を計算します。これらの勾配を使用して、勾配降下法を使用して重みとバイアスを更新します。
バックプロパゲーションアルゴリズムは、次のように要約することができます。
- フォワードパスを実行して予測された出力を計算
- 損失関数を使用して損失を計算
- 出力層の活性化に関する損失関数の勾配を計算
- 連瑣律を使用して、ネットワーク内の重みとバイアスに関する損失関数の勾配を計算
- 勾配降下法を使用して重みとバイアスを更新
バックプロパゲーションの導出
この章では、連瑣律と勾配降下法の最適化方法を使用して、バックプロパゲーションアルゴリズムをステップバイステップで導出します。まず、必要な記号を定義し、ネットワークの重みとバイアスの更新方程式を導出します。
記号
ニューラルネットワークのために、次の記号を定義します。
: ネットワーク内の層の数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: 出力層の活性化に関する損失関数の勾配を計算
ステップ:出力層のニューロンの誤差項を計算
層
連瑣律を使用して、
ステップ3: 隠れ層のニューロンの誤差項を計算
隠れ層では、次の層(層
連瑣律を再度適用すると、次のように表すことができます。
ステップ4: 重みに関する損失関数の勾配を計算
ニューロンの誤差項が全て揃ったら、重みに関する損失関数の勾配を計算できます。連瑣律を使用すると、次の式が得られます。
ステップ5: バイアスに関する損失関数の勾配を計算
同様に、バイアスに関する損失関数の勾配を計算できます。
ステップ6: 勾配降下法を使用して重みとバイアスを更新
重みとバイアスに関する損失関数の勾配が得られたら、勾配降下法を使用してそれらを更新できます。
これらの更新式をトレーニングプロセス中に反復的に適用することにより、バックプロパゲーションアルゴリズムはニューラルネットワークが入力データに適応し、損失関数を最小化し、学習することを可能にします。
フィードフォワードニューラルネットワークのバックプロパゲーションの例
以下は、PythonとNumpyを使用したシンプルなフィードフォワードニューラルネットワークのバックプロパゲーションの例です。
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つの隠れ層を持つシンプルなフィードフォワードニューラルネットワークを示しています。アーキテクチャとトレーニングパラメータを調整することで、このネットワークはより複雑な問題を解決するために適応することができます。
参考