誤差逆伝播法を用いたニューラルネットワーク

#include <iostream>
#include <vector>
#include <cmath>
#include <random>
#include <ctime>

// ニューラルネットワーククラス
class NeuralNetwork {
private:
    // ネットワークの構造
    int input_size;      // 入力層のサイズ(行動の数)
    int hidden_size;     // 隠れ層のニューロン数
    int output_size;     // 出力層のサイズ(評価値1つ)
    double learning_rate;// 学習率

    // 重みとバイアス
    std::vector<std::vector<double>> w1; // 入力層 -> 隠れ層の重み
    std::vector<double> b1;              // 隠れ層のバイアス
    std::vector<std::vector<double>> w2; // 隠れ層 -> 出力層の重み
    std::vector<double> b2;              // 出力層のバイアス

    // 中間結果の保存用
    std::vector<double> hidden_output;   // 隠れ層の出力
    std::vector<double> final_output;    // 最終出力

    // シグモイド活性化関数
    double sigmoid(double x) {
        return 1.0 / (1.0 + std::exp(-x));
    }

    // シグモイドの微分
    double sigmoid_derivative(double x) {
        double s = sigmoid(x);
        return s * (1.0 - s);
    }

    // 重みの初期化
    void initialize_weights() {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_real_distribution<> dis(-0.1, 0.1);

        // w1とb1の初期化
        w1.resize(hidden_size, std::vector<double>(input_size));
        b1.resize(hidden_size);
        for (int i = 0; i < hidden_size; i++) {
            for (int j = 0; j < input_size; j++) {
                w1[i][j] = dis(gen);
            }
            b1[i] = dis(gen);
        }

        // w2とb2の初期化
        w2.resize(output_size, std::vector<double>(hidden_size));
        b2.resize(output_size);
        for (int i = 0; i < output_size; i++) {
            for (int j = 0; j < hidden_size; j++) {
                w2[i][j] = dis(gen);
            }
            b2[i] = dis(gen);
        }
    }

public:
    NeuralNetwork(int in_size, int hid_size, int out_size, double lr = 0.01) 
        : input_size(in_size), hidden_size(hid_size), output_size(out_size), learning_rate(lr) {
        initialize_weights();
    }

    // 順伝播
    std::vector<double> forward(const std::vector<double>& input) {
        // 隠れ層の計算
        hidden_output.resize(hidden_size);
        for (int i = 0; i < hidden_size; i++) {
            double z = b1[i];
            for (int j = 0; j < input_size; j++) {
                z += w1[i][j] * input[j];
            }
            hidden_output[i] = sigmoid(z);
        }

        // 出力層の計算
        final_output.resize(output_size);
        for (int i = 0; i < output_size; i++) {
            double z = b2[i];
            for (int j = 0; j < hidden_size; j++) {
                z += w2[i][j] * hidden_output[j];
            }
            final_output[i] = sigmoid(z);
        }
        return final_output;
    }

    // 逆伝播
    void backward(const std::vector<double>& input, const std::vector<double>& target) {
        // 出力層の誤差
        std::vector<double> output_errors(output_size);
        for (int i = 0; i < output_size; i++) {
            output_errors[i] = (target[i] - final_output[i]) * sigmoid_derivative(final_output[i]);
        }

        // 隠れ層の誤差
        std::vector<double> hidden_errors(hidden_size);
        for (int i = 0; i < hidden_size; i++) {
            double error = 0.0;
            for (int j = 0; j < output_size; j++) {
                error += output_errors[j] * w2[j][i];
            }
            hidden_errors[i] = error * sigmoid_derivative(hidden_output[i]);
        }

        // 重みとバイアスの更新(出力層)
        for (int i = 0; i < output_size; i++) {
            for (int j = 0; j < hidden_size; j++) {
                w2[i][j] += learning_rate * output_errors[i] * hidden_output[j];
            }
            b2[i] += learning_rate * output_errors[i];
        }

        // 重みとバイアスの更新(隠れ層)
        for (int i = 0; i < hidden_size; i++) {
            for (int j = 0; j < input_size; j++) {
                w1[i][j] += learning_rate * hidden_errors[i] * input[j];
            }
            b1[i] += learning_rate * hidden_errors[i];
        }
    }

    // 学習メソッド
    void train(const std::vector<std::vector<double>>& inputs, 
               const std::vector<std::vector<double>>& targets, int epochs) {
        for (int epoch = 0; epoch < epochs; epoch++) {
            double total_error = 0.0;
            for (size_t i = 0; i < inputs.size(); i++) {
                std::vector<double> output = forward(inputs[i]);
                backward(inputs[i], targets[i]);
                total_error += std::pow(targets[i][0] - output[0], 2);
            }
            if (epoch % 100 == 0) {
                std::cout << "Epoch " << epoch << ", Error: " << total_error / inputs.size() << std::endl;
            }
        }
    }
};

// メイン関数
int main() {
    // ネットワークの設定: 入力5(行動の数), 隠れ層10, 出力1(評価値)
    NeuralNetwork nn(5, 10, 1, 0.1);

    // 学習データ(例: 5つ未満の行動の組み合わせ)
    std::vector<std::vector<double>> inputs = {
        {1, 0, 0, 0, 0}, // 行動Aのみ
        {0, 1, 0, 0, 0}, // 行動Bのみ
        {1, 1, 0, 0, 0}, // 行動A+B
        {0, 0, 1, 1, 0}  // 行動C+D
    };
    std::vector<std::vector<double>> targets = {
        {0.2}, // Aのみの評価値
        {0.3}, // Bのみの評価値
        {0.8}, // A+Bの評価値
        {0.6}  // C+Dの評価値
    };

    // 学習実行
    nn.train(inputs, targets, 1000);

    // テスト: 5つの行動の組み合わせを予測
    std::vector<double> test_input = {1, 1, 1, 1, 1}; // 全ての行動を選択
    std::vector<double> prediction = nn.forward(test_input);
    std::cout << "5つの行動の予測評価値: " << prediction[0] << std::endl;

    return 0;
}

・誤差逆伝播法を用いたニューラルネットワーク。
・5つの行動を扱い、2層構造(入力層、隠れ層、出力層)で評価値を予測。

1. モデルの構造

  • 入力層: 5つの行動を表す5次元のベクトル(例: [1, 0, 1, 0, 1]は行動A, C, Eを選択)。

  • 隠れ層: 10個のニューロン(調整可能)。

  • 出力層: 1つの評価値(0~1の範囲)。

  • 活性化関数: シグモイド関数を使用。

2. 学習データの準備

  • 5つ未満の行動の組み合わせ(例: 1つや2つの行動)とその評価値を用意。

  • 例では、{1, 0, 0, 0, 0}(行動Aのみ)や{1, 1, 0, 0, 0}(行動A+B)を学習データとして使用。

3. 学習プロセス

  • trainメソッドで、順伝播と逆伝播を繰り返し、重みを更新。

  • 100エポックごとに平均誤差を表示して学習状況を確認。

4. 予測

  • 学習後、5つの行動の組み合わせ(例: {1, 1, 1, 1, 1})を入力し、評価値を予測。


使い方と拡張

  1. 学習データの追加: 実際の用途に応じて、行動の組み合わせと評価値を増やす。

  2. 最適な組み合わせの探索: 全ての組み合わせ(2^5 = 32通り)を入力し、評価値が最も高いものを選ぶ。

  3. スケーラビリティ: 行動数が増える場合、隠れ層のニューロン数を調整。

いいなと思ったら応援しよう!

コメント

ログイン または 会員登録 するとコメントできます。
誤差逆伝播法を用いたニューラルネットワーク|古井和雄
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1