以下是我在处理神经网络时如何组织设计和代码的。这里的代码(显然)是伪代码,大致遵循面向对象的约定。
从下往上,你将拥有你的神经元。每个神经元都需要能够保存它对传入连接的权重、一个用于保存传入连接数据的缓冲区以及一个其传出边的列表。每个神经元需要能够做三件事:
- 一种从传入边缘接受数据的方法
- 一种处理输入数据和权重以制定该神经元将发出的值的方法
- 一种在传出边缘发送此神经元值的方法
在代码方面,这转化为:
// Each neuron needs to keep track of this data
float in_data[]; // Values sent to this neuron
float weights[]; // The weights on each edge
float value; // The value this neuron will be sending out
Neuron out_edges[]; // Each Neuron that this neuron should send data to
// Each neuron should expose this functionality
void accept_data( float data ) {
in_data.append(data); // Add the data to the incoming data buffer
}
void process() {
value = /* result of combining weights and incoming data here */;
}
void send_value() {
foreach ( neuron in out_edges ) {
neuron.accept_data( value );
}
}
接下来,我发现最简单的方法是创建一个包含神经元列表的 Layer 类。 (很可能跳过这个类,只让你的 NeuralNetwork 保存一个神经元列表。我发现有一个 Layer 类在组织和调试方面更容易。)每一层都应该暴露以下能力:
- 使每个神经元“激发”
- 返回此层环绕的原始神经元数组。 (当您需要在神经网络的第一层手动填充输入数据时,这很有用。)
在代码方面,这转化为:
//Each layer needs to keep track of this data.
Neuron[] neurons;
//Each layer should expose this functionality.
void fire() {
foreach ( neuron in neurons ) {
float value = neuron.process();
neuron.send_value( value );
}
}
Neuron[] get_neurons() {
return neurons;
}
最后,您有一个 NeuralNetwork 类,其中包含层列表、使用初始数据设置第一层的方法、学习算法以及运行整个神经网络的方法。在我的实现中,我通过添加由单个假神经元组成的第四层来收集最终输出数据,该神经元只是缓冲所有传入数据并返回。
// Each neural network needs to keep track of this data.
Layer[] layers;
// Each neural network should expose this functionality
void initialize( float[] input_data ) {
foreach ( neuron in layers[0].get_neurons() ) {
// do setup work here
}
}
void learn() {
foreach ( layer in layers ) {
foreach ( neuron in layer ) {
/* compare the neuron's computer value to the value it
* should have generated and adjust the weights accordingly
*/
}
}
}
void run() {
foreach (layer in layers) {
layer.fire();
}
}
我建议从反向传播开始作为您的学习算法,因为它被认为是最容易实现的。当我研究这个时,我很难找到一个非常简单的算法解释,但我的笔记列表this site 是一个很好的参考。
我希望这足以让你开始!