我用C++编写了我的第一个一维分类神经网络,其逻辑如下:
- 如果输入 <= 1:f(x) = 1
- 如果输入 > 1:f(x) = -1
起初我写的非常草率,但现在我知道它能工作后,我修改了代码,使其对输入数量更加通用,这样我就可以轻松更改[x]的大小。然而,新代码的逻辑不正确;它给出的答案完全错误,并且所有输入的权重相似。请注意,我的变量名很傻,变量“outputs”实际上是训练集。
这是程序的最终输出:
Input: 1 ; Class: 1 ; Eval = -1Weight for node 1: -2Input: 2 ; Class: -1 ; Eval = -1Weight for node 2: -2Input: 3 ; Class: -1 ; Eval = -1Weight for node 3: -1
“Class”是它应该有的值,而“Eval”是实际的值。请注意,第一个输入与其训练元素不匹配。
原始代码:
#include <iostream>using namespace std;double weights[2] = {0.0};double classify(double);int main() { double inputs[2] = {1.0, 2.0}; double outputs[2] = {1.0, -1.0}; int index = 0; bool trained = false; while(!trained) { trained = true; cout << inputs[0] << " , " << outputs[0] << " eval = " << classify(inputs[0]) << endl; cout << inputs[1] << " , " << outputs[1] << " eval = " << classify(inputs[1]) << endl; cout << "Weights = " << weights[0] << " , " << weights[1] << endl << endl; index = 0; while(index < 2) { double input = inputs[index]; double output = outputs[index]; double dClass = classify(input); if (dClass != output) { weights[0] += output * input; weights[1] += output * 1.0; trained = false; } index++; } } return 0;}double classify(double input){double products[2];double sum = 0;double threshhold;// Sumation of inputsproducts[0] = input * weights[0];products[1] = 1.0 * weights[1];sum = products[0] + products[1];// Threshold functionif (sum >= 0.0) threshhold = 1.0;else threshhold = -1.0;return threshhold;}
修改后的代码:
#include <iostream>#define NODES 3using namespace std;double weights[NODES] = {0.0};double classify(double);int main() { double inputs[NODES] = {1.0, 2.0, 3.0}; double outputs[NODES] = {1.0, -1.0, -1.0}; int index = 0; bool trained = false; index = 0; // 当分类不正确时 while(!trained) { trained = true; while(index < NODES) { double input = inputs[index]; // 输入节点 double output = outputs[index]; // 期望的类别 double dClass = classify(input); // 计算的类别 // 如果计算的类别 != 期望的类别: // 调整权重 if (dClass != output) { for(int i = 0; i < NODES - 1; i++) weights[i] += output * input; // 偏置权重 weights[NODES-1] += output * 1.0; trained = false; } index++; // 调试 for(int i = 0; i < NODES; i++){ cout << "Input: " << inputs[i] << " ; Class: " << outputs[i] << " ; Eval = " << dClass << endl; cout << "Weight for node " << i + 1 << ": " << weights[i] << endl; } cout << endl; } } return 0;}double classify(double input){ double products[NODES]; double sum = 0; double threshhold; // 将权重附加到节点 for(int i = 0; i < NODES - 1; i++) products[i] = input * weights[i]; // 带偏置的最后一个节点 products[NODES-1] = 1.0 * weights[NODES-1]; // 输入的总和 for(int i = 0; i < NODES; i++) sum += products[i]; // 阈值函数 if (sum >= 0.0) threshhold = 1.0; else threshhold = -1.0; return threshhold;}
如果你能回答这个问题,那么我有一个后续问题,如果你愿意给我一些建议(虽然这更像是一个对话性的问题)。我刚开始实现神经网络,我很好奇你们认为对于一个平均的反向传播、固定拓扑的ANN,以及一个动态的ANN(可能用于神经进化),最好的数据结构是什么?有没有一个好的神经网络实现惯例可以遵循?
回答:
看来我们遇到了一个谜团。在我们深入研究之前,尝试对main()
进行这个小的更改(只是更改它打印的内容),然后告诉我们你得到了什么。不要只是说它给出了错误的答案或没有达到期望的结果,告诉我们它实际产生了什么。
已删除过时的代码
编辑:
你有两个问题。首先,你对这段代码的作用有点困惑;节点的数量和训练集中的元素的数量在根本上是独立的,但你把它们当成是相同的,并且在迭代哪个时感到困惑。其次,你在内循环结束时忘记重置index
。将这段代码:
// 调试 for(int i = 0; i < NODES; i++){ cout << "Input: " << inputs[i] << " ; Class: " << outputs[i] << " ; Eval = " << dClass << endl; cout << "Weight for node " << i + 1 << ": " << weights[i] << endl; } cout << endl;}
更改为这段代码:
// 调试 cout << "Input: " << input << " ; Class: " << output << " ; Eval = " << dClass << endl; cout << "Weights:"; for(int i = 0; i < NODES; i++){ cout << " " << weights[i]; } cout << endl;}cout << endl;index = 0;
现在它能工作了。