問題
誤差逆伝播法では、勾配に各活性化関数の導関数を掛けます。activation_derivative(name, values) を実装し、すべての値での導関数を返してください。
| name | 導関数 |
|---|---|
"sigmoid" | s × (1 - s)、ただし s = 1 / (1 + e^(-x)) |
"relu" | x > 0 なら 1、それ以外は 0 |
"leaky_relu" | x > 0 なら 1、それ以外は 0.01 |
"tanh" | 1 - tanh(x)² |
入力
name: "sigmoid"、"relu"、"leaky_relu"、"tanh" のいずれか。
values: 活性化関数への入力 x。
出力
各値での導関数を同じ順序で返してください。
制約
1 ≤ 長さ ≤ 1,000
-50 ≤ 各値 ≤ 50
例
入力:
name = "sigmoid"
values = [0.0, 2.0]
期待される出力:
expected = [0.25, 0.104994]
入力:
std::string name = "sigmoid";
std::vector<double> values = {0.0, 2.0};
期待される出力:
std::vector<double> expected = {0.25, 0.104994};
入力:
string name = "sigmoid";
double[] values = new double[] {0.0, 2.0};
期待される出力:
double[] expected = new double[] {0.25, 0.104994};
解説
0 では s = 0.5 で、傾きは 0.5 × 0.5 = 0.25。sigmoid が最も急な点です。2 では s ≈ 0.880797 で、傾きは約 0.104994 です。
入力:
name = "relu"
values = [-3.0, 0.0, 4.5]
期待される出力:
expected = [0.0, 0.0, 1.0]
入力:
std::string name = "relu";
std::vector<double> values = {-3.0, 0.0, 4.5};
期待される出力:
std::vector<double> expected = {0.0, 0.0, 1.0};
入力:
string name = "relu";
double[] values = new double[] {-3.0, 0.0, 4.5};
期待される出力:
double[] expected = new double[] {0.0, 0.0, 1.0};
解説
ReLU は x ≤ 0 で平ら(傾き 0)、x > 0 で傾き 1 なので、結果は [0, 0, 1] です。
解き方のヒント
まずは自分で考えてから、ヒントを 1 つずつ開いてみましょう。
ヒント 1
微分は活性化の種類で決まるので、各入力値ごとに関数別で処理します。
ヒント 2
sigmoid と tanh は、再計算せずに活性化出力やその標準的な値を使い回します。
ヒント 3
符号の境界に注意してください。ReLU は厳密に正かどうかを見て、leaky ReLU は非正でも小さな傾きを持ちます。
目安の計算量
時間 O(n)、追加メモリ O(n)
参考資料
この課題はCodeUtility用に調整されています。上記の説明と制約に従ってください。