如何实现具有可配置数量和输入和输出动态行为的前馈神经网络?
我正在尝试将神经网络添加到我正在处理的游戏中的实体中。但是,对于我添加的每个实体类型,我必须创建一个具有不同数量的输入和输出的新神经网络,然后硬编码输入的设置方式以及输出如何用于指导行为。
我想找到一种方法来动态设置所有这些,所以我不必为每个实体类型重写一个新的神经网络。
当我使用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]);
}
}
}
我对实现这个想法的其他方式感到好奇,如果有任何资源可以解决这类问题。任何帮助将不胜感激。
答案 0 :(得分:0)
我很久以前写过这样的东西,所以很遗憾我没有源代码,但我记得我将网络结构定义为一个传递给创建网络的函数的数组。数组的每个元素都是一个描述网络层中神经元数量的int,因此[2,3,2]会创建一个神经网络,其中包含2个输入神经元,3个隐藏层和2个输出神经元。通过链接相邻层中的每个神经元自动创建突触。它非常简单,因此输入/输出层的设置/获取值是通过类似
的函数调用完成的double getValue(int layer, int neuron);
对不起,这有点模糊,但这是我所能记住的。