#include "nnfw/nnfw.h" #include "nnfw/biasedcluster.h" #include "nnfw/dotlinker.h" #include "nnfw/liboutputfunctions.h" #include "nnfw/backpropagationalgo.h" #include "nnfw/random.h" using namespace nnfw; //-------- Neural Network Structures BiasedCluster *in, *hid, *out; DotLinker *l1, *l2; BaseNeuralNet* net; int main( int , char* ) { Random::setSeed( time(0) ); net = new BaseNeuralNet(); // --- Create the Layers of network in = new BiasedCluster( 2 ); in->setFunction( SigmoidFunction( 1.0f ) ); hid = new BiasedCluster( 4 ); hid->setFunction( SigmoidFunction( 1.0f ) ); out = new BiasedCluster( 1 ); out->setFunction( SigmoidFunction( 1.0f ) ); // --- Create the Matrix connection among layers l1 = new DotLinker( in, hid ); l2 = new DotLinker( hid, out ); // --- Add all in the BaseNeuralNet class net->addCluster( in, true ); net->addCluster( hid ); net->addCluster( out, false, true ); net->addLinker( l1 ); net->addLinker( l2 ); // --- Specify the order on which layers and matrix weight will be updated UpdatableVec ord; net->setOrder( ord << in << l1 << hid << l2 << out ); // --- Randomize the parameters of network (biases of neuron's layers and weight of matrix linkers) net->randomize( -1.0, 1.0 );
UpdatableVec bp_ord;
bp_ord << out << l2 << hid << l1 << in;
BackPropagationAlgo* bp = new BackPropagationAlgo( net, bp_ord, 0.2 );
cout.precision( 10 );
// --- The learning Set
PatternSet learningSet(4);
// --- Input <0,0> -> Output <0>
learningSet[0].setInputsOf( in, RealVec() << 0.0 << 0.0 );
learningSet[0].setOutputsOf( out, RealVec() << 0.0 );
// --- Input <0,1> -> Output <1>
learningSet[1].setInputsOf( in, RealVec() << 0.0 << 1.0 );
learningSet[1].setOutputsOf( out, RealVec() << 1.0 );
// --- Input <1,0> -> Output <1>
learningSet[2].setInputsOf( in, RealVec() << 1.0 << 0.0 );
learningSet[2].setOutputsOf( out, RealVec() << 1.0 );
// --- Input <1,1> -> Output <0>
learningSet[3].setInputsOf( in, RealVec() << 1.0 << 1.0 );
learningSet[3].setOutputsOf( out, RealVec() << 0.0 );
// --- Main loop for learning the network
int i;
for( i = 0; i<50000; i++ ) {
bp->learnOnSet( learningSet );
// --- each 1000 iteration print out the error
if ( i%1000 == 0 ) {
cout << "Error: " << bp->calculateMSEOnSet( learningSet ) << endl;
}
}
cout << "Iterations: " << i << "\tError:" << bp->calculateMSEOnSet( learningSet ) << endl;
// --- compare the outputs with learning set
for( int i = 0; i<4; i++ ) {
in->inputs() = learningSet[i].inputsOf( in );
net->step();
Real out1 = out->getOutput(0);
Real out2 = learningSet[i].outputsOf( out )[0];
cout << "Target: " << out2 << "\tRete: " << out1 << endl;
}
return 0;
}
<nnfw version="1.0"> <neuralnet> <!-- The Input Layer of the Network --> <cluster name="Input" type="BiasedCluster" size="2" > <outfunction type="SigmoidFunction"> <lambda>1.0</lambda> </outfunction> <!-- Randomize the values of biases in the range specified --> <randomize min="-1.0" max="+1.0" /> </cluster> <!-- The Hidden Layer of the Network --> <cluster name="Hidden" type="BiasedCluster" size="4"> <outfunction type="SigmoidFunction"> <lambda>1.0</lambda> </outfunction> <!-- Randomize the values of biases in the range specified --> <randomize min="-1.0" max="+1.0" /> </cluster> <!-- The Output Layer of the Network --> <cluster name="Output" type="BiasedCluster" size="1" > <outfunction type="SigmoidFunction"> <lambda>1.0</lambda> </outfunction> <!-- Randomize the values of biases in the range specified --> <randomize min="-1.0" max="+1.0" /> </cluster> <!-- Full Connection from Input to Hidden --> <linker name="In2Hid" type="MatrixLinker" from="Input" to="Hidden"> <!-- Randomize the values of weights in the range specified --> <randomize min="-1.0" max="+1.0" /> </linker> <!-- Full Connection from Hidden to Ouput --> <linker name="Hid2Out" type="MatrixLinker" from="Hidden" to="Output"> <!-- Randomize the values of weights in the range specified --> <randomize min="-1.0" max="+1.0" /> </linker> <!-- Specify which are the Input layers --> <inputs> Input </inputs> <!-- Specify which are the Output layers --> <outputs> Output </outputs> <!-- Specify the update order during spreading of the net --> <order> Input In2Hid Hidden Hid2Out Output </order> </neuralnet> </nnfw>
#include "nnfw/nnfw.h" #include "nnfw/ionnfw.h" #include "nnfw/backpropagationalgo.h" using namespace nnfw; BaseNeuralNet* net; int main( int , char* ) { Random::setSeed( time(0) ); //--- load the neural network from the file net = loadXML( "../xor2/xor1.xml" ); //--- register the input and ouput cluster in local variable for fast access //--- WARNING: here we assume that there is only one cluster as Input and Output of the net //--- in general, this is not true. Pay attention when you change this tutorial Cluster* in = net->inputClusters()[0]; Cluster* out = net->outputClusters()[0]; //--- suppose that the reverse order is correct for backpropagation algorithm UpdatableVec bp_ord; bp_ord.resize( net->order().size() ); bp_ord.assign_reverse( net->order() ); BackPropagationAlgo* bp = new BackPropagationAlgo( net, bp_ord, 0.15 );
The above code substitute the code showed in overture_21 and overture_22. Attach the code showed in the overture_23 and you'll get a complete working program.
In addition, just before the "return 0" statement you can save your learned network in this way:
saveXML( "../xor2/xor1_learned.xml", net ); return 0; }