問題
ニューロンを学習させるには、各重みが誤差にどう影響するかを知る必要があります。1つの学習例について:
- z = inputs · weights + bias
- y = sigmoid(z) = 1 / (1 + e^(-z))
- 損失 L = (y - target)²
連鎖律により、delta = dL/dz = 2 × (y - target) × y × (1 - y) とすると:
- dL/dw_i = delta × x_i
- dL/dbias = delta
neuron_gradients(inputs, weights, bias, target) を実装してください。
入力
inputs, weights: 同じ長さ n のリスト。
bias: ニューロンのバイアス。
target: この例の正しい出力(0 から 1)。
出力
n + 1 個の数のリストを返してください。各重みの勾配を順番に並べ、最後にバイアスの勾配を置きます。
制約
1 ≤ n ≤ 100
-10 ≤ 各入力、重み、バイアス ≤ 10
0 ≤ target ≤ 1
例
入力:
bias = 0.0
inputs = [1.0, 2.0]
target = 1.0
weights = [0.5, -0.25]
期待される出力:
expected = [-0.25, -0.5, -0.25]
入力:
double bias = 0.0;
std::vector<double> inputs = {1.0, 2.0};
double target = 1.0;
std::vector<double> weights = {0.5, -0.25};
期待される出力:
std::vector<double> expected = {-0.25, -0.5, -0.25};
入力:
double bias = 0.0;
double[] inputs = new double[] {1.0, 2.0};
double target = 1.0;
double[] weights = new double[] {0.5, -0.25};
期待される出力:
double[] expected = new double[] {-0.25, -0.5, -0.25};
解説
z = 1×0.5 + 2×(-0.25) = 0 なので y = 0.5。delta = 2 × (0.5 - 1) × 0.5 × 0.5 = -0.25。勾配:[-0.25×1, -0.25×2, -0.25] = [-0.25, -0.5, -0.25]。
入力:
bias = 0.0
inputs = [3.0]
target = 0.0
weights = [0.0]
期待される出力:
expected = [0.75, 0.25]
入力:
double bias = 0.0;
std::vector<double> inputs = {3.0};
double target = 0.0;
std::vector<double> weights = {0.0};
期待される出力:
std::vector<double> expected = {0.75, 0.25};
入力:
double bias = 0.0;
double[] inputs = new double[] {3.0};
double target = 0.0;
double[] weights = new double[] {0.0};
期待される出力:
double[] expected = new double[] {0.75, 0.25};
解説
z = 0、y = 0.5。delta = 2 × (0.5 - 0) × 0.5 × 0.5 = 0.25 なので、勾配は [0.25×3, 0.25] = [0.75, 0.25]。勾配が正なら、その重みは下げるべきです。
解き方のヒント
まずは自分で考えてから、ヒントを 1 つずつ開いてみましょう。
ヒント 1
まず neuron の sigmoid 出力と、pre-activation 値に対する loss の導関数を求める。
ヒント 2
各 weight の gradient は同じ delta にその入力を掛けたもの、bias は delta そのものになる。
ヒント 3
weight の gradient は input の順に並べ、最後に bias の gradient を付ける。
目安の計算量
時間 O(n)、追加メモリ O(n)
参考資料
この課題はCodeUtility用に調整されています。上記の説明と制約に従ってください。