2016-06-22 6 views
0

自分自身に神経ネットワークの基礎を教えて、私はXOR機能を学ぶ超最小ネットワークで亀裂を起こすことにしました。これは、2つの入力ニューロン、2つの隠れニューロンおよび出力ニューロンからなる。問題はそれが学ばないということです。私は私の後方に何か間違っていなければなりませんか?コードは極小であり、コンパイラをサポートしているC++ 11でコンパイルする必要があります。スーパーミニマルXORニューラルネットワークは学習できません...どうしましたか?

#include <stdio.h> 
#include <stdlib.h> 
#include <vector> 
#include <cmath> 
#include <algorithm> 
#include <numeric> 

using namespace std; 

float tanh_activate(float x) { return (exp(2*x)-1)/(exp(2*x)+1); } 
float tanh_gradient(float x) { return 1-x*x; } 

vector<float> input = { 0.0f, 0.0f }; 
vector<float> hiddenW = { 0.5f, 0.5f }; 
vector<float> hidden = { 0.0f, 0.0f }; 
vector<float> output = { 0.0f }; 

void forward() 
{ 
    float inputSum = accumulate(input.begin(), input.end(), 0.0f); 
    hidden[0] = tanh_activate(inputSum) * hiddenW[0]; 
    hidden[1] = tanh_activate(inputSum) * hiddenW[1]; 
    output[0] = tanh_activate(accumulate(hidden.begin(), hidden.end(), 0.0f)); 
} 

void backward(float answer) 
{ 
    auto outputError = answer - output[0]; 

    auto error = outputError * tanh_gradient(output[0]); 

    auto layerError = accumulate(hiddenW.begin(), 
            hiddenW.end(), 
            0.0f, 
            [error](float sum, float w) { 
             return sum + (w * error); 
            }); 

    // Calculating error for each activation in hidden layer but this is unused 
    // currently since their is only one hidden layer. 
    vector<float> layerE(hidden.size()); 

    transform(hidden.begin(), 
       hidden.end(), 
       layerE.begin(), 
       [layerError](float a) { 
        return tanh_gradient(a) * layerError; 
       }); 

    // update weights 
    for(auto wi = hiddenW.begin(), ai = hidden.begin(); wi != hiddenW.end(); ++wi, ++ai) 
     *wi += *ai * error; 
} 

int main(int argc, char* argv[]) 
{ 
    for(int i = 0; i < 10000000; ++i) 
    { 
     // pick two bits at random... 
     int i1 = ((random() % 2)==0)?1.0f:0.0f; 
     int i2 = ((random() % 2)==0)?1.0f:0.0f; 

     // load our input layer... 
     input[0] = (float)i1; 
     input[1] = (float)i2; 

     // compute network output... 
     forward(); 

     // we're teaching our network XOR 
     float expected = ((i1^i2)==0) ? 0.0f : 1.0f; 

     if(i % 10000 == 0) 
     { 
      printf("output = %f\n",output[0]); 
      printf("expected = %f\n",expected); 
     } 

     // backprop... 
     backward(expected); 
    } 

    return 0; 
} 
+0

十分な反復が与えられると、出力は期待される出力(後方に渡される)と一致するはずです。それは決してしません。 – dicroce

答えて

4

あなたのニューロンモデルにバイアス(しきい値、ベース信号)がありません。

https://en.wikipedia.org/wiki/Artificial_neuron#Basic_structure

また、おそらく、バックプロパゲーションでは、このような大幅な補正を行う必要はありません。

https://en.wikipedia.org/wiki/Backpropagation#Phase_2:_Weight_update

重量から勾配の比率(パーセンテージ)を引き。

比率が100%より低い可能性があります。

+0

すべてのレイヤにバイアスが必要ですか? – dicroce

+0

@dicroceこの場合、隠されたものだけです。 –

関連する問題