誤差逆伝播法は、出力から入力へ向かって層ごとに連鎖律を適用します。ネットワークは 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)²
勾配:
- delta_out = 2 × (y - target) × y × (1 - y)
- 出力層:dL/doutput_weights[j] = delta_out × a_j、dL/doutput_bias = delta_out
- delta_j = delta_out × output_weights[j] × a_j × (1 - a_j)
- 隠れ層: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
例
入力:
inputs = [1.0]
target = 1.0
output_bias = 0.0
hidden_biases = [0.0]
hidden_weights = [
[0.0]
]
output_weights = [0.0]
期待される出力:
[
[0.0, 0.0],
[-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 だと勾配が伝わりません。
入力:
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]
期待される出力:
[
[0.0625, 0.0, 0.0625],
[0.0625, 0.0, 0.0625],
[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 未実行入力:
inputs = [1.0] target = 1.0 output_bias = 0.0 hidden_biases = [0.0] hidden_weights = [ [0.0] ] output_weights = [0.0]期待される出力:[ [0.0, 0.0], [-0.125, -0.25] ]あなたの出力 -
例 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]期待される出力:[ [0.0625, 0.0, 0.0625], [0.0625, 0.0, 0.0625], [0.125, 0.125, 0.25] ]あなたの出力
提出時に非公開テスト4件も実行されます。
C++オンラインコンパイラ&デバッガー
サーバーモードのGDBでブレークポイント、変数確認、ステップ実行を使ってC++をデバッグできます。
C/C++ を学んで練習する
実行できるレッスンの学習パスに沿って学び、コーディングチャレンジで力を試しましょう。
💻 このC++オンライン実行ツールについて
CodeUtility C++ Executor を使えば、ブラウザ上で直接C++コードを書いて実行できます - インストールやコンパイラ設定は一切不要です。安全なサンドボックスで動作し、 C++11、C++14、C++17から最新バージョンまでの実際のC++標準に対応しています。
このツールはクラウド上で動作する本物のC++コンパイラでコードをコンパイル・実行し、 バージョン間で正確かつ一貫した挙動を保証します。変数、関数、ループ、条件分岐、 オブジェクト指向といったC++の基本概念を自由に試せます。
面接の準備、モダンC++の学習、アルゴリズムのロジック検証など、どんな用途でも、 CodeUtility C++ Executor は、どのデバイスからでもすぐにコードを実行できるシンプルかつ強力な環境を提供します。
同じ実行環境で、複数ファイル対応エディター、分離された実行ターミナル、ランタイム別ライブラリ、永続ワークスペース、共有、リアルタイム共同作業を利用できます。
この実行環境の使い方
ランタイムを選択し、ファイルを開くか作成してコードを記述し、[実行]を選択します。出力はターミナルに表示されます。サインインしたユーザーは、ワークスペースにファイルを保存し、ライブラリをインストールして、共有を通じて共同作業できます。
- バージョンを選択して現在のファイルを編集するか、ワークスペース内の別のファイルを開きます。
- コードを実行し、求められた場合はターミナルに入力して、保存された実行履歴を確認します。
- 複数のコードスニペットが必要な作業では、ライブラリ、ワークスペースツール、共有、チャットを利用します。
💡 上で試せるC++の基本とサンプル
1. 変数と定数の宣言
C++では、各変数の型を宣言する必要があります。constを使うと、初期化後に変更できない読み取り専用の値を定義できます。
int age = 30;
double pi = 3.14159;
char grade = 'A';
std::string name = "Alice";
bool isActive = true;
// 定数
const int MAX_USERS = 100;
const std::string COMPANY = "CodeUtility";
// const を変更しようとするとコンパイル時エラーになります
// MAX_USERS = 200; // ❌ エラー
2. 条件分岐(if / switch)
分岐にはif、else if、elseを使います。複数の値を扱う場合はswitchを使います。
int x = 2;
if (x == 1) {
std::cout << "1\n";
} else if (x == 2) {
std::cout << "2\n";
} else {
std::cout << "その他\n";
}
// switch文
switch (x) {
case 1:
std::cout << "1\n";
break;
case 2:
std::cout << "2\n";
break;
default:
std::cout << "その他\n";
}
3. ループ
for、while、do-whileでコードブロックを繰り返します。
for (int i = 0; i < 3; i++) {
std::cout << i << "\n";
}
int n = 3;
while (n > 0) {
std::cout << n << "\n";
n--;
}
4. 配列
配列は同じ型の要素を複数格納します。
int numbers[3] = {10, 20, 30};
std::cout << numbers[1] << "\n";
5. 配列/ベクターの操作
動的配列にはstd::vectorを使います。
#include <vector>
std::vector nums = {1, 2, 3};
nums.push_back(4);
nums.pop_back();
for (int n : nums) {
std::cout << n << " ";
}
6. コンソール入出力
入力にはstd::cin、出力にはstd::coutを使います。
std::string name;
std::cout << "あなたの名前を入力してください: ";
std::cin >> name;
std::cout << "こんにちは、" << name << "\n";
7. 関数
関数は再利用可能な処理をまとめます。引数と戻り値の型を指定します。
int add(int a, int b) {
return a + b;
}
std::cout << add(3, 4);
8. マップ
std::map は辞書のようにキーと値のペアを格納します。
#include <map>
std::map ages;
ages["Alice"] = 30;
std::cout << ages["Alice"];
9. 例外処理
try と catch を使って実行時エラーを処理します。
try {
throw std::runtime_error("エラーが発生しました");
} catch (const std::exception& e) {
std::cout << e.what();
}
10. ファイル入出力
fstream を使ってファイルの読み書きを行います。
#include <fstream>
std::ofstream out("file.txt");
out << "こんにちは、ファイル";
out.close();
std::ifstream in("file.txt");
std::string line;
getline(in, line);
std::cout << line;
in.close();
11. 文字列操作
C++の文字列は length()、substr()、find() といったメソッドをサポートしています。
std::string text = "Hello World";
std::cout << text.length();
std::cout << text.substr(0, 5);
std::cout << text.find("World");
12. クラスとオブジェクト
C++はクラスを使ったオブジェクト指向プログラミングをサポートしています。
class Person {
public:
std::string name;
Person(std::string n) : name(n) {}
void greet() { std::cout << "こんにちは、私は " << name; }
};
Person p("Alice");
p.greet();
13. ポインタ
ポインタは別の変数のメモリアドレスを保持します。アドレスを取得するには &、
参照外し(そのアドレスの値にアクセス)には * を使います。
int x = 10;
int* ptr = &x;
std::cout << "x の値: " << x << "\n";
std::cout << "x のアドレス: " << ptr << "\n";
std::cout << "ポインタ経由の値: " << *ptr << "\n";
// ポインタ経由で x を変更
*ptr = 20;
std::cout << "更新後の x: " << x << "\n";
🐞 %{language}コードをオンラインでデバッグする方法
オンライン%{language}デバッガーなら、コンパイラやIDEをインストールせずに実行時エラーやロジックエラーを調査できます。サーバーモードはデバッグ情報付きでコンパイルし、GDBで実行します。
- 行番号の横にブレークポイントを設定します。
- Debugを選択してコンパイルし、最初のブレークポイントで停止します。
- 現在行、コールスタック、変数を確認します。
- Continue、Step Over、Step Into、Step Outで実行を制御します。
- 終了するときはStopを選択します。
再現可能な小さなコードから始め、想定外の動作が起きる直前にブレークポイントを置きましょう。