自分自身に神経ネットワークの基礎を教えて、私は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;
}
十分な反復が与えられると、出力は期待される出力(後方に渡される)と一致するはずです。それは決してしません。 – dicroce