チャレンジ一覧に戻る
難しい 0件解決済み 正答率0%

2層ネットワークの誤差逆伝播法

sigmoid の隠れ層1つと sigmoid の出力1つを持つネットワークの、すべての重みとバイアスの勾配を計算します。

このチャレンジで学べること

  • 2 層ネットワークのすべての勾配を計算する
  • 誤差を層をさかのぼって伝える
  • 数式とコードを 1 ステップずつ結び付ける

問題

原文(英語)を表示

誤差逆伝播法は、出力から入力へ向かって層ごとに連鎖律を適用します。ネットワークは n 個の入力、h 個の隠れニューロン、1つの出力を持ち、すべて sigmoid(σ(z) = 1 / (1 + e^(-z)))を使います。

  • 隠れ層:a_j = σ(inputs · hidden_weights[j] + hidden_biases[j])
  • 出力:y = σ(a · output_weights + output_bias)
  • 損失:L = (y - target)²

勾配:

  1. delta_out = 2 × (y - target) × y × (1 - y)
  2. 出力層:dL/doutput_weights[j] = delta_out × a_j、dL/doutput_bias = delta_out
  3. delta_j = delta_out × output_weights[j] × a_j × (1 - a_j)
  4. 隠れ層:dL/dhidden_weights[j][i] = delta_j × inputs[i]、dL/dhidden_biases[j] = delta_j

backprop_gradients(inputs, hidden_weights, hidden_biases, output_weights, output_bias, target) を実装してください。

出力

h + 1 行の行列を返してください。

  • 行 j(各隠れニューロン j について順番に):hidden_weights[j] の n 個の勾配、続いて hidden_biases[j] の勾配。
  • 最後の行:output_weights の h 個の勾配、続いて output_bias の勾配。

制約

1 ≤ n, h ≤ 20

-5 ≤ 各入力、重み、バイアス ≤ 5

0 ≤ target ≤ 1

例

例 1
入力:
inputs = [1.0]
target = 1.0
output_bias = 0.0
hidden_biases = [0.0]
hidden_weights = [
    [0.0]
]
output_weights = [0.0]

期待される出力:
expected = [
    [0.0, 0.0],
    [-0.125, -0.25]
]
入力:
std::vector<double> inputs = {1.0};
double target = 1.0;
double output_bias = 0.0;
std::vector<double> hidden_biases = {0.0};
std::vector<std::vector<double>> hidden_weights = {
    {0.0}
};
std::vector<double> output_weights = {0.0};

期待される出力:
std::vector<std::vector<double>> expected = {
    {0.0, 0.0},
    {-0.125, -0.25}
};
入力:
double[] inputs = new double[] {1.0};
double target = 1.0;
double output_bias = 0.0;
double[] hidden_biases = new double[] {0.0};
double[][] hidden_weights = new double[][] {
    new double[] {0.0}
};
double[] output_weights = new double[] {0.0};

期待される出力:
double[][] expected = new double[][] {
    new double[] {0.0, 0.0},
    new double[] {-0.125, -0.25}
};

解説

a = σ(0) = 0.5、y = σ(0) = 0.5。delta_out = 2 × (0.5 - 1) × 0.25 = -0.25。出力の行:[-0.25 × 0.5, -0.25] = [-0.125, -0.25]。delta_1 = -0.25 × 0 × 0.25 = 0 なので、隠れ層の行は [0, 0] です。出力の重みが 0 だと勾配が伝わりません。

例 2
入力:
inputs = [1.0, 0.0]
target = 0.0
output_bias = -1.0
hidden_biases = [0.0, 0.0]
hidden_weights = [
    [0.0, 1.0],
    [0.0, -1.0]
]
output_weights = [1.0, 1.0]

期待される出力:
expected = [
    [0.0625, 0.0, 0.0625],
    [0.0625, 0.0, 0.0625],
    [0.125, 0.125, 0.25]
]
入力:
std::vector<double> inputs = {1.0, 0.0};
double target = 0.0;
double output_bias = -1.0;
std::vector<double> hidden_biases = {0.0, 0.0};
std::vector<std::vector<double>> hidden_weights = {
    {0.0, 1.0},
    {0.0, -1.0}
};
std::vector<double> output_weights = {1.0, 1.0};

期待される出力:
std::vector<std::vector<double>> expected = {
    {0.0625, 0.0, 0.0625},
    {0.0625, 0.0, 0.0625},
    {0.125, 0.125, 0.25}
};
入力:
double[] inputs = new double[] {1.0, 0.0};
double target = 0.0;
double output_bias = -1.0;
double[] hidden_biases = new double[] {0.0, 0.0};
double[][] hidden_weights = new double[][] {
    new double[] {0.0, 1.0},
    new double[] {0.0, -1.0}
};
double[] output_weights = new double[] {1.0, 1.0};

期待される出力:
double[][] expected = new double[][] {
    new double[] {0.0625, 0.0, 0.0625},
    new double[] {0.0625, 0.0, 0.0625},
    new double[] {0.125, 0.125, 0.25}
};

解説

2つの隠れ値はどちらも σ(0) = 0.5 なので、y = σ(0.5 + 0.5 - 1) = 0.5、delta_out = 2 × 0.5 × 0.25 = 0.25。出力の行:[0.125, 0.125, 0.25]。各 delta_j = 0.25 × 1 × 0.25 = 0.0625 となり、隠れ層の行は [0.0625, 0, 0.0625] です(2番目の入力は 0)。

解き方のヒント

まずは自分で考えてから、ヒントを 1 つずつ開いてみましょう。

ヒント 1

まず output neuron から逆向きにたどり、その signal を再利用して各 hidden neuron の寄与を計算する。

ヒント 2

output layer 用の delta が1つ、hidden neuron ごとの delta が1つ必要で、どちらも sigmoid の導関数に基づく。

ヒント 3

エラーを各 hidden neuron に戻すとき、その neuron 固有の output weight を使うことに注意。

目安の計算量

時間 O(hn)、追加メモリ O(hn)

参考資料

この課題はCodeUtility用に調整されています。上記の説明と制約に従ってください。

他の人の解答から学ぶ

コミュニティの解答

まだ公開された解答がありません。この課題を解いて最初の解答を共有しましょう。