0

入力と出力の構成可能な数と動的な動作を備えたフィードフォワードニューラルネットワークをどのように実装しますか?

作業中のゲームのエンティティにニューラルネットワークを追加しようとしています。ただし、追加するエンティティタイプごとに、入力と出力の数が異なる新しいニューラルネットワークを作成し、入力の設定方法と出力を使用して動作を指示する方法をハードコーディングする必要があります。

これらすべてを動的に設定する方法を見つけたいので、エンティティタイプごとに新しいニューラルネットを書き直す必要はありません。

私はC++を使用しているので、現在、入力コンテナーと出力コンテナーとしてdoubleのベクトルがあります。現在、私のNNアルゴリズムは、レイヤー内のすべての要素(入力「レイヤー」を含む)を反復処理し、情報を次のレイヤーに渡します。これは今のところうまくいくと思います(ただし、提案は受け付けています)。しかし、私の本当の問題は、入力/出力の数、またはエンティティが持つことができる感覚/動作のタイプを制限することなく、エンティティのタイプごとに異なる動作をどのように行うかです。

例として、他のクリーチャーを見て、食べ物の匂いを嗅ぎ、攻撃として噛み、地面に沿って移動できるクリーチャーをゲームに追加したいとします。それぞれの目は、匂いの感覚とともに入力になります。噛むことは、xとyの動きとともに出力になります。入力値を計算し、ニューラルネットの出力値から意味を抽出する方法が必要です。

ここで、他の生き物の匂いを嗅ぎ、それ自体からの方向を特定し、棘を撃ち、空中に浮かぶことができる生き物も追加したい場合は、異なる数の入力と出力の計算が必要になります(入力:匂い、場所、出力:シュート、x、y、zの動き)。

各エンティティタイプに独自のニューラルネット構造を持たせながら、AIシステムが個々のネットワークを処理および反復するときに機能する全体的な標準インターフェイスを持たせたいと思います。より具体的には、ゲーム感覚から入力への変換、および出力からゲーム動作への変換を処理する場合。

追加したクリーチャーからの創発的な振る舞いが欲しいので、「正しい」出力がどうなるかわかりません。このため、私は単純な遺伝的アルゴリズムを使用して体重の進化を制御しています。

私は自分の問題に関する多くの情報を見つけることができなかったので、これまでに思いついた唯一のアイデアは、各エンティティの感覚と動作を関数ポインターのベクトルとして実装することです。各関数は特定の入力に対応します。出力。これにより、各エンティティの動作をカスタマイズし、AI用の単一のシステムを維持できますが、これが私が望むことを達成するための最も効率的な方法であるかどうかはわかりません。

プロセス関数は、LearningSystemクラスのすべての作業を実行します。

void LearningSystem::process(int const last_frame_time) {
    std::set<unsigned int> const& learning_list = eManager->getAllEntitiesPossessingComponent(ComponentType::intelligence);

    vector<double> outputs, inputs;
    for (auto entity : learning_list) {
        Intelligence& intel = eManager->getComponent<Intelligence>(entity, ComponentType::intelligence);
        Sensors& sensor = eManager->getComponent<Sensors>(entity, ComponentType::sensors);
        Behavior& behavior = eManager->getComponent<Behavior>(entity, ComponentType::behavior);

        // calculate each input value
        for (unsigned int i = 0; i < sensor.sensor_list.size(); ++i) {
            sensor.triggers[i](sensor.sensor_list[i]);
        }

        // retrieve the inputs from the sensors...
        inputs = sensor.sensor_list;
        // ...and add the bias
        inputs.push_back(bias);

        // for each layer
        for (auto i : intel.vecLayers) {
            // clear the internal outputs
            outputs.clear();

            // for each neuron
            for (auto j : i.vecNeurons) {
                // reset the neuron value
                double neuronValue = 0.0;

                // for each weight/input pair, sum the weights * inputs
                for (auto k = j.vecWeights.begin(), in = inputs.begin(); k != j.vecWeights.end(); ++k, ++in) {
                    neuronValue += (*k) * (*in);
                }

                // store the internal outputs for use by the next layer
                outputs.push_back(sigmoid(neuronValue));
            }

            // assign the inputs for the next layer...
            inputs = outputs;
            // ...and add the bias
            inputs.push_back(bias);
        }

        behavior.values = outputs;

        // calculate actions based on output values
        for (unsigned int i = 0; i < behavior.values.size(); ++i) {
            behavior.actions[i](behavior.values[i]);
        }
    }
}

このアイデアを実装する他の方法について、そしてこの種の問題に対処するリソースがあるかどうかについて興味があります。どんな助けでも大歓迎です。

4

1 に答える 1

0

私はかなり前にこのようなことを書いたので、残念ながらソースを持っていませんが、ネットワークを作成する関数に渡される配列としてネットワークの構造を定義したことを覚えています。配列の各要素は、ネットワーク層のニューロン数を表す int であったため、たとえば [2,3,2] は、2 つの入力ニューロン、3 つの隠れ層、および 2 つの出力ニューロンを持つニューラル ネットワークを作成します。シナプスは、隣接する層のすべてのニューロンをリンクすることによって自動的に作成されました。非常に単純だったので、入力/出力レイヤーからの値の設定/取得は、このような関数呼び出しで行われました

double getValue(int layer, int neuron);

曖昧で申し訳ありませんが、私が覚えているのはこれだけです。

于 2012-06-08T13:42:35.360 に答える