1 // Copyright (C) 2013-2019 CEA/DEN
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library 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 GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 \date Wed Nov 20 11:04:17 2013
25 \brief Implémentation de la classe PMMLlib
30 #include "PMMLlib.hxx"
46 //**************************************************************
50 // méthodes communes à tous les types de modèles *
54 //**************************************************************
57 * Constructor to read a PMML file.
58 * @param file Name of the PMML file to read
59 * @param log Flag to print logs or not
61 PMMLlib::PMMLlib(std::string file,bool log) :
68 _currentModelName(""),
69 _currentModelType(kUNDEFINED)
73 xmlKeepBlanksDefault(0);
75 _doc = xmlParseFile(_pmmlFile.c_str());
78 _rootNode = xmlDocGetRootElement(_doc);
82 throw string("Unable to read PMML file.");
84 catch ( std::string msg )
94 * Constructor to create a PMML file.
95 * @brief This constructor is mandatory for Swig because it can be used with no parameters.
96 * @param log Flag to print logs or not
98 PMMLlib::PMMLlib(bool log):
105 _currentModelName(""),
106 _currentModelType(kUNDEFINED)
112 * Destructor of the class.
120 cout << "~PMMLlib" << endl;
124 * Set the current model and its type.
125 * @param modelName Name of the model to load (ie content of 'modelName' attribute)
126 * @param type Type of PMML to read: one of kANN or kLR
128 void PMMLlib::SetCurrentModel(std::string modelName,
131 _currentModelName = modelName;
132 _currentModelType = type;
136 _currentModelNode = GetNeuralNetPtr(modelName);
139 _currentModelNode = GetRegressionPtr(modelName);
142 throw string("Unknown PMML type.");
145 if ( _currentModelNode == NULL )
146 throw string("Model not found.");
150 * Set the current model and its type.
151 * @brief Throw an exception if there is no model or more than one model with name "modelName" in the PMML file
152 * @param modelName Name of the model to load (ie content of 'modelName' attribute)
154 void PMMLlib::SetCurrentModel(std::string modelName)
156 if (_rootNode == NULL)
157 throw string("No PMML file set.");
158 xmlNodePtr node = NULL;
160 node = _rootNode->children;
163 string nodeModelName = _getProp(node, string("modelName"));
164 if ( nodeModelName == modelName )
167 _currentModelNode = node;
168 _currentModelName = modelName;
169 _currentModelType = GetCurrentModelType();
175 std::ostringstream oss;
177 string msg = "SetCurrentModel(modelName) : found " + oss.str() + " model(s) in PMML file.\n";
178 msg += "Use SetCurrentModel(modelName,type).";
184 * Set the current model and its type.
185 * @brief Throw an exception if no model is found or if there are more than one model in the PMLL file
187 void PMMLlib::SetCurrentModel()
192 std::ostringstream oss;
194 string msg = "SetCurrentModel() : found " + oss.str() + " model(s) in PMML file.\n";
195 msg += "Use SetCurrentModel(modelName) or SetCurrentModel(modelName,type).";
198 _currentModelNode = GetChildByName(_rootNode,"NeuralNetwork");
199 _currentModelType = kANN;
200 if (_currentModelNode == NULL)
202 _currentModelNode = GetChildByName(_rootNode,"RegressionModel");
203 _currentModelType = kLR;
205 if (_currentModelNode == NULL)
207 string msg("Couldn't get node in SetCurrentModel().");
210 _currentModelName = _getProp(_currentModelNode, string("modelName"));
214 * Make the string used by PMMLlib::printLog.
217 std::string PMMLlib::makeLog() const
220 out << "**\n**** Display of PMMLlib ****" << endl;
221 out << " ** _pmmlFile[" << _pmmlFile << "]" << endl;
222 out << " ** _log[" << (_log?1:0) << "]" << endl;
223 out << "**\n**** End of display of PMMLlib ****" << endl;
228 * Print some information about the current PMML object.
230 void PMMLlib::printLog() const
232 string log = makeLog();
237 * Set the root node in the tree:
239 * <PMML version="4.1" xmlns="http://www.dmg.org/PMML-4_1">
242 void PMMLlib::SetRootNode()
244 xmlChar * xs = _stringToXmlChar("1.0");
245 _doc = xmlNewDoc(xs);
248 xmlChar *xp = _stringToXmlChar("PMML");
249 _rootNode = xmlNewNode(0, xp);
252 xmlNewProp(_rootNode, (const xmlChar*)"xmlns", (const xmlChar*)"http://www.dmg.org/PMML-4_1");
253 xmlNewProp(_rootNode, (const xmlChar*)"version", (const xmlChar*)"4.1");
255 xmlDocSetRootElement(_doc, _rootNode);
260 * Set the header node in the tree.
261 * @param copyright Copyright of the PMML file
262 * @param description Description of the model
263 * @param appName Name of the application that produced the file
264 * @param appVersion Version of the application that produced the file
265 * @param annotation Some annotation
267 void PMMLlib::SetHeader(std::string copyright,
268 std::string description,
270 std::string appVersion,
271 std::string annotation)
273 xmlNodePtr headerNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"Header", 0);
274 xmlNewProp(headerNode, (const xmlChar*)"copyright", (const xmlChar*)(copyright.c_str()));
275 xmlNewProp(headerNode, (const xmlChar*)"description", (const xmlChar*)(description.c_str()));
277 xmlNodePtr appNode = xmlNewChild(headerNode, 0, (const xmlChar*)"Application", 0);
278 xmlNewProp(appNode, (const xmlChar*)"name", (const xmlChar*)(appName.c_str()));
279 xmlNewProp(appNode, (const xmlChar*)"version", (const xmlChar*)(appVersion.c_str()));
281 xmlNewChild(headerNode, 0, (const xmlChar*)"Annotation", (const xmlChar*)(annotation.c_str()));
285 * Add the MiningSchema node.
286 * @brief Common to all models.
287 * @param name Value of property "name".
288 * @param usageType Value of property "usageType".
290 void PMMLlib::AddMiningSchema(std::string name,
291 std::string usageType)
293 xmlNodePtr netNode = _currentModelNode;
295 // if 'MiningSchema' node does not exist, create it
296 xmlNodePtr miningSchemaNode = GetChildByName(netNode, "MiningSchema");
297 if(!miningSchemaNode)
299 miningSchemaNode = xmlNewChild(netNode, 0, (const xmlChar*)"MiningSchema", 0);
302 // then append the node
303 xmlNodePtr miningFieldNode = xmlNewChild(miningSchemaNode, 0, (const xmlChar*)"MiningField", 0);
304 xmlNewProp(miningFieldNode, (const xmlChar*)"name", (const xmlChar*)(name.c_str()) );
305 xmlNewProp(miningFieldNode, (const xmlChar*)"usageType", (const xmlChar*)(usageType.c_str()) );
309 * Get the child of a node from the name of this node
310 * @param node Start node for the research
311 * @param nodeName Name of the node to find
312 * @return Pointer to the node found
314 xmlNodePtr PMMLlib::GetChildByName(xmlNodePtr node,
315 std::string nodeName)
320 xmlNodePtr childNode = node->children;
321 if ( childNode == NULL )
324 const xmlChar* name = childNode->name;
327 strName = _xmlCharToString(name);
329 while( (childNode != NULL) && (strName != nodeName) )
331 childNode = childNode->next;
332 if ( childNode == NULL )
334 name = childNode->name;
336 strName = _xmlCharToString(name);
342 * Count the tags of all types of models (NeuralNetwork and RegressionModel).
343 * @return Number of models
345 void PMMLlib::CountModels()
348 nCount = CountNeuralNetModels() + CountRegressionModels();
350 cout << " ** End Of Count Models nCount[" << nCount << "]" << endl;
355 * Count NeuralNetwork models tags in the PMML file.
356 * @return Number of models
358 int PMMLlib::CountNeuralNetModels()
361 xmlNodePtr ptr = GetChildByName(_rootNode,"NeuralNetwork");
363 while (ptr != NULL && _xmlCharToString(ptr->name) == "NeuralNetwork")
367 cout << " ** nCount[" << nCount << "]" << endl;
371 cout << " ** End Of CountNetworks nCount[" << nCount << "]" << endl;
376 * Count RegressionModel models tags in the PMML file.
377 * @return Number of models
379 int PMMLlib::CountRegressionModels()
382 xmlNodePtr ptr = GetChildByName(_rootNode,"RegressionModel");
384 while (ptr != NULL && _xmlCharToString(ptr->name) == "RegressionModel")
388 cout << " ** nCount[" << nCount << "]" << endl;
392 cout << " ** End Of CountRegressions nCount[" << nCount << "]" << endl;
397 * Get the number of models
398 * @return Number of models
400 int PMMLlib::GetModelsNb()
406 * Get the name of the XML node of a given model
407 * @param node Model node
408 * @return value of attribute "modelName" of the model node
410 std::string PMMLlib::GetModelName(xmlNodePtr node)
413 name = _getProp(node, string("modelName") );
418 * Get a pointer to the index-th node named name
419 * @param index Index of the node to search
420 * @param name Name of the node
421 * @return Pointer to the node found
423 xmlNodePtr PMMLlib::GetPtr(int index,
426 xmlNodePtr node = NULL;
430 _rootNode = xmlDocGetRootElement(_doc);
431 node = GetChildByName(_rootNode, name);
434 while ((i != index) && (node != NULL))
444 * Get a pointer to the node named name whose 'modelName' attribute is ann_name
445 * @param modelName Model name of the node to search
446 * @param nodeName Name of the node
447 * @return Pointer to the node found
449 xmlNodePtr PMMLlib::GetPtr(std::string myModelName,
450 std::string nodeName)
452 xmlNodePtr node = NULL;
455 node = GetChildByName(_rootNode, nodeName);
458 string modelName = _getProp(node, string("modelName"));
460 while ( (node != NULL) && modelName != myModelName )
465 modelName = _getProp(node, string("modelName"));
474 * Get the tag of the current model.
475 * @return Current model tag
477 std::string PMMLlib::GetTypeString()
480 switch(_currentModelType)
483 name = "NeuralNetwork";
486 name = "RegressionModel";
489 throw string("Unknown PMML type.");
496 * Get the current model type.
497 * @brief type is kUNDEFINED if no model is set or if model type is not handled
500 PMMLType PMMLlib::GetCurrentModelType()
502 PMMLType type = kUNDEFINED ;
503 if ( ! _currentModelNode )
505 string name = _xmlCharToString(_currentModelNode->name);
506 if ( name == "NeuralNetwork" )
508 else if ( name == "RegressionModel" )
514 * Get the current model name.
515 * @brief name is "" if no model is set
518 std::string PMMLlib::GetCurrentModelName()
520 if ( ! _currentModelNode )
522 string name = _getProp(_currentModelNode, string("modelName"));
527 * Unlink the current model node.
529 void PMMLlib::UnlinkNode()
531 xmlNodePtr ptr = _currentModelNode ;
532 xmlUnlinkNode( ptr );
537 * Make a backup of the current model node.
539 void PMMLlib::BackupNode()
541 // Node name depending of PMML type
542 string name = GetTypeString();
543 // Find the last save index number
546 ss << _currentModelName << "_" << nCrtIndex;
547 xmlNodePtr ptr = GetPtr(ss.str(), name);
552 cout << " ** nCrtIndex[" << nCrtIndex << "]" << endl;
555 ss << _currentModelName << "_" << nCrtIndex;
556 ptr = GetPtr(ss.str(), name);
559 cout << " *** Node \"" << _currentModelName << "\" found, then backup it with index [" << nCrtIndex << "]" << endl;
561 xmlUnsetProp(_currentModelNode, (const xmlChar*)"modelName");
562 xmlNewProp(_currentModelNode, (const xmlChar*)"modelName", (const xmlChar*)(ss.str().c_str()));
566 * Save the XML tree in the PMML file
568 void PMMLlib::Write()
570 // Enregistrement de l'arbre DOM dans le fichier pmml
572 // Mise à jour du nombre de modèles
577 * Save the XML tree in a given file
578 * @param Name of the file
580 void PMMLlib::Write(std::string file)
582 // Enregistrement de l'arbre DOM sous forme de fichier pmml
583 int ret = xmlSaveFormatFile( file.c_str(), _doc, 1);
586 std::string msg(" *** Error :: unable to write the PMML file \"" + file + "\"") ;
591 cout << " *** Write the PMML file \"" << file <<"\"" << endl;
595 * Export the current model as a function in a Cpp file.
596 * @param file Name of the file
597 * @param functionName Name of the function
598 * @param header Header of the function
600 void PMMLlib::ExportCpp(std::string file,
601 std::string functionName,
604 if ( _currentModelType == kANN )
605 ExportNeuralNetworkCpp(file,functionName, header);
606 else if ( _currentModelType == kLR )
608 ExportLinearRegressionCpp(file, functionName, header);
611 throw string("ExportCpp : PMML type not handled.");
615 * Export the current model as a function in a Fortran file.
616 * @param file Name of the file
617 * @param functionName Name of the function
618 * @param header Header of the function
620 void PMMLlib::ExportFortran(std::string file,
621 std::string functionName,
624 if ( _currentModelType == kANN )
625 ExportNeuralNetworkFortran(file,functionName, header);
626 else if ( _currentModelType == kLR )
627 ExportLinearRegressionFortran(file,functionName, header);
629 throw string("ExportFortran : PMML type not handled.");
633 * Export the current model as a function in a Python file.
634 * @param file Name of the file
635 * @param functionName Name of the function
636 * @param header Header of the function
638 void PMMLlib::ExportPython(std::string file,
639 std::string functionName,
642 if ( _currentModelType == kANN )
643 ExportNeuralNetworkPython(file,functionName, header);
644 else if ( _currentModelType == kLR )
645 ExportLinearRegressionPython(file,functionName, header);
647 throw string("ExportPython : PMML type not handled.");
651 * Export the current model as a function in a Python string.
652 * @param file Name of the file
653 * @param functionName Name of the function
654 * @param header Header of the function
655 * @return Function as a string
657 std::string PMMLlib::ExportPyStr(std::string functionName,
660 if ( _currentModelType == kANN )
661 return ExportNeuralNetworkPyStr(functionName, header);
662 else if ( _currentModelType == kLR )
663 return ExportLinearRegressionPyStr(functionName, header);
665 throw string("ExportPyStr : PMML type not handled.");
669 * Conversion from a libxml2 string (xmlChar *) to a standard C++ string.
670 * \param xs a constant libxml string.
671 * \return a C++ std::string (contains the same text as xs).
673 std::string PMMLlib::_xmlCharToString(const xmlChar *xs) const
675 size_t i, L = xmlStrlen(xs);
678 for (i=0; *xs; s[i++] = *xs++);
683 * Conversion from a a standard C++ string to a libxml2 string (xmlChar *).
684 * \param s Constant C++ std::string (contains the same text as xs)
685 * \return Constant libxml string.
687 xmlChar * PMMLlib::_stringToXmlChar(const std::string &s) const
689 return xmlCharStrdup(s.c_str());
693 * Get the value of a node property.
695 * \param prop Property
696 * \return Constant libxml string.
698 std::string PMMLlib::_getProp(const xmlNodePtr node,
699 std::string const & prop ) const
701 std::string name("");
704 xmlChar *xp = _stringToXmlChar(prop);
706 attr = xmlGetProp(node, xp );
709 name = _xmlCharToString(attr );
717 //**************************************************************
721 // méthodes propres au NeuralNetwork *
725 //**************************************************************
728 * Check if the current model type is kANN.
729 * \brief Called in all methods specific to the NeuralNetwork model.
730 * \brief Throw an exception if the model type is not kANN.
732 void PMMLlib::CheckNeuralNetwork()
734 if ( _currentModelType != kANN )
735 throw string("Use this method with NeuralNetwork models.");
739 * Get the XML node of a given network from the index
740 * @param index Index of the neural network
741 * @return Pointer to the XML node
743 xmlNodePtr PMMLlib::GetNeuralNetPtr(int index)
745 return GetPtr(index, GetTypeString() );
749 * Get the XML node of a given network model
750 * @param name Name of the neural network
751 * @return Pointer to the XML node
753 xmlNodePtr PMMLlib::GetNeuralNetPtr(std::string name)
755 return GetPtr(name, GetTypeString() );
759 * Read the structure of the network
760 * @brief Specific to NeuralNetwork
761 * @return Structure read
763 std::string PMMLlib::ReadNetworkStructure()
765 CheckNeuralNetwork();
767 string structure("");
768 // Treatment of the input
769 xmlNodePtr inputNodes = GetChildByName(_currentModelNode,"NeuralInputs");
770 if ( inputNodes != NULL )
772 xmlNodePtr inputNode = GetChildByName(inputNodes,"NeuralInput");
773 if ( inputNode != NULL )
775 while (inputNode != NULL)
777 xmlNodePtr child = GetChildByName(inputNode,"DerivedField");
780 xmlNodePtr fieldName = child->children; // NormContinuous
781 if ( fieldName != NULL )
783 string field = _getProp(fieldName, string("field"));
788 inputNode = inputNode->next;
790 // Delete the last comma
791 structure.erase(structure.size()-1);
794 // Intermediary layers
795 xmlNodePtr node_layer = GetChildByName(_currentModelNode,"NeuralLayer");
796 if ( node_layer != NULL )
798 string name = string((const char*)(node_layer->name));
801 while ( node_layer != NULL &&
802 (string((const char*)(node_layer->name)) == "NeuralLayer") &&
803 node_layer->next != NULL &&
804 (string((const char*)(node_layer->next->name)) != "NeuralOutputs") )
806 // Get the number of neurons of the current layer
807 string nbneurons = _getProp(node_layer, string("numberOfNeurons"));
808 structure += nbneurons;
810 node_layer = node_layer->next;
814 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
815 if ( node_outputs != NULL )
817 xmlNodePtr node_output = GetChildByName(node_outputs,"NeuralOutput");
818 if ( node_output != NULL )
820 while (node_output != NULL)
822 // Get the input of the current layer
823 xmlNodePtr child = GetChildByName(node_output,"DerivedField");
826 xmlNodePtr fieldName = child->children; // NormContinuous
827 if ( fieldName != NULL )
829 if (string((const char*)(fieldName->name)) == "NormContinuous")
832 string field = _getProp(fieldName, string("field"));
837 node_output = node_output->next;
839 // Delete the last comma
840 structure.erase(structure.size()-1);
847 * Get the number of inputs, ie the number of NeuralInputs nodes.
848 * @brief Specific to NeuralNetwork
849 * @return Number of input nodes
851 int PMMLlib::GetNbInputs()
853 CheckNeuralNetwork();
856 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
857 if ( node_inputs == NULL )
860 node_inputs = node_inputs->children;
861 while (node_inputs != NULL)
864 node_inputs = node_inputs->next;
871 * Recover the number of outputs
872 * @brief Specific to NeuralNetwork
873 * @return Number of outputs
875 int PMMLlib::GetNbOutputs()
877 CheckNeuralNetwork();
880 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
881 if ( node_outputs == NULL )
884 node_outputs = node_outputs->children;
886 while (node_outputs != NULL)
889 node_outputs = node_outputs->next;
896 * Recovery of the name of an input in the current model.
897 * @brief Specific to NeuralNetwork
898 * @param index Index of the input
899 * @return Name of the input
901 std::string PMMLlib::GetNameInput(int index)
903 CheckNeuralNetwork();
906 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
907 if ( node_inputs == NULL )
910 node_inputs = node_inputs->children;
911 if ( node_inputs == NULL )
914 for(int i = 0;i<index;i++)
916 node_inputs = node_inputs->next;
917 if ( node_inputs == NULL )
921 node_inputs = node_inputs->children;
922 if ( node_inputs == NULL )
925 node_inputs = node_inputs->children;
926 if ( node_inputs == NULL )
929 name = _getProp(node_inputs, string("field"));
935 * Get the name of an output in the current model.
936 * @brief Specific to NeuralNetwork
937 * @param index Index of the output
938 * @return Name of the output
940 std::string PMMLlib::GetNameOutput(int index)
942 CheckNeuralNetwork();
945 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
946 if ( node_outputs == NULL )
948 node_outputs = node_outputs->children;
949 if ( node_outputs == NULL )
951 for(int i = 0;i<index;i++)
953 node_outputs = node_outputs->next;
954 if ( node_outputs == NULL )
958 node_outputs = node_outputs->children;
959 if ( node_outputs == NULL )
961 node_outputs = node_outputs->children;
962 if ( node_outputs == NULL )
965 name = _getProp(node_outputs, string("field") );
971 * Get the normalization type of the current model
972 * @brief Specific to NeuralNetwork
973 * @return Normalization type of the neural network
975 int PMMLlib::GetNormalizationType()
977 CheckNeuralNetwork();
979 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
980 node_inputs = GetChildByName(node_inputs,"NeuralInput");
981 xmlNodePtr nodeTmp = GetChildByName(node_inputs,"DerivedField");
982 xmlNodePtr node_field = nodeTmp->children;
983 xmlNodePtr node_linearnorm;
985 double dorig1, dnorm1;
986 double dorig2, dnorm2;
987 if (string((const char*)(node_field->name)) == "NormContinuous")
989 // Get mean and standard deviation
990 node_linearnorm = node_field->children;
991 str_tmp = _getProp(node_linearnorm, string("orig"));
992 dorig1 = atof(str_tmp.c_str());
993 str_tmp = _getProp(node_linearnorm, string("norm"));
994 dnorm1 = atof(str_tmp.c_str());
995 node_linearnorm = node_linearnorm->next;
996 str_tmp = _getProp(node_linearnorm, string("orig"));
997 dorig2 = atof(str_tmp.c_str());
998 str_tmp = _getProp(node_linearnorm, string("norm"));
999 dnorm2 = atof(str_tmp.c_str());
1000 if ( dnorm1 * dnorm2 < -0.5 )
1001 { // case of kMinusOneOne
1005 { // case of kCR, kZeroOne
1009 string msg("Unable to retrieve the normalization type.");
1014 * Get the input parameters on the normalization
1015 * @brief Specific to NeuralNetwork
1016 * @param node_ann Neural network node
1017 * @param index Index of the input
1018 * @param[out] dnorm Array that contains the mean and the standard deviation
1020 void PMMLlib::GetNormalisationInput(int index,
1023 CheckNeuralNetwork();
1026 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
1027 if ( node_inputs == NULL )
1029 node_inputs = GetChildByName(node_inputs,"NeuralInput");
1030 if ( node_inputs == NULL )
1032 // Positionnement sur la bonne entree
1033 for(int i=0;i<index;i++)
1035 node_inputs = node_inputs->next;
1036 if ( node_inputs == NULL )
1039 xmlNodePtr tmpNode = GetChildByName(node_inputs,"DerivedField");
1040 if ( tmpNode == NULL )
1042 xmlNodePtr node_field = GetChildByName(tmpNode,"NormContinuous");
1043 if ( node_field == NULL )
1045 if (string((const char*)(node_field->name)) == "NormContinuous")
1047 //Get mean and standard deviation
1049 xmlNodePtr node_linearnorm = node_field->children;
1050 str_tmp = _getProp(node_linearnorm, string("orig"));
1051 double dorig1 = atof(str_tmp.c_str());
1052 str_tmp = _getProp(node_linearnorm, string("norm"));
1053 double dnorm1 = atof(str_tmp.c_str());
1054 node_linearnorm = node_linearnorm->next;
1055 str_tmp = _getProp(node_linearnorm, string("orig"));
1056 double dorig2 = atof(str_tmp.c_str());
1057 str_tmp = _getProp(node_linearnorm, string("norm"));
1058 double dnorm2 = atof(str_tmp.c_str());
1059 if ( dnorm1 * dnorm2 < -0.5 ) // <=> GetNormalizationType == 0
1061 // case of kMinusOneOne
1065 else // <=> GetNormalizationType == 1
1067 // case of kCR, kZeroOne
1069 dnorm[1] = -1.0 * dnorm1 * dorig2; //dorig2 / dnorm1;
1075 * Get the parameters on the normalization of an output for the current model.
1076 * @brief Specific to NeuralNetwork
1077 * @param index Output index
1078 * @param[out] dnorm Array that contains the mean and the standard deviation
1080 void PMMLlib::GetNormalisationOutput(int index,
1083 CheckNeuralNetwork();
1087 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
1088 if ( node_outputs == NULL )
1090 node_outputs = GetChildByName(node_outputs,"NeuralOutput");
1091 if ( node_outputs == NULL )
1093 // Positionnement sur la bonne sortie
1094 for(int i=0;i< index;i++)
1096 node_outputs = node_outputs->next;
1097 if ( node_outputs == NULL )
1100 xmlNodePtr tmpNode = GetChildByName(node_outputs,"DerivedField");
1101 if ( tmpNode == NULL )
1103 xmlNodePtr node_field = GetChildByName(tmpNode,"NormContinuous");
1104 if ( node_field == NULL )
1107 if (string((const char*)(node_field->name)) == "NormContinuous")
1109 // Recuperation de la moyenne et de l'ecart type
1111 xmlNodePtr node_linearnorm = node_field->children;
1112 str_tmp = _getProp(node_linearnorm, string("orig"));
1113 double dorig1 = atof(str_tmp.c_str());
1114 str_tmp = _getProp(node_linearnorm, string("norm"));
1115 double dnorm1 = atof(str_tmp.c_str());
1116 node_linearnorm = node_linearnorm->next;
1117 str_tmp = _getProp(node_linearnorm,string("orig"));
1118 double dorig2 = atof(str_tmp.c_str());
1119 str_tmp = _getProp(node_linearnorm, string("norm"));
1120 double dnorm2 = atof(str_tmp.c_str());
1121 if ( dnorm1 * dnorm2 < -0.5 )
1123 // case of kMinusOneOne
1129 // case of kCR, kZeroOne
1131 dnorm[1] = -1.0 * dorig2 * dnorm1; //-1.0 * dorig2 / dnorm1;
1137 * Get the number of hidden layers
1138 * @brief Specific to NeuralNetwork
1139 * @return Number of hidden layers
1141 int PMMLlib::GetNbHiddenLayers()
1143 CheckNeuralNetwork();
1146 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1147 if ( node_layers == NULL )
1150 while (string((const char*)(node_layers->name)) == "NeuralLayer")
1153 node_layers = node_layers->next;
1154 if ( node_layers == NULL )
1161 * Get the total number of layers
1162 * @return Total number of layers
1164 int PMMLlib::GetNbLayers()
1166 return (GetNbHiddenLayers() + 2);
1170 * Get the number of neurons at a given layer
1171 * @param index Index of the layer
1172 * @return Number of neurons at given layer
1174 int PMMLlib::GetNbNeuronsAtLayer(int index)
1176 CheckNeuralNetwork();
1179 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1180 if ( node_layers == NULL )
1183 // Positionnement à la bonne couche
1184 for(int i=0;i<index;i++)
1186 node_layers = node_layers->next;
1187 if ( node_layers == NULL )
1191 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1192 while(node_neurons != NULL)
1195 node_neurons = node_neurons->next;
1202 * Get the bias of a neuron
1203 * @brief Specific to NeuralNetwork
1204 * @param layer_index Index of the layer to get bias
1205 * @param neu_index Index of the neuron
1206 * @return Bias of the specified neuron
1208 double PMMLlib::GetNeuronBias(int layer_index,
1211 CheckNeuralNetwork();
1214 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1215 if ( node_layers == NULL )
1217 // Positionnement a la bonne couche
1218 for(int i=0;i<layer_index;i++)
1220 node_layers = node_layers->next;
1221 if ( node_layers == NULL )
1224 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1225 // Positionnement sur le bon neurone
1226 for(int j=0;j<neu_index;j++)
1228 node_neurons = node_neurons->next;
1229 if ( node_neurons == NULL )
1232 string str_tmp = _getProp(node_neurons, string("bias"));
1233 bias = atof(str_tmp.c_str());
1238 * Get the synaptic weight
1239 * @brief Specific to NeuralNetwork
1240 * @param layer_index Index of the layer to get synaptic weight
1241 * @param neu_index Index of the neuron
1242 * @param prec_index Index of the synapse
1243 * @return Synaptic weight
1245 double PMMLlib::GetPrecNeuronSynapse(int layer_index,
1249 CheckNeuralNetwork();
1252 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1253 if ( node_layers == NULL )
1255 // Positionnement a la bonne couche
1256 for(int i=0;i<layer_index;i++)
1258 node_layers = node_layers->next;
1259 if ( node_layers == NULL )
1262 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1263 // Positionnement sur le bon neurone
1264 for(int i=0;i<neu_index;i++)
1266 node_neurons = node_neurons->next;
1267 if ( node_neurons == NULL )
1270 xmlNodePtr node_con = GetChildByName(node_neurons,"Con");
1271 // Positionnement sur la bonne synapse
1272 for(int i=0;i<prec_index;i++)
1274 node_con = node_con->next;
1275 if ( node_con == NULL )
1278 string str_tmp = _getProp(node_con, string("weight"));
1279 weight = atof(str_tmp.c_str());
1284 * Set the name of the neural network
1286 * @param index Neural network index
1287 * @param name Neural network name to set
1290 void PMMLlib::SetNeuralNetName(int index,
1293 CheckNeuralNetwork();
1298 xmlNodePtr node_ann = GetChildByName(_rootNode,"NeuralNetwork");
1299 while ((i != index) && (node_ann != NULL))
1301 node_ann = node_ann->next;
1304 xmlNewProp(node_ann, (const xmlChar*)"modelName", (const xmlChar*)(name.c_str()));
1306 xmlSaveFormatFile( string(_pmmlFile+".pmml").c_str(), _doc, 1);
1311 * Add a DataField node to the DataDictionnary node
1312 * @param fieldName Value of property "name"
1313 * @param displayName Value of property "displayName"
1314 * @param optype Value of property "optype"
1315 * @param dataType Value of property "dataType"
1316 * @param closure Value of property "closure" in node Interval
1317 * @param leftMargin Value of property "leftMargin" in node Interval
1318 * @param rightMargin Value of property "rightMargin" in node Interval
1319 * @param interval Flag to add a node Interval (if true)
1321 void PMMLlib::AddDataField(std::string fieldName,
1322 std::string displayName,
1324 std::string dataType,
1325 std::string closure,
1330 // if 'DataDictionary' node does not exist, create it
1331 xmlNodePtr dataDictNode = GetChildByName(_rootNode, "DataDictionary");
1334 dataDictNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"DataDictionary", 0);
1337 // then append the node
1338 xmlNodePtr dataFieldNode = xmlNewChild(dataDictNode, 0, (const xmlChar*)"DataField", 0);
1339 xmlNewProp(dataFieldNode, (const xmlChar*)"name", (const xmlChar*)(fieldName.c_str()) );
1340 xmlNewProp(dataFieldNode, (const xmlChar*)"displayName", (const xmlChar*)(displayName.c_str()) );
1341 xmlNewProp(dataFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1342 xmlNewProp(dataFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1346 xmlNodePtr intervalNode = xmlNewChild(dataFieldNode, 0, (const xmlChar*)"Interval", 0);
1347 xmlNewProp(intervalNode, (const xmlChar*)"closure", (const xmlChar*)(closure.c_str()) );
1349 ss << scientific << leftMargin;
1350 xmlNewProp(intervalNode, (const xmlChar*)"leftMargin", (const xmlChar*)(ss.str().c_str()) );
1352 ss << scientific << rightMargin;
1353 xmlNewProp(intervalNode, (const xmlChar*)"rightMargin", (const xmlChar*)(ss.str().c_str()) );
1358 * Add a NeuralNetwork node to the root node
1359 * @brief Specific to NeuralNetwork
1360 * @param modelName Model name
1361 * @param functionName PMMLMiningFunction. One of : kREGRESSION.
1363 void PMMLlib::AddNeuralNetwork(std::string modelName,
1364 PMMLMiningFunction functionName)
1366 _currentModelType = kANN;
1367 _currentModelName = modelName;
1369 CheckNeuralNetwork();
1372 switch(functionName)
1375 function = "regression";
1379 xmlNodePtr netNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"NeuralNetwork", 0);
1380 xmlNewProp(netNode, (const xmlChar*)"modelName", (const xmlChar*)(_currentModelName.c_str()) );
1381 xmlNewProp(netNode, (const xmlChar*)"functionName", (const xmlChar*)(function.c_str()) );
1382 xmlNewProp(netNode, (const xmlChar*)"numberOfLayers", (const xmlChar*)"0" );
1383 _currentModelNode = netNode;
1387 * Add a NeuralInput node to the current model.
1388 * @brief Specific to NeuralNetwork
1389 * @param id Id of the input
1390 * @param inputName Name of the input
1391 * @param optype Value of property "optype"
1392 * @param dataType Value of property "dataType"
1393 * @param orig1 Value of the first origin
1394 * @param norm1 Value of the first norm
1395 * @param orig2 Value of the second origin
1396 * @param norm2 Value of the second norm
1398 void PMMLlib::AddNeuralInput(int id,
1399 std::string inputName,
1401 std::string dataType,
1402 double orig1, double norm1,
1403 double orig2, double norm2)
1405 CheckNeuralNetwork();
1407 xmlNodePtr netNode = _currentModelNode;
1408 // if 'NeuralInputs' node does not exist, create it
1409 xmlNodePtr neuralInputsNode = GetChildByName(netNode, "NeuralInputs");
1410 if(!neuralInputsNode)
1412 neuralInputsNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralInputs", 0);
1413 xmlNewProp(neuralInputsNode, (const xmlChar*)"numberOfInputs", (const xmlChar*)"0" );
1415 // increment the number of inputs
1416 string numberOfInputsStr = _getProp(neuralInputsNode, string("numberOfInputs"));
1418 istringstream( numberOfInputsStr ) >> numberOfInputs;
1421 ss << numberOfInputs;
1422 xmlSetProp(neuralInputsNode, (const xmlChar*)"numberOfInputs", (const xmlChar*)(ss.str().c_str()) );
1423 // then append the node and its children
1424 xmlNodePtr neuralInputNode = xmlNewChild(neuralInputsNode, 0, (const xmlChar*)"NeuralInput", 0);
1425 ss.str(""); ss << id;
1426 xmlNewProp(neuralInputNode, (const xmlChar*)"id", (const xmlChar*)(ss.str().c_str()) );
1428 xmlNodePtr derivedFieldNode = xmlNewChild(neuralInputNode, 0, (const xmlChar*)"DerivedField", 0);
1429 xmlNewProp(derivedFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1430 xmlNewProp(derivedFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1432 xmlNodePtr normcontNode = xmlNewChild(derivedFieldNode, 0, (const xmlChar*)"NormContinuous", 0);
1433 xmlNewProp(normcontNode, (const xmlChar*)"field", (const xmlChar*)(inputName.c_str()) );
1435 xmlNodePtr node_linearnorm1 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1436 ss.str(""); ss << scientific << orig1;
1437 xmlNewProp(node_linearnorm1, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1438 ss.str(""); ss << scientific << norm1;
1439 xmlNewProp(node_linearnorm1, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1440 xmlNodePtr node_linearnorm2 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1441 ss.str(""); ss << scientific << orig2;
1442 xmlNewProp(node_linearnorm2, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1443 ss.str(""); ss << scientific << norm2;
1444 xmlNewProp(node_linearnorm2, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1448 * Add a NeuralOutput node to the current model.
1449 * @brief Specific to NeuralNetwork
1450 * @param outputNeuron Id of the output
1451 * @param outputName Name of the output
1452 * @param optype Value of property "optype"
1453 * @param dataType Value of property "dataType"
1454 * @param orig1 Value of the first origin
1455 * @param norm1 Value of the first norm
1456 * @param orig2 Value of the second origin
1457 * @param norm2 Value of the second norm
1459 void PMMLlib::AddNeuralOutput(int outputNeuron,
1460 std::string outputName,
1462 std::string dataType,
1463 double orig1, double norm1,
1464 double orig2, double norm2)
1466 CheckNeuralNetwork();
1468 xmlNodePtr netNode = _currentModelNode;
1469 // if 'NeuralOutputs' node does not exist, create it
1470 xmlNodePtr neuralOutputsNode = GetChildByName(netNode, "NeuralOutputs");
1471 if(!neuralOutputsNode)
1473 neuralOutputsNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralOutputs", 0);
1474 xmlNewProp(neuralOutputsNode, (const xmlChar*)"numberOfOutputs", (const xmlChar*)"0" );
1476 // increment the number of inputs
1477 string numberOfOutputsStr = _getProp(neuralOutputsNode, string("numberOfOutputs"));
1478 int numberOfOutputs;
1479 istringstream( numberOfOutputsStr ) >> numberOfOutputs;
1482 ss << numberOfOutputs;
1483 xmlSetProp(neuralOutputsNode, (const xmlChar*)"numberOfOutputs", (const xmlChar*)(ss.str().c_str()) );
1485 // then append the node and its children
1486 xmlNodePtr neuralOutputNode = xmlNewChild(neuralOutputsNode, 0, (const xmlChar*)"NeuralOutput", 0);
1487 ss.str(""); ss << outputNeuron;
1488 xmlNewProp(neuralOutputNode, (const xmlChar*)"outputNeuron", (const xmlChar*)(ss.str().c_str()) );
1490 xmlNodePtr derivedFieldNode = xmlNewChild(neuralOutputNode, 0, (const xmlChar*)"DerivedField", 0);
1491 xmlNewProp(derivedFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1492 xmlNewProp(derivedFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1494 xmlNodePtr normcontNode = xmlNewChild(derivedFieldNode, 0, (const xmlChar*)"NormContinuous", 0);
1495 xmlNewProp(normcontNode, (const xmlChar*)"field", (const xmlChar*)(outputName.c_str()) );
1497 xmlNodePtr node_linearnorm1 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1498 ss.str(""); ss << scientific << orig1;
1499 xmlNewProp(node_linearnorm1, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1500 ss.str(""); ss << scientific << norm1;
1501 xmlNewProp(node_linearnorm1, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1502 xmlNodePtr node_linearnorm2 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1503 ss.str(""); ss << scientific << orig2;
1504 xmlNewProp(node_linearnorm2, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1505 ss.str(""); ss << scientific << norm2;
1506 xmlNewProp(node_linearnorm2, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1510 * Add a NeuralLayer node to the current model.
1511 * @brief Specific to NeuralNetwork
1512 * @param activationFunction Activation function. One of kIDENTITY, kTANH, kLOGISTIC.
1514 void PMMLlib::AddNeuralLayer(PMMLActivationFunction activationFunction)
1516 CheckNeuralNetwork();
1518 string functionName;
1519 switch(activationFunction)
1522 functionName = "identity";
1525 functionName = "tanh";
1528 functionName = "logistic";
1531 xmlNodePtr netNode = _currentModelNode;
1532 // Increment the number of layers
1533 string numberOfLayersStr = _getProp(_currentModelNode, string("numberOfLayers"));
1535 istringstream( numberOfLayersStr ) >> numberOfLayers;
1538 ss << numberOfLayers;
1539 xmlSetProp(netNode, (const xmlChar*)"numberOfLayers", (const xmlChar*)(ss.str().c_str()) );
1540 // Add the neural layer node
1541 xmlNodePtr neuralLayerNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralLayer", 0);
1542 xmlNewProp(neuralLayerNode, (const xmlChar*)"activationFunction", (const xmlChar*)(functionName.c_str()) );
1543 xmlNewProp(neuralLayerNode, (const xmlChar*)"numberOfNeurons", (const xmlChar*)"0" );
1544 // Save the current layer in the _currentNode attribute
1545 _currentNode = neuralLayerNode;
1549 * Add a NeuralLayer node to the current model.
1550 * @brief Specific to NeuralNetwork
1551 * @param id Id of the layer
1552 * @param bias Value of property "bias"
1553 * @param conNb Number of Con nodes
1554 * @param firstFrom Value of property "from" for the first Con
1555 * @param weights Vector of weights (One per Con node)
1557 void PMMLlib::AddNeuron(int id,
1561 vector<double> weights)
1563 CheckNeuralNetwork();
1567 // increment the number of neurons
1568 string numberOfNeuronsStr = _getProp(_currentNode, string("numberOfNeurons"));
1569 int numberOfNeurons;
1570 istringstream( numberOfNeuronsStr ) >> numberOfNeurons;
1572 ss << numberOfNeurons;
1573 xmlSetProp(_currentNode, (const xmlChar*)"numberOfNeurons", (const xmlChar*)(ss.str().c_str()) );
1576 xmlNodePtr neuronNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"Neuron", 0);
1577 ss.str(""); ss << id;
1578 xmlNewProp(neuronNode, (const xmlChar*)"id", (const xmlChar*)(ss.str().c_str()) );
1579 ss.str(""); ss << scientific << bias;
1580 xmlNewProp(neuronNode, (const xmlChar*)"bias", (const xmlChar*)(ss.str().c_str()) );
1582 // append multiple 'Con' to the neuron
1583 for(int k=0 ; k<conNb ; k++)
1585 xmlNodePtr conNode = xmlNewChild(neuronNode, 0, (const xmlChar*)"Con", 0);
1586 ss.str(""); ss << firstFrom+k;
1587 xmlNewProp(conNode, (const xmlChar*)"from", (const xmlChar*)(ss.str().c_str()) ); // !!! ce n'est pas k !!!
1588 ss.str(""); ss << scientific << weights[k];
1589 xmlNewProp(conNode, (const xmlChar*)"weight", (const xmlChar*)(ss.str().c_str()) );
1594 * Fill the vectors used by the ExportXXX methods.
1595 * @brief Specific to NeuralNetwork
1606 void PMMLlib::fillVectorsForExport(int nInput,
1610 vector<double> &minInput,
1611 vector<double> &maxInput,
1612 vector<double> &minOutput,
1613 vector<double> &maxOutput,
1614 vector<double> &valW )
1616 CheckNeuralNetwork();
1618 xmlNodePtr netNode = _currentModelNode ;
1619 // Get the different values required
1620 // Build min/max input/output vectors
1621 for(int i=0 ; i<nInput ; i++)
1623 xmlNodePtr node_inputs = GetChildByName(netNode,"NeuralInputs");
1624 node_inputs = node_inputs->children;
1625 for(int j = 0;j<i;j++)
1627 node_inputs = node_inputs->next;
1629 node_inputs = node_inputs->children; // DerivedField
1630 node_inputs = node_inputs->children; // NormContinuous
1631 node_inputs = node_inputs->children; // LinearNorm
1632 string strOrig1 = _getProp(node_inputs, string("orig") );
1633 double orig1 = atof( strOrig1.c_str() );
1634 string strNorm1 = _getProp(node_inputs, string("norm") );
1635 double norm1 = atof( strNorm1.c_str() );
1636 node_inputs = node_inputs->next;
1637 string strOrig2 = _getProp(node_inputs, string("orig") );
1638 double orig2 = atof( strOrig2.c_str() );
1639 string strNorm2 = _getProp(node_inputs, string("norm") );
1642 minInput[i] = orig1;
1643 maxInput[i] = orig2;
1647 minInput[i] = orig2;
1648 maxInput[i] = -1.0*norm1*orig2;
1651 xmlNodePtr node_outputs = GetChildByName(netNode,"NeuralOutputs");
1652 node_outputs = node_outputs->children;
1653 node_outputs = node_outputs->children; // DerivedField
1654 node_outputs = node_outputs->children; // NormContinuous
1655 node_outputs = node_outputs->children; // LinearNorm
1656 string strOrig1 = _getProp(node_outputs, string("orig") );
1657 double orig1 = atof( strOrig1.c_str() );
1658 string strNorm1 = _getProp(node_outputs, string("norm") );
1659 double norm1 = atof( strNorm1.c_str() );
1660 node_outputs = node_outputs->next;
1661 string strOrig2 = _getProp(node_outputs, string("orig") );
1662 double orig2 = atof( strOrig2.c_str() );
1665 minOutput[0] = orig1;
1666 maxOutput[0] = orig2;
1670 minOutput[0] = orig2;
1671 maxOutput[0] = -1.0*norm1*orig2;
1673 // Build weight vector
1674 for(int j=0 ; j<nHidden ; j++) // hidden layers
1676 valW[j*(nInput+nOutput+1)+2] = GetNeuronBias( 0, j);
1677 for(int i=0 ; i<nInput ; i++)
1679 valW[j*(nInput+nOutput+1)+3+i] = GetPrecNeuronSynapse( 0, j, i);
1682 for(int j=0 ; j<nOutput ; j++) // output layers
1684 valW[0] = GetNeuronBias( 1, j);
1685 for(int i=0 ; i<nHidden ; i++)
1687 valW[i*(nInput+nOutput+1)+1] = GetPrecNeuronSynapse( 1, j, i);
1693 * Export the current model as a NeuralNetwork function in a Cpp file.
1694 * @brief Specific to NeuralNetwork
1695 * @param file Name of the file
1696 * @param functionName Name of the function
1697 * @param header Header of the function
1699 void PMMLlib::ExportNeuralNetworkCpp(std::string file,
1700 std::string functionName,
1703 CheckNeuralNetwork();
1705 // Get the different values required
1706 int nInput = GetNbInputs();
1707 int nOutput = GetNbOutputs();
1708 int nHidden = GetNbNeuronsAtLayer(0);
1709 int nNeurons = nInput+nOutput+nHidden;
1710 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
1711 int normType = GetNormalizationType();
1712 // Build min/max input/output vectors
1713 vector<double> minInput(nInput);
1714 vector<double> maxInput(nInput);
1715 vector<double> minOutput(nOutput);
1716 vector<double> maxOutput(nOutput);
1717 vector<double> valW(nWeights);
1718 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
1720 ofstream sourcefile(file.c_str());
1721 // ActivationFunction
1724 sourcefile << "#define ActivationFunction(sum) ( tanh(sum) )" << endl;
1728 sourcefile << "#define ActivationFunction(sum) ( 1.0 / ( 1.0 + exp( -1.0 * sum )) )" << endl;
1731 sourcefile << "void " << functionName <<"(double *param, double *res)" << endl;
1732 sourcefile << "{" << endl;
1734 sourcefile << " ////////////////////////////// " << endl;
1735 sourcefile << " //" << endl;
1736 // insert comments in header
1737 header = " // " + header;
1739 while ((pos = header.find("\n", pos)) != std::string::npos)
1741 header.replace(pos, 1, "\n //");
1744 sourcefile << header << endl;
1745 sourcefile << " //" << endl;
1746 sourcefile << " ////////////////////////////// " << endl;
1748 sourcefile << " int nInput = " << nInput << ";" << endl;
1749 sourcefile << " int nOutput = " << nOutput << ";" << endl;
1750 // sourcefile << " int nWeights = " << _nWeight << ";" << endl;
1751 sourcefile << " int nHidden = " << nHidden << ";" << endl;
1752 sourcefile << " const int nNeurones = " << nNeurons << ";" << endl;
1753 sourcefile << " double " << functionName << "_act[nNeurones];" << endl;
1755 sourcefile << " // --- Preprocessing of the inputs and outputs" << endl;
1756 sourcefile << " double " << functionName << "_minInput[] = {" << endl << " ";
1757 for(int i=0 ; i<nInput ; i++)
1759 sourcefile << minInput[i] << ", ";
1761 sourcefile << "\n ";
1765 sourcefile << " };" << endl;
1767 sourcefile << " double " << functionName << "_minOutput[] = {" << endl << " ";
1768 sourcefile << minOutput[0] << ", ";
1769 sourcefile << " };" << endl;
1771 sourcefile << " double " << functionName << "_maxInput[] = {" << endl << " ";
1772 for(int i=0 ; i<nInput ; i++)
1774 sourcefile << maxInput[i] << ", ";
1776 sourcefile << "\n ";
1780 sourcefile << " };" << endl;
1782 sourcefile << " double " << functionName << "_maxOutput[] = {" << endl << " ";
1783 sourcefile << maxOutput[0] << ", ";
1784 sourcefile << " };" << endl;
1787 sourcefile << " // --- Values of the weights" << endl;
1788 sourcefile << " double " << functionName << "_valW[] = {" << endl << " ";
1789 for(int i=0 ; i<nWeights ; i++)
1791 sourcefile << valW[i] << ", ";
1793 sourcefile << endl << " ";
1795 sourcefile << endl << " };"<<endl;
1797 sourcefile << " // --- Constants";
1799 sourcefile << " int indNeurone = 0;"<<endl;
1800 sourcefile << " int CrtW;"<<endl;
1801 sourcefile << " double sum;"<<endl;
1805 sourcefile << " // --- Input Layers"<<endl;
1806 sourcefile << " for(int i = 0; i < nInput; i++) {"<<endl;
1809 sourcefile << " " << functionName << "_act[indNeurone++] = 2.0 * ( param[i] - "
1810 << functionName << "_minInput[i] ) / ( " << functionName << "_maxInput[i] - "
1811 << functionName << "_minInput[i] ) - 1.0;"<<endl;
1815 sourcefile << " " << functionName << "_act[indNeurone++] = ( param[i] - "
1816 << functionName << "_minInput[i] ) / " << functionName << "_maxInput[i];"
1819 sourcefile << " }"<<endl;
1824 sourcefile << " // --- Hidden Layers"<<endl;
1825 sourcefile << " for (int member = 0; member < nHidden; member++) {"<<endl;
1826 sourcefile << " int CrtW = member * ( nInput + 2) + 2;" << endl;
1827 sourcefile << " sum = " << functionName << "_valW[CrtW++];" << endl;
1828 sourcefile << " for (int source = 0; source < nInput; source++) {" << endl;
1829 sourcefile << " sum += " << functionName << "_act[source] * " << functionName << "_valW[CrtW++];" << endl;
1830 sourcefile << " }" << endl;
1831 sourcefile << " " << functionName << "_act[indNeurone++] = ActivationFunction(sum);" << endl;
1832 sourcefile << " }"<<endl;
1835 sourcefile << " // --- Output"<<endl;
1836 sourcefile << " for (int member = 0; member < nOutput; member++) {"<<endl;
1837 sourcefile << " sum = " << functionName << "_valW[0];"<<endl;
1838 sourcefile << " for (int source = 0; source < nHidden; source++) {"<<endl;
1839 sourcefile << " CrtW = source * ( nInput + 2) + 1;"<<endl;
1840 sourcefile << " sum += " << functionName << "_act[nInput+source] * " << functionName << "_valW[CrtW];"<<endl;
1841 sourcefile << " }"<<endl;
1842 sourcefile << " " << functionName << "_act[indNeurone++] = sum;"<<endl;
1845 sourcefile << " res[member] = " << functionName
1846 << "_minOutput[member] + 0.5 * ( " << functionName
1847 << "_maxOutput[member] - " << functionName
1848 << "_minOutput[member] ) * ( sum + 1.0);" << endl;
1852 sourcefile << " res[member] = " << functionName
1853 << "_minOutput[member] + " << functionName
1854 << "_maxOutput[member] * sum;" << endl;
1856 sourcefile << " }"<<endl;
1858 sourcefile << "}" << endl;
1863 * Export the current model as a NeuralNetwork function in a Fortran file.
1864 * @brief Specific to NeuralNetwork
1865 * @param file Name of the file
1866 * @param functionName Name of the function
1867 * @param header Header of the function
1869 void PMMLlib::ExportNeuralNetworkFortran(std::string file,
1870 std::string functionName,
1873 CheckNeuralNetwork();
1875 // Get the different values required
1876 int nInput = GetNbInputs();
1877 int nOutput = GetNbOutputs();
1878 int nHidden = GetNbNeuronsAtLayer(0);
1879 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
1880 int normType = GetNormalizationType();
1881 // Build min/max input/output vectors
1882 vector<double> minInput(nInput);
1883 vector<double> maxInput(nInput);
1884 vector<double> minOutput(nOutput);
1885 vector<double> maxOutput(nOutput);
1886 vector<double> valW(nWeights);
1887 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
1889 ofstream sourcefile(file.c_str());
1891 sourcefile << " SUBROUTINE " << functionName << "(";
1892 for(int i=0 ; i<GetNbInputs() ; i++)
1894 sourcefile << GetNameInput(i) << ",";
1896 sourcefile << GetNameOutput(0) << ")" << endl;
1898 sourcefile << "C --- *********************************************" << endl;
1899 sourcefile << "C --- " << endl;
1900 // insert comments in header
1901 header = "C --- " + header;
1903 while ((pos = header.find("\n", pos)) != std::string::npos)
1905 header.replace(pos, 1, "\nC --- ");
1908 sourcefile << header << endl;
1909 sourcefile << "C --- " << endl;
1910 sourcefile << "C --- *********************************************" << endl;
1912 sourcefile << " IMPLICIT DOUBLE PRECISION (V)" << endl;
1913 for(int i=0 ; i<GetNbInputs() ; i++)
1915 sourcefile << " DOUBLE PRECISION " << GetNameInput(i) << endl;
1917 sourcefile << " DOUBLE PRECISION " << GetNameOutput(0) << endl;
1920 sourcefile << "C --- Preprocessing of the inputs" << endl;
1921 for(int i=0 ; i<GetNbInputs() ; i++)
1923 sourcefile << " VXN" << GetNameInput(i) << " = ";
1927 sourcefile << "2.D0 * ( " << GetNameInput(i) << " - " << minInput[i] << "D0 ) / " << maxInput[i] - minInput[i] << "D0 - 1.0" << endl;
1931 sourcefile << "( " << GetNameInput(i) << " - " << minInput[i] << "D0 ) / " << maxInput[i] << "D0" << endl;
1937 sourcefile << "C --- Values of the weights" << endl;
1938 for(int i=0 ; i<nWeights ; i++)
1940 sourcefile << " VW" << i+1 << " = " << valW[i] << endl;
1942 // Loop on hidden neurons
1944 for(int member = 0; member < nHidden; member++)
1946 sourcefile << "C --- hidden neural number " << member+1 << endl;
1947 int CrtW = member * ( nInput + 2) + 3;
1948 sourcefile << " VAct" << member+1 << " = VW" << CrtW++ << endl;
1949 for (int source = 0; source < nInput; source++)
1951 sourcefile << " 1 + VW"<< CrtW++ << " * VXN" << GetNameInput(source) << endl;
1958 sourcefile << " VPot" << member+1 << " = 2.D0 / (1.D0 + DEXP(-2.D0 * VAct" << member+1 <<")) - 1.D0" << endl;
1962 sourcefile << " VPot" << member+1 << " = 1.D0 / (1.D0 + DEXP(-1.D0 * VAct" << member+1 <<"))" << endl;
1967 // Ouput of the model
1968 sourcefile << "C --- Output" << endl;
1969 sourcefile << " VOut = VW1" << endl;
1970 for(int source=0 ; source < nHidden ; source++)
1972 int CrtW = source * ( nInput + 2) + 2;
1973 sourcefile << " 1 + VW"<< CrtW << " * VPot" << source+1 << endl;
1976 // Denormalize Output
1978 sourcefile << "C --- Pretraitment of the output" << endl;
1981 sourcefile << " VDelta = " << 0.5*(maxOutput[0]-minOutput[0]) << "D0 * ( VOut + 1.0D0)" << endl;
1982 sourcefile << " " << GetNameOutput(0) << " = " << minOutput[0] << "D0 + VDelta" << endl;
1987 sourcefile << " " << GetNameOutput(0) << " = "<< minOutput[0] << "D0 + " << maxOutput[0] << "D0 * VOut;" << endl;
1991 sourcefile << "C --- " << endl;
1992 sourcefile << " RETURN" << endl;
1993 sourcefile << " END" << endl;
1999 * Export the current model as a NeuralNetwork function in a Python file.
2000 * @brief Specific to NeuralNetwork
2001 * @param file Name of the file
2002 * @param functionName Name of the function
2003 * @param header Header of the function
2005 void PMMLlib::ExportNeuralNetworkPython(std::string file,
2006 std::string functionName,
2009 string str(ExportNeuralNetworkPyStr(functionName, header));
2011 ofstream exportfile(file.c_str());
2018 * Export the current model as a function in a Python string.
2019 * @brief Specific to NeuralNetwork
2020 * @param functionName Name of the function
2021 * @param header Header of the function
2022 * @return Function as a string
2024 std::string PMMLlib::ExportNeuralNetworkPyStr(std::string functionName,
2027 CheckNeuralNetwork();
2031 // Get the different values required
2032 int nInput = GetNbInputs();
2033 int nOutput = GetNbOutputs();
2034 int nHidden = GetNbNeuronsAtLayer(0);
2035 int nNeurons = nInput+nOutput+nHidden;
2036 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
2037 int normType = GetNormalizationType();
2038 // Build min/max input/output vectors
2039 vector<double> minInput(nInput);
2040 vector<double> maxInput(nInput);
2041 vector<double> minOutput(nOutput);
2042 vector<double> maxOutput(nOutput);
2043 vector<double> valW(nWeights);
2044 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
2046 // Shebang et imports
2047 out << "#!/usr/bin/env python3" << endl;
2048 out << "# -*- coding: utf-8 -*-" << endl;
2050 out << "from math import tanh, exp" << endl;
2053 // ActivationFunction
2056 out << "def ActivationFunction(sum): " << endl;
2057 out << " return tanh(sum); " << endl;
2061 out << "def ActivationFunction(sum): " << endl;
2062 out << " return ( 1.0 / ( 1.0 + exp( -1.0 * sum ) ) ); " << endl;
2066 out << "def " << functionName <<"(param):" << endl;
2070 out << " ############################## " << endl;
2071 out << " #" << endl;
2072 // insert comments in header
2073 header = " # " + header;
2075 while ((pos = header.find("\n", pos)) != std::string::npos)
2077 header.replace(pos, 1, "\n #");
2080 out << header << endl;
2081 out << " #" << endl;
2082 out << " ############################## " << endl;
2086 out << " nInput = " << nInput << ";" << endl;
2087 out << " nOutput = " << nOutput << ";" << endl;
2088 out << " nHidden = " << nHidden << ";" << endl;
2089 out << " nNeurones = " << nNeurons << ";" << endl;
2090 out << " " << functionName << "_act = [];" << endl;
2091 out << " res = [];" << endl;
2094 out << " # --- Preprocessing of the inputs and outputs" << endl;
2095 out << " " << functionName << "_minInput = [" << endl << " ";
2097 for(int i=0 ; i<nInput ; i++)
2099 out << minInput[i] << ", ";
2106 out << endl << " ];" << endl;
2108 out << " " << functionName << "_minOutput = [" << endl << " ";
2109 out << " " << minOutput[0] ;
2110 out << endl << " ];" << endl;
2112 out << " " << functionName << "_maxInput = [" << endl << " ";
2113 for(int i=0 ; i<nInput ; i++)
2115 out << maxInput[i] << ", ";
2122 out << endl << " ];" << endl;
2124 out << " " << functionName << "_maxOutput = [" << endl << " ";
2125 out << " " << maxOutput[0] ;
2126 out << endl << " ];" << endl;
2129 out << " # --- Values of the weights" << endl;
2130 out << " " << functionName << "_valW = [" << endl << " ";
2131 for(int i=0 ; i<nWeights ; i++)
2133 out << valW[i] << ", ";
2140 out << endl << " ];"<<endl;
2142 out << " # --- Constants" << endl;
2143 out << " indNeurone = 0;" << endl;
2147 out << " # --- Input Layers" << endl;
2148 out << " for i in range(nInput) :" << endl;
2151 out << " " << functionName << "_act.append( 2.0 * ( param[i] - "
2152 << functionName << "_minInput[i] ) / ( " << functionName << "_maxInput[i] - "
2153 << functionName << "_minInput[i] ) - 1.0 ) ;"
2158 out << " " << functionName << "_act.append( ( param[i] - "
2159 << functionName << "_minInput[i] ) / " << functionName << "_maxInput[i] ) ;"
2162 out << " indNeurone += 1 ;" << endl;
2163 out << " pass" << endl;
2167 out << " # --- Hidden Layers" << endl;
2168 out << " for member in range(nHidden):" << endl;
2169 out << " CrtW = member * ( nInput + 2) + 2;" << endl;
2170 out << " sum = " << functionName << "_valW[CrtW];" << endl;
2171 out << " CrtW += 1 ;" << endl;
2172 out << " for source in range(nInput) :" << endl;
2173 out << " sum += " << functionName << "_act[source] * " << functionName << "_valW[CrtW];" << endl;
2174 out << " CrtW += 1 ;" << endl;
2175 out << " pass" << endl;
2176 out << " " << functionName << "_act.append( ActivationFunction(sum) ) ;" << endl;
2177 out << " indNeurone += 1 ;" << endl;
2178 out << " pass" << endl;
2182 out << " # --- Output"<<endl;
2183 out << " for member in range(nOutput):" << endl;
2184 out << " sum = " << functionName << "_valW[0];" << endl;
2185 out << " for source in range(nHidden):" << endl;
2186 out << " CrtW = source * ( nInput + 2) + 1;"<<endl;
2187 out << " sum += " << functionName << "_act[nInput+source] * " << functionName << "_valW[CrtW];" << endl;
2188 out << " pass" << endl;
2189 out << " " << functionName << "_act.append( sum );" << endl;
2190 out << " indNeurone += 1 ;" << endl;
2193 out << " res[member] = " << functionName
2194 << "_minOutput[member] + 0.5 * ( " << functionName
2195 << "_maxOutput[member] - " << functionName
2196 << "_minOutput[member] ) * ( sum + 1.0);" << endl;
2200 out << " res.append( " << functionName
2201 << "_minOutput[member] + " << functionName
2202 << "_maxOutput[member] * sum );" << endl;
2204 out << " pass" << endl;
2208 out << " return res;" << endl << endl;
2214 //**************************************************************
2218 // méthodes propres au RegressionModel *
2222 //**************************************************************
2225 * Check if the current model type is kLR.
2226 * \brief Called in all methods specific to the RegressionModel model.
2227 * \brief Throw an exception if the model type is not kLR.
2229 void PMMLlib::CheckRegression()
2231 if ( _currentModelType != kLR )
2232 throw string("Use this method with Regression models.");
2236 * Get the pointeur to the regression model node.
2237 * @param name Name of the regression model
2238 * @return Pointer to the XML node
2240 xmlNodePtr PMMLlib::GetRegressionPtr(std::string name)
2242 return GetPtr(name, GetTypeString() );
2246 * Add a RegressionModel to the root node
2247 * @brief Specific to RegressionModel
2248 * @param modelName Name of the model (Value of property "modelName")
2249 * @param functionName Value of property "functionName"
2250 * @param targetFieldName Value of Property "targetFieldName"
2252 void PMMLlib::AddRegressionModel(std::string modelName,
2253 PMMLMiningFunction functionName,
2254 std::string targetFieldName)
2256 _currentModelType = kLR;
2257 _currentModelName = modelName;
2258 // Check regression after setting model type!
2262 switch(functionName)
2265 function = "regression";
2268 xmlNodePtr netNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"RegressionModel", 0);
2269 xmlNewProp(netNode, (const xmlChar*)"functionName", (const xmlChar*)(function.c_str()) );
2270 xmlNewProp(netNode, (const xmlChar*)"modelName", (const xmlChar*)(_currentModelName.c_str()) );
2271 xmlNewProp(netNode, (const xmlChar*)"targetFieldName", (const xmlChar*)(targetFieldName.c_str()) );
2272 _currentModelNode = netNode ;
2276 * Add a RegressionTable to the Regression model.
2277 * @brief No property "intercept" will be set.
2278 * @brief Specific to RegressionModel
2280 void PMMLlib::AddRegressionTable()
2283 xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionModel", 0);
2284 _currentNode = tableNode;
2288 * Add a RegressionTable to the Regression model with a given value of property "intercept".
2289 * @brief Specific to RegressionModel
2290 * @param intercept Value of property "intercept"
2292 void PMMLlib::AddRegressionTable(double intercept)
2297 xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionTable", 0);
2300 ss << scientific << intercept;
2301 xmlNewProp(tableNode, (const xmlChar*)"intercept", (const xmlChar*)(ss.str().c_str()) );
2303 _currentNode = tableNode;
2307 * Add a numeric predictor to the Regression model.
2308 * @brief Specific to RegressionModel
2309 * @param neuronName Value of property "name"
2310 * @param exponent Value of property "exponent"
2311 * @param coefficient Value of property "coefficient"
2313 void PMMLlib::AddNumericPredictor(std::string neuronName,
2319 xmlNodePtr numPrecNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"NumericPredictor", 0);
2320 xmlNewProp(numPrecNode, (const xmlChar*)"name", (const xmlChar*)(neuronName.c_str()) );
2321 ss.str(""); ss << exponent;
2322 xmlNewProp(numPrecNode, (const xmlChar*)"exponent", (const xmlChar*)(ss.str().c_str()) );
2323 ss.str(""); ss << scientific << coefficient;
2324 xmlNewProp(numPrecNode, (const xmlChar*)"coefficient", (const xmlChar*)(ss.str().c_str()) );
2328 * Add a predictor term to the Regression model.
2329 * @brief Specific to RegressionModel
2330 * @param coefficient Value of property "coefficient"
2331 * @param fieldRef List of values for property "field", one per FieldRef to add to the PredictorTerm
2333 void PMMLlib::AddPredictorTerm(double coefficient,
2334 std::vector<std::string> fieldRef)
2338 xmlNodePtr predTermNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"PredictorTerm", 0);
2339 ss.str(""); ss << scientific << coefficient;
2340 xmlNewProp(predTermNode, (const xmlChar*)"coefficient", (const xmlChar*)(ss.str().c_str()) );
2341 vector<string>::iterator it;
2342 for(it=fieldRef.begin() ; it!=fieldRef.end() ; it++)
2344 xmlNodePtr fieldRefNode = xmlNewChild(predTermNode, 0, (const xmlChar*)"FieldRef", 0);
2345 ss.str(""); ss << (*it);
2346 xmlNewProp(fieldRefNode, (const xmlChar*)"field", (const xmlChar*)(ss.str().c_str()) );
2351 * Check if the RegressionTable has a property called "intercept".
2352 * @brief Specific to RegressionModel
2353 * @return true if it has, false otherwise
2355 bool PMMLlib::HasIntercept()
2359 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2360 if ( tableNode == NULL )
2362 xmlChar *xp = _stringToXmlChar("intercept");
2364 attr = xmlGetProp(tableNode, xp);
2376 * Get the value of property "intercept" in the RegressionTable.
2377 * @brief Specific to RegressionModel
2378 * @return Value of property "intercept"
2380 double PMMLlib::GetRegressionTableIntercept()
2384 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2385 if ( tableNode == NULL )
2387 string strValue = _getProp(tableNode, string("intercept") );
2388 return atof(strValue.c_str());
2392 * Get the number of numeric predictors.
2393 * @brief Specific to RegressionModel
2394 * @return Number of numeric predictors
2396 int PMMLlib::GetNumericPredictorNb()
2401 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2402 if ( tableNode == NULL )
2404 xmlNodePtr numPredNodes = tableNode->children;
2405 while (numPredNodes != NULL )
2407 if ( string((const char*)(numPredNodes->name)) == "NumericPredictor" )
2409 numPredNodes = numPredNodes->next;
2415 * Get the number of predictor terms.
2416 * @brief Specific to RegressionModel
2417 * @return Number of predictor terms
2419 int PMMLlib::GetPredictorTermNb()
2423 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2424 if ( tableNode == NULL )
2426 xmlNodePtr numPredNodes = tableNode->children;
2427 while ( numPredNodes != NULL )
2429 if ( string((const char*)(numPredNodes->name)) == "PredictorTerm" )
2431 numPredNodes = numPredNodes->next;
2437 * Get the name of the numeric predictor given by its index.
2438 * @brief Specific to RegressionModel
2439 * @param num_pred_index Index of the numeric predictor
2440 * @return Name of the numeric predictor
2442 std::string PMMLlib::GetNumericPredictorName(int num_pred_index)
2446 xmlNodePtr numPredNodes = GetChildByName(_currentModelNode,"RegressionTable");
2447 if ( numPredNodes == NULL )
2450 numPredNodes = GetChildByName(numPredNodes,"NumericPredictor");
2451 if ( numPredNodes == NULL )
2453 // Positionnement sur la bonne sortie PredictorTerm
2454 for(int i=0;i<num_pred_index;i++)
2456 numPredNodes = numPredNodes->next;
2457 if ( numPredNodes == NULL ||
2458 string((const char*)(numPredNodes->name)) != "NumericPredictor" )
2461 strName = _getProp(numPredNodes, string("name"));
2466 * Get the name of the predictor term given by its index.
2467 * @brief Specific to RegressionModel
2468 * @param pred_term_index Index of the predictor term
2469 * @return Name of the predictor term
2471 std::string PMMLlib::GetPredictorTermName(int pred_term_index)
2475 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2476 if ( fieldRefNodes == NULL )
2479 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2480 if ( fieldRefNodes == NULL )
2482 // Positionnement sur la bonne sortie
2483 for(int i=0;i<pred_term_index;i++)
2485 fieldRefNodes = fieldRefNodes->next;
2486 if ( fieldRefNodes == NULL ||
2487 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2491 fieldRefNodes = fieldRefNodes->children;
2492 while (fieldRefNodes != NULL)
2494 strName += _getProp(fieldRefNodes, string("field"));
2495 fieldRefNodes = fieldRefNodes->next;
2501 * Get the coefficient of the numeric predictor given by its index.
2502 * @brief (The coefficient is the value of property "coefficient")
2503 * @brief Specific to RegressionModel
2504 * @param num_pred_index Index of the numeric predictor
2505 * @return Coefficient of the numeric predictor
2507 double PMMLlib::GetNumericPredictorCoefficient(int num_pred_index)
2512 xmlNodePtr numPredNodes = GetChildByName(_currentModelNode,"RegressionTable");
2513 if ( numPredNodes == NULL )
2515 numPredNodes = GetChildByName(numPredNodes,"NumericPredictor");
2516 if ( numPredNodes == NULL )
2518 // Positionnement sur la bonne sortie
2519 for(int i=0;i<num_pred_index;i++)
2521 numPredNodes = numPredNodes->next;
2522 if ( numPredNodes == NULL ||
2523 string((const char*)(numPredNodes->name)) != "NumericPredictor" )
2526 string strValue = _getProp(numPredNodes, string("coefficient"));
2527 coef = atof(strValue.c_str());
2532 * Get the coefficient of the predictor term given by its index.
2533 * @brief (The coefficient is the value of property "coefficient")
2534 * @brief Specific to RegressionModel
2535 * @param pred_term_index Index of the predictor term
2536 * @return Coefficient of the predictor term
2538 double PMMLlib::GetPredictorTermCoefficient(int pred_term_index)
2543 xmlNodePtr predTermNodes = GetChildByName(_currentModelNode,"RegressionTable");
2544 if ( predTermNodes == NULL )
2546 predTermNodes = GetChildByName(predTermNodes,"PredictorTerm");
2547 if ( predTermNodes == NULL )
2549 // Positionnement sur la bonne sortie
2550 for(int i=0;i<pred_term_index;i++)
2552 predTermNodes = predTermNodes->next;
2553 if ( predTermNodes == NULL ||
2554 string((const char*)(predTermNodes->name)) != "PredictorTerm" )
2557 string strValue = _getProp(predTermNodes, string("coefficient"));
2558 coef = atof(strValue.c_str());
2563 * Get the number of FieldRef for the predictor term given by its index.
2564 * @brief Specific to RegressionModel
2565 * @param indsex Index of the predictor term
2566 * @return Number of FieldRef
2568 int PMMLlib::GetPredictorTermFieldRefNb(int index)
2573 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2574 if ( fieldRefNodes == NULL )
2576 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2577 if ( fieldRefNodes == NULL )
2579 // Positionnement sur la bonne sortie
2580 for(int i=0;i<index;i++)
2582 fieldRefNodes = fieldRefNodes->next;
2583 if ( fieldRefNodes == NULL ||
2584 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2587 fieldRefNodes = fieldRefNodes->children;
2588 while (fieldRefNodes != NULL)
2591 fieldRefNodes = fieldRefNodes->next;
2597 * Get the name of the field_index-th FieldRef for the pred_term_index-th predictor term.
2598 * @brief (The name is the value of property "field")
2599 * @brief Specific to RegressionModel
2600 * @param pred_term_index Index of the predictor term
2601 * @param field_index Index of the FieldRef
2602 * @return Name of the FieldRef
2604 std::string PMMLlib::GetPredictorTermFieldRefName(int pred_term_index, int field_index)
2609 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2610 if ( fieldRefNodes == NULL )
2612 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2613 if ( fieldRefNodes == NULL )
2615 // Positionnement sur la bonne sortie PredictorTerm
2616 for(int i=0;i<pred_term_index;i++)
2618 fieldRefNodes = fieldRefNodes->next;
2619 if ( fieldRefNodes == NULL ||
2620 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2623 fieldRefNodes = fieldRefNodes->children;
2624 if ( fieldRefNodes == NULL )
2626 // Positionnement sur la bonne sortie FieldRef
2627 for(int i=0;i<field_index;i++)
2629 fieldRefNodes = fieldRefNodes->next;
2630 if ( fieldRefNodes == NULL )
2633 strName = _getProp(fieldRefNodes, string("field"));
2638 * Export the current model as a NeuralNetwork function in a Cpp file.
2639 * @brief Specific to RegressionModel
2640 * @param file Name of the file
2641 * @param functionName Name of the function
2642 * @param header Header of the function
2644 void PMMLlib::ExportLinearRegressionCpp(std::string file,
2645 std::string functionName,
2651 ofstream exportfile(file.c_str());
2653 exportfile << "void " << functionName <<"(double *param, double *res)" << endl;
2654 exportfile << "{" << endl;
2656 exportfile << " ////////////////////////////// " << endl;
2657 exportfile << " //" << endl;
2658 // insert comments in header
2659 header = " // " + header;
2661 while ((pos = header.find("\n", pos)) != std::string::npos)
2663 header.replace(pos, 1, "\n //");
2666 exportfile << header << endl;
2667 exportfile << " //" << endl;
2668 exportfile << " ////////////////////////////// " << endl << endl;
2670 double intercept = 0.0;
2671 if ( HasIntercept() )
2673 exportfile << " // Intercept"<< endl;
2674 intercept = GetRegressionTableIntercept();
2677 exportfile << " // No Intercept"<< endl;
2678 exportfile << " double y = " << intercept << ";";
2679 exportfile << endl << endl;
2681 int nPred = GetNumericPredictorNb();
2682 for (int i=0; i<nPred; i++)
2684 exportfile << " // Attribute : " << GetNumericPredictorName(i) << endl;
2685 exportfile << " y += param["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2686 exportfile << endl << endl;
2688 nPred = GetPredictorTermNb();
2689 for (int i=0; i<nPred; i++)
2691 exportfile << " // Attribute : " << GetPredictorTermName(i) << endl;
2692 exportfile << " y += param["<<(i+nPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2693 exportfile << endl << endl;
2696 exportfile << " // Return the value"<< endl;
2697 exportfile << " res[0] = y;" << endl;
2698 exportfile << "}" << endl;
2703 * Export the current model as a NeuralNetwork function in a Fortran file.
2704 * @brief Specific to Regression
2705 * @param file Name of the file
2706 * @param functionName Name of the function
2707 * @param header Header of the function
2709 void PMMLlib::ExportLinearRegressionFortran(std::string file,
2710 std::string functionName,
2715 int nNumPred = GetNumericPredictorNb();
2716 int nPredTerm = GetPredictorTermNb();
2717 vector<string>strParam(nNumPred+nPredTerm);
2718 for(int i=0; i<(nNumPred+nPredTerm); i++)
2720 strParam[i] = "P" + NumberToString(i) ;
2724 ofstream exportfile(file.c_str());
2726 exportfile << " SUBROUTINE " << functionName <<"(";
2727 for(int i=0; i<(nNumPred+nPredTerm); i++)
2729 exportfile << strParam[i] << ", ";
2731 exportfile << "RES)" << endl;
2734 exportfile << "C --- *********************************************" << endl;
2735 exportfile << "C --- " << endl;
2736 // insert comments in header
2737 header = "C --- " + header;
2739 while ((pos = header.find("\n", pos)) != std::string::npos)
2741 header.replace(pos, 1, "\nC --- ");
2744 exportfile << header << endl;
2745 exportfile << "C --- " << endl;
2746 exportfile << "C --- *********************************************" << endl << endl;
2748 exportfile << " IMPLICIT DOUBLE PRECISION (P)" << endl;
2749 exportfile << " DOUBLE PRECISION RES" << endl;
2750 exportfile << " DOUBLE PRECISION Y" << endl;
2753 double intercept = 0.0;
2754 if ( HasIntercept() )
2756 exportfile << "C --- Intercept"<< endl;
2757 intercept = GetRegressionTableIntercept();
2760 exportfile << "C --- No Intercept"<< endl;
2761 exportfile << " Y = " << intercept << ";";
2762 exportfile << endl << endl;
2764 for (int i=0; i<nNumPred; i++)
2766 exportfile << "C --- Attribute : " << GetNumericPredictorName(i) << endl;
2767 exportfile << " Y += P["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2768 exportfile << endl << endl;
2771 for (int i=0; i<nPredTerm; i++)
2773 exportfile << "C --- Attribute : " << GetPredictorTermName(i) << endl;
2774 exportfile << " Y += P["<<(i+nNumPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2775 exportfile << endl << endl;
2778 exportfile << "C --- Return the value"<< endl;
2779 exportfile << " RES = Y " << endl;
2780 exportfile << " RETURN" << endl;
2781 exportfile << " END" << endl;
2786 * Export the current model as a NeuralNetwork function in a Python file.
2787 * @brief Specific to Regression
2788 * @param file Name of the file
2789 * @param functionName Name of the function
2790 * @param header Header of the function
2792 void PMMLlib::ExportLinearRegressionPython(std::string file,
2793 std::string functionName,
2796 string str(ExportLinearRegressionPyStr(functionName, header));
2798 ofstream exportfile(file.c_str());
2804 * Export the current model as a NeuralNetwork function in a Python string.
2805 * @brief Specific to Regression
2806 * @param functionName Name of the function
2807 * @param header Header of the function
2809 std::string PMMLlib::ExportLinearRegressionPyStr(std::string functionName,
2816 // Shebang et imports
2817 out << "#!/usr/bin/env python3" << endl;
2818 out << "# -*- coding: utf-8 -*-" << endl;
2822 out << "def " << functionName <<"(param):" << endl;
2826 out << " ############################## " << endl;
2827 out << " # " << endl;
2828 // insert comments in header
2829 header = " # " + header;
2831 while ((pos = header.find("\n", pos)) != std::string::npos)
2833 header.replace(pos, 1, "\n #");
2836 out << header << endl;
2837 out << " # " << endl;
2838 out << " ############################## " << endl << endl;
2840 double intercept = 0.0;
2841 if ( HasIntercept() )
2843 out << " # Intercept"<< endl;
2844 intercept = GetRegressionTableIntercept();
2847 out << " # No Intercept"<< endl;
2848 out << " y = " << intercept << ";";
2849 out << endl << endl;
2851 int nPred = GetNumericPredictorNb();
2852 for (int i=0; i<nPred; i++)
2854 out << " # Attribute : " << GetNumericPredictorName(i) << endl;
2855 out << " y += param["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2856 out << endl << endl;
2858 nPred = GetPredictorTermNb();
2859 for (int i=0; i<nPred; i++)
2861 out << " # Attribute : " << GetPredictorTermName(i) << endl;
2862 out << " y += param["<<(i+nPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2863 out << endl << endl;
2866 out << " # Return the value"<< endl;
2867 out << " return [y];" << endl;
2873 * Read the structure of the regression model
2874 * @brief Specific to RegressionModel
2875 * @return Structure read
2877 std::string PMMLlib::ReadRegressionStructure()
2881 string structure("");
2882 string structureActive("");
2883 string structurePredicted("@");
2885 xmlNodePtr mNode = GetChildByName(_currentModelNode,"MiningSchema");
2886 if ( mNode != NULL )
2888 xmlNodePtr dNode = GetChildByName(mNode,"MiningField");
2889 while (dNode != NULL)
2891 string name = _getProp(dNode, string("name"));
2892 string usage = _getProp(dNode, string("usageType"));
2893 if ( usage == "active" )
2895 structureActive += name;
2896 structureActive += ":";
2898 else if ( usage == "predicted" )
2900 structurePredicted += name;
2901 structurePredicted += ":";
2904 dNode = dNode->next;
2906 // Delete the last ":"
2907 if ( structureActive.length() > 0 )
2908 structureActive.erase(structureActive.size()-1);
2909 structurePredicted.erase(structurePredicted.size()-1);
2911 std::ostringstream oss;
2913 structure = structureActive + "," + oss.str() + "," + structurePredicted;
2917 } // end of namespace