1 // Copyright (C) 2013-2022 CEA/DEN
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU Lesser General Public License as published
5 // by the Free Software Foundation, either version 3 of the License, or any
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 \date Wed Nov 20 11:04:17 2013
21 \brief Implémentation de la classe PMMLlib
26 #include "PMMLlib.hxx"
42 //**************************************************************
46 // méthodes communes à tous les types de modèles *
50 //**************************************************************
53 * Constructor to read a PMML file.
54 * @param file Name of the PMML file to read
55 * @param log Flag to print logs or not
57 PMMLlib::PMMLlib(std::string file,bool log) :
64 _currentModelName(""),
65 _currentModelType(kUNDEFINED)
69 xmlKeepBlanksDefault(0);
71 _doc = xmlParseFile(_pmmlFile.c_str());
74 _rootNode = xmlDocGetRootElement(_doc);
78 throw string("Unable to read PMML file.");
80 catch ( std::string msg )
90 * Constructor to create a PMML file.
91 * @brief This constructor is mandatory for Swig because it can be used with no parameters.
92 * @param log Flag to print logs or not
94 PMMLlib::PMMLlib(bool log):
101 _currentModelName(""),
102 _currentModelType(kUNDEFINED)
108 * Destructor of the class.
116 cout << "~PMMLlib" << endl;
120 * Set the current model and its type.
121 * @param modelName Name of the model to load (ie content of 'modelName' attribute)
122 * @param type Type of PMML to read: one of kANN or kLR
124 void PMMLlib::SetCurrentModel(std::string modelName,
127 _currentModelName = modelName;
128 _currentModelType = type;
132 _currentModelNode = GetNeuralNetPtr(modelName);
135 _currentModelNode = GetRegressionPtr(modelName);
138 throw string("Unknown PMML type.");
141 if ( _currentModelNode == NULL )
142 throw string("Model not found.");
146 * Set the current model and its type.
147 * @brief Throw an exception if there is no model or more than one model with name "modelName" in the PMML file
148 * @param modelName Name of the model to load (ie content of 'modelName' attribute)
150 void PMMLlib::SetCurrentModel(std::string modelName)
152 if (_rootNode == NULL)
153 throw string("No PMML file set.");
154 xmlNodePtr node = NULL;
156 node = _rootNode->children;
159 string nodeModelName = _getProp(node, string("modelName"));
160 if ( nodeModelName == modelName )
163 _currentModelNode = node;
164 _currentModelName = modelName;
165 _currentModelType = GetCurrentModelType();
171 std::ostringstream oss;
173 string msg = "SetCurrentModel(modelName) : found " + oss.str() + " model(s) in PMML file.\n";
174 msg += "Use SetCurrentModel(modelName,type).";
180 * Set the current model and its type.
181 * @brief Throw an exception if no model is found or if there are more than one model in the PMLL file
183 void PMMLlib::SetCurrentModel()
188 std::ostringstream oss;
190 string msg = "SetCurrentModel() : found " + oss.str() + " model(s) in PMML file.\n";
191 msg += "Use SetCurrentModel(modelName) or SetCurrentModel(modelName,type).";
194 _currentModelNode = GetChildByName(_rootNode,"NeuralNetwork");
195 _currentModelType = kANN;
196 if (_currentModelNode == NULL)
198 _currentModelNode = GetChildByName(_rootNode,"RegressionModel");
199 _currentModelType = kLR;
201 if (_currentModelNode == NULL)
203 string msg("Couldn't get node in SetCurrentModel().");
206 _currentModelName = _getProp(_currentModelNode, string("modelName"));
210 * Make the string used by PMMLlib::printLog.
213 std::string PMMLlib::makeLog() const
216 out << "**\n**** Display of PMMLlib ****" << endl;
217 out << " ** _pmmlFile[" << _pmmlFile << "]" << endl;
218 out << " ** _log[" << (_log?1:0) << "]" << endl;
219 out << "**\n**** End of display of PMMLlib ****" << endl;
224 * Print some information about the current PMML object.
226 void PMMLlib::printLog() const
228 string log = makeLog();
233 * Set the root node in the tree:
235 * <PMML version="4.1" xmlns="http://www.dmg.org/PMML-4_1">
238 void PMMLlib::SetRootNode()
240 xmlChar * xs = _stringToXmlChar("1.0");
241 _doc = xmlNewDoc(xs);
244 xmlChar *xp = _stringToXmlChar("PMML");
245 _rootNode = xmlNewNode(0, xp);
248 xmlNewProp(_rootNode, (const xmlChar*)"xmlns", (const xmlChar*)"http://www.dmg.org/PMML-4_1");
249 xmlNewProp(_rootNode, (const xmlChar*)"version", (const xmlChar*)"4.1");
251 xmlDocSetRootElement(_doc, _rootNode);
256 * Set the header node in the tree.
257 * @param copyright Copyright of the PMML file
258 * @param description Description of the model
259 * @param appName Name of the application that produced the file
260 * @param appVersion Version of the application that produced the file
261 * @param annotation Some annotation
263 void PMMLlib::SetHeader(std::string copyright,
264 std::string description,
266 std::string appVersion,
267 std::string annotation)
269 xmlNodePtr headerNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"Header", 0);
270 xmlNewProp(headerNode, (const xmlChar*)"copyright", (const xmlChar*)(copyright.c_str()));
271 xmlNewProp(headerNode, (const xmlChar*)"description", (const xmlChar*)(description.c_str()));
273 xmlNodePtr appNode = xmlNewChild(headerNode, 0, (const xmlChar*)"Application", 0);
274 xmlNewProp(appNode, (const xmlChar*)"name", (const xmlChar*)(appName.c_str()));
275 xmlNewProp(appNode, (const xmlChar*)"version", (const xmlChar*)(appVersion.c_str()));
277 xmlNewChild(headerNode, 0, (const xmlChar*)"Annotation", (const xmlChar*)(annotation.c_str()));
281 * Add the MiningSchema node.
282 * @brief Common to all models.
283 * @param name Value of property "name".
284 * @param usageType Value of property "usageType".
286 void PMMLlib::AddMiningSchema(std::string name,
287 std::string usageType)
289 xmlNodePtr netNode = _currentModelNode;
291 // if 'MiningSchema' node does not exist, create it
292 xmlNodePtr miningSchemaNode = GetChildByName(netNode, "MiningSchema");
293 if(!miningSchemaNode)
295 miningSchemaNode = xmlNewChild(netNode, 0, (const xmlChar*)"MiningSchema", 0);
298 // then append the node
299 xmlNodePtr miningFieldNode = xmlNewChild(miningSchemaNode, 0, (const xmlChar*)"MiningField", 0);
300 xmlNewProp(miningFieldNode, (const xmlChar*)"name", (const xmlChar*)(name.c_str()) );
301 xmlNewProp(miningFieldNode, (const xmlChar*)"usageType", (const xmlChar*)(usageType.c_str()) );
305 * Get the child of a node from the name of this node
306 * @param node Start node for the research
307 * @param nodeName Name of the node to find
308 * @return Pointer to the node found
310 xmlNodePtr PMMLlib::GetChildByName(xmlNodePtr node,
311 std::string nodeName)
316 xmlNodePtr childNode = node->children;
317 if ( childNode == NULL )
320 const xmlChar* name = childNode->name;
323 strName = _xmlCharToString(name);
325 while( (childNode != NULL) && (strName != nodeName) )
327 childNode = childNode->next;
328 if ( childNode == NULL )
330 name = childNode->name;
332 strName = _xmlCharToString(name);
338 * Count the tags of all types of models (NeuralNetwork and RegressionModel).
339 * @return Number of models
341 void PMMLlib::CountModels()
344 nCount = CountNeuralNetModels() + CountRegressionModels();
346 cout << " ** End Of Count Models nCount[" << nCount << "]" << endl;
351 * Count NeuralNetwork models tags in the PMML file.
352 * @return Number of models
354 int PMMLlib::CountNeuralNetModels()
357 xmlNodePtr ptr = GetChildByName(_rootNode,"NeuralNetwork");
359 while (ptr != NULL && _xmlCharToString(ptr->name) == "NeuralNetwork")
363 cout << " ** nCount[" << nCount << "]" << endl;
367 cout << " ** End Of CountNetworks nCount[" << nCount << "]" << endl;
372 * Count RegressionModel models tags in the PMML file.
373 * @return Number of models
375 int PMMLlib::CountRegressionModels()
378 xmlNodePtr ptr = GetChildByName(_rootNode,"RegressionModel");
380 while (ptr != NULL && _xmlCharToString(ptr->name) == "RegressionModel")
384 cout << " ** nCount[" << nCount << "]" << endl;
388 cout << " ** End Of CountRegressions nCount[" << nCount << "]" << endl;
393 * Get the number of models
394 * @return Number of models
396 int PMMLlib::GetModelsNb()
402 * Get the name of the XML node of a given model
403 * @param node Model node
404 * @return value of attribute "modelName" of the model node
406 std::string PMMLlib::GetModelName(xmlNodePtr node)
409 name = _getProp(node, string("modelName") );
414 * Get a pointer to the index-th node named name
415 * @param index Index of the node to search
416 * @param name Name of the node
417 * @return Pointer to the node found
419 xmlNodePtr PMMLlib::GetPtr(int index,
422 xmlNodePtr node = NULL;
426 _rootNode = xmlDocGetRootElement(_doc);
427 node = GetChildByName(_rootNode, name);
430 while ((i != index) && (node != NULL))
440 * Get a pointer to the node named name whose 'modelName' attribute is ann_name
441 * @param modelName Model name of the node to search
442 * @param nodeName Name of the node
443 * @return Pointer to the node found
445 xmlNodePtr PMMLlib::GetPtr(std::string myModelName,
446 std::string nodeName)
448 xmlNodePtr node = NULL;
451 node = GetChildByName(_rootNode, nodeName);
454 string modelName = _getProp(node, string("modelName"));
456 while ( (node != NULL) && modelName != myModelName )
461 modelName = _getProp(node, string("modelName"));
470 * Get the tag of the current model.
471 * @return Current model tag
473 std::string PMMLlib::GetTypeString()
476 switch(_currentModelType)
479 name = "NeuralNetwork";
482 name = "RegressionModel";
485 throw string("Unknown PMML type.");
492 * Get the current model type.
493 * @brief type is kUNDEFINED if no model is set or if model type is not handled
496 PMMLType PMMLlib::GetCurrentModelType()
498 PMMLType type = kUNDEFINED ;
499 if ( ! _currentModelNode )
501 string name = _xmlCharToString(_currentModelNode->name);
502 if ( name == "NeuralNetwork" )
504 else if ( name == "RegressionModel" )
510 * Get the current model name.
511 * @brief name is "" if no model is set
514 std::string PMMLlib::GetCurrentModelName()
516 if ( ! _currentModelNode )
518 string name = _getProp(_currentModelNode, string("modelName"));
523 * Unlink the current model node.
525 void PMMLlib::UnlinkNode()
527 xmlNodePtr ptr = _currentModelNode ;
528 xmlUnlinkNode( ptr );
533 * Make a backup of the current model node.
535 void PMMLlib::BackupNode()
537 // Node name depending of PMML type
538 string name = GetTypeString();
539 // Find the last save index number
542 ss << _currentModelName << "_" << nCrtIndex;
543 xmlNodePtr ptr = GetPtr(ss.str(), name);
548 cout << " ** nCrtIndex[" << nCrtIndex << "]" << endl;
551 ss << _currentModelName << "_" << nCrtIndex;
552 ptr = GetPtr(ss.str(), name);
555 cout << " *** Node \"" << _currentModelName << "\" found, then backup it with index [" << nCrtIndex << "]" << endl;
557 xmlUnsetProp(_currentModelNode, (const xmlChar*)"modelName");
558 xmlNewProp(_currentModelNode, (const xmlChar*)"modelName", (const xmlChar*)(ss.str().c_str()));
562 * Save the XML tree in the PMML file
564 void PMMLlib::Write()
566 // Enregistrement de l'arbre DOM dans le fichier pmml
568 // Mise à jour du nombre de modèles
573 * Save the XML tree in a given file
574 * @param Name of the file
576 void PMMLlib::Write(std::string file)
578 // Enregistrement de l'arbre DOM sous forme de fichier pmml
579 int ret = xmlSaveFormatFile( file.c_str(), _doc, 1);
582 std::string msg(" *** Error :: unable to write the PMML file \"" + file + "\"") ;
587 cout << " *** Write the PMML file \"" << file <<"\"" << endl;
591 * Export the current model as a function in a Cpp file.
592 * @param file Name of the file
593 * @param functionName Name of the function
594 * @param header Header of the function
596 void PMMLlib::ExportCpp(std::string file,
597 std::string functionName,
600 if ( _currentModelType == kANN )
601 ExportNeuralNetworkCpp(file,functionName, header);
602 else if ( _currentModelType == kLR )
604 ExportLinearRegressionCpp(file, functionName, header);
607 throw string("ExportCpp : PMML type not handled.");
611 * Export the current model as a function in a Fortran file.
612 * @param file Name of the file
613 * @param functionName Name of the function
614 * @param header Header of the function
616 void PMMLlib::ExportFortran(std::string file,
617 std::string functionName,
620 if ( _currentModelType == kANN )
621 ExportNeuralNetworkFortran(file,functionName, header);
622 else if ( _currentModelType == kLR )
623 ExportLinearRegressionFortran(file,functionName, header);
625 throw string("ExportFortran : PMML type not handled.");
629 * Export the current model as a function in a Python file.
630 * @param file Name of the file
631 * @param functionName Name of the function
632 * @param header Header of the function
634 void PMMLlib::ExportPython(std::string file,
635 std::string functionName,
638 if ( _currentModelType == kANN )
639 ExportNeuralNetworkPython(file,functionName, header);
640 else if ( _currentModelType == kLR )
641 ExportLinearRegressionPython(file,functionName, header);
643 throw string("ExportPython : PMML type not handled.");
647 * Export the current model as a function in a Python string.
648 * @param file Name of the file
649 * @param functionName Name of the function
650 * @param header Header of the function
651 * @return Function as a string
653 std::string PMMLlib::ExportPyStr(std::string functionName,
656 if ( _currentModelType == kANN )
657 return ExportNeuralNetworkPyStr(functionName, header);
658 else if ( _currentModelType == kLR )
659 return ExportLinearRegressionPyStr(functionName, header);
661 throw string("ExportPyStr : PMML type not handled.");
665 * Conversion from a libxml2 string (xmlChar *) to a standard C++ string.
666 * \param xs a constant libxml string.
667 * \return a C++ std::string (contains the same text as xs).
669 std::string PMMLlib::_xmlCharToString(const xmlChar *xs) const
671 size_t i, L = xmlStrlen(xs);
674 for (i=0; *xs; s[i++] = *xs++);
679 * Conversion from a a standard C++ string to a libxml2 string (xmlChar *).
680 * \param s Constant C++ std::string (contains the same text as xs)
681 * \return Constant libxml string.
683 xmlChar * PMMLlib::_stringToXmlChar(const std::string &s) const
685 return xmlCharStrdup(s.c_str());
689 * Get the value of a node property.
691 * \param prop Property
692 * \return Constant libxml string.
694 std::string PMMLlib::_getProp(const xmlNodePtr node,
695 std::string const & prop ) const
697 std::string name("");
700 xmlChar *xp = _stringToXmlChar(prop);
702 attr = xmlGetProp(node, xp );
705 name = _xmlCharToString(attr );
713 //**************************************************************
717 // méthodes propres au NeuralNetwork *
721 //**************************************************************
724 * Check if the current model type is kANN.
725 * \brief Called in all methods specific to the NeuralNetwork model.
726 * \brief Throw an exception if the model type is not kANN.
728 void PMMLlib::CheckNeuralNetwork()
730 if ( _currentModelType != kANN )
731 throw string("Use this method with NeuralNetwork models.");
735 * Get the XML node of a given network from the index
736 * @param index Index of the neural network
737 * @return Pointer to the XML node
739 xmlNodePtr PMMLlib::GetNeuralNetPtr(int index)
741 return GetPtr(index, GetTypeString() );
745 * Get the XML node of a given network model
746 * @param name Name of the neural network
747 * @return Pointer to the XML node
749 xmlNodePtr PMMLlib::GetNeuralNetPtr(std::string name)
751 return GetPtr(name, GetTypeString() );
755 * Read the structure of the network
756 * @brief Specific to NeuralNetwork
757 * @return Structure read
759 std::string PMMLlib::ReadNetworkStructure()
761 CheckNeuralNetwork();
763 string structure("");
764 // Treatment of the input
765 xmlNodePtr inputNodes = GetChildByName(_currentModelNode,"NeuralInputs");
766 if ( inputNodes != NULL )
768 xmlNodePtr inputNode = GetChildByName(inputNodes,"NeuralInput");
769 if ( inputNode != NULL )
771 while (inputNode != NULL)
773 xmlNodePtr child = GetChildByName(inputNode,"DerivedField");
776 xmlNodePtr fieldName = child->children; // NormContinuous
777 if ( fieldName != NULL )
779 string field = _getProp(fieldName, string("field"));
784 inputNode = inputNode->next;
786 // Delete the last comma
787 structure.erase(structure.size()-1);
790 // Intermediary layers
791 xmlNodePtr node_layer = GetChildByName(_currentModelNode,"NeuralLayer");
792 if ( node_layer != NULL )
794 string name = string((const char*)(node_layer->name));
797 while ( node_layer != NULL &&
798 (string((const char*)(node_layer->name)) == "NeuralLayer") &&
799 node_layer->next != NULL &&
800 (string((const char*)(node_layer->next->name)) != "NeuralOutputs") )
802 // Get the number of neurons of the current layer
803 string nbneurons = _getProp(node_layer, string("numberOfNeurons"));
804 structure += nbneurons;
806 node_layer = node_layer->next;
810 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
811 if ( node_outputs != NULL )
813 xmlNodePtr node_output = GetChildByName(node_outputs,"NeuralOutput");
814 if ( node_output != NULL )
816 while (node_output != NULL)
818 // Get the input of the current layer
819 xmlNodePtr child = GetChildByName(node_output,"DerivedField");
822 xmlNodePtr fieldName = child->children; // NormContinuous
823 if ( fieldName != NULL )
825 if (string((const char*)(fieldName->name)) == "NormContinuous")
828 string field = _getProp(fieldName, string("field"));
833 node_output = node_output->next;
835 // Delete the last comma
836 structure.erase(structure.size()-1);
843 * Get the number of inputs, ie the number of NeuralInputs nodes.
844 * @brief Specific to NeuralNetwork
845 * @return Number of input nodes
847 int PMMLlib::GetNbInputs()
849 CheckNeuralNetwork();
852 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
853 if ( node_inputs == NULL )
856 node_inputs = node_inputs->children;
857 while (node_inputs != NULL)
860 node_inputs = node_inputs->next;
867 * Recover the number of outputs
868 * @brief Specific to NeuralNetwork
869 * @return Number of outputs
871 int PMMLlib::GetNbOutputs()
873 CheckNeuralNetwork();
876 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
877 if ( node_outputs == NULL )
880 node_outputs = node_outputs->children;
882 while (node_outputs != NULL)
885 node_outputs = node_outputs->next;
892 * Recovery of the name of an input in the current model.
893 * @brief Specific to NeuralNetwork
894 * @param index Index of the input
895 * @return Name of the input
897 std::string PMMLlib::GetNameInput(int index)
899 CheckNeuralNetwork();
902 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
903 if ( node_inputs == NULL )
906 node_inputs = node_inputs->children;
907 if ( node_inputs == NULL )
910 for(int i = 0;i<index;i++)
912 node_inputs = node_inputs->next;
913 if ( node_inputs == NULL )
917 node_inputs = node_inputs->children;
918 if ( node_inputs == NULL )
921 node_inputs = node_inputs->children;
922 if ( node_inputs == NULL )
925 name = _getProp(node_inputs, string("field"));
931 * Get the name of an output in the current model.
932 * @brief Specific to NeuralNetwork
933 * @param index Index of the output
934 * @return Name of the output
936 std::string PMMLlib::GetNameOutput(int index)
938 CheckNeuralNetwork();
941 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
942 if ( node_outputs == NULL )
944 node_outputs = node_outputs->children;
945 if ( node_outputs == NULL )
947 for(int i = 0;i<index;i++)
949 node_outputs = node_outputs->next;
950 if ( node_outputs == NULL )
954 node_outputs = node_outputs->children;
955 if ( node_outputs == NULL )
957 node_outputs = node_outputs->children;
958 if ( node_outputs == NULL )
961 name = _getProp(node_outputs, string("field") );
967 * Get the normalization type of the current model
968 * @brief Specific to NeuralNetwork
969 * @return Normalization type of the neural network
971 int PMMLlib::GetNormalizationType()
973 CheckNeuralNetwork();
975 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
976 node_inputs = GetChildByName(node_inputs,"NeuralInput");
977 xmlNodePtr nodeTmp = GetChildByName(node_inputs,"DerivedField");
978 xmlNodePtr node_field = nodeTmp->children;
979 xmlNodePtr node_linearnorm;
981 double dorig1, dnorm1;
982 double dorig2, dnorm2;
983 if (string((const char*)(node_field->name)) == "NormContinuous")
985 // Get mean and standard deviation
986 node_linearnorm = node_field->children;
987 str_tmp = _getProp(node_linearnorm, string("orig"));
988 dorig1 = atof(str_tmp.c_str());
989 str_tmp = _getProp(node_linearnorm, string("norm"));
990 dnorm1 = atof(str_tmp.c_str());
991 node_linearnorm = node_linearnorm->next;
992 str_tmp = _getProp(node_linearnorm, string("orig"));
993 dorig2 = atof(str_tmp.c_str());
994 str_tmp = _getProp(node_linearnorm, string("norm"));
995 dnorm2 = atof(str_tmp.c_str());
996 if ( dnorm1 * dnorm2 < -0.5 )
997 { // case of kMinusOneOne
1001 { // case of kCR, kZeroOne
1005 string msg("Unable to retrieve the normalization type.");
1010 * Get the input parameters on the normalization
1011 * @brief Specific to NeuralNetwork
1012 * @param node_ann Neural network node
1013 * @param index Index of the input
1014 * @param[out] dnorm Array that contains the mean and the standard deviation
1016 void PMMLlib::GetNormalisationInput(int index,
1019 CheckNeuralNetwork();
1022 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
1023 if ( node_inputs == NULL )
1025 node_inputs = GetChildByName(node_inputs,"NeuralInput");
1026 if ( node_inputs == NULL )
1028 // Positionnement sur la bonne entree
1029 for(int i=0;i<index;i++)
1031 node_inputs = node_inputs->next;
1032 if ( node_inputs == NULL )
1035 xmlNodePtr tmpNode = GetChildByName(node_inputs,"DerivedField");
1036 if ( tmpNode == NULL )
1038 xmlNodePtr node_field = GetChildByName(tmpNode,"NormContinuous");
1039 if ( node_field == NULL )
1041 if (string((const char*)(node_field->name)) == "NormContinuous")
1043 //Get mean and standard deviation
1045 xmlNodePtr node_linearnorm = node_field->children;
1046 str_tmp = _getProp(node_linearnorm, string("orig"));
1047 double dorig1 = atof(str_tmp.c_str());
1048 str_tmp = _getProp(node_linearnorm, string("norm"));
1049 double dnorm1 = atof(str_tmp.c_str());
1050 node_linearnorm = node_linearnorm->next;
1051 str_tmp = _getProp(node_linearnorm, string("orig"));
1052 double dorig2 = atof(str_tmp.c_str());
1053 str_tmp = _getProp(node_linearnorm, string("norm"));
1054 double dnorm2 = atof(str_tmp.c_str());
1055 if ( dnorm1 * dnorm2 < -0.5 ) // <=> GetNormalizationType == 0
1057 // case of kMinusOneOne
1061 else // <=> GetNormalizationType == 1
1063 // case of kCR, kZeroOne
1065 dnorm[1] = -1.0 * dnorm1 * dorig2; //dorig2 / dnorm1;
1071 * Get the parameters on the normalization of an output for the current model.
1072 * @brief Specific to NeuralNetwork
1073 * @param index Output index
1074 * @param[out] dnorm Array that contains the mean and the standard deviation
1076 void PMMLlib::GetNormalisationOutput(int index,
1079 CheckNeuralNetwork();
1083 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
1084 if ( node_outputs == NULL )
1086 node_outputs = GetChildByName(node_outputs,"NeuralOutput");
1087 if ( node_outputs == NULL )
1089 // Positionnement sur la bonne sortie
1090 for(int i=0;i< index;i++)
1092 node_outputs = node_outputs->next;
1093 if ( node_outputs == NULL )
1096 xmlNodePtr tmpNode = GetChildByName(node_outputs,"DerivedField");
1097 if ( tmpNode == NULL )
1099 xmlNodePtr node_field = GetChildByName(tmpNode,"NormContinuous");
1100 if ( node_field == NULL )
1103 if (string((const char*)(node_field->name)) == "NormContinuous")
1105 // Recuperation de la moyenne et de l'ecart type
1107 xmlNodePtr node_linearnorm = node_field->children;
1108 str_tmp = _getProp(node_linearnorm, string("orig"));
1109 double dorig1 = atof(str_tmp.c_str());
1110 str_tmp = _getProp(node_linearnorm, string("norm"));
1111 double dnorm1 = atof(str_tmp.c_str());
1112 node_linearnorm = node_linearnorm->next;
1113 str_tmp = _getProp(node_linearnorm,string("orig"));
1114 double dorig2 = atof(str_tmp.c_str());
1115 str_tmp = _getProp(node_linearnorm, string("norm"));
1116 double dnorm2 = atof(str_tmp.c_str());
1117 if ( dnorm1 * dnorm2 < -0.5 )
1119 // case of kMinusOneOne
1125 // case of kCR, kZeroOne
1127 dnorm[1] = -1.0 * dorig2 * dnorm1; //-1.0 * dorig2 / dnorm1;
1133 * Get the number of hidden layers
1134 * @brief Specific to NeuralNetwork
1135 * @return Number of hidden layers
1137 int PMMLlib::GetNbHiddenLayers()
1139 CheckNeuralNetwork();
1142 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1143 if ( node_layers == NULL )
1146 while (string((const char*)(node_layers->name)) == "NeuralLayer")
1149 node_layers = node_layers->next;
1150 if ( node_layers == NULL )
1157 * Get the total number of layers
1158 * @return Total number of layers
1160 int PMMLlib::GetNbLayers()
1162 return (GetNbHiddenLayers() + 2);
1166 * Get the number of neurons at a given layer
1167 * @param index Index of the layer
1168 * @return Number of neurons at given layer
1170 int PMMLlib::GetNbNeuronsAtLayer(int index)
1172 CheckNeuralNetwork();
1175 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1176 if ( node_layers == NULL )
1179 // Positionnement à la bonne couche
1180 for(int i=0;i<index;i++)
1182 node_layers = node_layers->next;
1183 if ( node_layers == NULL )
1187 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1188 while(node_neurons != NULL)
1191 node_neurons = node_neurons->next;
1198 * Get the bias of a neuron
1199 * @brief Specific to NeuralNetwork
1200 * @param layer_index Index of the layer to get bias
1201 * @param neu_index Index of the neuron
1202 * @return Bias of the specified neuron
1204 double PMMLlib::GetNeuronBias(int layer_index,
1207 CheckNeuralNetwork();
1210 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1211 if ( node_layers == NULL )
1213 // Positionnement a la bonne couche
1214 for(int i=0;i<layer_index;i++)
1216 node_layers = node_layers->next;
1217 if ( node_layers == NULL )
1220 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1221 // Positionnement sur le bon neurone
1222 for(int j=0;j<neu_index;j++)
1224 node_neurons = node_neurons->next;
1225 if ( node_neurons == NULL )
1228 string str_tmp = _getProp(node_neurons, string("bias"));
1229 bias = atof(str_tmp.c_str());
1234 * Get the synaptic weight
1235 * @brief Specific to NeuralNetwork
1236 * @param layer_index Index of the layer to get synaptic weight
1237 * @param neu_index Index of the neuron
1238 * @param prec_index Index of the synapse
1239 * @return Synaptic weight
1241 double PMMLlib::GetPrecNeuronSynapse(int layer_index,
1245 CheckNeuralNetwork();
1248 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1249 if ( node_layers == NULL )
1251 // Positionnement a la bonne couche
1252 for(int i=0;i<layer_index;i++)
1254 node_layers = node_layers->next;
1255 if ( node_layers == NULL )
1258 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1259 // Positionnement sur le bon neurone
1260 for(int i=0;i<neu_index;i++)
1262 node_neurons = node_neurons->next;
1263 if ( node_neurons == NULL )
1266 xmlNodePtr node_con = GetChildByName(node_neurons,"Con");
1267 // Positionnement sur la bonne synapse
1268 for(int i=0;i<prec_index;i++)
1270 node_con = node_con->next;
1271 if ( node_con == NULL )
1274 string str_tmp = _getProp(node_con, string("weight"));
1275 weight = atof(str_tmp.c_str());
1280 * Set the name of the neural network
1282 * @param index Neural network index
1283 * @param name Neural network name to set
1286 void PMMLlib::SetNeuralNetName(int index,
1289 CheckNeuralNetwork();
1294 xmlNodePtr node_ann = GetChildByName(_rootNode,"NeuralNetwork");
1295 while ((i != index) && (node_ann != NULL))
1297 node_ann = node_ann->next;
1300 xmlNewProp(node_ann, (const xmlChar*)"modelName", (const xmlChar*)(name.c_str()));
1302 xmlSaveFormatFile( string(_pmmlFile+".pmml").c_str(), _doc, 1);
1307 * Add a DataField node to the DataDictionnary node
1308 * @param fieldName Value of property "name"
1309 * @param displayName Value of property "displayName"
1310 * @param optype Value of property "optype"
1311 * @param dataType Value of property "dataType"
1312 * @param closure Value of property "closure" in node Interval
1313 * @param leftMargin Value of property "leftMargin" in node Interval
1314 * @param rightMargin Value of property "rightMargin" in node Interval
1315 * @param interval Flag to add a node Interval (if true)
1317 void PMMLlib::AddDataField(std::string fieldName,
1318 std::string displayName,
1320 std::string dataType,
1321 std::string closure,
1326 // if 'DataDictionary' node does not exist, create it
1327 xmlNodePtr dataDictNode = GetChildByName(_rootNode, "DataDictionary");
1330 dataDictNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"DataDictionary", 0);
1333 // then append the node
1334 xmlNodePtr dataFieldNode = xmlNewChild(dataDictNode, 0, (const xmlChar*)"DataField", 0);
1335 xmlNewProp(dataFieldNode, (const xmlChar*)"name", (const xmlChar*)(fieldName.c_str()) );
1336 xmlNewProp(dataFieldNode, (const xmlChar*)"displayName", (const xmlChar*)(displayName.c_str()) );
1337 xmlNewProp(dataFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1338 xmlNewProp(dataFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1342 xmlNodePtr intervalNode = xmlNewChild(dataFieldNode, 0, (const xmlChar*)"Interval", 0);
1343 xmlNewProp(intervalNode, (const xmlChar*)"closure", (const xmlChar*)(closure.c_str()) );
1345 ss << scientific << leftMargin;
1346 xmlNewProp(intervalNode, (const xmlChar*)"leftMargin", (const xmlChar*)(ss.str().c_str()) );
1348 ss << scientific << rightMargin;
1349 xmlNewProp(intervalNode, (const xmlChar*)"rightMargin", (const xmlChar*)(ss.str().c_str()) );
1354 * Add a NeuralNetwork node to the root node
1355 * @brief Specific to NeuralNetwork
1356 * @param modelName Model name
1357 * @param functionName PMMLMiningFunction. One of : kREGRESSION.
1359 void PMMLlib::AddNeuralNetwork(std::string modelName,
1360 PMMLMiningFunction functionName)
1362 _currentModelType = kANN;
1363 _currentModelName = modelName;
1365 CheckNeuralNetwork();
1368 switch(functionName)
1371 function = "regression";
1375 xmlNodePtr netNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"NeuralNetwork", 0);
1376 xmlNewProp(netNode, (const xmlChar*)"modelName", (const xmlChar*)(_currentModelName.c_str()) );
1377 xmlNewProp(netNode, (const xmlChar*)"functionName", (const xmlChar*)(function.c_str()) );
1378 xmlNewProp(netNode, (const xmlChar*)"numberOfLayers", (const xmlChar*)"0" );
1379 _currentModelNode = netNode;
1383 * Add a NeuralInput node to the current model.
1384 * @brief Specific to NeuralNetwork
1385 * @param id Id of the input
1386 * @param inputName Name of the input
1387 * @param optype Value of property "optype"
1388 * @param dataType Value of property "dataType"
1389 * @param orig1 Value of the first origin
1390 * @param norm1 Value of the first norm
1391 * @param orig2 Value of the second origin
1392 * @param norm2 Value of the second norm
1394 void PMMLlib::AddNeuralInput(int id,
1395 std::string inputName,
1397 std::string dataType,
1398 double orig1, double norm1,
1399 double orig2, double norm2)
1401 CheckNeuralNetwork();
1403 xmlNodePtr netNode = _currentModelNode;
1404 // if 'NeuralInputs' node does not exist, create it
1405 xmlNodePtr neuralInputsNode = GetChildByName(netNode, "NeuralInputs");
1406 if(!neuralInputsNode)
1408 neuralInputsNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralInputs", 0);
1409 xmlNewProp(neuralInputsNode, (const xmlChar*)"numberOfInputs", (const xmlChar*)"0" );
1411 // increment the number of inputs
1412 string numberOfInputsStr = _getProp(neuralInputsNode, string("numberOfInputs"));
1414 istringstream( numberOfInputsStr ) >> numberOfInputs;
1417 ss << numberOfInputs;
1418 xmlSetProp(neuralInputsNode, (const xmlChar*)"numberOfInputs", (const xmlChar*)(ss.str().c_str()) );
1419 // then append the node and its children
1420 xmlNodePtr neuralInputNode = xmlNewChild(neuralInputsNode, 0, (const xmlChar*)"NeuralInput", 0);
1421 ss.str(""); ss << id;
1422 xmlNewProp(neuralInputNode, (const xmlChar*)"id", (const xmlChar*)(ss.str().c_str()) );
1424 xmlNodePtr derivedFieldNode = xmlNewChild(neuralInputNode, 0, (const xmlChar*)"DerivedField", 0);
1425 xmlNewProp(derivedFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1426 xmlNewProp(derivedFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1428 xmlNodePtr normcontNode = xmlNewChild(derivedFieldNode, 0, (const xmlChar*)"NormContinuous", 0);
1429 xmlNewProp(normcontNode, (const xmlChar*)"field", (const xmlChar*)(inputName.c_str()) );
1431 xmlNodePtr node_linearnorm1 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1432 ss.str(""); ss << scientific << orig1;
1433 xmlNewProp(node_linearnorm1, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1434 ss.str(""); ss << scientific << norm1;
1435 xmlNewProp(node_linearnorm1, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1436 xmlNodePtr node_linearnorm2 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1437 ss.str(""); ss << scientific << orig2;
1438 xmlNewProp(node_linearnorm2, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1439 ss.str(""); ss << scientific << norm2;
1440 xmlNewProp(node_linearnorm2, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1444 * Add a NeuralOutput node to the current model.
1445 * @brief Specific to NeuralNetwork
1446 * @param outputNeuron Id of the output
1447 * @param outputName Name of the output
1448 * @param optype Value of property "optype"
1449 * @param dataType Value of property "dataType"
1450 * @param orig1 Value of the first origin
1451 * @param norm1 Value of the first norm
1452 * @param orig2 Value of the second origin
1453 * @param norm2 Value of the second norm
1455 void PMMLlib::AddNeuralOutput(int outputNeuron,
1456 std::string outputName,
1458 std::string dataType,
1459 double orig1, double norm1,
1460 double orig2, double norm2)
1462 CheckNeuralNetwork();
1464 xmlNodePtr netNode = _currentModelNode;
1465 // if 'NeuralOutputs' node does not exist, create it
1466 xmlNodePtr neuralOutputsNode = GetChildByName(netNode, "NeuralOutputs");
1467 if(!neuralOutputsNode)
1469 neuralOutputsNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralOutputs", 0);
1470 xmlNewProp(neuralOutputsNode, (const xmlChar*)"numberOfOutputs", (const xmlChar*)"0" );
1472 // increment the number of inputs
1473 string numberOfOutputsStr = _getProp(neuralOutputsNode, string("numberOfOutputs"));
1474 int numberOfOutputs;
1475 istringstream( numberOfOutputsStr ) >> numberOfOutputs;
1478 ss << numberOfOutputs;
1479 xmlSetProp(neuralOutputsNode, (const xmlChar*)"numberOfOutputs", (const xmlChar*)(ss.str().c_str()) );
1481 // then append the node and its children
1482 xmlNodePtr neuralOutputNode = xmlNewChild(neuralOutputsNode, 0, (const xmlChar*)"NeuralOutput", 0);
1483 ss.str(""); ss << outputNeuron;
1484 xmlNewProp(neuralOutputNode, (const xmlChar*)"outputNeuron", (const xmlChar*)(ss.str().c_str()) );
1486 xmlNodePtr derivedFieldNode = xmlNewChild(neuralOutputNode, 0, (const xmlChar*)"DerivedField", 0);
1487 xmlNewProp(derivedFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1488 xmlNewProp(derivedFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1490 xmlNodePtr normcontNode = xmlNewChild(derivedFieldNode, 0, (const xmlChar*)"NormContinuous", 0);
1491 xmlNewProp(normcontNode, (const xmlChar*)"field", (const xmlChar*)(outputName.c_str()) );
1493 xmlNodePtr node_linearnorm1 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1494 ss.str(""); ss << scientific << orig1;
1495 xmlNewProp(node_linearnorm1, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1496 ss.str(""); ss << scientific << norm1;
1497 xmlNewProp(node_linearnorm1, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1498 xmlNodePtr node_linearnorm2 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1499 ss.str(""); ss << scientific << orig2;
1500 xmlNewProp(node_linearnorm2, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1501 ss.str(""); ss << scientific << norm2;
1502 xmlNewProp(node_linearnorm2, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1506 * Add a NeuralLayer node to the current model.
1507 * @brief Specific to NeuralNetwork
1508 * @param activationFunction Activation function. One of kIDENTITY, kTANH, kLOGISTIC.
1510 void PMMLlib::AddNeuralLayer(PMMLActivationFunction activationFunction)
1512 CheckNeuralNetwork();
1514 string functionName;
1515 switch(activationFunction)
1518 functionName = "identity";
1521 functionName = "tanh";
1524 functionName = "logistic";
1527 xmlNodePtr netNode = _currentModelNode;
1528 // Increment the number of layers
1529 string numberOfLayersStr = _getProp(_currentModelNode, string("numberOfLayers"));
1531 istringstream( numberOfLayersStr ) >> numberOfLayers;
1534 ss << numberOfLayers;
1535 xmlSetProp(netNode, (const xmlChar*)"numberOfLayers", (const xmlChar*)(ss.str().c_str()) );
1536 // Add the neural layer node
1537 xmlNodePtr neuralLayerNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralLayer", 0);
1538 xmlNewProp(neuralLayerNode, (const xmlChar*)"activationFunction", (const xmlChar*)(functionName.c_str()) );
1539 xmlNewProp(neuralLayerNode, (const xmlChar*)"numberOfNeurons", (const xmlChar*)"0" );
1540 // Save the current layer in the _currentNode attribute
1541 _currentNode = neuralLayerNode;
1545 * Add a NeuralLayer node to the current model.
1546 * @brief Specific to NeuralNetwork
1547 * @param id Id of the layer
1548 * @param bias Value of property "bias"
1549 * @param conNb Number of Con nodes
1550 * @param firstFrom Value of property "from" for the first Con
1551 * @param weights Vector of weights (One per Con node)
1553 void PMMLlib::AddNeuron(int id,
1557 vector<double> weights)
1559 CheckNeuralNetwork();
1563 // increment the number of neurons
1564 string numberOfNeuronsStr = _getProp(_currentNode, string("numberOfNeurons"));
1565 int numberOfNeurons;
1566 istringstream( numberOfNeuronsStr ) >> numberOfNeurons;
1568 ss << numberOfNeurons;
1569 xmlSetProp(_currentNode, (const xmlChar*)"numberOfNeurons", (const xmlChar*)(ss.str().c_str()) );
1572 xmlNodePtr neuronNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"Neuron", 0);
1573 ss.str(""); ss << id;
1574 xmlNewProp(neuronNode, (const xmlChar*)"id", (const xmlChar*)(ss.str().c_str()) );
1575 ss.str(""); ss << scientific << bias;
1576 xmlNewProp(neuronNode, (const xmlChar*)"bias", (const xmlChar*)(ss.str().c_str()) );
1578 // append multiple 'Con' to the neuron
1579 for(int k=0 ; k<conNb ; k++)
1581 xmlNodePtr conNode = xmlNewChild(neuronNode, 0, (const xmlChar*)"Con", 0);
1582 ss.str(""); ss << firstFrom+k;
1583 xmlNewProp(conNode, (const xmlChar*)"from", (const xmlChar*)(ss.str().c_str()) ); // !!! ce n'est pas k !!!
1584 ss.str(""); ss << scientific << weights[k];
1585 xmlNewProp(conNode, (const xmlChar*)"weight", (const xmlChar*)(ss.str().c_str()) );
1590 * Fill the vectors used by the ExportXXX methods.
1591 * @brief Specific to NeuralNetwork
1602 void PMMLlib::fillVectorsForExport(int nInput,
1606 vector<double> &minInput,
1607 vector<double> &maxInput,
1608 vector<double> &minOutput,
1609 vector<double> &maxOutput,
1610 vector<double> &valW )
1612 CheckNeuralNetwork();
1614 xmlNodePtr netNode = _currentModelNode ;
1615 // Get the different values required
1616 // Build min/max input/output vectors
1617 for(int i=0 ; i<nInput ; i++)
1619 xmlNodePtr node_inputs = GetChildByName(netNode,"NeuralInputs");
1620 node_inputs = node_inputs->children;
1621 for(int j = 0;j<i;j++)
1623 node_inputs = node_inputs->next;
1625 node_inputs = node_inputs->children; // DerivedField
1626 node_inputs = node_inputs->children; // NormContinuous
1627 node_inputs = node_inputs->children; // LinearNorm
1628 string strOrig1 = _getProp(node_inputs, string("orig") );
1629 double orig1 = atof( strOrig1.c_str() );
1630 string strNorm1 = _getProp(node_inputs, string("norm") );
1631 double norm1 = atof( strNorm1.c_str() );
1632 node_inputs = node_inputs->next;
1633 string strOrig2 = _getProp(node_inputs, string("orig") );
1634 double orig2 = atof( strOrig2.c_str() );
1635 string strNorm2 = _getProp(node_inputs, string("norm") );
1638 minInput[i] = orig1;
1639 maxInput[i] = orig2;
1643 minInput[i] = orig2;
1644 maxInput[i] = -1.0*norm1*orig2;
1647 xmlNodePtr node_outputs = GetChildByName(netNode,"NeuralOutputs");
1648 node_outputs = node_outputs->children;
1649 node_outputs = node_outputs->children; // DerivedField
1650 node_outputs = node_outputs->children; // NormContinuous
1651 node_outputs = node_outputs->children; // LinearNorm
1652 string strOrig1 = _getProp(node_outputs, string("orig") );
1653 double orig1 = atof( strOrig1.c_str() );
1654 string strNorm1 = _getProp(node_outputs, string("norm") );
1655 double norm1 = atof( strNorm1.c_str() );
1656 node_outputs = node_outputs->next;
1657 string strOrig2 = _getProp(node_outputs, string("orig") );
1658 double orig2 = atof( strOrig2.c_str() );
1661 minOutput[0] = orig1;
1662 maxOutput[0] = orig2;
1666 minOutput[0] = orig2;
1667 maxOutput[0] = -1.0*norm1*orig2;
1669 // Build weight vector
1670 for(int j=0 ; j<nHidden ; j++) // hidden layers
1672 valW[j*(nInput+nOutput+1)+2] = GetNeuronBias( 0, j);
1673 for(int i=0 ; i<nInput ; i++)
1675 valW[j*(nInput+nOutput+1)+3+i] = GetPrecNeuronSynapse( 0, j, i);
1678 for(int j=0 ; j<nOutput ; j++) // output layers
1680 valW[0] = GetNeuronBias( 1, j);
1681 for(int i=0 ; i<nHidden ; i++)
1683 valW[i*(nInput+nOutput+1)+1] = GetPrecNeuronSynapse( 1, j, i);
1689 * Export the current model as a NeuralNetwork function in a Cpp file.
1690 * @brief Specific to NeuralNetwork
1691 * @param file Name of the file
1692 * @param functionName Name of the function
1693 * @param header Header of the function
1695 void PMMLlib::ExportNeuralNetworkCpp(std::string file,
1696 std::string functionName,
1699 CheckNeuralNetwork();
1701 // Get the different values required
1702 int nInput = GetNbInputs();
1703 int nOutput = GetNbOutputs();
1704 int nHidden = GetNbNeuronsAtLayer(0);
1705 int nNeurons = nInput+nOutput+nHidden;
1706 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
1707 int normType = GetNormalizationType();
1708 // Build min/max input/output vectors
1709 vector<double> minInput(nInput);
1710 vector<double> maxInput(nInput);
1711 vector<double> minOutput(nOutput);
1712 vector<double> maxOutput(nOutput);
1713 vector<double> valW(nWeights);
1714 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
1716 ofstream sourcefile(file.c_str());
1717 // ActivationFunction
1720 sourcefile << "#define ActivationFunction(sum) ( tanh(sum) )" << endl;
1724 sourcefile << "#define ActivationFunction(sum) ( 1.0 / ( 1.0 + exp( -1.0 * sum )) )" << endl;
1727 sourcefile << "void " << functionName <<"(double *param, double *res)" << endl;
1728 sourcefile << "{" << endl;
1730 sourcefile << " ////////////////////////////// " << endl;
1731 sourcefile << " //" << endl;
1732 // insert comments in header
1733 header = " // " + header;
1735 while ((pos = header.find("\n", pos)) != std::string::npos)
1737 header.replace(pos, 1, "\n //");
1740 sourcefile << header << endl;
1741 sourcefile << " //" << endl;
1742 sourcefile << " ////////////////////////////// " << endl;
1744 sourcefile << " int nInput = " << nInput << ";" << endl;
1745 sourcefile << " int nOutput = " << nOutput << ";" << endl;
1746 // sourcefile << " int nWeights = " << _nWeight << ";" << endl;
1747 sourcefile << " int nHidden = " << nHidden << ";" << endl;
1748 sourcefile << " const int nNeurones = " << nNeurons << ";" << endl;
1749 sourcefile << " double " << functionName << "_act[nNeurones];" << endl;
1751 sourcefile << " // --- Preprocessing of the inputs and outputs" << endl;
1752 sourcefile << " double " << functionName << "_minInput[] = {" << endl << " ";
1753 for(int i=0 ; i<nInput ; i++)
1755 sourcefile << minInput[i] << ", ";
1757 sourcefile << "\n ";
1761 sourcefile << " };" << endl;
1763 sourcefile << " double " << functionName << "_minOutput[] = {" << endl << " ";
1764 sourcefile << minOutput[0] << ", ";
1765 sourcefile << " };" << endl;
1767 sourcefile << " double " << functionName << "_maxInput[] = {" << endl << " ";
1768 for(int i=0 ; i<nInput ; i++)
1770 sourcefile << maxInput[i] << ", ";
1772 sourcefile << "\n ";
1776 sourcefile << " };" << endl;
1778 sourcefile << " double " << functionName << "_maxOutput[] = {" << endl << " ";
1779 sourcefile << maxOutput[0] << ", ";
1780 sourcefile << " };" << endl;
1783 sourcefile << " // --- Values of the weights" << endl;
1784 sourcefile << " double " << functionName << "_valW[] = {" << endl << " ";
1785 for(int i=0 ; i<nWeights ; i++)
1787 sourcefile << valW[i] << ", ";
1789 sourcefile << endl << " ";
1791 sourcefile << endl << " };"<<endl;
1793 sourcefile << " // --- Constants";
1795 sourcefile << " int indNeurone = 0;"<<endl;
1796 sourcefile << " int CrtW;"<<endl;
1797 sourcefile << " double sum;"<<endl;
1801 sourcefile << " // --- Input Layers"<<endl;
1802 sourcefile << " for(int i = 0; i < nInput; i++) {"<<endl;
1805 sourcefile << " " << functionName << "_act[indNeurone++] = 2.0 * ( param[i] - "
1806 << functionName << "_minInput[i] ) / ( " << functionName << "_maxInput[i] - "
1807 << functionName << "_minInput[i] ) - 1.0;"<<endl;
1811 sourcefile << " " << functionName << "_act[indNeurone++] = ( param[i] - "
1812 << functionName << "_minInput[i] ) / " << functionName << "_maxInput[i];"
1815 sourcefile << " }"<<endl;
1820 sourcefile << " // --- Hidden Layers"<<endl;
1821 sourcefile << " for (int member = 0; member < nHidden; member++) {"<<endl;
1822 sourcefile << " int CrtW = member * ( nInput + 2) + 2;" << endl;
1823 sourcefile << " sum = " << functionName << "_valW[CrtW++];" << endl;
1824 sourcefile << " for (int source = 0; source < nInput; source++) {" << endl;
1825 sourcefile << " sum += " << functionName << "_act[source] * " << functionName << "_valW[CrtW++];" << endl;
1826 sourcefile << " }" << endl;
1827 sourcefile << " " << functionName << "_act[indNeurone++] = ActivationFunction(sum);" << endl;
1828 sourcefile << " }"<<endl;
1831 sourcefile << " // --- Output"<<endl;
1832 sourcefile << " for (int member = 0; member < nOutput; member++) {"<<endl;
1833 sourcefile << " sum = " << functionName << "_valW[0];"<<endl;
1834 sourcefile << " for (int source = 0; source < nHidden; source++) {"<<endl;
1835 sourcefile << " CrtW = source * ( nInput + 2) + 1;"<<endl;
1836 sourcefile << " sum += " << functionName << "_act[nInput+source] * " << functionName << "_valW[CrtW];"<<endl;
1837 sourcefile << " }"<<endl;
1838 sourcefile << " " << functionName << "_act[indNeurone++] = sum;"<<endl;
1841 sourcefile << " res[member] = " << functionName
1842 << "_minOutput[member] + 0.5 * ( " << functionName
1843 << "_maxOutput[member] - " << functionName
1844 << "_minOutput[member] ) * ( sum + 1.0);" << endl;
1848 sourcefile << " res[member] = " << functionName
1849 << "_minOutput[member] + " << functionName
1850 << "_maxOutput[member] * sum;" << endl;
1852 sourcefile << " }"<<endl;
1854 sourcefile << "}" << endl;
1859 * Export the current model as a NeuralNetwork function in a Fortran file.
1860 * @brief Specific to NeuralNetwork
1861 * @param file Name of the file
1862 * @param functionName Name of the function
1863 * @param header Header of the function
1865 void PMMLlib::ExportNeuralNetworkFortran(std::string file,
1866 std::string functionName,
1869 CheckNeuralNetwork();
1871 // Get the different values required
1872 int nInput = GetNbInputs();
1873 int nOutput = GetNbOutputs();
1874 int nHidden = GetNbNeuronsAtLayer(0);
1875 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
1876 int normType = GetNormalizationType();
1877 // Build min/max input/output vectors
1878 vector<double> minInput(nInput);
1879 vector<double> maxInput(nInput);
1880 vector<double> minOutput(nOutput);
1881 vector<double> maxOutput(nOutput);
1882 vector<double> valW(nWeights);
1883 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
1885 ofstream sourcefile(file.c_str());
1887 sourcefile << " SUBROUTINE " << functionName << "(";
1888 for(int i=0 ; i<GetNbInputs() ; i++)
1890 sourcefile << GetNameInput(i) << ",";
1892 sourcefile << GetNameOutput(0) << ")" << endl;
1894 sourcefile << "C --- *********************************************" << endl;
1895 sourcefile << "C --- " << endl;
1896 // insert comments in header
1897 header = "C --- " + header;
1899 while ((pos = header.find("\n", pos)) != std::string::npos)
1901 header.replace(pos, 1, "\nC --- ");
1904 sourcefile << header << endl;
1905 sourcefile << "C --- " << endl;
1906 sourcefile << "C --- *********************************************" << endl;
1908 sourcefile << " IMPLICIT DOUBLE PRECISION (V)" << endl;
1909 for(int i=0 ; i<GetNbInputs() ; i++)
1911 sourcefile << " DOUBLE PRECISION " << GetNameInput(i) << endl;
1913 sourcefile << " DOUBLE PRECISION " << GetNameOutput(0) << endl;
1916 sourcefile << "C --- Preprocessing of the inputs" << endl;
1917 for(int i=0 ; i<GetNbInputs() ; i++)
1919 sourcefile << " VXN" << GetNameInput(i) << " = ";
1923 sourcefile << "2.D0 * ( " << GetNameInput(i) << " - " << minInput[i] << "D0 ) / " << maxInput[i] - minInput[i] << "D0 - 1.0" << endl;
1927 sourcefile << "( " << GetNameInput(i) << " - " << minInput[i] << "D0 ) / " << maxInput[i] << "D0" << endl;
1933 sourcefile << "C --- Values of the weights" << endl;
1934 for(int i=0 ; i<nWeights ; i++)
1936 sourcefile << " VW" << i+1 << " = " << valW[i] << endl;
1938 // Loop on hidden neurons
1940 for(int member = 0; member < nHidden; member++)
1942 sourcefile << "C --- hidden neural number " << member+1 << endl;
1943 int CrtW = member * ( nInput + 2) + 3;
1944 sourcefile << " VAct" << member+1 << " = VW" << CrtW++ << endl;
1945 for (int source = 0; source < nInput; source++)
1947 sourcefile << " 1 + VW"<< CrtW++ << " * VXN" << GetNameInput(source) << endl;
1954 sourcefile << " VPot" << member+1 << " = 2.D0 / (1.D0 + DEXP(-2.D0 * VAct" << member+1 <<")) - 1.D0" << endl;
1958 sourcefile << " VPot" << member+1 << " = 1.D0 / (1.D0 + DEXP(-1.D0 * VAct" << member+1 <<"))" << endl;
1963 // Ouput of the model
1964 sourcefile << "C --- Output" << endl;
1965 sourcefile << " VOut = VW1" << endl;
1966 for(int source=0 ; source < nHidden ; source++)
1968 int CrtW = source * ( nInput + 2) + 2;
1969 sourcefile << " 1 + VW"<< CrtW << " * VPot" << source+1 << endl;
1972 // Denormalize Output
1974 sourcefile << "C --- Pretraitment of the output" << endl;
1977 sourcefile << " VDelta = " << 0.5*(maxOutput[0]-minOutput[0]) << "D0 * ( VOut + 1.0D0)" << endl;
1978 sourcefile << " " << GetNameOutput(0) << " = " << minOutput[0] << "D0 + VDelta" << endl;
1983 sourcefile << " " << GetNameOutput(0) << " = "<< minOutput[0] << "D0 + " << maxOutput[0] << "D0 * VOut;" << endl;
1987 sourcefile << "C --- " << endl;
1988 sourcefile << " RETURN" << endl;
1989 sourcefile << " END" << endl;
1995 * Export the current model as a NeuralNetwork function in a Python file.
1996 * @brief Specific to NeuralNetwork
1997 * @param file Name of the file
1998 * @param functionName Name of the function
1999 * @param header Header of the function
2001 void PMMLlib::ExportNeuralNetworkPython(std::string file,
2002 std::string functionName,
2005 string str(ExportNeuralNetworkPyStr(functionName, header));
2007 ofstream exportfile(file.c_str());
2014 * Export the current model as a function in a Python string.
2015 * @brief Specific to NeuralNetwork
2016 * @param functionName Name of the function
2017 * @param header Header of the function
2018 * @return Function as a string
2020 std::string PMMLlib::ExportNeuralNetworkPyStr(std::string functionName,
2023 CheckNeuralNetwork();
2027 // Get the different values required
2028 int nInput = GetNbInputs();
2029 int nOutput = GetNbOutputs();
2030 int nHidden = GetNbNeuronsAtLayer(0);
2031 int nNeurons = nInput+nOutput+nHidden;
2032 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
2033 int normType = GetNormalizationType();
2034 // Build min/max input/output vectors
2035 vector<double> minInput(nInput);
2036 vector<double> maxInput(nInput);
2037 vector<double> minOutput(nOutput);
2038 vector<double> maxOutput(nOutput);
2039 vector<double> valW(nWeights);
2040 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
2042 // Shebang et imports
2043 out << "#!/usr/bin/env python3" << endl;
2044 out << "# -*- coding: utf-8 -*-" << endl;
2046 out << "from math import tanh, exp" << endl;
2049 // ActivationFunction
2052 out << "def ActivationFunction(sum): " << endl;
2053 out << " return tanh(sum); " << endl;
2057 out << "def ActivationFunction(sum): " << endl;
2058 out << " return ( 1.0 / ( 1.0 + exp( -1.0 * sum ) ) ); " << endl;
2062 out << "def " << functionName <<"(param):" << endl;
2066 out << " ############################## " << endl;
2067 out << " #" << endl;
2068 // insert comments in header
2069 header = " # " + header;
2071 while ((pos = header.find("\n", pos)) != std::string::npos)
2073 header.replace(pos, 1, "\n #");
2076 out << header << endl;
2077 out << " #" << endl;
2078 out << " ############################## " << endl;
2082 out << " nInput = " << nInput << ";" << endl;
2083 out << " nOutput = " << nOutput << ";" << endl;
2084 out << " nHidden = " << nHidden << ";" << endl;
2085 out << " nNeurones = " << nNeurons << ";" << endl;
2086 out << " " << functionName << "_act = [];" << endl;
2087 out << " res = [];" << endl;
2090 out << " # --- Preprocessing of the inputs and outputs" << endl;
2091 out << " " << functionName << "_minInput = [" << endl << " ";
2093 for(int i=0 ; i<nInput ; i++)
2095 out << minInput[i] << ", ";
2102 out << endl << " ];" << endl;
2104 out << " " << functionName << "_minOutput = [" << endl << " ";
2105 out << " " << minOutput[0] ;
2106 out << endl << " ];" << endl;
2108 out << " " << functionName << "_maxInput = [" << endl << " ";
2109 for(int i=0 ; i<nInput ; i++)
2111 out << maxInput[i] << ", ";
2118 out << endl << " ];" << endl;
2120 out << " " << functionName << "_maxOutput = [" << endl << " ";
2121 out << " " << maxOutput[0] ;
2122 out << endl << " ];" << endl;
2125 out << " # --- Values of the weights" << endl;
2126 out << " " << functionName << "_valW = [" << endl << " ";
2127 for(int i=0 ; i<nWeights ; i++)
2129 out << valW[i] << ", ";
2136 out << endl << " ];"<<endl;
2138 out << " # --- Constants" << endl;
2139 out << " indNeurone = 0;" << endl;
2143 out << " # --- Input Layers" << endl;
2144 out << " for i in range(nInput) :" << endl;
2147 out << " " << functionName << "_act.append( 2.0 * ( param[i] - "
2148 << functionName << "_minInput[i] ) / ( " << functionName << "_maxInput[i] - "
2149 << functionName << "_minInput[i] ) - 1.0 ) ;"
2154 out << " " << functionName << "_act.append( ( param[i] - "
2155 << functionName << "_minInput[i] ) / " << functionName << "_maxInput[i] ) ;"
2158 out << " indNeurone += 1 ;" << endl;
2159 out << " pass" << endl;
2163 out << " # --- Hidden Layers" << endl;
2164 out << " for member in range(nHidden):" << endl;
2165 out << " CrtW = member * ( nInput + 2) + 2;" << endl;
2166 out << " sum = " << functionName << "_valW[CrtW];" << endl;
2167 out << " CrtW += 1 ;" << endl;
2168 out << " for source in range(nInput) :" << endl;
2169 out << " sum += " << functionName << "_act[source] * " << functionName << "_valW[CrtW];" << endl;
2170 out << " CrtW += 1 ;" << endl;
2171 out << " pass" << endl;
2172 out << " " << functionName << "_act.append( ActivationFunction(sum) ) ;" << endl;
2173 out << " indNeurone += 1 ;" << endl;
2174 out << " pass" << endl;
2178 out << " # --- Output"<<endl;
2179 out << " for member in range(nOutput):" << endl;
2180 out << " sum = " << functionName << "_valW[0];" << endl;
2181 out << " for source in range(nHidden):" << endl;
2182 out << " CrtW = source * ( nInput + 2) + 1;"<<endl;
2183 out << " sum += " << functionName << "_act[nInput+source] * " << functionName << "_valW[CrtW];" << endl;
2184 out << " pass" << endl;
2185 out << " " << functionName << "_act.append( sum );" << endl;
2186 out << " indNeurone += 1 ;" << endl;
2189 out << " res[member] = " << functionName
2190 << "_minOutput[member] + 0.5 * ( " << functionName
2191 << "_maxOutput[member] - " << functionName
2192 << "_minOutput[member] ) * ( sum + 1.0);" << endl;
2196 out << " res.append( " << functionName
2197 << "_minOutput[member] + " << functionName
2198 << "_maxOutput[member] * sum );" << endl;
2200 out << " pass" << endl;
2204 out << " return res;" << endl << endl;
2210 //**************************************************************
2214 // méthodes propres au RegressionModel *
2218 //**************************************************************
2221 * Check if the current model type is kLR.
2222 * \brief Called in all methods specific to the RegressionModel model.
2223 * \brief Throw an exception if the model type is not kLR.
2225 void PMMLlib::CheckRegression()
2227 if ( _currentModelType != kLR )
2228 throw string("Use this method with Regression models.");
2232 * Get the pointeur to the regression model node.
2233 * @param name Name of the regression model
2234 * @return Pointer to the XML node
2236 xmlNodePtr PMMLlib::GetRegressionPtr(std::string name)
2238 return GetPtr(name, GetTypeString() );
2242 * Add a RegressionModel to the root node
2243 * @brief Specific to RegressionModel
2244 * @param modelName Name of the model (Value of property "modelName")
2245 * @param functionName Value of property "functionName"
2246 * @param targetFieldName Value of Property "targetFieldName"
2248 void PMMLlib::AddRegressionModel(std::string modelName,
2249 PMMLMiningFunction functionName,
2250 std::string targetFieldName)
2252 _currentModelType = kLR;
2253 _currentModelName = modelName;
2254 // Check regression after setting model type!
2258 switch(functionName)
2261 function = "regression";
2264 xmlNodePtr netNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"RegressionModel", 0);
2265 xmlNewProp(netNode, (const xmlChar*)"functionName", (const xmlChar*)(function.c_str()) );
2266 xmlNewProp(netNode, (const xmlChar*)"modelName", (const xmlChar*)(_currentModelName.c_str()) );
2267 xmlNewProp(netNode, (const xmlChar*)"targetFieldName", (const xmlChar*)(targetFieldName.c_str()) );
2268 _currentModelNode = netNode ;
2272 * Add a RegressionTable to the Regression model.
2273 * @brief No property "intercept" will be set.
2274 * @brief Specific to RegressionModel
2276 void PMMLlib::AddRegressionTable()
2279 xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionModel", 0);
2280 _currentNode = tableNode;
2284 * Add a RegressionTable to the Regression model with a given value of property "intercept".
2285 * @brief Specific to RegressionModel
2286 * @param intercept Value of property "intercept"
2288 void PMMLlib::AddRegressionTable(double intercept)
2293 xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionTable", 0);
2296 ss << scientific << intercept;
2297 xmlNewProp(tableNode, (const xmlChar*)"intercept", (const xmlChar*)(ss.str().c_str()) );
2299 _currentNode = tableNode;
2303 * Add a numeric predictor to the Regression model.
2304 * @brief Specific to RegressionModel
2305 * @param neuronName Value of property "name"
2306 * @param exponent Value of property "exponent"
2307 * @param coefficient Value of property "coefficient"
2309 void PMMLlib::AddNumericPredictor(std::string neuronName,
2315 xmlNodePtr numPrecNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"NumericPredictor", 0);
2316 xmlNewProp(numPrecNode, (const xmlChar*)"name", (const xmlChar*)(neuronName.c_str()) );
2317 ss.str(""); ss << exponent;
2318 xmlNewProp(numPrecNode, (const xmlChar*)"exponent", (const xmlChar*)(ss.str().c_str()) );
2319 ss.str(""); ss << scientific << coefficient;
2320 xmlNewProp(numPrecNode, (const xmlChar*)"coefficient", (const xmlChar*)(ss.str().c_str()) );
2324 * Add a predictor term to the Regression model.
2325 * @brief Specific to RegressionModel
2326 * @param coefficient Value of property "coefficient"
2327 * @param fieldRef List of values for property "field", one per FieldRef to add to the PredictorTerm
2329 void PMMLlib::AddPredictorTerm(double coefficient,
2330 std::vector<std::string> fieldRef)
2334 xmlNodePtr predTermNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"PredictorTerm", 0);
2335 ss.str(""); ss << scientific << coefficient;
2336 xmlNewProp(predTermNode, (const xmlChar*)"coefficient", (const xmlChar*)(ss.str().c_str()) );
2337 vector<string>::iterator it;
2338 for(it=fieldRef.begin() ; it!=fieldRef.end() ; it++)
2340 xmlNodePtr fieldRefNode = xmlNewChild(predTermNode, 0, (const xmlChar*)"FieldRef", 0);
2341 ss.str(""); ss << (*it);
2342 xmlNewProp(fieldRefNode, (const xmlChar*)"field", (const xmlChar*)(ss.str().c_str()) );
2347 * Check if the RegressionTable has a property called "intercept".
2348 * @brief Specific to RegressionModel
2349 * @return true if it has, false otherwise
2351 bool PMMLlib::HasIntercept()
2355 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2356 if ( tableNode == NULL )
2358 xmlChar *xp = _stringToXmlChar("intercept");
2360 attr = xmlGetProp(tableNode, xp);
2372 * Get the value of property "intercept" in the RegressionTable.
2373 * @brief Specific to RegressionModel
2374 * @return Value of property "intercept"
2376 double PMMLlib::GetRegressionTableIntercept()
2380 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2381 if ( tableNode == NULL )
2383 string strValue = _getProp(tableNode, string("intercept") );
2384 return atof(strValue.c_str());
2388 * Get the number of numeric predictors.
2389 * @brief Specific to RegressionModel
2390 * @return Number of numeric predictors
2392 int PMMLlib::GetNumericPredictorNb()
2397 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2398 if ( tableNode == NULL )
2400 xmlNodePtr numPredNodes = tableNode->children;
2401 while (numPredNodes != NULL )
2403 if ( string((const char*)(numPredNodes->name)) == "NumericPredictor" )
2405 numPredNodes = numPredNodes->next;
2411 * Get the number of predictor terms.
2412 * @brief Specific to RegressionModel
2413 * @return Number of predictor terms
2415 int PMMLlib::GetPredictorTermNb()
2419 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2420 if ( tableNode == NULL )
2422 xmlNodePtr numPredNodes = tableNode->children;
2423 while ( numPredNodes != NULL )
2425 if ( string((const char*)(numPredNodes->name)) == "PredictorTerm" )
2427 numPredNodes = numPredNodes->next;
2433 * Get the name of the numeric predictor given by its index.
2434 * @brief Specific to RegressionModel
2435 * @param num_pred_index Index of the numeric predictor
2436 * @return Name of the numeric predictor
2438 std::string PMMLlib::GetNumericPredictorName(int num_pred_index)
2442 xmlNodePtr numPredNodes = GetChildByName(_currentModelNode,"RegressionTable");
2443 if ( numPredNodes == NULL )
2446 numPredNodes = GetChildByName(numPredNodes,"NumericPredictor");
2447 if ( numPredNodes == NULL )
2449 // Positionnement sur la bonne sortie PredictorTerm
2450 for(int i=0;i<num_pred_index;i++)
2452 numPredNodes = numPredNodes->next;
2453 if ( numPredNodes == NULL ||
2454 string((const char*)(numPredNodes->name)) != "NumericPredictor" )
2457 strName = _getProp(numPredNodes, string("name"));
2462 * Get the name of the predictor term given by its index.
2463 * @brief Specific to RegressionModel
2464 * @param pred_term_index Index of the predictor term
2465 * @return Name of the predictor term
2467 std::string PMMLlib::GetPredictorTermName(int pred_term_index)
2471 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2472 if ( fieldRefNodes == NULL )
2475 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2476 if ( fieldRefNodes == NULL )
2478 // Positionnement sur la bonne sortie
2479 for(int i=0;i<pred_term_index;i++)
2481 fieldRefNodes = fieldRefNodes->next;
2482 if ( fieldRefNodes == NULL ||
2483 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2487 fieldRefNodes = fieldRefNodes->children;
2488 while (fieldRefNodes != NULL)
2490 strName += _getProp(fieldRefNodes, string("field"));
2491 fieldRefNodes = fieldRefNodes->next;
2497 * Get the coefficient of the numeric predictor given by its index.
2498 * @brief (The coefficient is the value of property "coefficient")
2499 * @brief Specific to RegressionModel
2500 * @param num_pred_index Index of the numeric predictor
2501 * @return Coefficient of the numeric predictor
2503 double PMMLlib::GetNumericPredictorCoefficient(int num_pred_index)
2508 xmlNodePtr numPredNodes = GetChildByName(_currentModelNode,"RegressionTable");
2509 if ( numPredNodes == NULL )
2511 numPredNodes = GetChildByName(numPredNodes,"NumericPredictor");
2512 if ( numPredNodes == NULL )
2514 // Positionnement sur la bonne sortie
2515 for(int i=0;i<num_pred_index;i++)
2517 numPredNodes = numPredNodes->next;
2518 if ( numPredNodes == NULL ||
2519 string((const char*)(numPredNodes->name)) != "NumericPredictor" )
2522 string strValue = _getProp(numPredNodes, string("coefficient"));
2523 coef = atof(strValue.c_str());
2528 * Get the coefficient of the predictor term given by its index.
2529 * @brief (The coefficient is the value of property "coefficient")
2530 * @brief Specific to RegressionModel
2531 * @param pred_term_index Index of the predictor term
2532 * @return Coefficient of the predictor term
2534 double PMMLlib::GetPredictorTermCoefficient(int pred_term_index)
2539 xmlNodePtr predTermNodes = GetChildByName(_currentModelNode,"RegressionTable");
2540 if ( predTermNodes == NULL )
2542 predTermNodes = GetChildByName(predTermNodes,"PredictorTerm");
2543 if ( predTermNodes == NULL )
2545 // Positionnement sur la bonne sortie
2546 for(int i=0;i<pred_term_index;i++)
2548 predTermNodes = predTermNodes->next;
2549 if ( predTermNodes == NULL ||
2550 string((const char*)(predTermNodes->name)) != "PredictorTerm" )
2553 string strValue = _getProp(predTermNodes, string("coefficient"));
2554 coef = atof(strValue.c_str());
2559 * Get the number of FieldRef for the predictor term given by its index.
2560 * @brief Specific to RegressionModel
2561 * @param indsex Index of the predictor term
2562 * @return Number of FieldRef
2564 int PMMLlib::GetPredictorTermFieldRefNb(int index)
2569 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2570 if ( fieldRefNodes == NULL )
2572 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2573 if ( fieldRefNodes == NULL )
2575 // Positionnement sur la bonne sortie
2576 for(int i=0;i<index;i++)
2578 fieldRefNodes = fieldRefNodes->next;
2579 if ( fieldRefNodes == NULL ||
2580 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2583 fieldRefNodes = fieldRefNodes->children;
2584 while (fieldRefNodes != NULL)
2587 fieldRefNodes = fieldRefNodes->next;
2593 * Get the name of the field_index-th FieldRef for the pred_term_index-th predictor term.
2594 * @brief (The name is the value of property "field")
2595 * @brief Specific to RegressionModel
2596 * @param pred_term_index Index of the predictor term
2597 * @param field_index Index of the FieldRef
2598 * @return Name of the FieldRef
2600 std::string PMMLlib::GetPredictorTermFieldRefName(int pred_term_index, int field_index)
2605 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2606 if ( fieldRefNodes == NULL )
2608 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2609 if ( fieldRefNodes == NULL )
2611 // Positionnement sur la bonne sortie PredictorTerm
2612 for(int i=0;i<pred_term_index;i++)
2614 fieldRefNodes = fieldRefNodes->next;
2615 if ( fieldRefNodes == NULL ||
2616 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2619 fieldRefNodes = fieldRefNodes->children;
2620 if ( fieldRefNodes == NULL )
2622 // Positionnement sur la bonne sortie FieldRef
2623 for(int i=0;i<field_index;i++)
2625 fieldRefNodes = fieldRefNodes->next;
2626 if ( fieldRefNodes == NULL )
2629 strName = _getProp(fieldRefNodes, string("field"));
2634 * Export the current model as a NeuralNetwork function in a Cpp file.
2635 * @brief Specific to RegressionModel
2636 * @param file Name of the file
2637 * @param functionName Name of the function
2638 * @param header Header of the function
2640 void PMMLlib::ExportLinearRegressionCpp(std::string file,
2641 std::string functionName,
2647 ofstream exportfile(file.c_str());
2649 exportfile << "void " << functionName <<"(double *param, double *res)" << endl;
2650 exportfile << "{" << endl;
2652 exportfile << " ////////////////////////////// " << endl;
2653 exportfile << " //" << endl;
2654 // insert comments in header
2655 header = " // " + header;
2657 while ((pos = header.find("\n", pos)) != std::string::npos)
2659 header.replace(pos, 1, "\n //");
2662 exportfile << header << endl;
2663 exportfile << " //" << endl;
2664 exportfile << " ////////////////////////////// " << endl << endl;
2666 double intercept = 0.0;
2667 if ( HasIntercept() )
2669 exportfile << " // Intercept"<< endl;
2670 intercept = GetRegressionTableIntercept();
2673 exportfile << " // No Intercept"<< endl;
2674 exportfile << " double y = " << intercept << ";";
2675 exportfile << endl << endl;
2677 int nPred = GetNumericPredictorNb();
2678 for (int i=0; i<nPred; i++)
2680 exportfile << " // Attribute : " << GetNumericPredictorName(i) << endl;
2681 exportfile << " y += param["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2682 exportfile << endl << endl;
2684 nPred = GetPredictorTermNb();
2685 for (int i=0; i<nPred; i++)
2687 exportfile << " // Attribute : " << GetPredictorTermName(i) << endl;
2688 exportfile << " y += param["<<(i+nPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2689 exportfile << endl << endl;
2692 exportfile << " // Return the value"<< endl;
2693 exportfile << " res[0] = y;" << endl;
2694 exportfile << "}" << endl;
2699 * Export the current model as a NeuralNetwork function in a Fortran file.
2700 * @brief Specific to Regression
2701 * @param file Name of the file
2702 * @param functionName Name of the function
2703 * @param header Header of the function
2705 void PMMLlib::ExportLinearRegressionFortran(std::string file,
2706 std::string functionName,
2711 int nNumPred = GetNumericPredictorNb();
2712 int nPredTerm = GetPredictorTermNb();
2713 vector<string>strParam(nNumPred+nPredTerm);
2714 for(int i=0; i<(nNumPred+nPredTerm); i++)
2716 strParam[i] = "P" + NumberToString(i) ;
2720 ofstream exportfile(file.c_str());
2722 exportfile << " SUBROUTINE " << functionName <<"(";
2723 for(int i=0; i<(nNumPred+nPredTerm); i++)
2725 exportfile << strParam[i] << ", ";
2727 exportfile << "RES)" << endl;
2730 exportfile << "C --- *********************************************" << endl;
2731 exportfile << "C --- " << endl;
2732 // insert comments in header
2733 header = "C --- " + header;
2735 while ((pos = header.find("\n", pos)) != std::string::npos)
2737 header.replace(pos, 1, "\nC --- ");
2740 exportfile << header << endl;
2741 exportfile << "C --- " << endl;
2742 exportfile << "C --- *********************************************" << endl << endl;
2744 exportfile << " IMPLICIT DOUBLE PRECISION (P)" << endl;
2745 exportfile << " DOUBLE PRECISION RES" << endl;
2746 exportfile << " DOUBLE PRECISION Y" << endl;
2749 double intercept = 0.0;
2750 if ( HasIntercept() )
2752 exportfile << "C --- Intercept"<< endl;
2753 intercept = GetRegressionTableIntercept();
2756 exportfile << "C --- No Intercept"<< endl;
2757 exportfile << " Y = " << intercept << ";";
2758 exportfile << endl << endl;
2760 for (int i=0; i<nNumPred; i++)
2762 exportfile << "C --- Attribute : " << GetNumericPredictorName(i) << endl;
2763 exportfile << " Y += P["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2764 exportfile << endl << endl;
2767 for (int i=0; i<nPredTerm; i++)
2769 exportfile << "C --- Attribute : " << GetPredictorTermName(i) << endl;
2770 exportfile << " Y += P["<<(i+nNumPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2771 exportfile << endl << endl;
2774 exportfile << "C --- Return the value"<< endl;
2775 exportfile << " RES = Y " << endl;
2776 exportfile << " RETURN" << endl;
2777 exportfile << " END" << endl;
2782 * Export the current model as a NeuralNetwork function in a Python file.
2783 * @brief Specific to Regression
2784 * @param file Name of the file
2785 * @param functionName Name of the function
2786 * @param header Header of the function
2788 void PMMLlib::ExportLinearRegressionPython(std::string file,
2789 std::string functionName,
2792 string str(ExportLinearRegressionPyStr(functionName, header));
2794 ofstream exportfile(file.c_str());
2800 * Export the current model as a NeuralNetwork function in a Python string.
2801 * @brief Specific to Regression
2802 * @param functionName Name of the function
2803 * @param header Header of the function
2805 std::string PMMLlib::ExportLinearRegressionPyStr(std::string functionName,
2812 // Shebang et imports
2813 out << "#!/usr/bin/env python3" << endl;
2814 out << "# -*- coding: utf-8 -*-" << endl;
2818 out << "def " << functionName <<"(param):" << endl;
2822 out << " ############################## " << endl;
2823 out << " # " << endl;
2824 // insert comments in header
2825 header = " # " + header;
2827 while ((pos = header.find("\n", pos)) != std::string::npos)
2829 header.replace(pos, 1, "\n #");
2832 out << header << endl;
2833 out << " # " << endl;
2834 out << " ############################## " << endl << endl;
2836 double intercept = 0.0;
2837 if ( HasIntercept() )
2839 out << " # Intercept"<< endl;
2840 intercept = GetRegressionTableIntercept();
2843 out << " # No Intercept"<< endl;
2844 out << " y = " << intercept << ";";
2845 out << endl << endl;
2847 int nPred = GetNumericPredictorNb();
2848 for (int i=0; i<nPred; i++)
2850 out << " # Attribute : " << GetNumericPredictorName(i) << endl;
2851 out << " y += param["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2852 out << endl << endl;
2854 nPred = GetPredictorTermNb();
2855 for (int i=0; i<nPred; i++)
2857 out << " # Attribute : " << GetPredictorTermName(i) << endl;
2858 out << " y += param["<<(i+nPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2859 out << endl << endl;
2862 out << " # Return the value"<< endl;
2863 out << " return [y];" << endl;
2869 * Read the structure of the regression model
2870 * @brief Specific to RegressionModel
2871 * @return Structure read
2873 std::string PMMLlib::ReadRegressionStructure()
2877 string structure("");
2878 string structureActive("");
2879 string structurePredicted("@");
2881 xmlNodePtr mNode = GetChildByName(_currentModelNode,"MiningSchema");
2882 if ( mNode != NULL )
2884 xmlNodePtr dNode = GetChildByName(mNode,"MiningField");
2885 while (dNode != NULL)
2887 string name = _getProp(dNode, string("name"));
2888 string usage = _getProp(dNode, string("usageType"));
2889 if ( usage == "active" )
2891 structureActive += name;
2892 structureActive += ":";
2894 else if ( usage == "predicted" )
2896 structurePredicted += name;
2897 structurePredicted += ":";
2900 dNode = dNode->next;
2902 // Delete the last ":"
2903 if ( structureActive.length() > 0 )
2904 structureActive.erase(structureActive.size()-1);
2905 structurePredicted.erase(structurePredicted.size()-1);
2907 std::ostringstream oss;
2909 structure = structureActive + "," + oss.str() + "," + structurePredicted;
2913 } // end of namespace