Over the day I try to find a normal full example of the implementation of a simple neural network on C++ in Google, I do not understand why for so many years of popularity of this topic, the network has not yet appeared ton of information on this topic. Help please.
PS
The only thing that is https://habr.com/ru/post/440162/ Where why – What reality the author criticized the head to the head, maybe he missed something wrong?
There is still a question on his code, which is not clear to me at all, as far as I understand, the neural network consists of neurons, which consist in layers and which are related to each other, the neuron itself contains the value (weight) of Float
What makes this author:
void setio (int inputs, int outputs)
{
// --- INITIALIZATION VALUES AND ALLOCATING MEMORY
in = inputs;
Out = Outputs;
Errors = (Float *) Malloc ((Out) * SizeOF (Float);
Hidden = (Float *) Malloc ((Out) * SizeOF (Float));
Matrix = (Float **) malloc ((in + 1) * SizeOF (Float *));
For (int Inp = 0; Inp & lt; in + 1; Inp ++)
{
Matrix [INP] = (Float *) Malloc (Out * Sizeof (Float));
}
For (int Inp = 0; Inp & lt; in + 1; Inp ++)
{
For (int Outp = 0; Outp & lt; Out; Outp ++)
{
Matrix [INP] [OUTP] = RANDWEIGHT;
}
}
}
It creates a layer that consists of an inputs-number of neurons that have more than one value, but as much as Outputs, why so? and why separately do
errors = (float *) malloc ((out) * Sizeof (Float);
Hidden = (Float *) Malloc ((Out) * SizeOF (Float));
Answer 1, Authority 100%
For example, so
// HAD A LOT OF TROUBLE WITH SHUFFLE
#Include & lt; iostream & gt;
# INCLUDE & LT; vector & gt;
#Include & lt; List & gt;
#Include & lt; Cstdlib & gt;
#Include & lt; math.h & gt;
#Define Pi 3.141592653589793238463.
#Define N.
#Define Epsilon 0.1.
#Define Epoch 2000.
Using Namespace STD;
// Just for gnu plot issues
Extern "C" File * Popen (Const Char * Command, Const Char * Mode);
// Defining Activation Functions
// Double Sigmoid (Double X) {Return 1.0F / (1.0f + Exp (-X)); }
// Double DSIGMOID (Double x) {Return x * (1.0f - x); }
Double Tanh (Double X) {Return (exp (x) -Exp (-X) / (exp (x) + exp (-X));}
Double DTANH (Double X) {Return 1.0f - x * x;}
Double Lin (Double X) {Return X;}
Double Dlin (Double X) {RETURN 1.0F;}
Double init_weight () {return (2 * Rand () / Rand_max -1); }
Double Maxx = -9999999999999999; // MAXIMUM VALUE OF INPUT EXAMPLE
// Network Configuration.
static const int numinputs = 1;
static const int numhiddennodes = 7;
static const int numoutputs = 1;
// Learning Rate.
const double LR = 0.05F;
Double HiddenLayer [Numhiddennodes];
Double OutputLayer [NumOutputs];
Double HiddenLayerbias [Numhiddennodes];
Double OutputLayerbias [NumOutputs];
Double HiddenWeights [Numinputs] [numhiddennodes];
Double OutputWeights [numhiddennodes] [NumOutputs];
static const int numtrainingsets = 50;
Double Training_Inputs [NumtrainingSets] [NUMINPUTS];
Double Training_outPuts [NumtrainingSets] [NumoutPuts];
// SHUFFLING THE DATA WITH EACH EPOCH
Void Shuffle (Int * Array, Size_t N)
{
if (N & GT; 1) // if no. of TRAINING EXAMPLES & GT; 1
{
SIZE_T I;
for (i = 0; i & lt; n - 1; i ++)
{
Size_t j = i + Rand () / (Rand_max / (n - i) + 1);
int t = array [j];
array [j] = array [i];
Array [i] = T;
}
}
}
// Forward Propagation. ONLY Used After Training Is Done.
Void Predict (Double Test_Sample [])
{
for (int j = 0; j & lt; numhiddennodes; j ++)
{
Double Activation = HiddenLayerbias [J];
For (int k = 0; k & lt; numinputs; k ++)
{
Activation + = test_sample [k] * hiddenweights [k] [j];
}
hiddenlayer [j] = tanh (Activation);
}
for (int j = 0; j & lt; numoutputs; j ++)
{
Double Activation = OutputLayerbias [J];
for (int k = 0; k & lt; numhiddennodes; k ++)
{
Activation + = HiddenLayer [k] * OutputWeights [k] [j];
}
OUTPUTLAYER [J] = LIN (Activation);
}
// STD :: COUT & LT; & LT; OutputLayer [0] & lt; & lt; "\ n";
// Return OutputLayer [0];
// STD :: COUT & LT; & LT; "INPUT:" & lt; & lt; TRAINING_INPUTS [I] [0] & lt; & lt; "" & lt; & lt; TRAINING_INPUTS [I] [1] & lt; & lt; "Output:" & lt; & lt; OutputLayer [0] & lt; & lt; "EXPECTED OUTPUT:" & lt; & lt; TRAINING_OUTPUTS [I] [0] & lt; & lt; "\ n";
}
Int Main (Int Argc, Const Char * Argv [])
{
/// TRAINING DATA Generation
for (int i = 0; i & lt; numtrainingsets; i ++)
{
Double P = (2 * PI * (Double) I / NUMTRAININGSETS);
TRAINING_INPUTS [I] [0] = (P);
TRAINING_OUTPUTS [I] [0] = SIN (P);
/// Finding Normalizing Factor
for (int m = 0; m & lt; numinputs; ++ m)
IF (Maxx & LT; TRAINING_INPUTS [I] [M])
Maxx = TRAINING_INPUTS [I] [M];
For (int m = 0; m & lt; numoutputs; ++ m)
If (Maxx & LT; TRAINING_OUTPUTS [I] [M])
MAXX = TRAINING_OUTPUTS [I] [M];
}
/// Normalizing.
for (int i = 0; i & lt; numtrainingsets; i ++)
{
for (int m = 0; m & lt; numinputs; ++ m)
TRAINING_INPUTS [I] [M] / = 1.0F * MAXX;
For (int m = 0; m & lt; numoutputs; ++ m)
TRAINING_OUTPUTS [I] [M] / = 1.0F * MAXX;
COUT & LT; & lt; "in:" & lt; & lt; english_inputs [i] [0] & lt; & lt; "Out:" & lt; & lt; Training_outPuts [i] [0] & lt; & lt; Endl;
}
/// weight & amp; Bias Initialization
For (int i = 0; i & lt; numinputs; i ++) {
For (int j = 0; j & lt; numhiddennodes; j ++) {
HiddenWeights [i] [j] = init_weight ();
}
}
For (int i = 0; i & lt; numhiddennodes; i ++) {
hiddenlayerbias [i] = init_weight ();
For (int j = 0; j & lt; numoutPuts; j ++) {
OUTPUTWEIGHTS [I] [J] = init_weight ();
}
}
For (int i = 0; i & lt; numoutputs; i ++) {
// OutputLayerbias [i] = init_weight ();
OutputLayerbias [i] = 0;
}
/// for index shuffling
INT TrainingSetORDER [numtrainingsets];
For (int j = 0; j & lt; numinputs; ++ j)
TRAININGSETORDER [J] = J;
/// Training
// STD :: COUT & LT; & LT; "START TRAIN \ N";
Vector & lt; Double & GT; Performance, EPO; /// Store MSE, Epoch
for (int n = 0; n & lt; epoch; n ++)
{
Double MSE = 0;
Shuffle (TrainingsetOrder, NumtrainingSets);
STD :: COUT & LT; & LT; "EPOCH:" & lt; & lt; n & lt; & lt; "\ n";
for (int i = 0; i & lt; numtrainingsets; i ++)
{
// int i = TRAININGSETORDER [x];
int x = i;
// STD :: COUT & LT; & LT; "TRAINING SET:" & lt; & lt; x & lt; & lt; "\ n";
/// Forward Pass
for (int j = 0; j & lt; numhiddennodes; j ++)
{
Double Activation = HiddenLayerbias [J];
// STD :: COUT & LT; & LT; "TRAINING SET:" & lt; & lt; x & lt; & lt; "\ n";
For (int k = 0; k & lt; numinputs; k ++) {
Activation + = TRAINING_Inputs [x] [k] * hiddenweights [k] [j];
}
hiddenlayer [j] = tanh (Activation);
}
For (int j = 0; j & lt; numoutPuts; j ++) {
Double Activation = OutputLayerbias [J];
for (int k = 0; k & lt; numhiddennodes; k ++)
{
Activation + = HiddenLayer [k] * OutputWeights [k] [j];
}
OUTPUTLAYER [J] = LIN (Activation);
}
// STD :: COUT & LT; & LT; "INPUT:" & lt; & lt; TRAINING_INPUTS [X] [0] & lt; & lt; "" & lt; & lt; "Output:" & lt; & lt; OutputLayer [0] & lt; & lt; "EXPECTED OUTPUT:" & lt; & lt; TRAINING_OUTPUTS [X] [0] & lt; & lt; "\ n";
For (int k = 0; k & lt; numoutpets; ++ k)
MSE + = (1.0f / NumoutPuts) * Pow (TRAINING_OUTPUTS [X] [K] - OUTPUTLAYER [K], 2);
/// backprop.
/// for V.
Double DeltaoutPut [NumOutputs];
For (int j = 0; j & lt; numoutPuts; j ++) {
Double erroroutput = (TRAINING_OUTPUTS [I] [J] -OutputLayer [J]);
DeltaoutPut [j] = erroroutput * dlin (OutputLayer [J]);
}
/// for w.
Double Deltahidden [numhiddennodes];
For (int j = 0; j & lt; numhiddennodes; j ++) {
double errorHidden = 0.0f;
for (int k = 0; k & lt; numOutputs; k ++) {
errorHidden + = deltaOutput [k] * outputWeights [j] [k];
}
deltaHidden [j] = errorHidden * dtanh (hiddenLayer [j]);
}
/// Updation
/// For V and b
for (int j = 0; j & lt; numOutputs; j ++) {
// b
outputLayerBias [j] + = deltaOutput [j] * lr;
for (int k = 0; k & lt; numHiddenNodes; k ++)
{
outputWeights [k] [j] + = hiddenLayer [k] * deltaOutput [j] * lr;
}
}
/// For W and c
for (int j = 0; j & lt; numHiddenNodes; j ++) {
// c
hiddenLayerBias [j] + = deltaHidden [j] * lr;
// W
for (int k = 0; k & lt; numInputs; k ++) {
hiddenWeights [k] [j] + = training_inputs [i] [k] * deltaHidden [j] * lr;
}
}
}
// Averaging the MSE
MSE / = 1.0f * numTrainingSets;
// cout & lt; & lt; "MSE:" & lt; & lt; MSE & lt; & lt; endl;
/// Steps to PLOT PERFORMANCE PER EPOCH
performance.push_back (MSE * 100);
epo.push_back (n);
}
// Print weights
std :: cout & lt; & lt; "Final Hidden Weights \ n [";
for (int j = 0; j & lt; numHiddenNodes; j ++) {
std :: cout & lt; & lt; "[";
for (int k = 0; k & lt; numInputs; k ++) {
std :: cout & lt; & lt; hiddenWeights [k] [j] & lt; & lt; "";
}
std :: cout & lt; & lt; "]";
}
std :: cout & lt; & lt; "] \ n";
std :: cout & lt; & lt; "Final Hidden Biases \ n [";
for (int j = 0; j & lt; numHiddenNodes; j ++) {
std :: cout & lt; & lt; hiddenLayerBias [j] & lt; & lt; "";
}
std :: cout & lt; & lt; "] \ n";
std :: cout & lt; & lt; "Final Output Weights";
for (int j = 0; j & lt; numOutputs; j ++) {
std :: cout & lt; & lt; "[";
for (int k = 0; k & lt; numHiddenNodes; k ++) {
std :: cout & lt; & lt; outputWeights [k] [j] & lt; & lt; "";
}
std :: cout & lt; & lt; "] \ n";
}
std :: cout & lt; & lt; "Final Output Biases \ n [";
for (int j = 0; j & lt; numOutputs; j ++) {
std :: cout & lt; & lt; outputLayerBias [j] & lt; & lt; "";
}
std :: cout & lt; & lt; "] \ n";
/ * This part is just for plotting the results.
This requires installing GNU Plot. You can also comment it out.
* /
// Plot the results
vector & lt; float & gt; x;
vector & lt; float & gt; y1, y2;
// double test_input [1000] [numInputs];
int numTestSets = numTrainingSets;
for (float i = 0; i & lt; numTestSets; i = i + 0.25)
{
double p = (2 * PI * (double) i / numTestSets);
x.push_back (p);
y1.push_back (sin (p));
double test_input [1];
test_input [0] = p / MAXX;
predict (test_input);
y2.push_back (outputLayer [0] * MAXX);
}
FILE * gp = popen ("gnuplot", "w");
fprintf (gp, "set terminal wxt size 600,400 \ n");
fprintf (gp, "set grid \ n");
fprintf (gp, "set title '% s' \ n", "f (x) = x sin (x)");
fprintf (gp, "set style line 1 lt 3 pt 7 ps 0.1 lc rgb 'green' lw 1 \ n");
fprintf (gp, "set style line 2 lt 3 pt 7 ps 0.1 lc rgb 'red' lw 1 \ n");
fprintf (gp, "plot '-' w p ls 1, '-' w p ls 2 \ n");
/// Exact f (x) = sin (x) - & gt; Green graph
for (int k = 0; k & lt; x.size (); k ++) {
fprintf (gp, "% f% f \ n", x [k], y1 [k]);
}
fprintf (gp, "e \ n");
/// Neural Network Approximate f (x) = xsin (x) - & gt; Red graph
for (int k = 0; k & lt; x.size (); k ++) {
fprintf (gp, "% f% f \ n", x [k], y2 [k]);
}
fprintf (gp, "e \ n");
fflush (gp);
/// FILE POINTER FOR SECOND PLOT (PERFORMANCE GRAPH)
FILE * gp1 = popen ("gnuplot", "w");
fprintf (gp1, "set terminal wxt size 600,400 \ n");
fprintf (gp1, "set grid \ n");
fprintf (gp1, "set title '% s' \ n", "Performance");
fprintf (gp1, "set style line 1 lt 3 pt 7 ps 0.1 lc rgb 'green' lw 1 \ n");
fprintf (gp1, "set style line 2 lt 3 pt 7 ps 0.1 lc rgb 'red' lw 1 \ n");
fprintf (gp1, "plot '-' w p ls 1 \ n");
for (int k = 0; k & lt; epo.size (); k ++) {
fprintf (gp1, "% f% f \ n", epo [k], performance [k]);
}
fprintf (gp1, "e \ n");
fflush (gp1);
system ("pause");
// _ pclose (gp);
return 0;
}