私は最初の 1 次元分類ニューラル ネットワークを C++ で作成しました。ロジックは次のとおりです。
- 入力 <= 1 の場合: f(x) = 1
- 入力 > 1 の場合: f(x) = -1
最初は非常にずさんにしましたが、動作することがわかったので、コードを変更して入力数をより一般的にし、[x] のサイズを簡単に変更できるようにしました。ただし、新しいコードはロジックが正しくありません。すべての入力に対して完全に間違った答えと同様の重みが出てきます。* 私の変数名はばかげており、変数の「出力」は実際にはトレーニング セットであることに注意してください。
これは、プログラムからの最終的な出力です。
Input: 1 ; Class: 1 ; Eval = -1
Weight for node 1: -2
Input: 2 ; Class: -1 ; Eval = -1
Weight for node 2: -2
Input: 3 ; Class: -1 ; Eval = -1
Weight for node 3: -1
「クラス」はあるべき姿であり、「評価」は実際の姿です。最初の入力がトレーニング要素と一致しないことに注意してください。
元のコード:
#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 inputs
products[0] = input * weights[0];
products[1] = 1.0 * weights[1];
sum = products[0] + products[1];
// Threshold function
if (sum >= 0.0)
threshhold = 1.0;
else
threshhold = -1.0;
return threshhold;
}
変更されたコード:
#include <iostream>
#define NODES 3
using 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 the classifications are incrorrect
while(!trained) {
trained = true;
while(index < NODES) {
double input = inputs[index]; // Input nodes
double output = outputs[index]; // Desired class
double dClass = classify(input); // Calculated class
// If calculated class != desired class:
// adjust the weights
if (dClass != output) {
for(int i = 0; i < NODES - 1; i++)
weights[i] += output * input;
// Bias weight
weights[NODES-1] += output * 1.0;
trained = false;
}
index++;
// Debugging
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;
// Attach weights to nodes
for(int i = 0; i < NODES - 1; i++)
products[i] = input * weights[i];
// Last node with bias
products[NODES-1] = 1.0 * weights[NODES-1];
// Sumation of inputs
for(int i = 0; i < NODES; i++)
sum += products[i];
// Threshold function
if (sum >= 0.0)
threshhold = 1.0;
else
threshhold = -1.0;
return threshhold;
}
この質問に答えていただける場合は、ご意見をお聞かせいただければフォローアップいたします (会話の質問に近いですが)。私はニューラル ネットワークを実装するのが初めてで、平均的な逆伝播、固定トポロジ ANN、および動的 ANN (おそらく神経進化で使用される) の推定データ構造について皆さんが考えていることに興味があります。適切なニューラル ネットワークの実装規則はありますか?