32 int const*
const& numNeuronsPerLayer,
40 "ERROR: Neural network must have at least three layers\n");
54 numNeuronsPerLayer[0],
55 activationFunctionsPerLayer[0]);
59 numNeuronsPerLayer[i-1],
60 numNeuronsPerLayer[i],
61 activationFunctionsPerLayer[i]);
101 for (
int j = 0; j <
layers[i].numNeurons; j++)
103 delete[]
layers[i].neurons[j].weights;
105 delete[]
layers[i].neurons;
126 count +=
layers[i].numNeurons;
153 for (
int j = 0; j <
layers[i].numNeuronsPrevLayer; j++)
155 for (
int k = 0; k <
layers[i].numNeurons; k++)
157 layers[i].neurons[k].weights[j] = connections[count];
161 for (
int j = 0; j <
layers[i].numNeurons; j++)
163 layers[i].neurons[j].bias = connections[count];
177 for (
int j = 0; j <
layers[i].numNeuronsPrevLayer; j++)
179 for (
int k = 0; k <
layers[i].numNeurons; k++)
181 connections[count] =
layers[i].neurons[k].weights[j] ;
185 for (
int j = 0; j <
layers[i].numNeurons; j++)
187 connections[count] =
layers[i].neurons[j].bias;
202 connections[i] = -1.0 + 2.0 * (double)rand() / RAND_MAX;
207 delete[] connections;
218 for (
int j = 0; j <
layers[i].numNeurons; j++)
220 layers[i].neurons[j].bias = 0.0;
228 for (
int j = 0; j <
outputLayer->numNeuronsPrevLayer; j++)
234 else if (modificationScheme ==
MS_FANIN)
240 for (
int j = 0; j <
layers[i].numNeurons; j++)
242 for (
int k = 0; k <
layers[i].numNeuronsPrevLayer; k++)
244 layers[i].neurons[j].weights[k] /=
245 sqrt(
layers[i].numNeuronsPrevLayer);
257 for (
int j = 0; j <
layers[i].numNeurons; j++)
259 for (
int k = 0; k <
layers[i].numNeuronsPrevLayer; k++)
261 layers[i].neurons[j].weights[k] *= sqrt(6.0 / (
262 layers[i].numNeuronsPrevLayer
277 beta = 0.7 * pow(
layers[i].numNeurons,
278 1.0 /
double(
layers[i].numNeuronsPrevLayer));
279 for (
int j = 0; j <
layers[i].numNeurons; j++)
282 for (
int k = 0; k <
layers[i].numNeuronsPrevLayer; k++)
284 weight =
layers[i].neurons[j].weights[k];
285 sum += weight * weight;
288 for (
int k = 0; k <
layers[i].numNeuronsPrevLayer; k++)
290 layers[i].neurons[j].weights[k] *= beta / sum;
293 layers[i].neurons[j].weights[k] *= 2.0;
296 layers[i].neurons[j].bias *= beta;
299 layers[i].neurons[j].bias *= 2.0;
310 fprintf(stderr,
"ERROR: Incorrect modifyConnections call.\n");
323 double mean = parameter1;
324 double sigma = parameter2;
328 for (
int j = 0; j <
outputLayer->numNeuronsPrevLayer; j++)
337 fprintf(stderr,
"ERROR: Incorrect modifyConnections call.\n");
349 n.min = min(value, n.min);
350 n.max = max(value, n.max);
352 n.sum2 += value * value;
359 for (
int i = 0; i <
inputLayer->numNeurons; i++)
363 double const& value = input[i];
367 n.
min = min(value, n.
min);
368 n.
max = max(value, n.
max);
370 n.
sum2 += value * value;
403 inner[i] =
new double[
layers[i+1].numNeurons];
404 outer[i] =
new double[
layers[i+2].numNeurons];
407 for (
int k = 0; k <
layers[0].numNeurons; k++)
409 for (
int i = 0; i <
layers[1].numNeurons; i++)
411 inner[0][i] =
layers[1].neurons[i].weights[k]
412 *
layers[1].neurons[i].dfdx;
417 for (
int i2 = 0; i2 <
layers[l+1].numNeurons; i2++)
419 outer[l-1][i2] = 0.0;
420 for (
int i1 = 0; i1 <
layers[l].numNeurons; i1++)
422 outer[l-1][i2] +=
layers[l+1].neurons[i2].weights[i1]
425 outer[l-1][i2] *=
layers[l+1].neurons[i2].dfdx;
466 for (
int j = 0; j <
layers[i].numNeurons; j++)
468 for (
int k = 0; k <
layers[i+1].numNeurons; k++)
471 *
layers[i].neurons[j].value;
476 *
layers[i+1].neurons[k].weights[j]
477 *
layers[i].neurons[j].dfdx;
491 double const*
const& dGdxyz)
const
507 for (
int i = 0; i <
layers[0].numNeurons; i++)
519 dFdc[j] -= d2EdGdc[j] * dGdxyz[i];
532 vector<string> title;
533 vector<string> colName;
534 vector<string> colInfo;
535 vector<size_t> colSize;
536 title.push_back(
"Neural network connection values (weights and biases).");
537 colSize.push_back(24);
538 colName.push_back(
"connection");
539 colInfo.push_back(
"Neural network connection value.");
540 colSize.push_back(1);
541 colName.push_back(
"t");
542 colInfo.push_back(
"Connection type (a = weight, b = bias).");
543 colSize.push_back(9);
544 colName.push_back(
"index");
545 colInfo.push_back(
"Index enumerating weights.");
546 colSize.push_back(5);
547 colName.push_back(
"l_s");
548 colInfo.push_back(
"Starting point layer (end point layer for biases).");
549 colSize.push_back(5);
550 colName.push_back(
"n_s");
551 colInfo.push_back(
"Starting point neuron in starting layer (end point "
552 "neuron for biases).");
553 colSize.push_back(5);
554 colName.push_back(
"l_e");
555 colInfo.push_back(
"End point layer.");
556 colSize.push_back(5);
557 colName.push_back(
"n_e");
558 colInfo.push_back(
"End point neuron in end layer.");
565 for (
int j = 0; j <
layers[i].numNeuronsPrevLayer; j++)
567 for (
int k = 0; k <
layers[i].numNeurons; k++)
570 file <<
strpr(
"%24.16E a %9d %5d %5d %5d %5d\n",
571 layers[i].neurons[k].weights[j],
579 for (
int j = 0; j <
layers[i].numNeurons; j++)
582 file <<
strpr(
"%24.16E b %9d %5d %5d\n",
583 layers[i].neurons[j].bias,
607 for (
int j = 0; j <
layers[i].numNeurons; j++)
609 for (
int k = 0; k <
layers[i+1].numNeurons; k++)
614 *
layers[i+1].neurons[k].weights[j]
615 *
layers[i].neurons[j].dfdx;
630 for (
int i = 0; i <
layers[1].numNeurons; i++)
632 layers[1].neurons[i].dxdG =
layers[1].neurons[i].weights[index];
635 layers[1].neurons[i].dxdG /=
layers[1].numNeuronsPrevLayer;
640 for (
int j = 0; j <
layers[i].numNeurons; j++)
642 layers[i].neurons[j].dxdG = 0.0;
643 for (
int k = 0; k <
layers[i-1].numNeurons; k++)
645 layers[i].neurons[j].dxdG +=
layers[i].neurons[j].weights[k]
646 *
layers[i-1].neurons[k].dfdx
647 *
layers[i-1].neurons[k].dxdG;
651 layers[i].neurons[j].dxdG /=
layers[i].numNeuronsPrevLayer;
660 double const*
const& dEdb,
661 double* d2EdGdc)
const
679 for (
int j = 0; j <
layers[i].numNeurons; j++)
681 for (
int k = 0; k <
layers[i+1].numNeurons; k++)
698 *
layers[i].neurons[j].dxdG;
704 layers[i+1].neurons[k].weights[j]
707 *
layers[i].neurons[j].d2fdx2
708 *
layers[i].neurons[j].dxdG);
722 int numNeuronsPrevLayer,
740 layer.
neurons[i].
min = numeric_limits<double>::max();
741 layer.
neurons[i].
max = -numeric_limits<double>::max();
808 dtmp = 1.0 / (1.0 + exp(-dtmp));
812 * (1.0 - 2.0 * dtmp);
833 dtmp = 1.0 / (1.0 + 1.0 / dtmp);
855 double const tmpexp = exp(-0.5 * dtmp * dtmp);
862 double const tmpcos = cos(dtmp);
869 dtmp = 1.0 / (1.0 + exp(-dtmp));
872 layer.
neurons[i].
d2fdx2 = dtmp * (dtmp - 1.0) * (1.0 - 2.0 * dtmp);
902 for (
int j = 0; j <
layers[i].numNeurons; j++)
904 layers[i].neurons[j].count = 0;
905 layers[i].neurons[j].min = numeric_limits<double>::max();
906 layers[i].neurons[j].max = -numeric_limits<double>::max();
907 layers[i].neurons[j].sum = 0.0;
908 layers[i].neurons[j].sum2 = 0.0;
925 for (
int j = 0; j <
layers[i].numNeurons; j++)
927 count[iNeuron] =
layers[i].neurons[j].count;
928 min [iNeuron] =
layers[i].neurons[j].min;
929 max [iNeuron] =
layers[i].neurons[j].max;
930 sum [iNeuron] =
layers[i].neurons[j].sum;
931 sum2 [iNeuron] =
layers[i].neurons[j].sum2;
983 long mem =
sizeof(*this);
990 mem += numNeurons *
sizeof(
Neuron);
1004 v.push_back(
strpr(
"Architecture "));
1007 maxNeurons = max(
layers[i].numNeurons, maxNeurons);
1011 v.push_back(
"-----------------------------------------"
1012 "--------------------------------------\n");
1014 for (
int i = 0; i < maxNeurons; ++i)
1016 v.push_back(
strpr(
"%4d", i + 1));
1020 if (i <
layers[j].numNeurons)
1024 s +=
strpr(
" %3s",
"G");
1028 s +=
strpr(
" %3s",
"l");
1032 s +=
strpr(
" %3s",
"t");
1036 s +=
strpr(
" %3s",
"s");
1040 s +=
strpr(
" %3s",
"p");
1044 s +=
strpr(
" %3s",
"r");
1048 s +=
strpr(
" %3s",
"g");
1052 s +=
strpr(
" %3s",
"c");
1056 s +=
strpr(
" %3s",
"S");
1060 s +=
strpr(
" %3s",
"e");
1064 s +=
strpr(
" %3s",
"h");
1072 v.push_back(s +=
"\n");
1094 throw runtime_error(
"ERROR: Unknown activation function.\n");
ActivationFunction
List of available activation function types.
@ AF_RELU
(NOT recommended for HDNNPs!)
int getNumConnections() const
Return total number of connections.
Layer * inputLayer
Pointer to input layer.
void setInput(double const *const &input) const
Set neural network input layer node values.
int getNumNeurons() const
Return total number of neurons.
int * biasOnlyOffset
Offset adress of biases per layer in bias only array.
void modifyConnections(ModificationScheme modificationScheme)
Change connections according to a given modification scheme.
int numLayers
Total number of layers (includes input and output layers).
void calculateDEdb(double *dEdb) const
Calculate derivative of output neuron with respect to biases.
int getNumWeights() const
Return number of weights.
void setConnections(double const *const &connections)
Set neural network weights and biases.
void writeConnections(std::ofstream &file) const
Write connections to file.
bool normalizeNeurons
If neurons are normalized.
void calculateDFdc(double *dFdc, double const *const &dGdxyz) const
Calculate "second" derivative of output with respect to connections.
void propagateLayer(Layer &layer, Layer &layerPrev)
Propagate information from one layer to the next.
void allocateLayer(Layer &layer, int numNeuronsPrevLayer, int numNeurons, ActivationFunction activationFunction)
Allocate a single layer.
int * weightOffset
Offset adress of weights per layer in combined weights+bias array.
void initializeConnectionsRandomUniform(unsigned int seed)
Initialize connections with random numbers.
int * biasOffset
Offset adress of biases per layer in combined weights+bias array.
void calculateD2EdGdc(int index, double const *const &dEdb, double *d2EdGdc) const
Calculate second derivative of output neuron with respect to input neuron and connections.
void getNeuronStatistics(long *count, double *min, double *max, double *sum, double *sum2) const
Return gathered neuron statistics.
int numBiases
Number of NN biases only.
void resetNeuronStatistics()
Reset neuron statistics.
ModificationScheme
List of available connection modification schemes.
@ MS_ZEROOUTPUTWEIGHTS
Set all weights connecting to the output layer to zero.
@ MS_ZEROBIAS
Set all bias values to zero.
@ MS_PRECONDITIONOUTPUT
Apply preconditioning to output layer connections.
@ MS_FANIN
Normalize weights via number of neuron inputs (fan-in).
@ MS_GLOROTBENGIO
Normalize connections according to Glorot and Bengio.
@ MS_NGUYENWIDROW
Initialize connections according to Nguyen-Widrow scheme.
void getConnections(double *connections) const
Get neural network weights and biases.
int numConnections
Number of NN connections (weights + biases).
void propagate()
Propagate input information through all layers.
void calculateDEdc(double *dEdc) const
Calculate derivative of output neuron with respect to connections.
void setNormalizeNeurons(bool normalizeNeurons)
Turn on/off neuron normalization.
int getNumBiases() const
Return number of biases.
void calculateDEdG(double *dEdG) const
Calculate derivative of output neuron with respect to input neurons.
void calculateDxdG(int index) const
Calculate derivative of neuron values before activation function with respect to input neuron.
Layer * layers
Neural network layers.
int numWeights
Number of NN weights only.
void getOutput(double *output) const
Get neural network output layer node values.
Layer * outputLayer
Pointer to output layer.
NeuralNetwork(int numLayers, int const *const &numNeuronsPerLayer, ActivationFunction const *const &activationFunctionsPerLayer)
Neural network class constructor.
int numHiddenLayers
Number of hidden layers.
std::vector< std::string > info() const
Print neural network architecture.
string strpr(const char *format,...)
String version of printf function.
vector< string > createFileHeader(vector< string > const &title, vector< size_t > const &colSize, vector< string > const &colName, vector< string > const &colInfo, char const &commentChar)
NeuralNetwork::ActivationFunction activationFromString(std::string c)
Convert string to activation function.
void appendLinesToFile(ofstream &file, vector< string > const lines)
Append multiple lines of strings to open file stream.
One neural network layer.
int numNeurons
Number of neurons in this layer .
Neuron * neurons
Array of neurons in this layer.
ActivationFunction activationFunction
Common activation function for all neurons in this layer.
int numNeuronsPrevLayer
Number of neurons in previous layer .
double * weights
NN weights assigned to neuron.
double bias
Bias value assigned to this neuron (if this is neuron this bias value is ).
double max
Maximum neuron value over data set (neuron statistics).
double sum
Sum of neuron values over data set (neuron statistics).
double dxdG
Derivative of neuron value before application of activation function with respect to input layer neur...
double value
Neuron value.
long count
How often the value of this neuron has been evaluated.
double d2fdx2
Second derivative of activation function with respect to its argument .
double dfdx
Derivative of activation function with respect to its argument .
double min
Minimum neuron value over data set (neuron statistics).
double x
Neuron value before application of activation function.
double sum2
Sum of squared neuron values over data set (neuron statistics).