データを3つのクラスに分類する多層パーセプトロンをプログラムする学校のプロジェクトがあります。http://home.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.htmlからバックプロパゲーションアルゴリズムを実装しました。アルゴリズムがこの説明されたステップを実際に満たし、満たされているかどうかを(バックプロパゲーションの各ステップを手動で計算することによって)チェックしました。
分類には、ワンホットコードを使用しており、2つの値を持つベクトルと3つの出力ニューロン(それぞれが個々のクラス用)で構成される入力があります。各エポックの後、入力データをシャッフルします。分類にはシグモイド関数を使用しています。ソフトマックスも実装しようとしましたが、微分ソフトマックスがどのように見えるかわかりません。重みの調整に微分ソフトマックスが必要ですか?ネットワークが入力を正常に分類したかどうかを確認するために、出力ニューロンからの最大出力を持つ出力ニューロンの位置が、1に等しい現在の入力ワンホットコードベクトルからの位置に対応するかどうかを比較しています。
しかし、私の実装はこのニューラルネットワークをトレーニングしていません。私はこれに取り組んでいて、数日間デバッグし、インターネットを調べて自分が間違っていることを見つけていますが、答えが見つかりません。どこを間違えているのか本当にわかりません。私のニューラルネットワークは、10個の入力があると正常にトレーニングされますが、100個、200個、400個、800個の入力があると、分類された入力が半分になると循環を開始します。私が言ったように、私のバックプロパゲーションアルゴリズムは良いです。入力ファイルを含むVisualStudio2010のC++プロジェクト全体は次のとおりです:http ://www.st.fmph.uniba.sk/~vajda10/mlp.zip
構造:
struct input {
vector<double> x;
vector<double> cls;
};
struct neuron {
double output;
double error;
neuron(double o, double e): output(o), error(e) { };
};
グローバル変数:
double alpha = 0.5;
vector<vector<input>> data;
vector<vector<neuron>> hiddenNeurons;
vector<neuron> outputNeurons;
vector<vector<vector<double>>> weights;
これがバックプロパゲーションアルゴリズムの私のコードです:
for (int b = 0; b < data[0].size(); b++) {
// calculate output of hidden neurons
for (int i = 0; i < hiddenNeurons.size(); i++) {
for (int j = 0; j < hiddenNeurons[i].size(); j++) {
double activation = neuronActivation(0, b, i, j);
hiddenNeurons[i][j].output = sigmoid(activation);
}
}
double partError = 0;
// calculate output and errors on output neurons
for (int k = 0; k < outputNeurons.size(); k++) {
double activation = neuronActivation(0, b, hiddenNeurons.size(), k);
outputNeurons[k].output = sigmoid(activation);
outputNeurons[k].error = data[0][b].cls[k] - outputNeurons[k].output;
partError += pow(outputNeurons[k].error, 2);
}
error += sqrt(partError)/outputNeurons.size();
// if classification is wrong
if (data[0][b].cls[maxOutputIndex(outputNeurons)] != 1) {
wrongClass++;
// error backpropagation
for (int i = hiddenNeurons.size()-1; i >= 0; i--) {
for (int j = 0; j < hiddenNeurons[i].size(); j++) {
hiddenNeurons[i][j].error = 0.0;
if (i < hiddenNeurons.size()-1) {
for (int k = 0; k < hiddenNeurons[i+1].size(); k++) {
hiddenNeurons[i][j].error += hiddenNeurons[i+1][k].error * weights[i+1][j][k];
}
}
else {
for (int k = 0; k < outputNeurons.size(); k++) {
hiddenNeurons[i][j].error += outputNeurons[k].error * weights[i+1][j][k];
}
}
}
}
// adjust weights
for (int i = 0; i < weights.size(); i++) {
int n;
if (i < weights.size()-1) {
n = hiddenNeurons[i].size();
}
else {
n = outputNeurons.size();
}
for (int k = 0; k < n; k++) {
for (int j = 0; j < weights[i].size(); j++) {
double y;
if (i == 0) {
y = data[0][b].x[j];
}
else {
y = hiddenNeurons[i-1][j].output;
}
if (i < weights.size()-1) {
weights[i][j][k] += alpha * hiddenNeurons[i][k].error * derivedSigmoid(hiddenNeurons[i][k].output) * y;
}
else {
weights[i][j][k] += alpha * outputNeurons[k].error * derivedSigmoid(outputNeurons[k].output) * y;
}
}
}
}
}
}
誰かが私が間違っていることを教えてもらえますか、または私が間違いを探す必要がある場所についてアドバイスをくれますか?私はすべての重要なことを話したと思います。どうか、私の悪い英語を許してください。