9#include "perceptron_layer.h"
36 set(new_inputs_number, new_neurons_number, new_activation_function);
68Index PerceptronLayer::get_biases_number()
const
119 const Index parameters_size = parameters.size();
121 const Index start_synaptic_weights_number = (parameters_size - synaptic_weights_number);
123 Tensor<type, 1> new_synaptic_weights = parameters.slice(Eigen::array<Eigen::Index, 1>({start_synaptic_weights_number}), Eigen::array<Eigen::Index, 1>({synaptic_weights_number}));
125 Eigen::array<Index, 2> two_dim{{inputs_number, neurons_number}};
127 return new_synaptic_weights.reshape(two_dim);
133 const Index biases_number =
biases.size();
135 Tensor<type, 1> new_biases(biases_number);
137 new_biases = parameters.slice(Eigen::array<Eigen::Index, 1>({0}), Eigen::array<Eigen::Index, 1>({biases_number}));
139 Eigen::array<Index, 2> two_dim{{1,
biases.dimension(1)}};
141 return new_biases.reshape(two_dim);
154 for(Index i = 0; i <
biases.size(); i++)
156 fill_n(parameters.data()+i, 1,
biases(i));
184 case ActivationFunction::Logistic:
187 case ActivationFunction::HyperbolicTangent:
188 return "HyperbolicTangent";
190 case ActivationFunction::Threshold:
193 case ActivationFunction::SymmetricThreshold:
194 return "SymmetricThreshold";
196 case ActivationFunction::Linear:
199 case ActivationFunction::RectifiedLinear:
200 return "RectifiedLinear";
202 case ActivationFunction::ScaledExponentialLinear:
203 return "ScaledExponentialLinear";
205 case ActivationFunction::SoftPlus:
208 case ActivationFunction::SoftSign:
211 case ActivationFunction::HardSigmoid:
212 return "HardSigmoid";
214 case ActivationFunction::ExponentialLinear:
215 return "ExponentialLinear";
252 biases.resize(1, new_neurons_number);
281void PerceptronLayer::set_name(
const string& new_layer_name)
295 biases.resize(1,neurons_number);
309 biases.resize(1, new_neurons_number);
340 const Index biases_number = get_biases_number();
344 new_parameters.data() + index,
345 static_cast<size_t>(biases_number)*
sizeof(type));
348 new_parameters.data() + biases_number + index,
349 static_cast<size_t>(synaptic_weights_number)*
sizeof(type));
368 if(new_activation_function_name ==
"Logistic")
372 else if(new_activation_function_name ==
"HyperbolicTangent")
376 else if(new_activation_function_name ==
"Threshold")
380 else if(new_activation_function_name ==
"SymmetricThreshold")
384 else if(new_activation_function_name ==
"Linear")
388 else if(new_activation_function_name ==
"RectifiedLinear")
392 else if(new_activation_function_name ==
"ScaledExponentialLinear")
396 else if(new_activation_function_name ==
"SoftPlus")
400 else if(new_activation_function_name ==
"SoftSign")
404 else if(new_activation_function_name ==
"HardSigmoid")
408 else if(new_activation_function_name ==
"ExponentialLinear")
414 ostringstream buffer;
416 buffer <<
"OpenNN Exception: PerceptronLayer class.\n"
417 <<
"void set_activation_function(const string&) method.\n"
418 <<
"Unknown activation function: " << new_activation_function_name <<
".\n";
420 throw logic_error(buffer.str());
441 biases.setConstant(value);
459 biases.setConstant(value);
470 const type minimum = type(-0.2);
471 const type maximum = type(0.2);
473 for(Index i = 0; i <
biases.size(); i++)
475 const type random =
static_cast<type
>(rand()/(RAND_MAX+1.0));
477 biases(i) = minimum + (maximum - minimum)*random;
482 const type random =
static_cast<type
>(rand()/(RAND_MAX+1.0));
489void PerceptronLayer::calculate_combinations(
const Tensor<type, 2>& inputs,
490 const Tensor<type, 2>& biases,
491 const Tensor<type, 2>& synaptic_weights,
492 Tensor<type, 2>& combinations)
const
501 const Index batch_samples_number = inputs.dimension(0);
502 const Index biases_number = get_biases_number();
504 for(Index i = 0; i < biases_number; i++)
506 fill_n(combinations.data() + i*batch_samples_number, batch_samples_number,
biases(i));
509 combinations.device(*thread_pool_device) += inputs.contract(
synaptic_weights, A_B);
513void PerceptronLayer::calculate_activations(
const Tensor<type, 2>& combinations, Tensor<type, 2>& activations)
const
522 case ActivationFunction::Linear: linear(combinations, activations);
return;
524 case ActivationFunction::Logistic: logistic(combinations, activations);
return;
526 case ActivationFunction::HyperbolicTangent: hyperbolic_tangent(combinations, activations);
return;
528 case ActivationFunction::Threshold: threshold(combinations, activations);
return;
530 case ActivationFunction::SymmetricThreshold: symmetric_threshold(combinations, activations);
return;
532 case ActivationFunction::RectifiedLinear: rectified_linear(combinations, activations);
return;
534 case ActivationFunction::ScaledExponentialLinear: scaled_exponential_linear(combinations, activations);
return;
536 case ActivationFunction::SoftPlus: soft_plus(combinations, activations);
return;
538 case ActivationFunction::SoftSign: soft_sign(combinations, activations);
return;
540 case ActivationFunction::HardSigmoid: hard_sigmoid(combinations, activations);
return;
542 case ActivationFunction::ExponentialLinear: exponential_linear(combinations, activations);
return;
547void PerceptronLayer::calculate_activations_derivatives(
const Tensor<type, 2>& combinations,
548 Tensor<type, 2>& activations,
549 Tensor<type, 2>& activations_derivatives)
const
554 check_dimensions(activations_derivatives, combinations.dimension(0),
get_neurons_number(), LOG);
559 case ActivationFunction::Linear: linear_derivatives(combinations, activations, activations_derivatives);
return;
561 case ActivationFunction::Logistic: logistic_derivatives(combinations, activations, activations_derivatives);
return;
563 case ActivationFunction::HyperbolicTangent: hyperbolic_tangent_derivatives(combinations, activations, activations_derivatives);
return;
565 case ActivationFunction::Threshold: threshold_derivatives(combinations, activations, activations_derivatives);
return;
567 case ActivationFunction::SymmetricThreshold: symmetric_threshold_derivatives(combinations, activations, activations_derivatives);
return;
569 case ActivationFunction::RectifiedLinear: rectified_linear_derivatives(combinations, activations, activations_derivatives);
return;
571 case ActivationFunction::ScaledExponentialLinear: scaled_exponential_linear_derivatives(combinations, activations, activations_derivatives);
return;
573 case ActivationFunction::SoftPlus: soft_plus_derivatives(combinations, activations, activations_derivatives);
return;
575 case ActivationFunction::SoftSign: soft_sign_derivatives(combinations, activations, activations_derivatives);
return;
577 case ActivationFunction::HardSigmoid: hard_sigmoid_derivatives(combinations, activations, activations_derivatives);
return;
579 case ActivationFunction::ExponentialLinear: exponential_linear_derivatives(combinations, activations, activations_derivatives);
return;
584Tensor<type, 2> PerceptronLayer::calculate_outputs(
const Tensor<type, 2>& inputs)
590 const Index batch_size = inputs.dimension(0);
593 Tensor<type, 2> outputs(batch_size, outputs_number);
597 calculate_activations(outputs, outputs);
603void PerceptronLayer::forward_propagate(
const Tensor<type, 2>& inputs,
604 LayerForwardPropagation* forward_propagation)
610 PerceptronLayerForwardPropagation* perceptron_layer_forward_propagation
611 =
static_cast<PerceptronLayerForwardPropagation*
>(forward_propagation);
613 calculate_combinations(inputs,
616 perceptron_layer_forward_propagation->combinations);
618 calculate_activations_derivatives(perceptron_layer_forward_propagation->combinations,
619 perceptron_layer_forward_propagation->activations,
620 perceptron_layer_forward_propagation->activations_derivatives);
624void PerceptronLayer::forward_propagate(
const Tensor<type, 2>& inputs,
625 Tensor<type, 1> potential_parameters,
626 LayerForwardPropagation* forward_propagation)
637 const TensorMap<Tensor<type, 2>> potential_biases(potential_parameters.data(), neurons_number, 1);
639 const TensorMap<Tensor<type, 2>> potential_synaptic_weights(potential_parameters.data()+neurons_number, inputs_number, neurons_number);
641 PerceptronLayerForwardPropagation* perceptron_layer_forward_propagation
642 =
static_cast<PerceptronLayerForwardPropagation*
>(forward_propagation);
644 calculate_combinations(inputs,
646 potential_synaptic_weights,
647 perceptron_layer_forward_propagation->combinations);
649 calculate_activations_derivatives(perceptron_layer_forward_propagation->combinations,
650 perceptron_layer_forward_propagation->activations,
651 perceptron_layer_forward_propagation->activations_derivatives);
655void PerceptronLayer::calculate_hidden_delta(LayerForwardPropagation* next_layer_forward_propagation,
656 LayerBackPropagation* next_layer_back_propagation,
657 LayerBackPropagation* layer_back_propagation)
const
659 PerceptronLayerBackPropagation* perceptron_layer_back_propagation =
660 static_cast<PerceptronLayerBackPropagation*
>(layer_back_propagation);
662 switch(next_layer_back_propagation->layer_pointer->get_type())
664 case Type::Perceptron:
666 PerceptronLayerForwardPropagation* next_perceptron_layer_forward_propagation =
667 static_cast<PerceptronLayerForwardPropagation*
>(next_layer_forward_propagation);
669 PerceptronLayerBackPropagation* next_perceptron_layer_back_propagation =
670 static_cast<PerceptronLayerBackPropagation*
>(next_layer_back_propagation);
672 calculate_hidden_delta_perceptron(next_perceptron_layer_forward_propagation,
673 next_perceptron_layer_back_propagation,
674 perceptron_layer_back_propagation);
678 case Type::Probabilistic:
680 ProbabilisticLayerForwardPropagation* next_probabilistic_layer_forward_propagation =
681 static_cast<ProbabilisticLayerForwardPropagation*
>(next_layer_forward_propagation);
683 ProbabilisticLayerBackPropagation* next_probabilistic_layer_back_propagation =
684 static_cast<ProbabilisticLayerBackPropagation*
>(next_layer_back_propagation);
686 calculate_hidden_delta_probabilistic(next_probabilistic_layer_forward_propagation,
687 next_probabilistic_layer_back_propagation,
688 perceptron_layer_back_propagation);
697void PerceptronLayer::calculate_hidden_delta_perceptron(PerceptronLayerForwardPropagation* next_forward_propagation,
698 PerceptronLayerBackPropagation* next_back_propagation,
699 PerceptronLayerBackPropagation* back_propagation)
const
703 back_propagation->delta.device(*thread_pool_device) =
704 (next_back_propagation->delta*next_forward_propagation->activations_derivatives).contract(next_synaptic_weights, A_BT);
708void PerceptronLayer::calculate_hidden_delta_probabilistic(ProbabilisticLayerForwardPropagation* next_forward_propagation,
709 ProbabilisticLayerBackPropagation* next_back_propagation,
710 PerceptronLayerBackPropagation* back_propagation)
const
712 const ProbabilisticLayer* probabilistic_layer_pointer =
static_cast<ProbabilisticLayer*
>(next_back_propagation->layer_pointer);
714 const Tensor<type, 2>& next_synaptic_weights = probabilistic_layer_pointer->get_synaptic_weights();
716 const Index batch_samples_number = back_propagation->batch_samples_number;
718 const Index next_neurons_number = probabilistic_layer_pointer->get_biases_number();
720 if(probabilistic_layer_pointer->get_neurons_number() == 1)
722 TensorMap< Tensor<type, 2> > activations_derivatives_2d(next_forward_propagation->activations_derivatives.data(),
723 batch_samples_number, next_neurons_number);
724 back_propagation->delta.device(*thread_pool_device) =
725 (next_back_propagation->delta*activations_derivatives_2d.reshape(Eigen::array<Index,2> {{activations_derivatives_2d.dimension(0),1}})).contract(next_synaptic_weights, A_BT);
729 if(probabilistic_layer_pointer->get_activation_function() != ProbabilisticLayer::ActivationFunction::Softmax)
731 back_propagation->delta.device(*thread_pool_device) =
732 (next_back_propagation->delta*next_forward_propagation->activations_derivatives.reshape(Eigen::array<Index,2> {{next_forward_propagation->activations_derivatives.dimension(0),1}})).contract(next_synaptic_weights, A_BT);
736 const Index samples_number = next_back_propagation->delta.dimension(0);
737 const Index outputs_number = next_back_propagation->delta.dimension(1);
738 const Index next_layer_neurons_number = probabilistic_layer_pointer->get_neurons_number();
740 if(outputs_number != next_layer_neurons_number)
742 ostringstream buffer;
744 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
745 <<
"void calculate_hidden_delta_probabilistic(ProbabilisticLayerForwardPropagation*,ProbabilisticLayerBackPropagation*,PerceptronLayerBackPropagation*) const.\n"
746 <<
"Number of columns in delta (" << outputs_number <<
") must be equal to number of neurons in probabilistic layer (" << next_layer_neurons_number <<
").\n";
748 throw logic_error(buffer.str());
751 if(next_forward_propagation->activations_derivatives.dimension(1) != next_layer_neurons_number)
753 ostringstream buffer;
755 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
756 <<
"void calculate_hidden_delta_probabilistic(ProbabilisticLayerForwardPropagation*,ProbabilisticLayerBackPropagation*,PerceptronLayerBackPropagation*) const.\n"
757 <<
"Dimension 1 of activations derivatives (" << outputs_number <<
") must be equal to number of neurons in probabilistic layer (" << next_layer_neurons_number <<
").\n";
759 throw logic_error(buffer.str());
762 if(next_forward_propagation->activations_derivatives.dimension(2) != next_layer_neurons_number)
764 ostringstream buffer;
766 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
767 <<
"void calculate_hidden_delta_probabilistic(ProbabilisticLayerForwardPropagation*,ProbabilisticLayerBackPropagation*,PerceptronLayerBackPropagation*) const.\n"
768 <<
"Dimension 2 of activations derivatives (" << outputs_number <<
") must be equal to number of neurons in probabilistic layer (" << next_layer_neurons_number <<
").\n";
770 throw logic_error(buffer.str());
773 const Index step = next_layer_neurons_number*next_layer_neurons_number;
775 for(Index i = 0; i < samples_number; i++)
777 next_back_propagation->delta_row = next_back_propagation->delta.chip(i,0);
779 TensorMap< Tensor<type, 2> > activations_derivatives_matrix(next_forward_propagation->activations_derivatives.data() + i*step,
780 next_layer_neurons_number, next_layer_neurons_number);
782 next_back_propagation->error_combinations_derivatives.chip(i,0) =
783 next_back_propagation->delta_row.contract(activations_derivatives_matrix, AT_B);
786 back_propagation->delta.device(*thread_pool_device) =
787 next_back_propagation->error_combinations_derivatives.contract(next_synaptic_weights, A_BT);
793void PerceptronLayer::calculate_hidden_delta_lm(LayerForwardPropagation* next_layer_forward_propagation,
794 LayerBackPropagationLM* next_layer_back_propagation,
795 LayerBackPropagationLM* layer_back_propagation)
const
797 PerceptronLayerBackPropagationLM* perceptron_layer_back_propagation =
798 static_cast<PerceptronLayerBackPropagationLM*
>(layer_back_propagation);
800 switch(next_layer_back_propagation->layer_pointer->get_type())
802 case Type::Perceptron:
804 PerceptronLayerForwardPropagation* next_perceptron_layer_forward_propagation =
805 static_cast<PerceptronLayerForwardPropagation*
>(next_layer_forward_propagation);
807 PerceptronLayerBackPropagationLM* next_perceptron_layer_back_propagation =
808 static_cast<PerceptronLayerBackPropagationLM*
>(next_layer_back_propagation);
810 calculate_hidden_delta_perceptron_lm(next_perceptron_layer_forward_propagation,
811 next_perceptron_layer_back_propagation,
812 perceptron_layer_back_propagation);
816 case Type::Probabilistic:
818 ProbabilisticLayerForwardPropagation* next_probabilistic_layer_forward_propagation =
819 static_cast<ProbabilisticLayerForwardPropagation*
>(next_layer_forward_propagation);
821 ProbabilisticLayerBackPropagationLM* next_probabilistic_layer_back_propagation =
822 static_cast<ProbabilisticLayerBackPropagationLM*
>(next_layer_back_propagation);
824 calculate_hidden_delta_probabilistic_lm(next_probabilistic_layer_forward_propagation,
825 next_probabilistic_layer_back_propagation,
826 perceptron_layer_back_propagation);
835void PerceptronLayer::calculate_hidden_delta_perceptron_lm(PerceptronLayerForwardPropagation* next_forward_propagation,
836 PerceptronLayerBackPropagationLM* next_back_propagation,
837 PerceptronLayerBackPropagationLM* back_propagation)
const
841 back_propagation->delta.device(*thread_pool_device) =
842 (next_back_propagation->delta*next_forward_propagation->activations_derivatives.reshape(Eigen::array<Index,2> {{next_forward_propagation->activations_derivatives.dimension(0),1}})).contract(next_synaptic_weights, A_BT);
846void PerceptronLayer::calculate_hidden_delta_probabilistic_lm(ProbabilisticLayerForwardPropagation* next_forward_propagation,
847 ProbabilisticLayerBackPropagationLM* next_back_propagation,
848 PerceptronLayerBackPropagationLM* back_propagation)
const
850 const ProbabilisticLayer* probabilistic_layer_pointer =
static_cast<ProbabilisticLayer*
>(next_back_propagation->layer_pointer);
852 const Tensor<type, 2>& next_synaptic_weights = probabilistic_layer_pointer->get_synaptic_weights();
854 if(probabilistic_layer_pointer->get_activation_function() == ProbabilisticLayer::ActivationFunction::Softmax)
856 const Index samples_number = next_back_propagation->delta.dimension(0);
857 const Index outputs_number = next_back_propagation->delta.dimension(1);
858 const Index next_layer_neurons_number = probabilistic_layer_pointer->get_neurons_number();
860 if(outputs_number != next_layer_neurons_number)
862 ostringstream buffer;
864 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
865 <<
"void calculate_hidden_delta_probabilistic(ProbabilisticLayerForwardPropagation*,ProbabilisticLayerBackPropagationLM*,PerceptronLayerBackPropagationLM*) const.\n"
866 <<
"Number of columns in delta (" << outputs_number <<
") must be equal to number of neurons in probabilistic layer (" << next_layer_neurons_number <<
").\n";
868 throw logic_error(buffer.str());
871 if(next_forward_propagation->activations_derivatives.dimension(1) != next_layer_neurons_number)
873 ostringstream buffer;
875 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
876 <<
"void calculate_hidden_delta_probabilistic(ProbabilisticLayerForwardPropagation*,ProbabilisticLayerBackPropagationLM*,PerceptronLayerBackPropagationLM*) const.\n"
877 <<
"Dimension 1 of activations derivatives (" << outputs_number <<
") must be equal to number of neurons in probabilistic layer (" << next_layer_neurons_number <<
").\n";
879 throw logic_error(buffer.str());
882 if(next_forward_propagation->activations_derivatives.dimension(2) != next_layer_neurons_number)
884 ostringstream buffer;
886 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
887 <<
"void calculate_hidden_delta_probabilistic(ProbabilisticLayerForwardPropagation*,ProbabilisticLayerBackPropagationLM*,PerceptronLayerBackPropagationLM*) const.\n"
888 <<
"Dimension 2 of activations derivatives (" << outputs_number <<
") must be equal to number of neurons in probabilistic layer (" << next_layer_neurons_number <<
").\n";
890 throw logic_error(buffer.str());
893 const Index step = next_layer_neurons_number*next_layer_neurons_number;
895 for(Index i = 0; i < samples_number; i++)
897 next_back_propagation->delta_row = next_back_propagation->delta.chip(i,0);
899 TensorMap< Tensor<type, 2> > activations_derivatives_matrix(next_forward_propagation->activations_derivatives.data() + i*step,
900 next_layer_neurons_number, next_layer_neurons_number);
902 next_back_propagation->error_combinations_derivatives.chip(i,0) =
903 next_back_propagation->delta_row.contract(activations_derivatives_matrix, AT_B);
906 back_propagation->delta.device(*thread_pool_device) =
907 (next_back_propagation->error_combinations_derivatives).contract(next_synaptic_weights, A_BT);
911 back_propagation->delta.device(*thread_pool_device) =
912 (next_back_propagation->delta*next_forward_propagation->activations_derivatives.reshape(Eigen::array<Index,2> {{next_forward_propagation->activations_derivatives.dimension(0),1}})).contract(next_synaptic_weights, A_BT);
917void PerceptronLayer::calculate_squared_errors_Jacobian_lm(
const Tensor<type, 2>& inputs,
918 LayerForwardPropagation* forward_propagation,
919 LayerBackPropagationLM* back_propagation)
921 PerceptronLayerForwardPropagation* perceptron_layer_forward_propagation =
922 static_cast<PerceptronLayerForwardPropagation*
>(forward_propagation);
924 PerceptronLayerBackPropagationLM* perceptron_layer_back_propagation_lm =
925 static_cast<PerceptronLayerBackPropagationLM*
>(back_propagation);
927 const Index samples_number = inputs.dimension(0);
932 Index parameter_index = 0;
934 for(Index sample = 0; sample < samples_number; sample++)
938 for(Index neuron = 0; neuron < neurons_number; neuron++)
940 for(Index input = 0; input < inputs_number; input++)
942 perceptron_layer_back_propagation_lm->squared_errors_Jacobian(sample, neurons_number+parameter_index) =
943 perceptron_layer_back_propagation_lm->delta(sample, neuron) *
944 perceptron_layer_forward_propagation->activations_derivatives(sample, neuron) *
945 inputs(sample, input);
950 perceptron_layer_back_propagation_lm->squared_errors_Jacobian(sample, neuron) =
951 perceptron_layer_back_propagation_lm->delta(sample, neuron) *
952 perceptron_layer_forward_propagation->activations_derivatives(sample, neuron);
958void PerceptronLayer::insert_squared_errors_Jacobian_lm(LayerBackPropagationLM * back_propagation ,
960 Tensor<type, 2>& squared_errors_Jacobian)
const
962 PerceptronLayerBackPropagationLM* perceptron_layer_back_propagation_lm =
963 static_cast<PerceptronLayerBackPropagationLM*
>(back_propagation);
965 const Index batch_samples_number = perceptron_layer_back_propagation_lm->squared_errors_Jacobian.dimension(0);
968 memcpy(squared_errors_Jacobian.data() + index,
969 perceptron_layer_back_propagation_lm->squared_errors_Jacobian.data(),
970 static_cast<size_t>(layer_parameters_number*batch_samples_number)*
sizeof(type));
974void PerceptronLayer::calculate_error_gradient(
const Tensor<type, 2>& inputs,
975 LayerForwardPropagation* forward_propagation,
976 LayerBackPropagation* back_propagation)
const
978 PerceptronLayerForwardPropagation* perceptron_layer_forward_propagation =
979 static_cast<PerceptronLayerForwardPropagation*
>(forward_propagation);
981 PerceptronLayerBackPropagation* perceptron_layer_back_propagation =
982 static_cast<PerceptronLayerBackPropagation*
>(back_propagation);
984 perceptron_layer_back_propagation->biases_derivatives.device(*thread_pool_device) =
985 (perceptron_layer_back_propagation->delta*perceptron_layer_forward_propagation->activations_derivatives).sum(Eigen::array<Index, 1>({0}));
987 perceptron_layer_back_propagation->synaptic_weights_derivatives.device(*thread_pool_device) =
988 inputs.contract(perceptron_layer_back_propagation->delta*perceptron_layer_forward_propagation->activations_derivatives, AT_B);
992void PerceptronLayer::insert_gradient(LayerBackPropagation* back_propagation,
994 Tensor<type, 1>& gradient)
const
996 PerceptronLayerBackPropagation* perceptron_layer_back_propagation =
997 static_cast<PerceptronLayerBackPropagation*
>(back_propagation);
999 const Index biases_number = get_biases_number();
1002 memcpy(gradient.data() + index,
1003 perceptron_layer_back_propagation->biases_derivatives.data(),
1004 static_cast<size_t>(biases_number)*
sizeof(type));
1006 memcpy(gradient.data() + index + biases_number,
1007 perceptron_layer_back_propagation->synaptic_weights_derivatives.data(),
1008 static_cast<size_t>(synaptic_weights_number)*
sizeof(type));
1023 ostringstream buffer;
1025 for(Index j = 0; j < outputs_names.size(); j++)
1027 const Tensor<type, 1> synaptic_weights_column =
synaptic_weights.chip(j,1);
1029 buffer << outputs_names[j] <<
" = " << write_activation_function_expression() <<
"( " <<
biases(0,j) <<
" +";
1031 for(Index i = 0; i < inputs_names.size() - 1; i++)
1033 buffer <<
" (" << inputs_names[i] <<
"*" << synaptic_weights_column(i) <<
") +";
1036 buffer <<
" (" << inputs_names[inputs_names.size() - 1] <<
"*" << synaptic_weights_column[inputs_names.size() - 1] <<
") );\n";
1039 return buffer.str();
1045 ostringstream buffer;
1049 const tinyxml2::XMLElement* perceptron_layer_element = document.FirstChildElement(
"PerceptronLayer");
1051 if(!perceptron_layer_element)
1053 buffer <<
"OpenNN Exception: PerceptronLayer class.\n"
1054 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1055 <<
"PerceptronLayer element is nullptr.\n";
1057 throw logic_error(buffer.str());
1062 const tinyxml2::XMLElement* layer_name_element = perceptron_layer_element->FirstChildElement(
"LayerName");
1064 if(!layer_name_element)
1066 buffer <<
"OpenNN Exception: PerceptronLayer class.\n"
1067 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1068 <<
"LayerName element is nullptr.\n";
1070 throw logic_error(buffer.str());
1073 if(layer_name_element->GetText())
1075 set_name(layer_name_element->GetText());
1080 const tinyxml2::XMLElement* inputs_number_element = perceptron_layer_element->FirstChildElement(
"InputsNumber");
1082 if(!inputs_number_element)
1084 buffer <<
"OpenNN Exception: PerceptronLayer class.\n"
1085 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1086 <<
"InputsNumber element is nullptr.\n";
1088 throw logic_error(buffer.str());
1091 if(inputs_number_element->GetText())
1098 const tinyxml2::XMLElement* neurons_number_element = perceptron_layer_element->FirstChildElement(
"NeuronsNumber");
1100 if(!neurons_number_element)
1102 buffer <<
"OpenNN Exception: PerceptronLayer class.\n"
1103 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1104 <<
"NeuronsNumber element is nullptr.\n";
1106 throw logic_error(buffer.str());
1109 if(neurons_number_element->GetText())
1116 const tinyxml2::XMLElement* activation_function_element = perceptron_layer_element->FirstChildElement(
"ActivationFunction");
1118 if(!activation_function_element)
1120 buffer <<
"OpenNN Exception: PerceptronLayer class.\n"
1121 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1122 <<
"ActivationFunction element is nullptr.\n";
1124 throw logic_error(buffer.str());
1127 if(activation_function_element->GetText())
1134 const tinyxml2::XMLElement* parameters_element = perceptron_layer_element->FirstChildElement(
"Parameters");
1136 if(!parameters_element)
1138 buffer <<
"OpenNN Exception: PerceptronLayer class.\n"
1139 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1140 <<
"Parameters element is nullptr.\n";
1142 throw logic_error(buffer.str());
1145 if(parameters_element->GetText())
1147 const string parameters_string = parameters_element->GetText();
1156 ostringstream buffer;
1160 file_stream.OpenElement(
"PerceptronLayer");
1163 file_stream.OpenElement(
"LayerName");
1166 file_stream.
PushText(buffer.str().c_str());
1170 file_stream.OpenElement(
"InputsNumber");
1175 file_stream.
PushText(buffer.str().c_str());
1181 file_stream.OpenElement(
"NeuronsNumber");
1186 file_stream.
PushText(buffer.str().c_str());
1192 file_stream.OpenElement(
"ActivationFunction");
1200 file_stream.OpenElement(
"Parameters");
1205 const Index parameters_size = parameters.size();
1207 for(Index i = 0; i < parameters_size; i++)
1209 buffer << parameters(i);
1211 if(i != (parameters_size-1)) buffer <<
" ";
1214 file_stream.
PushText(buffer.str().c_str());
1224string PerceptronLayer::write_activation_function_expression()
const
1228 case ActivationFunction::Threshold:
1231 case ActivationFunction::SymmetricThreshold:
1232 return "symmetric_threshold";
1234 case ActivationFunction::Logistic:
1237 case ActivationFunction::HyperbolicTangent:
1240 case ActivationFunction::Linear:
1243 case ActivationFunction::RectifiedLinear:
1246 case ActivationFunction::ExponentialLinear:
1249 case ActivationFunction::ScaledExponentialLinear:
1252 case ActivationFunction::SoftPlus:
1255 case ActivationFunction::SoftSign:
1258 case ActivationFunction::HardSigmoid:
1259 return "hard_sigmoid";
1266string PerceptronLayer::write_combinations_c()
const
1268 ostringstream buffer;
1273 buffer <<
"\tvector<float> combinations(" << neurons_number <<
");\n" << endl;
1275 for(Index i = 0; i < neurons_number; i++)
1277 buffer <<
"\tcombinations[" << i <<
"] = " <<
biases(i);
1279 for(Index j = 0; j < inputs_number; j++)
1284 buffer <<
";" << endl;
1287 return buffer.str();
1293 ostringstream buffer;
1297 buffer <<
"\n\tvector<float> activations(" << neurons_number <<
");\n" << endl;
1299 for(Index i = 0; i < neurons_number; i++)
1301 buffer <<
"\tactivations[" << i <<
"] = ";
1305 case ActivationFunction::HyperbolicTangent:
1306 buffer <<
"tanh(combinations[" << i <<
"]);\n";
1309 case ActivationFunction::RectifiedLinear:
1310 buffer <<
"combinations[" << i <<
"] < 0.0 ? 0.0 : combinations[" << i <<
"];\n";
1313 case ActivationFunction::Logistic:
1314 buffer <<
"1.0/(1.0 + exp(-combinations[" << i <<
"]));\n";
1317 case ActivationFunction::Threshold:
1318 buffer <<
"combinations[" << i <<
"] >= 0.0 ? 1.0 : 0.0;\n";
1321 case ActivationFunction::SymmetricThreshold:
1322 buffer <<
"combinations[" << i <<
"] >= 0.0 ? 1.0 : -1.0;\n";
1325 case ActivationFunction::Linear:
1326 buffer <<
"combinations[" << i <<
"];\n";
1329 case ActivationFunction::ScaledExponentialLinear:
1330 buffer <<
"combinations[" << i <<
"] < 0.0 ? 1.0507*1.67326*(exp(combinations[" << i <<
"]) - 1.0) : 1.0507*combinations[" << i <<
"];\n";
1333 case ActivationFunction::SoftPlus:
1334 buffer <<
"log(1.0 + exp(combinations[" << i <<
"]));\n";
1337 case ActivationFunction::SoftSign:
1338 buffer <<
"combinations[" << i <<
"] < 0.0 ? combinations[" << i <<
"]/(1.0 - combinations[" << i <<
"] ) : combinations[" << i <<
"]/(1.0 + combinations[" << i <<
"] );\n";
1341 case ActivationFunction::ExponentialLinear:
1342 buffer <<
"combinations[" << i <<
"] < 0.0 ? 1.0*(exp(combinations[" << i <<
"]) - 1.0) : combinations[" << i <<
"];\n";
1345 case ActivationFunction::HardSigmoid:
1351 return buffer.str();
1355string PerceptronLayer::write_combinations_python()
const
1357 ostringstream buffer;
1362 buffer <<
"\t\tcombinations = [None] * "<<neurons_number<<
"\n" << endl;
1364 for(Index i = 0; i < neurons_number; i++)
1366 buffer <<
"\t\tcombinations[" << i <<
"] = " <<
biases(i);
1368 for(Index j = 0; j < inputs_number; j++)
1373 buffer <<
" " << endl;
1376 buffer <<
"\t\t" << endl;
1378 return buffer.str();
1384 ostringstream buffer;
1388 buffer <<
"\t\tactivations = [None] * "<<neurons_number<<
"\n" << endl;
1390 for(Index i = 0; i < neurons_number; i++)
1392 buffer <<
"\t\tactivations[" << i <<
"] = ";
1397 case ActivationFunction::HyperbolicTangent:
1398 buffer <<
"np.tanh(combinations[" << i <<
"])\n";
1401 case ActivationFunction::RectifiedLinear:
1402 buffer <<
"np.maximum(0.0, combinations[" << i <<
"])\n";
1405 case ActivationFunction::Logistic:
1406 buffer <<
"1.0/(1.0 + np.exp(-combinations[" << i <<
"]))\n";
1409 case ActivationFunction::Threshold:
1410 buffer <<
"1.0 if combinations[" << i <<
"] >= 0.0 else 0.0\n";
1413 case ActivationFunction::SymmetricThreshold:
1414 buffer <<
"1.0 if combinations[" << i <<
"] >= 0.0 else -1.0\n";
1417 case ActivationFunction::Linear:
1418 buffer <<
"combinations[" << i <<
"]\n";
1421 case ActivationFunction::ScaledExponentialLinear:
1422 buffer <<
"1.0507*1.67326*(np.exp(combinations[" << i <<
"]) - 1.0) if combinations[" << i <<
"] < 0.0 else 1.0507*combinations[" << i <<
"]\n";
1425 case ActivationFunction::SoftPlus:
1426 buffer <<
"np.log(1.0 + np.exp(combinations[" << i <<
"]))\n";
1429 case ActivationFunction::SoftSign:
1430 buffer <<
"combinations[" << i <<
"]/(1.0 - combinations[" << i <<
"] ) if combinations[" << i <<
"] < 0.0 else combinations[" << i <<
"]/(1.0 + combinations[" << i <<
"] )\n";
1433 case ActivationFunction::ExponentialLinear:
1434 buffer <<
"1.0*(np.exp(combinations[" << i <<
"]) - 1.0) if combinations[" << i <<
"] < 0.0 else combinations[" << i <<
"]\n";
1437 case ActivationFunction::HardSigmoid:
1443 return buffer.str();
1447string PerceptronLayer::write_expression_c()
const
1449 ostringstream buffer;
1451 buffer <<
"vector<float> " <<
layer_name <<
"(const vector<float>& inputs)\n{" << endl;
1453 buffer << write_combinations_c();
1457 buffer <<
"\n\treturn activations;\n}" << endl;
1459 return buffer.str();
1463string PerceptronLayer::write_expression_python()
const
1465 ostringstream buffer;
1467 buffer <<
"\tdef " <<
layer_name <<
"(self,inputs):\n" << endl;
1469 buffer << write_combinations_python();
1473 buffer <<
"\n\t\treturn activations;\n" << endl;
1475 return buffer.str();
This abstract class represents the concept of layer of neurons in OpenNN.
string layer_name
Layer name.
Type layer_type
Layer type.
void set_parameters(const Tensor< type, 1 > &, const Index &index=0)
Sets the parameters of this layer.
string write_activation_function() const
void set_parameters_constant(const type &)
Index get_synaptic_weights_number() const
Returns the number of layer's synaptic weights.
string write_activations_python() const
const bool & get_display() const
virtual ~PerceptronLayer()
Index get_inputs_number() const
Returns the number of inputs to the layer.
void set_biases_constant(const type &)
string write_expression(const Tensor< string, 1 > &, const Tensor< string, 1 > &) const
bool display
Display messages to screen.
ActivationFunction
Enumeration of available activation functions for the perceptron neuron model.
void set_activation_function(const ActivationFunction &)
const Tensor< type, 2 > & get_biases() const
void set_synaptic_weights(const Tensor< type, 2 > &)
void set_inputs_number(const Index &)
void set_biases(const Tensor< type, 2 > &)
Index get_neurons_number() const
Returns the number of neurons in the layer.
string write_activations_c() const
void set_parameters_random()
const PerceptronLayer::ActivationFunction & get_activation_function() const
void set_synaptic_weights_constant(const type &)
void set_display(const bool &)
Tensor< type, 2 > synaptic_weights
This matrix containing conection strengths from a layer's inputs to its neurons.
const Tensor< type, 2 > & get_synaptic_weights() const
Index get_parameters_number() const
Returns the number of parameters(biases and synaptic weights) of the layer.
ActivationFunction activation_function
Activation function variable.
void set_neurons_number(const Index &)
Tensor< type, 1 > get_parameters() const
void PushText(const char *text, bool cdata=false)
Add a text node.
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.