2

データを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;
              }
            }
          }
        }
      }
    }

誰かが私が間違っていることを教えてもらえますか、または私が間違いを探す必要がある場所についてアドバイスをくれますか?私はすべての重要なことを話したと思います。どうか、私の悪い英語を許してください。

4

1 に答える 1

2

ガウス分類器(BackpropNNなど)は、連続したエグザンプラセットのみをスプライン化します。

あなたのネットは小さなセットの標本で学習するので、小さなセットには不連続性がないと思います。

ここで例えば。例のトレーニングセットの不連続性です(入力ベクトル--->出力ベクトル):

[0,1,0,1,1,0,1,0] ---> [0,1,0]
[0,1,0,1,1,0,1,0] ---> [1,1,0]

アルゴはこれを分類(スプライン)できません。特定の入力ベクトルの出力ベクトルは一意(連続)である必要があります。

エグザンプラをランダムに生成している場合、これは、小さなセットが常に機能しているように見える理由を説明します-不連続性を生成する可能性は低いです。セットが大きいほど、この問題が保証されます。

したがって、これが実際に問題である場合は、問題のエグザンプラをスキャンして削除するだけです。伝達関数は実際にはノーマライザーであるため、異なるように見える実際の入力ベクトルはIDに正規化される可能性があることに注意してください。

それでも極大値または極小値に固執している場合は、イプシロン(学習率)を変更してみてください。.5にハードコーディングされています。他の値を試してください。

最後の努力として、シグモイド伝達関数をステップ関数に置き換えることもお勧めします。シグモイドは、このデジタル関数の生物学的類似物にすぎません。デジタル転送を直接使用して、この変換を削除します(ステップ関数)。

アナログ伝達関数とデジタル伝達関数

シグモイドがバックプロパゲーションで使用される理由は、ヒントンの元の研究が認知科学からのものであり、ニューロンの伝達関数がシグモイドであるためです。これは、デジタル関数に最も近い自然なアナログです。

于 2012-04-06T17:00:14.513 に答える