0

如何实现具有可配置数量和输入和输出的动态行为的前馈神经网络?

我正在尝试将神经网络添加到我正在开发的游戏中的实体中。但是,对于我添加的每种实体类型,我必须创建一个具有不同数量的输入和输出的新神经网络,然后硬编码如何设置输入以及如何使用输出来指导行为。

我想找到一种方法来动态设置所有这些,这样我就不必为每种实体类型重写一个新的神经网络。

当我使用 C++ 时,我目前有一个双精度向量作为输入和输出容器。目前,我的 NN 算法遍历层中的每个元素(包括输入“层”)并将信息传递到下一层,我相信这现在可以正常工作(尽管我愿意接受建议)。然而,我真正的问题是如何在不限制输入/输出的数量或允许实体拥有的感觉/行为类型的情况下为每种类型的实体提供不同的行为。

例如,假设我想在游戏中添加一个生物,它可以看到其他生物、闻到食物气味、作为攻击进行咬伤以及沿地面移动。每只眼睛和嗅觉都是一种输入;咬是输出,以及 x 和 y 运动。我需要一种方法来计算输入值,并从神经网络中的输出值中提取含义。

现在,如果我还想添加一个可以闻其他生物的生物,从自身定位它们的方向,射出刺,并在空中漂浮,我需要不同数量的输入和输出计算(输入:气味,位置;输出:射击、x、y、z 运动)。

我希望每种实体类型都有自己的神经网络结构,但在处理和迭代每个单独的网络时,有一个供 AI 系统使用的整体标准接口。更具体地说,在处理游戏感觉到输入转换以及输出到游戏行为转换时。

我想要我添加的生物的紧急行为,所以我不知道“正确”的输出是什么。正因为如此,我使用一个简单的遗传算法来控制体重进化。

由于我无法找到有关我的问题的太多信息,所以到目前为止我想出的唯一想法是将每个实体的感觉和行为实现为函数指针的向量,每个函数对应于特定的输入或输出。虽然这允许我自定义每个实体的工作方式,并为 AI 保留一个系统,但我不确定这是否是实现我想要的最有效的方式。

process 函数完成 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 回答