9#include "probabilistic_layer.h"
30 set(new_inputs_number, new_neurons_number);
32 if(new_neurons_number > 1)
53Index ProbabilisticLayer::get_neurons_number()
const
59Index ProbabilisticLayer::get_biases_number()
const
77 return decision_threshold;
105 return "Competitive";
113 ostringstream buffer;
115 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
116 <<
"string write_activation_function() const method.\n"
117 <<
"Unknown probabilistic method.\n";
119 throw logic_error(buffer.str());
139 return "competitive";
147 ostringstream buffer;
149 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
150 <<
"string write_activation_function_text() const method.\n"
151 <<
"Unknown probabilistic method.\n";
153 throw logic_error(buffer.str());
188 const Index neurons_number = get_neurons_number();
190 const TensorMap < Tensor<type, 2> > bias_tensor(parameters.data(), 1, neurons_number);
202 const Index neurons_number = get_neurons_number();
203 const Index biases_number = get_biases_number();
205 const TensorMap< Tensor<type, 2> > synaptic_weights_tensor(parameters.data()+biases_number, inputs_number, neurons_number);
207 return synaptic_weights_tensor;
227 for(Index i = 0; i <
biases.size(); i++)
229 fill_n(parameters.data()+i, 1,
biases(i));
261 biases.resize(1, new_neurons_number);
280 decision_threshold = other_probabilistic_layer.decision_threshold;
286void ProbabilisticLayer::set_inputs_number(
const Index& new_inputs_number)
288 const Index neurons_number = get_neurons_number();
290 biases.resize(1, neurons_number);
296void ProbabilisticLayer::set_neurons_number(
const Index& new_neurons_number)
300 biases.resize(1, new_neurons_number);
306void ProbabilisticLayer::set_biases(
const Tensor<type, 2>& new_biases)
312void ProbabilisticLayer::set_synaptic_weights(
const Tensor<type, 2>& new_synaptic_weights)
318void ProbabilisticLayer::set_parameters(
const Tensor<type, 1>& new_parameters,
const Index& index)
320 const Index biases_number =
biases.size();
323 memcpy(
biases.data(), new_parameters.data() + index,
static_cast<size_t>(biases_number)*
sizeof(type));
324 memcpy(
synaptic_weights.data(), new_parameters.data() + biases_number + index,
static_cast<size_t>(synaptic_weights_number)*
sizeof(type));
335 if(new_decision_threshold <= 0)
337 ostringstream buffer;
339 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
340 <<
"void set_decision_threshold(const type&) method.\n"
341 <<
"Decision threshold(" << decision_threshold <<
") must be greater than zero.\n";
343 throw logic_error(buffer.str());
345 else if(new_decision_threshold >= 1)
347 ostringstream buffer;
349 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
350 <<
"void set_decision_threshold(const type&) method.\n"
351 <<
"Decision threshold(" << decision_threshold <<
") must be less than one.\n";
353 throw logic_error(buffer.str());
358 decision_threshold = new_decision_threshold;
374 const Index neurons_number = get_neurons_number();
376 if(neurons_number == 1)
385 decision_threshold = type(0.5);
399 const Index neurons_number = get_neurons_number();
401 if(neurons_number == 1 && new_activation_function == Competitive)
403 ostringstream buffer;
405 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
406 <<
"void set_activation_function(const ActivationFunction&) method.\n"
407 <<
"Activation function cannot be Competitive when the number of neurons is 1.\n";
409 throw logic_error(buffer.str());
412 if(neurons_number == 1 && new_activation_function == Softmax)
414 ostringstream buffer;
416 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
417 <<
"void set_activation_function(const ActivationFunction&) method.\n"
418 <<
"Activation function cannot be Softmax when the number of neurons is 1.\n";
420 throw logic_error(buffer.str());
423 if(neurons_number != 1 && new_activation_function == Binary)
425 ostringstream buffer;
427 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
428 <<
"void set_activation_function(const ActivationFunction&) method.\n"
429 <<
"Activation function cannot be Binary when the number of neurons is greater than 1.\n";
431 throw logic_error(buffer.str());
434 if(neurons_number != 1 && new_activation_function == Logistic)
436 ostringstream buffer;
438 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
439 <<
"void set_activation_function(const ActivationFunction&) method.\n"
440 <<
"Activation function cannot be Logistic when the number of neurons is greater than 1.\n";
442 throw logic_error(buffer.str());
457 if(new_activation_function ==
"Binary")
461 else if(new_activation_function ==
"Logistic")
465 else if(new_activation_function ==
"Competitive")
469 else if(new_activation_function ==
"Softmax")
475 ostringstream buffer;
477 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
478 <<
"void set_activation_function(const string&) method.\n"
479 <<
"Unknown probabilistic method: " << new_activation_function <<
".\n";
481 throw logic_error(buffer.str());
502 biases.setConstant(value);
515void ProbabilisticLayer::set_synaptic_weights_constant_Glorot()
526 biases.setConstant(value);
537 const type minimum = type(-0.2);
538 const type maximum = type(0.2);
540 for(Index i = 0; i <
biases.size(); i++)
542 const type random =
static_cast<type
>(rand()/(RAND_MAX+1.0));
544 biases(i) = minimum + (maximum - minimum)*random;
549 const type random =
static_cast<type
>(rand()/(RAND_MAX+1.0));
556void ProbabilisticLayer::insert_parameters(
const Tensor<type, 1>& parameters,
const Index& )
558 const Index biases_number = get_biases_number();
561 memcpy(
biases.data() , parameters.data(),
static_cast<size_t>(biases_number)*
sizeof(type));
562 memcpy(
synaptic_weights.data(), parameters.data() + biases_number,
static_cast<size_t>(synaptic_weights_number)*
sizeof(type));
566void ProbabilisticLayer::calculate_combinations(
const Tensor<type, 2>& inputs,
567 const Tensor<type, 2>& biases,
568 const Tensor<type, 2>& synaptic_weights,
569 Tensor<type, 2>& combinations)
const
571 const Index batch_samples_number = inputs.dimension(0);
572 const Index biases_number = get_neurons_number();
574 for(Index i = 0; i < biases_number; i++)
576 fill_n(combinations.data()+i*batch_samples_number, batch_samples_number,
biases(i));
579 combinations.device(*thread_pool_device) += inputs.contract(
synaptic_weights, A_B);
585void ProbabilisticLayer::calculate_activations(
const Tensor<type, 2>& combinations, Tensor<type, 2>& activations)
const
589 const Index dimensions_number = combinations.rank();
591 if(dimensions_number != 2)
593 ostringstream buffer;
595 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
596 <<
"void calculate_activations(const Tensor<type, 2>&, Tensor<type, 2>&) const method.\n"
597 <<
"Dimensions of combinations (" << dimensions_number <<
") must be 2.\n";
599 throw logic_error(buffer.str());
602 const Index neurons_number = get_neurons_number();
604 const Index combinations_columns_number = combinations.dimension(1);
606 if(combinations_columns_number != neurons_number)
608 ostringstream buffer;
610 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
611 <<
"void calculate_activations(const Tensor<type, 2>&, Tensor<type, 2>&) const method.\n"
612 <<
"Number of combinations columns (" << combinations_columns_number <<
") must be equal to number of neurons (" << neurons_number <<
").\n";
614 throw logic_error(buffer.str());
621 case ActivationFunction::Binary: binary(combinations, activations);
return;
623 case ActivationFunction::Logistic: logistic(combinations, activations);
return;
625 case ActivationFunction::Competitive: competitive(combinations, activations);
return;
627 case ActivationFunction::Softmax: softmax(combinations, activations);
return;
630 ostringstream buffer;
632 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
633 <<
"void calculate_activations(const Tensor<type, 2>&, Tensor<type, 2>&) const method.\n"
634 <<
"Unknown probabilistic method.\n";
636 throw logic_error(buffer.str());
640void ProbabilisticLayer::calculate_activations_derivatives(
const Tensor<type, 2>& combinations,
641 Tensor<type, 2>& activations,
642 Tensor<type, 3>& activations_derivatives)
const
646 const Index neurons_number = get_neurons_number();
648 const Index combinations_columns_number = combinations.dimension(1);
650 if(combinations_columns_number != neurons_number)
652 ostringstream buffer;
654 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
655 <<
"void calculate_activations_derivatives(const Tensor<type, 2>&, Tensor<type, 2>&) const method.\n"
656 <<
"Number of combinations columns (" << combinations_columns_number
657 <<
") must be equal to number of neurons (" << neurons_number <<
").\n";
659 throw logic_error(buffer.str());
666 case ActivationFunction::Logistic: logistic_derivatives(combinations, activations, activations_derivatives);
return;
668 case ActivationFunction::Softmax: softmax_derivatives(combinations, activations, activations_derivatives);
return;
682 const Index batch_size = inputs.dimension(0);
683 const Index outputs_number = get_neurons_number();
685 Tensor<type, 2> outputs(batch_size, outputs_number);
689 calculate_activations(outputs, outputs);
695void ProbabilisticLayer::forward_propagate(
const Tensor<type, 2>& inputs,
LayerForwardPropagation* forward_propagation)
700 calculate_combinations(inputs,
biases,
synaptic_weights, probabilistic_layer_forward_propagation->combinations);
702 calculate_activations_derivatives(probabilistic_layer_forward_propagation->combinations,
703 probabilistic_layer_forward_propagation->activations,
704 probabilistic_layer_forward_propagation->activations_derivatives);
708void ProbabilisticLayer::forward_propagate(
const Tensor<type, 2>& inputs,
709 Tensor<type, 1> potential_parameters,
710 LayerForwardPropagation* forward_propagation)
712 const Index neurons_number = get_neurons_number();
717 if(inputs_number != inputs.dimension(1))
719 ostringstream buffer;
721 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
722 <<
"void forward_propagate(const Tensor<type, 2>&, Tensor<type, 1>&, ForwardPropagation&) method.\n"
723 <<
"Number of inputs columns (" << inputs.dimension(1) <<
") must be equal to number of inputs ("
724 << inputs_number <<
").\n";
726 throw logic_error(buffer.str());
731 ProbabilisticLayerForwardPropagation* probabilistic_layer_forward_propagation
732 =
static_cast<ProbabilisticLayerForwardPropagation*
>(forward_propagation);
734 const TensorMap<Tensor<type, 2>> potential_biases(potential_parameters.data(), neurons_number, 1);
736 const TensorMap<Tensor<type, 2>> potential_synaptic_weights(potential_parameters.data()+neurons_number,
737 inputs_number, neurons_number);
739 calculate_combinations(inputs, potential_biases, potential_synaptic_weights, probabilistic_layer_forward_propagation->combinations);
741 calculate_activations_derivatives(probabilistic_layer_forward_propagation->combinations,
742 probabilistic_layer_forward_propagation->activations,
743 probabilistic_layer_forward_propagation->activations_derivatives);
749void ProbabilisticLayer::calculate_error_gradient(
const Tensor<type, 2>& inputs,
750 LayerForwardPropagation* forward_propagation,
751 LayerBackPropagation* back_propagation)
const
753 ProbabilisticLayerForwardPropagation* probabilistic_layer_forward_propagation =
754 static_cast<ProbabilisticLayerForwardPropagation*
>(forward_propagation);
756 ProbabilisticLayerBackPropagation* probabilistic_layer_back_propagation =
757 static_cast<ProbabilisticLayerBackPropagation*
>(back_propagation);
759 const Index samples_number = inputs.dimension(0);
760 const Index neurons_number = get_neurons_number();
762 if(neurons_number == 1)
764 TensorMap< Tensor<type, 2> > activations_derivatives(probabilistic_layer_forward_propagation->activations_derivatives.data(), samples_number, neurons_number);
766 probabilistic_layer_back_propagation->biases_derivatives.device(*thread_pool_device) =
767 (probabilistic_layer_back_propagation->delta * activations_derivatives).sum(Eigen::array<Index, 1>({0}));
769 probabilistic_layer_back_propagation->synaptic_weights_derivatives.device(*thread_pool_device) =
770 inputs.contract((probabilistic_layer_back_propagation->delta * activations_derivatives), AT_B);
776 const Index step = neurons_number * neurons_number;
778 for(Index i = 0; i < samples_number; i++)
780 probabilistic_layer_back_propagation->delta_row = probabilistic_layer_back_propagation->delta.chip(i,0);
782 TensorMap< Tensor<type, 2> > activations_derivatives_matrix(probabilistic_layer_forward_propagation->activations_derivatives.data() + i*step,
783 neurons_number, neurons_number);
785 probabilistic_layer_back_propagation->error_combinations_derivatives.chip(i,0) =
786 probabilistic_layer_back_propagation->delta_row.contract(activations_derivatives_matrix, AT_B);
789 probabilistic_layer_back_propagation->biases_derivatives.device(*thread_pool_device) =
790 (probabilistic_layer_back_propagation->error_combinations_derivatives).sum(Eigen::array<Index, 1>({0}));
792 probabilistic_layer_back_propagation->synaptic_weights_derivatives.device(*thread_pool_device) =
793 inputs.contract(probabilistic_layer_back_propagation->error_combinations_derivatives, AT_B);
797 TensorMap< Tensor<type, 2> > activations_derivatives(probabilistic_layer_forward_propagation->activations_derivatives.data(), samples_number, neurons_number);
799 probabilistic_layer_back_propagation->biases_derivatives.device(*thread_pool_device) =
800 (probabilistic_layer_back_propagation->delta*activations_derivatives).sum(Eigen::array<Index, 1>({0}));
802 probabilistic_layer_back_propagation->synaptic_weights_derivatives.device(*thread_pool_device) =
803 inputs.contract((probabilistic_layer_back_propagation->delta*activations_derivatives), AT_B);
809void ProbabilisticLayer::insert_gradient(LayerBackPropagation* back_propagation,
const Index& index, Tensor<type, 1>& gradient)
const
811 const Index biases_number = get_biases_number();
814 const ProbabilisticLayerBackPropagation* probabilistic_layer_back_propagation =
815 static_cast<ProbabilisticLayerBackPropagation*
>(back_propagation);
817 memcpy(gradient.data() + index,
818 probabilistic_layer_back_propagation->biases_derivatives.data(),
819 static_cast<size_t>(biases_number)*
sizeof(type));
821 memcpy(gradient.data() + index + biases_number,
822 probabilistic_layer_back_propagation->synaptic_weights_derivatives.data(),
823 static_cast<size_t>(synaptic_weights_number)*
sizeof(type));
827void ProbabilisticLayer::calculate_squared_errors_Jacobian_lm(
const Tensor<type, 2>& inputs,
828 LayerForwardPropagation* forward_propagation,
829 LayerBackPropagationLM* back_propagation)
831 ProbabilisticLayerForwardPropagation* probabilistic_layer_forward_propagation =
832 static_cast<ProbabilisticLayerForwardPropagation*
>(forward_propagation);
834 ProbabilisticLayerBackPropagationLM* probabilistic_layer_back_propagation_lm =
835 static_cast<ProbabilisticLayerBackPropagationLM*
>(back_propagation);
837 const Index samples_number = inputs.dimension(0);
840 const Index neurons_number = get_neurons_number();
842 probabilistic_layer_back_propagation_lm->squared_errors_Jacobian.setZero();
846 Index parameter_index = 0;
848 for(Index sample = 0; sample < samples_number; sample++)
852 for(Index neuron = 0; neuron < neurons_number; neuron++)
854 for(Index input = 0; input < inputs_number; input++)
856 probabilistic_layer_back_propagation_lm->squared_errors_Jacobian(sample, neurons_number+parameter_index) =
857 probabilistic_layer_back_propagation_lm->error_combinations_derivatives(sample, neuron) *
858 inputs(sample, input);
863 probabilistic_layer_back_propagation_lm->squared_errors_Jacobian(sample, neuron) =
864 probabilistic_layer_back_propagation_lm->error_combinations_derivatives(sample, neuron);
870 Index parameter_index = 0;
872 for(Index sample = 0; sample < samples_number; sample++)
876 for(Index neuron = 0; neuron < neurons_number; neuron++)
878 for(Index input = 0; input < inputs_number; input++)
880 probabilistic_layer_back_propagation_lm->squared_errors_Jacobian(sample, neurons_number+parameter_index) =
881 probabilistic_layer_back_propagation_lm->delta(sample, neuron) *
882 probabilistic_layer_forward_propagation->activations_derivatives(sample, neuron, 0) *
883 inputs(sample, input);
888 probabilistic_layer_back_propagation_lm->squared_errors_Jacobian(sample, neuron) =
889 probabilistic_layer_back_propagation_lm->delta(sample, neuron) *
890 probabilistic_layer_forward_propagation->activations_derivatives(sample, neuron, 0);
897void ProbabilisticLayer::insert_squared_errors_Jacobian_lm(LayerBackPropagationLM * back_propagation ,
899 Tensor<type, 2>& squared_errors_Jacobian)
const
901 ProbabilisticLayerBackPropagationLM* probabilistic_layer_back_propagation_lm =
902 static_cast<ProbabilisticLayerBackPropagationLM*
>(back_propagation);
904 const Index batch_samples_number = probabilistic_layer_back_propagation_lm->squared_errors_Jacobian.dimension(0);
907 memcpy(squared_errors_Jacobian.data() + index,
908 probabilistic_layer_back_propagation_lm->squared_errors_Jacobian.data(),
909 static_cast<size_t>(layer_parameters_number*batch_samples_number)*
sizeof(type));
918 ostringstream buffer;
922 file_stream.OpenElement(
"ProbabilisticLayer");
926 file_stream.OpenElement(
"InputsNumber");
931 file_stream.
PushText(buffer.str().c_str());
937 file_stream.OpenElement(
"NeuronsNumber");
940 buffer << get_neurons_number();
942 file_stream.
PushText(buffer.str().c_str());
948 file_stream.OpenElement(
"ActivationFunction");
956 file_stream.OpenElement(
"Parameters");
961 const Index parameters_size = parameters.size();
963 for(Index i = 0; i < parameters_size; i++)
965 buffer << parameters(i);
967 if(i != (parameters_size-1)) buffer <<
" ";
970 file_stream.
PushText(buffer.str().c_str());
976 file_stream.OpenElement(
"DecisionThreshold");
979 buffer << decision_threshold;
981 file_stream.
PushText(buffer.str().c_str());
996 ostringstream buffer;
1000 const tinyxml2::XMLElement* probabilistic_layer_element = document.FirstChildElement(
"ProbabilisticLayer");
1002 if(!probabilistic_layer_element)
1004 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
1005 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1006 <<
"Probabilistic layer element is nullptr.\n";
1008 throw logic_error(buffer.str());
1013 const tinyxml2::XMLElement* inputs_number_element = probabilistic_layer_element->FirstChildElement(
"InputsNumber");
1015 if(!inputs_number_element)
1017 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
1018 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1019 <<
"Inputs number element is nullptr.\n";
1021 throw logic_error(buffer.str());
1024 Index new_inputs_number;
1026 if(inputs_number_element->GetText())
1028 new_inputs_number =
static_cast<Index
>(stoi(inputs_number_element->GetText()));
1033 const tinyxml2::XMLElement* neurons_number_element = probabilistic_layer_element->FirstChildElement(
"NeuronsNumber");
1035 if(!inputs_number_element)
1037 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
1038 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1039 <<
"Neurons number element is nullptr.\n";
1041 throw logic_error(buffer.str());
1044 Index new_neurons_number;
1046 if(neurons_number_element->GetText())
1048 new_neurons_number =
static_cast<Index
>(stoi(neurons_number_element->GetText()));
1051 set(new_inputs_number, new_neurons_number);
1055 const tinyxml2::XMLElement* activation_function_element = probabilistic_layer_element->FirstChildElement(
"ActivationFunction");
1057 if(!activation_function_element)
1059 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
1060 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1061 <<
"Activation function element is nullptr.\n";
1063 throw logic_error(buffer.str());
1066 if(activation_function_element->GetText())
1073 const tinyxml2::XMLElement* parameters_element = probabilistic_layer_element->FirstChildElement(
"Parameters");
1075 if(!parameters_element)
1077 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
1078 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1079 <<
"Parameters element is nullptr.\n";
1081 throw logic_error(buffer.str());
1084 if(parameters_element->GetText())
1086 const string parameters_string = parameters_element->GetText();
1088 set_parameters(to_type_vector(parameters_string,
' '));
1093 const tinyxml2::XMLElement* decision_threshold_element = probabilistic_layer_element->FirstChildElement(
"DecisionThreshold");
1095 if(!decision_threshold_element)
1097 buffer <<
"OpenNN Exception: ProbabilisticLayer class.\n"
1098 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1099 <<
"Decision threshold element is nullptr.\n";
1101 throw logic_error(buffer.str());
1104 if(decision_threshold_element->GetText())
1111 const tinyxml2::XMLElement* display_element = probabilistic_layer_element->FirstChildElement(
"Display");
1115 const string new_display_string = display_element->GetText();
1121 catch(
const logic_error& e)
1123 cerr << e.what() << endl;
1135 ostringstream buffer;
1139 for(Index j = 0; j < outputs_names.size(); j++)
1141 buffer << outputs_names(j) <<
" = binary(" << inputs_names(j) <<
");\n";
1143 return buffer.str();
1152 const Tensor<string, 1>& outputs_names)
const
1154 ostringstream buffer;
1156 for(Index j = 0; j < outputs_names.size(); j++)
1158 buffer << outputs_names(j) <<
" = logistic(" << inputs_names(j) <<
");\n";
1160 return buffer.str();
1170 ostringstream buffer;
1172 for(Index j = 0; j < outputs_names.size(); j++)
1174 buffer << outputs_names(j) <<
" = competitive(" << inputs_names(j) <<
");\n";
1176 return buffer.str();
1186 ostringstream buffer;
1188 for(Index j = 0; j < outputs_names.size(); j++)
1190 buffer << outputs_names(j) <<
" = softmax(" << inputs_names(j) <<
");\n";
1193 return buffer.str();
1202 const Tensor<string, 1>& outputs_names)
const
1204 ostringstream buffer;
1206 for(Index j = 0; j < outputs_names.size(); j++)
1208 buffer << outputs_names(j) <<
" = (" << inputs_names(j) <<
");\n";
1210 return buffer.str();
1214string ProbabilisticLayer::write_combinations_c()
const
1216 ostringstream buffer;
1219 const Index neurons_number = get_neurons_number();
1221 buffer <<
"\tvector<float> combinations(" << neurons_number <<
");\n" << endl;
1223 for(Index i = 0; i < neurons_number; i++)
1225 buffer <<
"\tcombinations[" << i <<
"] = " <<
biases(i);
1227 for(Index j = 0; j < inputs_number; j++)
1232 buffer <<
";" << endl;
1235 return buffer.str();
1241 ostringstream buffer;
1243 const Index neurons_number = get_neurons_number();
1245 buffer <<
"\n\tvector<float> activations(" << neurons_number <<
");\n" << endl;
1247 for(Index i = 0; i < neurons_number; i++)
1251 case ActivationFunction::Binary:
1252 buffer <<
"\tactivations[" << i <<
"] = combinations[" << i <<
"] < 0.5 ? 0.0 : 1.0;\n";
1255 case ActivationFunction::Logistic:
1256 buffer <<
"\tactivations[" << i <<
"] = 1.0/(1.0 + exp(-combinations[" << i <<
"]));\n";
1259 case ActivationFunction::Competitive:
1266 case ActivationFunction::Softmax:
1270 buffer <<
"\tfloat sum = 0;\n" << endl;
1272 buffer <<
"\tsum = ";
1274 for(Index i = 0; i < neurons_number; i++)
1276 buffer <<
"exp(combinations[" << i <<
"])";
1278 if(i != neurons_number-1) buffer <<
" + ";
1281 buffer <<
";\n" << endl;
1283 for(Index i = 0; i < neurons_number; i++)
1285 buffer <<
"\tactivations[" << i <<
"] = exp(combinations[" << i <<
"])/sum;\n";
1292 return buffer.str();
1296string ProbabilisticLayer::write_combinations_python()
const
1298 ostringstream buffer;
1301 const Index neurons_number = get_neurons_number();
1303 buffer <<
"\t\tcombinations = [None] * "<<neurons_number<<
"\n" << endl;
1305 for(Index i = 0; i < neurons_number; i++)
1307 buffer <<
"\t\tcombinations[" << i <<
"] = " <<
biases(i);
1309 for(Index j = 0; j < inputs_number; j++)
1314 buffer <<
" " << endl;
1317 buffer <<
"\t\t" << endl;
1319 return buffer.str();
1323string ProbabilisticLayer::write_activations_python()
const
1325 ostringstream buffer;
1327 const Index neurons_number = get_neurons_number();
1329 buffer <<
"\t\tactivations = [None] * "<<neurons_number<<
"\n" << endl;
1331 for(Index i = 0; i < neurons_number; i++)
1335 case ActivationFunction::Binary:
1336 buffer <<
"\t\tactivations[" << i <<
"] = 0.0 if combinations[" << i <<
"] < 0.5 else 1.0\n";
1339 case ActivationFunction::Logistic:
1340 buffer <<
"\t\tactivations[" << i <<
"] = 1.0/(1.0 + np.exp(-combinations[" << i <<
"]));\n";
1343 case ActivationFunction::Competitive:
1347 buffer <<
"\t\tfor i, value in enumerate(combinations):"<<endl;
1349 buffer <<
"\t\t\tif(max(combinations) == value):"<<endl;
1351 buffer <<
"\t\t\t\tactivations[i] = 1"<<endl;
1353 buffer <<
"\t\t\telse:"<<endl;
1355 buffer <<
"\t\t\t\tactivations[i] = 0"<<endl;
1360 case ActivationFunction::Softmax:
1364 buffer <<
"\t\tsum_ = 0;\n" << endl;
1366 buffer <<
"\t\tsum_ = ";
1368 for(Index i = 0; i < neurons_number; i++)
1370 buffer <<
"\tnp.exp(combinations[" << i <<
"])";
1372 if(i != neurons_number-1) buffer <<
" + ";
1375 buffer <<
";\n" << endl;
1377 for(Index i = 0; i < neurons_number; i++)
1379 buffer <<
"\t\tactivations[" << i <<
"] = np.exp(combinations[" << i <<
"])/sum_;\n";
1387 return buffer.str();
1391string ProbabilisticLayer::write_combinations(
const Tensor<string, 1>& inputs_names)
const
1393 ostringstream buffer;
1396 const Index neurons_number = get_neurons_number();
1398 for(Index i = 0; i < neurons_number; i++)
1400 buffer <<
"probabilistic_layer_combinations_" << to_string(i) <<
" = " <<
biases(i);
1402 for(Index j = 0; j < inputs_number; j++)
1407 buffer <<
" " << endl;
1410 buffer <<
"\t" << endl;
1412 return buffer.str();
1416string ProbabilisticLayer::write_activations(
const Tensor<string, 1>& outputs_names)
const
1418 ostringstream buffer;
1420 const Index neurons_number = get_neurons_number();
1422 for(Index i = 0; i < neurons_number; i++)
1426 case ActivationFunction::Binary:
1428 buffer <<
"\tif" <<
"probabilistic_layer_combinations_" << to_string(i) <<
" < 0.5, " << outputs_names(i) <<
"= 0.0. Else " << outputs_names(i) <<
" = 1.0\n";
1432 case ActivationFunction::Logistic:
1434 buffer << outputs_names(i) <<
" = 1.0/(1.0 + exp(-" <<
"probabilistic_layer_combinations_" << to_string(i) <<
");\n";
1438 case ActivationFunction::Competitive:
1441 buffer <<
"\tfor each probabilistic_layer_combinations_i:"<<endl;
1443 buffer <<
"\t\tif probabilistic_layer_combinations_i is equal to max(probabilistic_layer_combinations_i):"<<endl;
1445 buffer <<
"\t\t\tactivations[i] = 1"<<endl;
1447 buffer <<
"\t\telse:"<<endl;
1449 buffer <<
"\t\t\tactivations[i] = 0"<<endl;
1454 case ActivationFunction::Softmax:
1460 for(Index i = 0; i < neurons_number; i++)
1462 buffer <<
"exp(probabilistic_layer_combinations_" << to_string(i) <<
")";
1464 if(i != neurons_number-1) buffer <<
" + ";
1467 buffer <<
";\n" << endl;
1469 for(Index i = 0; i < neurons_number; i++)
1471 buffer << outputs_names(i) <<
" = exp(probabilistic_layer_combinations_" << to_string(i) <<
")/sum;\n";
1479 return buffer.str();
1483string ProbabilisticLayer::write_expression_c()
const
1485 ostringstream buffer;
1487 buffer <<
"vector<float> " <<
layer_name <<
"(const vector<float>& inputs)\n{" << endl;
1489 buffer << write_combinations_c();
1493 buffer <<
"\n\treturn activations;\n}" << endl;
1495 return buffer.str();
1499string ProbabilisticLayer::write_expression_python()
const
1501 ostringstream buffer;
1503 buffer <<
"\tdef " <<
layer_name <<
"(self, inputs):\n" << endl;
1505 buffer << write_combinations_python();
1507 buffer << write_activations_python();
1509 buffer <<
"\n\t\treturn activations;\n" << endl;
1511 return buffer.str();
1515string ProbabilisticLayer::write_expression(
const Tensor<string, 1>& inputs_names,
1516 const Tensor<string, 1>& outputs_names)
const
1518 ostringstream buffer;
1520 buffer << write_combinations(inputs_names);
1522 buffer << write_activations(outputs_names);
1524 return buffer.str();
string layer_name
Layer name.
Type layer_type
Layer type.
This class represents a layer of probabilistic neurons.
string write_activation_function() const
void set_parameters_constant(const type &)
string write_softmax_expression(const Tensor< string, 1 > &, const Tensor< string, 1 > &) const
Index get_synaptic_weights_number() const
Returns the number of layer's synaptic weights.
const bool & get_display() const
Index get_inputs_number() const
Returns the number of inputs.
const ActivationFunction & get_activation_function() const
string write_activation_function_text() const
void set_biases_constant(const type &)
string write_logistic_expression(const Tensor< string, 1 > &, const Tensor< string, 1 > &) const
void from_XML(const tinyxml2::XMLDocument &)
virtual void set_default()
bool display
Display messages to screen.
ActivationFunction
Enumeration of available methods for interpreting variables as probabilities.
virtual ~ProbabilisticLayer()
void set_activation_function(const ActivationFunction &)
const Tensor< type, 2 > & get_biases() const
Returns the biases of the layer.
const type & get_decision_threshold() const
Returns the decision threshold.
string write_no_probabilistic_expression(const Tensor< string, 1 > &, const Tensor< string, 1 > &) const
Tensor< type, 2 > calculate_outputs(const Tensor< type, 2 > &)
string write_activations_c() const
string write_competitive_expression(const Tensor< string, 1 > &, const Tensor< string, 1 > &) const
void set_parameters_random()
string write_binary_expression(const Tensor< string, 1 > &, const Tensor< string, 1 > &) const
void set_decision_threshold(const type &)
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.
void write_XML(tinyxml2::XMLPrinter &) const
const Tensor< type, 2 > & get_synaptic_weights() const
Returns the synaptic weights of the layer.
Index get_parameters_number() const
Returns the number of parameters(biases and synaptic weights) of the layer.
ActivationFunction activation_function
Activation function variable.
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.