1 //////////////////////////////////////////////////////////////
2 // Copyright (C) 2013 CEA/DEN
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as published
6 // by the Free Software Foundation, either version 3 of the License, or any
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 //////////////////////////////////////////////////////////////
20 \date Wed Nov 20 11:04:17 2013
22 \brief Implémentation de la classe PMMLlib
27 #include "PMMLlib.hxx"
43 //**************************************************************
47 // méthodes communes à tous les types de modèles *
51 //**************************************************************
54 * Constructor to read a PMML file.
55 * @param file Name of the PMML file to read
56 * @param log Flag to print logs or not
58 PMMLlib::PMMLlib(std::string file,bool log) :
65 _currentModelName(""),
66 _currentModelType(kUNDEFINED)
70 xmlKeepBlanksDefault(0);
72 _doc = xmlParseFile(_pmmlFile.c_str());
75 _rootNode = xmlDocGetRootElement(_doc);
79 throw string("Unable to read PMML file.");
81 catch ( std::string msg )
91 * Constructor to create a PMML file.
92 * @brief This constructor is mandatory for Swig because it can be used with no parameters.
93 * @param log Flag to print logs or not
95 PMMLlib::PMMLlib(bool log):
102 _currentModelName(""),
103 _currentModelType(kUNDEFINED)
109 * Destructor of the class.
117 cout << "~PMMLlib" << endl;
121 * Set the current model and its type.
122 * @param modelName Name of the model to load (ie content of 'modelName' attribute)
123 * @param type Type of PMML to read: one of kANN or kLR
125 void PMMLlib::SetCurrentModel(std::string modelName,
128 _currentModelName = modelName;
129 _currentModelType = type;
133 _currentModelNode = GetNeuralNetPtr(modelName);
136 _currentModelNode = GetRegressionPtr(modelName);
139 throw string("Unknown PMML type.");
142 if ( _currentModelNode == NULL )
143 throw string("Model not found.");
147 * Set the current model and its type.
148 * @brief Throw an exception if there is no model or more than one model with name "modelName" in the PMML file
149 * @param modelName Name of the model to load (ie content of 'modelName' attribute)
151 void PMMLlib::SetCurrentModel(std::string modelName)
153 if (_rootNode == NULL)
154 throw string("No PMML file set.");
155 xmlNodePtr node = NULL;
157 node = _rootNode->children;
160 string nodeModelName = _getProp(node, string("modelName"));
161 if ( nodeModelName == modelName )
164 _currentModelNode = node;
165 _currentModelName = modelName;
166 _currentModelType = GetCurrentModelType();
172 std::ostringstream oss;
174 string msg = "SetCurrentModel(modelName) : found " + oss.str() + " model(s) in PMML file.\n";
175 msg += "Use SetCurrentModel(modelName,type).";
181 * Set the current model and its type.
182 * @brief Throw an exception if no model is found or if there are more than one model in the PMLL file
184 void PMMLlib::SetCurrentModel()
189 std::ostringstream oss;
191 string msg = "SetCurrentModel() : found " + oss.str() + " model(s) in PMML file.\n";
192 msg += "Use SetCurrentModel(modelName) or SetCurrentModel(modelName,type).";
195 _currentModelNode = GetChildByName(_rootNode,"NeuralNetwork");
196 _currentModelType = kANN;
197 if (_currentModelNode == NULL)
199 _currentModelNode = GetChildByName(_rootNode,"RegressionModel");
200 _currentModelType = kLR;
202 if (_currentModelNode == NULL)
204 string msg("Couldn't get node in SetCurrentModel().");
207 _currentModelName = _getProp(_currentModelNode, string("modelName"));
211 * Make the string used by PMMLlib::printLog.
214 std::string PMMLlib::makeLog() const
217 out << "**\n**** Display of PMMLlib ****" << endl;
218 out << " ** _pmmlFile[" << _pmmlFile << "]" << endl;
219 out << " ** _log[" << (_log?1:0) << "]" << endl;
220 out << "**\n**** End of display of PMMLlib ****" << endl;
225 * Print some information about the current PMML object.
227 void PMMLlib::printLog() const
229 string log = makeLog();
234 * Set the root node in the tree:
236 * <PMML version="4.1" xmlns="http://www.dmg.org/PMML-4_1">
239 void PMMLlib::SetRootNode()
241 xmlChar * xs = _stringToXmlChar("1.0");
242 _doc = xmlNewDoc(xs);
245 xmlChar *xp = _stringToXmlChar("PMML");
246 _rootNode = xmlNewNode(0, xp);
249 xmlNewProp(_rootNode, (const xmlChar*)"xmlns", (const xmlChar*)"http://www.dmg.org/PMML-4_1");
250 xmlNewProp(_rootNode, (const xmlChar*)"version", (const xmlChar*)"4.1");
252 xmlDocSetRootElement(_doc, _rootNode);
257 * Set the header node in the tree.
258 * @param copyright Copyright of the PMML file
259 * @param description Description of the model
260 * @param appName Name of the application that produced the file
261 * @param appVersion Version of the application that produced the file
262 * @param annotation Some annotation
264 void PMMLlib::SetHeader(std::string copyright,
265 std::string description,
267 std::string appVersion,
268 std::string annotation)
270 xmlNodePtr headerNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"Header", 0);
271 xmlNewProp(headerNode, (const xmlChar*)"copyright", (const xmlChar*)(copyright.c_str()));
272 xmlNewProp(headerNode, (const xmlChar*)"description", (const xmlChar*)(description.c_str()));
274 xmlNodePtr appNode = xmlNewChild(headerNode, 0, (const xmlChar*)"Application", 0);
275 xmlNewProp(appNode, (const xmlChar*)"name", (const xmlChar*)(appName.c_str()));
276 xmlNewProp(appNode, (const xmlChar*)"version", (const xmlChar*)(appVersion.c_str()));
278 xmlNewChild(headerNode, 0, (const xmlChar*)"Annotation", (const xmlChar*)(annotation.c_str()));
282 * Add the MiningSchema node.
283 * @brief Common to all models.
284 * @param name Value of property "name".
285 * @param usageType Value of property "usageType".
287 void PMMLlib::AddMiningSchema(std::string name,
288 std::string usageType)
290 xmlNodePtr netNode = _currentModelNode;
292 // if 'MiningSchema' node does not exist, create it
293 xmlNodePtr miningSchemaNode = GetChildByName(netNode, "MiningSchema");
294 if(!miningSchemaNode)
296 miningSchemaNode = xmlNewChild(netNode, 0, (const xmlChar*)"MiningSchema", 0);
299 // then append the node
300 xmlNodePtr miningFieldNode = xmlNewChild(miningSchemaNode, 0, (const xmlChar*)"MiningField", 0);
301 xmlNewProp(miningFieldNode, (const xmlChar*)"name", (const xmlChar*)(name.c_str()) );
302 xmlNewProp(miningFieldNode, (const xmlChar*)"usageType", (const xmlChar*)(usageType.c_str()) );
306 * Get the child of a node from the name of this node
307 * @param node Start node for the research
308 * @param nodeName Name of the node to find
309 * @return Pointer to the node found
311 xmlNodePtr PMMLlib::GetChildByName(xmlNodePtr node,
312 std::string nodeName)
317 xmlNodePtr childNode = node->children;
318 if ( childNode == NULL )
321 const xmlChar* name = childNode->name;
324 strName = _xmlCharToString(name);
326 while( (childNode != NULL) && (strName != nodeName) )
328 childNode = childNode->next;
329 if ( childNode == NULL )
331 name = childNode->name;
333 strName = _xmlCharToString(name);
339 * Count the tags of all types of models (NeuralNetwork and RegressionModel).
340 * @return Number of models
342 void PMMLlib::CountModels()
345 nCount = CountNeuralNetModels() + CountRegressionModels();
347 cout << " ** End Of Count Models nCount[" << nCount << "]" << endl;
352 * Count NeuralNetwork models tags in the PMML file.
353 * @return Number of models
355 int PMMLlib::CountNeuralNetModels()
358 xmlNodePtr ptr = GetChildByName(_rootNode,"NeuralNetwork");
360 while (ptr != NULL && _xmlCharToString(ptr->name) == "NeuralNetwork")
364 cout << " ** nCount[" << nCount << "]" << endl;
368 cout << " ** End Of CountNetworks nCount[" << nCount << "]" << endl;
373 * Count RegressionModel models tags in the PMML file.
374 * @return Number of models
376 int PMMLlib::CountRegressionModels()
379 xmlNodePtr ptr = GetChildByName(_rootNode,"RegressionModel");
381 while (ptr != NULL && _xmlCharToString(ptr->name) == "RegressionModel")
385 cout << " ** nCount[" << nCount << "]" << endl;
389 cout << " ** End Of CountRegressions nCount[" << nCount << "]" << endl;
394 * Get the number of models
395 * @return Number of models
397 int PMMLlib::GetModelsNb()
403 * Get the name of the XML node of a given model
404 * @param node Model node
405 * @return value of attribute "modelName" of the model node
407 std::string PMMLlib::GetModelName(xmlNodePtr node)
410 name = _getProp(node, string("modelName") );
415 * Get a pointer to the index-th node named name
416 * @param index Index of the node to search
417 * @param name Name of the node
418 * @return Pointer to the node found
420 xmlNodePtr PMMLlib::GetPtr(int index,
423 xmlNodePtr node = NULL;
427 _rootNode = xmlDocGetRootElement(_doc);
428 node = GetChildByName(_rootNode, name);
431 while ((i != index) && (node != NULL))
441 * Get a pointer to the node named name whose 'modelName' attribute is ann_name
442 * @param modelName Model name of the node to search
443 * @param nodeName Name of the node
444 * @return Pointer to the node found
446 xmlNodePtr PMMLlib::GetPtr(std::string myModelName,
447 std::string nodeName)
449 xmlNodePtr node = NULL;
452 node = GetChildByName(_rootNode, nodeName);
455 string modelName = _getProp(node, string("modelName"));
457 while ( (node != NULL) && modelName != myModelName )
462 modelName = _getProp(node, string("modelName"));
471 * Get the tag of the current model.
472 * @return Current model tag
474 std::string PMMLlib::GetTypeString()
477 switch(_currentModelType)
480 name = "NeuralNetwork";
483 name = "RegressionModel";
486 throw string("Unknown PMML type.");
493 * Get the current model type.
494 * @brief type is kUNDEFINED if no model is set or if model type is not handled
497 PMMLType PMMLlib::GetCurrentModelType()
499 PMMLType type = kUNDEFINED ;
500 if ( ! _currentModelNode )
502 string name = _xmlCharToString(_currentModelNode->name);
503 if ( name == "NeuralNetwork" )
505 else if ( name == "RegressionModel" )
511 * Get the current model name.
512 * @brief name is "" if no model is set
515 std::string PMMLlib::GetCurrentModelName()
517 if ( ! _currentModelNode )
519 string name = _getProp(_currentModelNode, string("modelName"));
524 * Unlink the current model node.
526 void PMMLlib::UnlinkNode()
528 xmlNodePtr ptr = _currentModelNode ;
529 xmlUnlinkNode( ptr );
534 * Make a backup of the current model node.
536 void PMMLlib::BackupNode()
538 // Node name depending of PMML type
539 string name = GetTypeString();
540 // Find the last save index number
543 ss << _currentModelName << "_" << nCrtIndex;
544 xmlNodePtr ptr = GetPtr(ss.str(), name);
549 cout << " ** nCrtIndex[" << nCrtIndex << "]" << endl;
552 ss << _currentModelName << "_" << nCrtIndex;
553 ptr = GetPtr(ss.str(), name);
556 cout << " *** Node \"" << _currentModelName << "\" found, then backup it with index [" << nCrtIndex << "]" << endl;
558 xmlUnsetProp(_currentModelNode, (const xmlChar*)"modelName");
559 xmlNewProp(_currentModelNode, (const xmlChar*)"modelName", (const xmlChar*)(ss.str().c_str()));
563 * Save the XML tree in the PMML file
565 void PMMLlib::Write()
567 // Enregistrement de l'arbre DOM dans le fichier pmml
569 // Mise à jour du nombre de modèles
574 * Save the XML tree in a given file
575 * @param Name of the file
577 void PMMLlib::Write(std::string file)
579 // Enregistrement de l'arbre DOM sous forme de fichier pmml
580 int ret = xmlSaveFormatFile( file.c_str(), _doc, 1);
583 std::string msg(" *** Error :: unable to write the PMML file \"" + file + "\"") ;
588 cout << " *** Write the PMML file \"" << file <<"\"" << endl;
592 * Export the current model as a function in a Cpp file.
593 * @param file Name of the file
594 * @param functionName Name of the function
595 * @param header Header of the function
597 void PMMLlib::ExportCpp(std::string file,
598 std::string functionName,
601 if ( _currentModelType == kANN )
602 ExportNeuralNetworkCpp(file,functionName, header);
603 else if ( _currentModelType == kLR )
605 ExportLinearRegressionCpp(file, functionName, header);
608 throw string("ExportCpp : PMML type not handled.");
612 * Export the current model as a function in a Fortran file.
613 * @param file Name of the file
614 * @param functionName Name of the function
615 * @param header Header of the function
617 void PMMLlib::ExportFortran(std::string file,
618 std::string functionName,
621 if ( _currentModelType == kANN )
622 ExportNeuralNetworkFortran(file,functionName, header);
623 else if ( _currentModelType == kLR )
624 ExportLinearRegressionFortran(file,functionName, header);
626 throw string("ExportFortran : PMML type not handled.");
630 * Export the current model as a function in a Python file.
631 * @param file Name of the file
632 * @param functionName Name of the function
633 * @param header Header of the function
635 void PMMLlib::ExportPython(std::string file,
636 std::string functionName,
639 if ( _currentModelType == kANN )
640 ExportNeuralNetworkPython(file,functionName, header);
641 else if ( _currentModelType == kLR )
642 ExportLinearRegressionPython(file,functionName, header);
644 throw string("ExportPython : PMML type not handled.");
648 * Export the current model as a function in a Python string.
649 * @param file Name of the file
650 * @param functionName Name of the function
651 * @param header Header of the function
652 * @return Function as a string
654 std::string PMMLlib::ExportPyStr(std::string functionName,
657 if ( _currentModelType == kANN )
658 return ExportNeuralNetworkPyStr(functionName, header);
659 else if ( _currentModelType == kLR )
660 return ExportLinearRegressionPyStr(functionName, header);
662 throw string("ExportPyStr : PMML type not handled.");
666 * Conversion from a libxml2 string (xmlChar *) to a standard C++ string.
667 * \param xs a constant libxml string.
668 * \return a C++ std::string (contains the same text as xs).
670 std::string PMMLlib::_xmlCharToString(const xmlChar *xs) const
672 size_t i, L = xmlStrlen(xs);
675 for (i=0; *xs; s[i++] = *xs++);
680 * Conversion from a a standard C++ string to a libxml2 string (xmlChar *).
681 * \param s Constant C++ std::string (contains the same text as xs)
682 * \return Constant libxml string.
684 xmlChar * PMMLlib::_stringToXmlChar(const std::string &s) const
686 return xmlCharStrdup(s.c_str());
690 * Get the value of a node property.
692 * \param prop Property
693 * \return Constant libxml string.
695 std::string PMMLlib::_getProp(const xmlNodePtr node,
696 std::string const & prop ) const
698 std::string name("");
701 xmlChar *xp = _stringToXmlChar(prop);
703 attr = xmlGetProp(node, xp );
706 name = _xmlCharToString(attr );
714 //**************************************************************
718 // méthodes propres au NeuralNetwork *
722 //**************************************************************
725 * Check if the current model type is kANN.
726 * \brief Called in all methods specific to the NeuralNetwork model.
727 * \brief Throw an exception if the model type is not kANN.
729 void PMMLlib::CheckNeuralNetwork()
731 if ( _currentModelType != kANN )
732 throw string("Use this method with NeuralNetwork models.");
736 * Get the XML node of a given network from the index
737 * @param index Index of the neural network
738 * @return Pointer to the XML node
740 xmlNodePtr PMMLlib::GetNeuralNetPtr(int index)
742 return GetPtr(index, GetTypeString() );
746 * Get the XML node of a given network model
747 * @param name Name of the neural network
748 * @return Pointer to the XML node
750 xmlNodePtr PMMLlib::GetNeuralNetPtr(std::string name)
752 return GetPtr(name, GetTypeString() );
756 * Read the structure of the network
757 * @brief Specific to NeuralNetwork
758 * @return Structure read
760 std::string PMMLlib::ReadNetworkStructure()
762 CheckNeuralNetwork();
764 string structure("");
765 // Treatment of the input
766 xmlNodePtr inputNodes = GetChildByName(_currentModelNode,"NeuralInputs");
767 if ( inputNodes != NULL )
769 xmlNodePtr inputNode = GetChildByName(inputNodes,"NeuralInput");
770 if ( inputNode != NULL )
772 while (inputNode != NULL)
774 xmlNodePtr child = GetChildByName(inputNode,"DerivedField");
777 xmlNodePtr fieldName = child->children; // NormContinuous
778 if ( fieldName != NULL )
780 string field = _getProp(fieldName, string("field"));
785 inputNode = inputNode->next;
787 // Delete the last comma
788 structure.erase(structure.size()-1);
791 // Intermediary layers
792 xmlNodePtr node_layer = GetChildByName(_currentModelNode,"NeuralLayer");
793 if ( node_layer != NULL )
795 string name = string((const char*)(node_layer->name));
798 while ( node_layer != NULL &&
799 (string((const char*)(node_layer->name)) == "NeuralLayer") &&
800 node_layer->next != NULL &&
801 (string((const char*)(node_layer->next->name)) != "NeuralOutputs") )
803 // Get the number of neurons of the current layer
804 string nbneurons = _getProp(node_layer, string("numberOfNeurons"));
805 structure += nbneurons;
807 node_layer = node_layer->next;
811 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
812 if ( node_outputs != NULL )
814 xmlNodePtr node_output = GetChildByName(node_outputs,"NeuralOutput");
815 if ( node_output != NULL )
817 while (node_output != NULL)
819 // Get the input of the current layer
820 xmlNodePtr child = GetChildByName(node_output,"DerivedField");
823 xmlNodePtr fieldName = child->children; // NormContinuous
824 if ( fieldName != NULL )
826 if (string((const char*)(fieldName->name)) == "NormContinuous")
829 string field = _getProp(fieldName, string("field"));
834 node_output = node_output->next;
836 // Delete the last comma
837 structure.erase(structure.size()-1);
844 * Get the number of inputs, ie the number of NeuralInputs nodes.
845 * @brief Specific to NeuralNetwork
846 * @return Number of input nodes
848 int PMMLlib::GetNbInputs()
850 CheckNeuralNetwork();
853 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
854 if ( node_inputs == NULL )
857 node_inputs = node_inputs->children;
858 while (node_inputs != NULL)
861 node_inputs = node_inputs->next;
868 * Recover the number of outputs
869 * @brief Specific to NeuralNetwork
870 * @return Number of outputs
872 int PMMLlib::GetNbOutputs()
874 CheckNeuralNetwork();
877 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
878 if ( node_outputs == NULL )
881 node_outputs = node_outputs->children;
883 while (node_outputs != NULL)
886 node_outputs = node_outputs->next;
893 * Recovery of the name of an input in the current model.
894 * @brief Specific to NeuralNetwork
895 * @param index Index of the input
896 * @return Name of the input
898 std::string PMMLlib::GetNameInput(int index)
900 CheckNeuralNetwork();
903 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
904 if ( node_inputs == NULL )
907 node_inputs = node_inputs->children;
908 if ( node_inputs == NULL )
911 for(int i = 0;i<index;i++)
913 node_inputs = node_inputs->next;
914 if ( node_inputs == NULL )
918 node_inputs = node_inputs->children;
919 if ( node_inputs == NULL )
922 node_inputs = node_inputs->children;
923 if ( node_inputs == NULL )
926 name = _getProp(node_inputs, string("field"));
932 * Get the name of an output in the current model.
933 * @brief Specific to NeuralNetwork
934 * @param index Index of the output
935 * @return Name of the output
937 std::string PMMLlib::GetNameOutput(int index)
939 CheckNeuralNetwork();
942 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
943 if ( node_outputs == NULL )
945 node_outputs = node_outputs->children;
946 if ( node_outputs == NULL )
948 for(int i = 0;i<index;i++)
950 node_outputs = node_outputs->next;
951 if ( node_outputs == NULL )
955 node_outputs = node_outputs->children;
956 if ( node_outputs == NULL )
958 node_outputs = node_outputs->children;
959 if ( node_outputs == NULL )
962 name = _getProp(node_outputs, string("field") );
968 * Get the normalization type of the current model
969 * @brief Specific to NeuralNetwork
970 * @return Normalization type of the neural network
972 int PMMLlib::GetNormalizationType()
974 CheckNeuralNetwork();
976 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
977 node_inputs = GetChildByName(node_inputs,"NeuralInput");
978 xmlNodePtr nodeTmp = GetChildByName(node_inputs,"DerivedField");
979 xmlNodePtr node_field = nodeTmp->children;
980 xmlNodePtr node_linearnorm;
982 double dorig1, dnorm1;
983 double dorig2, dnorm2;
984 if (string((const char*)(node_field->name)) == "NormContinuous")
986 // Get mean and standard deviation
987 node_linearnorm = node_field->children;
988 str_tmp = _getProp(node_linearnorm, string("orig"));
989 dorig1 = atof(str_tmp.c_str());
990 str_tmp = _getProp(node_linearnorm, string("norm"));
991 dnorm1 = atof(str_tmp.c_str());
992 node_linearnorm = node_linearnorm->next;
993 str_tmp = _getProp(node_linearnorm, string("orig"));
994 dorig2 = atof(str_tmp.c_str());
995 str_tmp = _getProp(node_linearnorm, string("norm"));
996 dnorm2 = atof(str_tmp.c_str());
997 if ( dnorm1 * dnorm2 < -0.5 )
998 { // case of kMinusOneOne
1002 { // case of kCR, kZeroOne
1006 string msg("Unable to retrieve the normalization type.");
1011 * Get the input parameters on the normalization
1012 * @brief Specific to NeuralNetwork
1013 * @param node_ann Neural network node
1014 * @param index Index of the input
1015 * @param[out] dnorm Array that contains the mean and the standard deviation
1017 void PMMLlib::GetNormalisationInput(int index,
1020 CheckNeuralNetwork();
1023 xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
1024 if ( node_inputs == NULL )
1026 node_inputs = GetChildByName(node_inputs,"NeuralInput");
1027 if ( node_inputs == NULL )
1029 // Positionnement sur la bonne entree
1030 for(int i=0;i<index;i++)
1032 node_inputs = node_inputs->next;
1033 if ( node_inputs == NULL )
1036 xmlNodePtr tmpNode = GetChildByName(node_inputs,"DerivedField");
1037 if ( tmpNode == NULL )
1039 xmlNodePtr node_field = GetChildByName(tmpNode,"NormContinuous");
1040 if ( node_field == NULL )
1042 if (string((const char*)(node_field->name)) == "NormContinuous")
1044 //Get mean and standard deviation
1046 xmlNodePtr node_linearnorm = node_field->children;
1047 str_tmp = _getProp(node_linearnorm, string("orig"));
1048 double dorig1 = atof(str_tmp.c_str());
1049 str_tmp = _getProp(node_linearnorm, string("norm"));
1050 double dnorm1 = atof(str_tmp.c_str());
1051 node_linearnorm = node_linearnorm->next;
1052 str_tmp = _getProp(node_linearnorm, string("orig"));
1053 double dorig2 = atof(str_tmp.c_str());
1054 str_tmp = _getProp(node_linearnorm, string("norm"));
1055 double dnorm2 = atof(str_tmp.c_str());
1056 if ( dnorm1 * dnorm2 < -0.5 ) // <=> GetNormalizationType == 0
1058 // case of kMinusOneOne
1062 else // <=> GetNormalizationType == 1
1064 // case of kCR, kZeroOne
1066 dnorm[1] = -1.0 * dnorm1 * dorig2; //dorig2 / dnorm1;
1072 * Get the parameters on the normalization of an output for the current model.
1073 * @brief Specific to NeuralNetwork
1074 * @param index Output index
1075 * @param[out] dnorm Array that contains the mean and the standard deviation
1077 void PMMLlib::GetNormalisationOutput(int index,
1080 CheckNeuralNetwork();
1084 xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
1085 if ( node_outputs == NULL )
1087 node_outputs = GetChildByName(node_outputs,"NeuralOutput");
1088 if ( node_outputs == NULL )
1090 // Positionnement sur la bonne sortie
1091 for(int i=0;i< index;i++)
1093 node_outputs = node_outputs->next;
1094 if ( node_outputs == NULL )
1097 xmlNodePtr tmpNode = GetChildByName(node_outputs,"DerivedField");
1098 if ( tmpNode == NULL )
1100 xmlNodePtr node_field = GetChildByName(tmpNode,"NormContinuous");
1101 if ( node_field == NULL )
1104 if (string((const char*)(node_field->name)) == "NormContinuous")
1106 // Recuperation de la moyenne et de l'ecart type
1108 xmlNodePtr node_linearnorm = node_field->children;
1109 str_tmp = _getProp(node_linearnorm, string("orig"));
1110 double dorig1 = atof(str_tmp.c_str());
1111 str_tmp = _getProp(node_linearnorm, string("norm"));
1112 double dnorm1 = atof(str_tmp.c_str());
1113 node_linearnorm = node_linearnorm->next;
1114 str_tmp = _getProp(node_linearnorm,string("orig"));
1115 double dorig2 = atof(str_tmp.c_str());
1116 str_tmp = _getProp(node_linearnorm, string("norm"));
1117 double dnorm2 = atof(str_tmp.c_str());
1118 if ( dnorm1 * dnorm2 < -0.5 )
1120 // case of kMinusOneOne
1126 // case of kCR, kZeroOne
1128 dnorm[1] = -1.0 * dorig2 * dnorm1; //-1.0 * dorig2 / dnorm1;
1134 * Get the number of hidden layers
1135 * @brief Specific to NeuralNetwork
1136 * @return Number of hidden layers
1138 int PMMLlib::GetNbHiddenLayers()
1140 CheckNeuralNetwork();
1143 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1144 if ( node_layers == NULL )
1147 while (string((const char*)(node_layers->name)) == "NeuralLayer")
1150 node_layers = node_layers->next;
1151 if ( node_layers == NULL )
1158 * Get the total number of layers
1159 * @return Total number of layers
1161 int PMMLlib::GetNbLayers()
1163 return (GetNbHiddenLayers() + 2);
1167 * Get the number of neurons at a given layer
1168 * @param index Index of the layer
1169 * @return Number of neurons at given layer
1171 int PMMLlib::GetNbNeuronsAtLayer(int index)
1173 CheckNeuralNetwork();
1176 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1177 if ( node_layers == NULL )
1180 // Positionnement à la bonne couche
1181 for(int i=0;i<index;i++)
1183 node_layers = node_layers->next;
1184 if ( node_layers == NULL )
1188 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1189 while(node_neurons != NULL)
1192 node_neurons = node_neurons->next;
1199 * Get the bias of a neuron
1200 * @brief Specific to NeuralNetwork
1201 * @param layer_index Index of the layer to get bias
1202 * @param neu_index Index of the neuron
1203 * @return Bias of the specified neuron
1205 double PMMLlib::GetNeuronBias(int layer_index,
1208 CheckNeuralNetwork();
1211 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1212 if ( node_layers == NULL )
1214 // Positionnement a la bonne couche
1215 for(int i=0;i<layer_index;i++)
1217 node_layers = node_layers->next;
1218 if ( node_layers == NULL )
1221 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1222 // Positionnement sur le bon neurone
1223 for(int j=0;j<neu_index;j++)
1225 node_neurons = node_neurons->next;
1226 if ( node_neurons == NULL )
1229 string str_tmp = _getProp(node_neurons, string("bias"));
1230 bias = atof(str_tmp.c_str());
1235 * Get the synaptic weight
1236 * @brief Specific to NeuralNetwork
1237 * @param layer_index Index of the layer to get synaptic weight
1238 * @param neu_index Index of the neuron
1239 * @param prec_index Index of the synapse
1240 * @return Synaptic weight
1242 double PMMLlib::GetPrecNeuronSynapse(int layer_index,
1246 CheckNeuralNetwork();
1249 xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1250 if ( node_layers == NULL )
1252 // Positionnement a la bonne couche
1253 for(int i=0;i<layer_index;i++)
1255 node_layers = node_layers->next;
1256 if ( node_layers == NULL )
1259 xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1260 // Positionnement sur le bon neurone
1261 for(int i=0;i<neu_index;i++)
1263 node_neurons = node_neurons->next;
1264 if ( node_neurons == NULL )
1267 xmlNodePtr node_con = GetChildByName(node_neurons,"Con");
1268 // Positionnement sur la bonne synapse
1269 for(int i=0;i<prec_index;i++)
1271 node_con = node_con->next;
1272 if ( node_con == NULL )
1275 string str_tmp = _getProp(node_con, string("weight"));
1276 weight = atof(str_tmp.c_str());
1281 * Set the name of the neural network
1283 * @param index Neural network index
1284 * @param name Neural network name to set
1287 void PMMLlib::SetNeuralNetName(int index,
1290 CheckNeuralNetwork();
1295 xmlNodePtr node_ann = GetChildByName(_rootNode,"NeuralNetwork");
1296 while ((i != index) && (node_ann != NULL))
1298 node_ann = node_ann->next;
1301 xmlNewProp(node_ann, (const xmlChar*)"modelName", (const xmlChar*)(name.c_str()));
1303 xmlSaveFormatFile( string(_pmmlFile+".pmml").c_str(), _doc, 1);
1308 * Add a DataField node to the DataDictionnary node
1309 * @param fieldName Value of property "name"
1310 * @param displayName Value of property "displayName"
1311 * @param optype Value of property "optype"
1312 * @param dataType Value of property "dataType"
1313 * @param closure Value of property "closure" in node Interval
1314 * @param leftMargin Value of property "leftMargin" in node Interval
1315 * @param rightMargin Value of property "rightMargin" in node Interval
1316 * @param interval Flag to add a node Interval (if true)
1318 void PMMLlib::AddDataField(std::string fieldName,
1319 std::string displayName,
1321 std::string dataType,
1322 std::string closure,
1327 // if 'DataDictionary' node does not exist, create it
1328 xmlNodePtr dataDictNode = GetChildByName(_rootNode, "DataDictionary");
1331 dataDictNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"DataDictionary", 0);
1334 // then append the node
1335 xmlNodePtr dataFieldNode = xmlNewChild(dataDictNode, 0, (const xmlChar*)"DataField", 0);
1336 xmlNewProp(dataFieldNode, (const xmlChar*)"name", (const xmlChar*)(fieldName.c_str()) );
1337 xmlNewProp(dataFieldNode, (const xmlChar*)"displayName", (const xmlChar*)(displayName.c_str()) );
1338 xmlNewProp(dataFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1339 xmlNewProp(dataFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1343 xmlNodePtr intervalNode = xmlNewChild(dataFieldNode, 0, (const xmlChar*)"Interval", 0);
1344 xmlNewProp(intervalNode, (const xmlChar*)"closure", (const xmlChar*)(closure.c_str()) );
1346 ss << scientific << leftMargin;
1347 xmlNewProp(intervalNode, (const xmlChar*)"leftMargin", (const xmlChar*)(ss.str().c_str()) );
1349 ss << scientific << rightMargin;
1350 xmlNewProp(intervalNode, (const xmlChar*)"rightMargin", (const xmlChar*)(ss.str().c_str()) );
1355 * Add a NeuralNetwork node to the root node
1356 * @brief Specific to NeuralNetwork
1357 * @param modelName Model name
1358 * @param functionName PMMLMiningFunction. One of : kREGRESSION.
1360 void PMMLlib::AddNeuralNetwork(std::string modelName,
1361 PMMLMiningFunction functionName)
1363 _currentModelType = kANN;
1364 _currentModelName = modelName;
1366 CheckNeuralNetwork();
1369 switch(functionName)
1372 function = "regression";
1376 xmlNodePtr netNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"NeuralNetwork", 0);
1377 xmlNewProp(netNode, (const xmlChar*)"modelName", (const xmlChar*)(_currentModelName.c_str()) );
1378 xmlNewProp(netNode, (const xmlChar*)"functionName", (const xmlChar*)(function.c_str()) );
1379 xmlNewProp(netNode, (const xmlChar*)"numberOfLayers", (const xmlChar*)"0" );
1380 _currentModelNode = netNode;
1384 * Add a NeuralInput node to the current model.
1385 * @brief Specific to NeuralNetwork
1386 * @param id Id of the input
1387 * @param inputName Name of the input
1388 * @param optype Value of property "optype"
1389 * @param dataType Value of property "dataType"
1390 * @param orig1 Value of the first origin
1391 * @param norm1 Value of the first norm
1392 * @param orig2 Value of the second origin
1393 * @param norm2 Value of the second norm
1395 void PMMLlib::AddNeuralInput(int id,
1396 std::string inputName,
1398 std::string dataType,
1399 double orig1, double norm1,
1400 double orig2, double norm2)
1402 CheckNeuralNetwork();
1404 xmlNodePtr netNode = _currentModelNode;
1405 // if 'NeuralInputs' node does not exist, create it
1406 xmlNodePtr neuralInputsNode = GetChildByName(netNode, "NeuralInputs");
1407 if(!neuralInputsNode)
1409 neuralInputsNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralInputs", 0);
1410 xmlNewProp(neuralInputsNode, (const xmlChar*)"numberOfInputs", (const xmlChar*)"0" );
1412 // increment the number of inputs
1413 string numberOfInputsStr = _getProp(neuralInputsNode, string("numberOfInputs"));
1415 istringstream( numberOfInputsStr ) >> numberOfInputs;
1418 ss << numberOfInputs;
1419 xmlSetProp(neuralInputsNode, (const xmlChar*)"numberOfInputs", (const xmlChar*)(ss.str().c_str()) );
1420 // then append the node and its children
1421 xmlNodePtr neuralInputNode = xmlNewChild(neuralInputsNode, 0, (const xmlChar*)"NeuralInput", 0);
1422 ss.str(""); ss << id;
1423 xmlNewProp(neuralInputNode, (const xmlChar*)"id", (const xmlChar*)(ss.str().c_str()) );
1425 xmlNodePtr derivedFieldNode = xmlNewChild(neuralInputNode, 0, (const xmlChar*)"DerivedField", 0);
1426 xmlNewProp(derivedFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1427 xmlNewProp(derivedFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1429 xmlNodePtr normcontNode = xmlNewChild(derivedFieldNode, 0, (const xmlChar*)"NormContinuous", 0);
1430 xmlNewProp(normcontNode, (const xmlChar*)"field", (const xmlChar*)(inputName.c_str()) );
1432 xmlNodePtr node_linearnorm1 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1433 ss.str(""); ss << scientific << orig1;
1434 xmlNewProp(node_linearnorm1, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1435 ss.str(""); ss << scientific << norm1;
1436 xmlNewProp(node_linearnorm1, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1437 xmlNodePtr node_linearnorm2 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1438 ss.str(""); ss << scientific << orig2;
1439 xmlNewProp(node_linearnorm2, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1440 ss.str(""); ss << scientific << norm2;
1441 xmlNewProp(node_linearnorm2, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1445 * Add a NeuralOutput node to the current model.
1446 * @brief Specific to NeuralNetwork
1447 * @param outputNeuron Id of the output
1448 * @param outputName Name of the output
1449 * @param optype Value of property "optype"
1450 * @param dataType Value of property "dataType"
1451 * @param orig1 Value of the first origin
1452 * @param norm1 Value of the first norm
1453 * @param orig2 Value of the second origin
1454 * @param norm2 Value of the second norm
1456 void PMMLlib::AddNeuralOutput(int outputNeuron,
1457 std::string outputName,
1459 std::string dataType,
1460 double orig1, double norm1,
1461 double orig2, double norm2)
1463 CheckNeuralNetwork();
1465 xmlNodePtr netNode = _currentModelNode;
1466 // if 'NeuralOutputs' node does not exist, create it
1467 xmlNodePtr neuralOutputsNode = GetChildByName(netNode, "NeuralOutputs");
1468 if(!neuralOutputsNode)
1470 neuralOutputsNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralOutputs", 0);
1471 xmlNewProp(neuralOutputsNode, (const xmlChar*)"numberOfOutputs", (const xmlChar*)"0" );
1473 // increment the number of inputs
1474 string numberOfOutputsStr = _getProp(neuralOutputsNode, string("numberOfOutputs"));
1475 int numberOfOutputs;
1476 istringstream( numberOfOutputsStr ) >> numberOfOutputs;
1479 ss << numberOfOutputs;
1480 xmlSetProp(neuralOutputsNode, (const xmlChar*)"numberOfOutputs", (const xmlChar*)(ss.str().c_str()) );
1482 // then append the node and its children
1483 xmlNodePtr neuralOutputNode = xmlNewChild(neuralOutputsNode, 0, (const xmlChar*)"NeuralOutput", 0);
1484 ss.str(""); ss << outputNeuron;
1485 xmlNewProp(neuralOutputNode, (const xmlChar*)"outputNeuron", (const xmlChar*)(ss.str().c_str()) );
1487 xmlNodePtr derivedFieldNode = xmlNewChild(neuralOutputNode, 0, (const xmlChar*)"DerivedField", 0);
1488 xmlNewProp(derivedFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1489 xmlNewProp(derivedFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1491 xmlNodePtr normcontNode = xmlNewChild(derivedFieldNode, 0, (const xmlChar*)"NormContinuous", 0);
1492 xmlNewProp(normcontNode, (const xmlChar*)"field", (const xmlChar*)(outputName.c_str()) );
1494 xmlNodePtr node_linearnorm1 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1495 ss.str(""); ss << scientific << orig1;
1496 xmlNewProp(node_linearnorm1, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1497 ss.str(""); ss << scientific << norm1;
1498 xmlNewProp(node_linearnorm1, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1499 xmlNodePtr node_linearnorm2 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1500 ss.str(""); ss << scientific << orig2;
1501 xmlNewProp(node_linearnorm2, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1502 ss.str(""); ss << scientific << norm2;
1503 xmlNewProp(node_linearnorm2, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1507 * Add a NeuralLayer node to the current model.
1508 * @brief Specific to NeuralNetwork
1509 * @param activationFunction Activation function. One of kIDENTITY, kTANH, kLOGISTIC.
1511 void PMMLlib::AddNeuralLayer(PMMLActivationFunction activationFunction)
1513 CheckNeuralNetwork();
1515 string functionName;
1516 switch(activationFunction)
1519 functionName = "identity";
1522 functionName = "tanh";
1525 functionName = "logistic";
1528 xmlNodePtr netNode = _currentModelNode;
1529 // Increment the number of layers
1530 string numberOfLayersStr = _getProp(_currentModelNode, string("numberOfLayers"));
1532 istringstream( numberOfLayersStr ) >> numberOfLayers;
1535 ss << numberOfLayers;
1536 xmlSetProp(netNode, (const xmlChar*)"numberOfLayers", (const xmlChar*)(ss.str().c_str()) );
1537 // Add the neural layer node
1538 xmlNodePtr neuralLayerNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralLayer", 0);
1539 xmlNewProp(neuralLayerNode, (const xmlChar*)"activationFunction", (const xmlChar*)(functionName.c_str()) );
1540 xmlNewProp(neuralLayerNode, (const xmlChar*)"numberOfNeurons", (const xmlChar*)"0" );
1541 // Save the current layer in the _currentNode attribute
1542 _currentNode = neuralLayerNode;
1546 * Add a NeuralLayer node to the current model.
1547 * @brief Specific to NeuralNetwork
1548 * @param id Id of the layer
1549 * @param bias Value of property "bias"
1550 * @param conNb Number of Con nodes
1551 * @param firstFrom Value of property "from" for the first Con
1552 * @param weights Vector of weights (One per Con node)
1554 void PMMLlib::AddNeuron(int id,
1558 vector<double> weights)
1560 CheckNeuralNetwork();
1564 // increment the number of neurons
1565 string numberOfNeuronsStr = _getProp(_currentNode, string("numberOfNeurons"));
1566 int numberOfNeurons;
1567 istringstream( numberOfNeuronsStr ) >> numberOfNeurons;
1569 ss << numberOfNeurons;
1570 xmlSetProp(_currentNode, (const xmlChar*)"numberOfNeurons", (const xmlChar*)(ss.str().c_str()) );
1573 xmlNodePtr neuronNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"Neuron", 0);
1574 ss.str(""); ss << id;
1575 xmlNewProp(neuronNode, (const xmlChar*)"id", (const xmlChar*)(ss.str().c_str()) );
1576 ss.str(""); ss << scientific << bias;
1577 xmlNewProp(neuronNode, (const xmlChar*)"bias", (const xmlChar*)(ss.str().c_str()) );
1579 // append multiple 'Con' to the neuron
1580 for(int k=0 ; k<conNb ; k++)
1582 xmlNodePtr conNode = xmlNewChild(neuronNode, 0, (const xmlChar*)"Con", 0);
1583 ss.str(""); ss << firstFrom+k;
1584 xmlNewProp(conNode, (const xmlChar*)"from", (const xmlChar*)(ss.str().c_str()) ); // !!! ce n'est pas k !!!
1585 ss.str(""); ss << scientific << weights[k];
1586 xmlNewProp(conNode, (const xmlChar*)"weight", (const xmlChar*)(ss.str().c_str()) );
1591 * Fill the vectors used by the ExportXXX methods.
1592 * @brief Specific to NeuralNetwork
1603 void PMMLlib::fillVectorsForExport(int nInput,
1607 vector<double> &minInput,
1608 vector<double> &maxInput,
1609 vector<double> &minOutput,
1610 vector<double> &maxOutput,
1611 vector<double> &valW )
1613 CheckNeuralNetwork();
1615 xmlNodePtr netNode = _currentModelNode ;
1616 // Get the different values required
1617 // Build min/max input/output vectors
1618 for(int i=0 ; i<nInput ; i++)
1620 xmlNodePtr node_inputs = GetChildByName(netNode,"NeuralInputs");
1621 node_inputs = node_inputs->children;
1622 for(int j = 0;j<i;j++)
1624 node_inputs = node_inputs->next;
1626 node_inputs = node_inputs->children; // DerivedField
1627 node_inputs = node_inputs->children; // NormContinuous
1628 node_inputs = node_inputs->children; // LinearNorm
1629 string strOrig1 = _getProp(node_inputs, string("orig") );
1630 double orig1 = atof( strOrig1.c_str() );
1631 string strNorm1 = _getProp(node_inputs, string("norm") );
1632 double norm1 = atof( strNorm1.c_str() );
1633 node_inputs = node_inputs->next;
1634 string strOrig2 = _getProp(node_inputs, string("orig") );
1635 double orig2 = atof( strOrig2.c_str() );
1636 string strNorm2 = _getProp(node_inputs, string("norm") );
1639 minInput[i] = orig1;
1640 maxInput[i] = orig2;
1644 minInput[i] = orig2;
1645 maxInput[i] = -1.0*norm1*orig2;
1648 xmlNodePtr node_outputs = GetChildByName(netNode,"NeuralOutputs");
1649 node_outputs = node_outputs->children;
1650 node_outputs = node_outputs->children; // DerivedField
1651 node_outputs = node_outputs->children; // NormContinuous
1652 node_outputs = node_outputs->children; // LinearNorm
1653 string strOrig1 = _getProp(node_outputs, string("orig") );
1654 double orig1 = atof( strOrig1.c_str() );
1655 string strNorm1 = _getProp(node_outputs, string("norm") );
1656 double norm1 = atof( strNorm1.c_str() );
1657 node_outputs = node_outputs->next;
1658 string strOrig2 = _getProp(node_outputs, string("orig") );
1659 double orig2 = atof( strOrig2.c_str() );
1662 minOutput[0] = orig1;
1663 maxOutput[0] = orig2;
1667 minOutput[0] = orig2;
1668 maxOutput[0] = -1.0*norm1*orig2;
1670 // Build weight vector
1671 for(int j=0 ; j<nHidden ; j++) // hidden layers
1673 valW[j*(nInput+nOutput+1)+2] = GetNeuronBias( 0, j);
1674 for(int i=0 ; i<nInput ; i++)
1676 valW[j*(nInput+nOutput+1)+3+i] = GetPrecNeuronSynapse( 0, j, i);
1679 for(int j=0 ; j<nOutput ; j++) // output layers
1681 valW[0] = GetNeuronBias( 1, j);
1682 for(int i=0 ; i<nHidden ; i++)
1684 valW[i*(nInput+nOutput+1)+1] = GetPrecNeuronSynapse( 1, j, i);
1690 * Export the current model as a NeuralNetwork function in a Cpp file.
1691 * @brief Specific to NeuralNetwork
1692 * @param file Name of the file
1693 * @param functionName Name of the function
1694 * @param header Header of the function
1696 void PMMLlib::ExportNeuralNetworkCpp(std::string file,
1697 std::string functionName,
1700 CheckNeuralNetwork();
1702 // Get the different values required
1703 int nInput = GetNbInputs();
1704 int nOutput = GetNbOutputs();
1705 int nHidden = GetNbNeuronsAtLayer(0);
1706 int nNeurons = nInput+nOutput+nHidden;
1707 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
1708 int normType = GetNormalizationType();
1709 // Build min/max input/output vectors
1710 vector<double> minInput(nInput);
1711 vector<double> maxInput(nInput);
1712 vector<double> minOutput(nOutput);
1713 vector<double> maxOutput(nOutput);
1714 vector<double> valW(nWeights);
1715 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
1717 ofstream sourcefile(file.c_str());
1718 // ActivationFunction
1721 sourcefile << "#define ActivationFunction(sum) ( tanh(sum) )" << endl;
1725 sourcefile << "#define ActivationFunction(sum) ( 1.0 / ( 1.0 + exp( -1.0 * sum )) )" << endl;
1728 sourcefile << "void " << functionName <<"(double *param, double *res)" << endl;
1729 sourcefile << "{" << endl;
1731 sourcefile << " ////////////////////////////// " << endl;
1732 sourcefile << " //" << endl;
1733 // insert comments in header
1734 header = " // " + header;
1736 while ((pos = header.find("\n", pos)) != std::string::npos)
1738 header.replace(pos, 1, "\n //");
1741 sourcefile << header << endl;
1742 sourcefile << " //" << endl;
1743 sourcefile << " ////////////////////////////// " << endl;
1745 sourcefile << " int nInput = " << nInput << ";" << endl;
1746 sourcefile << " int nOutput = " << nOutput << ";" << endl;
1747 // sourcefile << " int nWeights = " << _nWeight << ";" << endl;
1748 sourcefile << " int nHidden = " << nHidden << ";" << endl;
1749 sourcefile << " const int nNeurones = " << nNeurons << ";" << endl;
1750 sourcefile << " double " << functionName << "_act[nNeurones];" << endl;
1752 sourcefile << " // --- Preprocessing of the inputs and outputs" << endl;
1753 sourcefile << " double " << functionName << "_minInput[] = {" << endl << " ";
1754 for(int i=0 ; i<nInput ; i++)
1756 sourcefile << minInput[i] << ", ";
1758 sourcefile << "\n ";
1762 sourcefile << " };" << endl;
1764 sourcefile << " double " << functionName << "_minOutput[] = {" << endl << " ";
1765 sourcefile << minOutput[0] << ", ";
1766 sourcefile << " };" << endl;
1768 sourcefile << " double " << functionName << "_maxInput[] = {" << endl << " ";
1769 for(int i=0 ; i<nInput ; i++)
1771 sourcefile << maxInput[i] << ", ";
1773 sourcefile << "\n ";
1777 sourcefile << " };" << endl;
1779 sourcefile << " double " << functionName << "_maxOutput[] = {" << endl << " ";
1780 sourcefile << maxOutput[0] << ", ";
1781 sourcefile << " };" << endl;
1784 sourcefile << " // --- Values of the weights" << endl;
1785 sourcefile << " double " << functionName << "_valW[] = {" << endl << " ";
1786 for(int i=0 ; i<nWeights ; i++)
1788 sourcefile << valW[i] << ", ";
1790 sourcefile << endl << " ";
1792 sourcefile << endl << " };"<<endl;
1794 sourcefile << " // --- Constants";
1796 sourcefile << " int indNeurone = 0;"<<endl;
1797 sourcefile << " int CrtW;"<<endl;
1798 sourcefile << " double sum;"<<endl;
1802 sourcefile << " // --- Input Layers"<<endl;
1803 sourcefile << " for(int i = 0; i < nInput; i++) {"<<endl;
1806 sourcefile << " " << functionName << "_act[indNeurone++] = 2.0 * ( param[i] - "
1807 << functionName << "_minInput[i] ) / ( " << functionName << "_maxInput[i] - "
1808 << functionName << "_minInput[i] ) - 1.0;"<<endl;
1812 sourcefile << " " << functionName << "_act[indNeurone++] = ( param[i] - "
1813 << functionName << "_minInput[i] ) / " << functionName << "_maxInput[i];"
1816 sourcefile << " }"<<endl;
1821 sourcefile << " // --- Hidden Layers"<<endl;
1822 sourcefile << " for (int member = 0; member < nHidden; member++) {"<<endl;
1823 sourcefile << " int CrtW = member * ( nInput + 2) + 2;" << endl;
1824 sourcefile << " sum = " << functionName << "_valW[CrtW++];" << endl;
1825 sourcefile << " for (int source = 0; source < nInput; source++) {" << endl;
1826 sourcefile << " sum += " << functionName << "_act[source] * " << functionName << "_valW[CrtW++];" << endl;
1827 sourcefile << " }" << endl;
1828 sourcefile << " " << functionName << "_act[indNeurone++] = ActivationFunction(sum);" << endl;
1829 sourcefile << " }"<<endl;
1832 sourcefile << " // --- Output"<<endl;
1833 sourcefile << " for (int member = 0; member < nOutput; member++) {"<<endl;
1834 sourcefile << " sum = " << functionName << "_valW[0];"<<endl;
1835 sourcefile << " for (int source = 0; source < nHidden; source++) {"<<endl;
1836 sourcefile << " CrtW = source * ( nInput + 2) + 1;"<<endl;
1837 sourcefile << " sum += " << functionName << "_act[nInput+source] * " << functionName << "_valW[CrtW];"<<endl;
1838 sourcefile << " }"<<endl;
1839 sourcefile << " " << functionName << "_act[indNeurone++] = sum;"<<endl;
1842 sourcefile << " res[member] = " << functionName
1843 << "_minOutput[member] + 0.5 * ( " << functionName
1844 << "_maxOutput[member] - " << functionName
1845 << "_minOutput[member] ) * ( sum + 1.0);" << endl;
1849 sourcefile << " res[member] = " << functionName
1850 << "_minOutput[member] + " << functionName
1851 << "_maxOutput[member] * sum;" << endl;
1853 sourcefile << " }"<<endl;
1855 sourcefile << "}" << endl;
1860 * Export the current model as a NeuralNetwork function in a Fortran file.
1861 * @brief Specific to NeuralNetwork
1862 * @param file Name of the file
1863 * @param functionName Name of the function
1864 * @param header Header of the function
1866 void PMMLlib::ExportNeuralNetworkFortran(std::string file,
1867 std::string functionName,
1870 CheckNeuralNetwork();
1872 // Get the different values required
1873 int nInput = GetNbInputs();
1874 int nOutput = GetNbOutputs();
1875 int nHidden = GetNbNeuronsAtLayer(0);
1876 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
1877 int normType = GetNormalizationType();
1878 // Build min/max input/output vectors
1879 vector<double> minInput(nInput);
1880 vector<double> maxInput(nInput);
1881 vector<double> minOutput(nOutput);
1882 vector<double> maxOutput(nOutput);
1883 vector<double> valW(nWeights);
1884 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
1886 ofstream sourcefile(file.c_str());
1888 sourcefile << " SUBROUTINE " << functionName << "(";
1889 for(int i=0 ; i<GetNbInputs() ; i++)
1891 sourcefile << GetNameInput(i) << ",";
1893 sourcefile << GetNameOutput(0) << ")" << endl;
1895 sourcefile << "C --- *********************************************" << endl;
1896 sourcefile << "C --- " << endl;
1897 // insert comments in header
1898 header = "C --- " + header;
1900 while ((pos = header.find("\n", pos)) != std::string::npos)
1902 header.replace(pos, 1, "\nC --- ");
1905 sourcefile << header << endl;
1906 sourcefile << "C --- " << endl;
1907 sourcefile << "C --- *********************************************" << endl;
1909 sourcefile << " IMPLICIT DOUBLE PRECISION (V)" << endl;
1910 for(int i=0 ; i<GetNbInputs() ; i++)
1912 sourcefile << " DOUBLE PRECISION " << GetNameInput(i) << endl;
1914 sourcefile << " DOUBLE PRECISION " << GetNameOutput(0) << endl;
1917 sourcefile << "C --- Preprocessing of the inputs" << endl;
1918 for(int i=0 ; i<GetNbInputs() ; i++)
1920 sourcefile << " VXN" << GetNameInput(i) << " = ";
1924 sourcefile << "2.D0 * ( " << GetNameInput(i) << " - " << minInput[i] << "D0 ) / " << maxInput[i] - minInput[i] << "D0 - 1.0" << endl;
1928 sourcefile << "( " << GetNameInput(i) << " - " << minInput[i] << "D0 ) / " << maxInput[i] << "D0" << endl;
1934 sourcefile << "C --- Values of the weights" << endl;
1935 for(int i=0 ; i<nWeights ; i++)
1937 sourcefile << " VW" << i+1 << " = " << valW[i] << endl;
1939 // Loop on hidden neurons
1941 for(int member = 0; member < nHidden; member++)
1943 sourcefile << "C --- hidden neural number " << member+1 << endl;
1944 int CrtW = member * ( nInput + 2) + 3;
1945 sourcefile << " VAct" << member+1 << " = VW" << CrtW++ << endl;
1946 for (int source = 0; source < nInput; source++)
1948 sourcefile << " 1 + VW"<< CrtW++ << " * VXN" << GetNameInput(source) << endl;
1955 sourcefile << " VPot" << member+1 << " = 2.D0 / (1.D0 + DEXP(-2.D0 * VAct" << member+1 <<")) - 1.D0" << endl;
1959 sourcefile << " VPot" << member+1 << " = 1.D0 / (1.D0 + DEXP(-1.D0 * VAct" << member+1 <<"))" << endl;
1964 // Ouput of the model
1965 sourcefile << "C --- Output" << endl;
1966 sourcefile << " VOut = VW1" << endl;
1967 for(int source=0 ; source < nHidden ; source++)
1969 int CrtW = source * ( nInput + 2) + 2;
1970 sourcefile << " 1 + VW"<< CrtW << " * VPot" << source+1 << endl;
1973 // Denormalize Output
1975 sourcefile << "C --- Pretraitment of the output" << endl;
1978 sourcefile << " VDelta = " << 0.5*(maxOutput[0]-minOutput[0]) << "D0 * ( VOut + 1.0D0)" << endl;
1979 sourcefile << " " << GetNameOutput(0) << " = " << minOutput[0] << "D0 + VDelta" << endl;
1984 sourcefile << " " << GetNameOutput(0) << " = "<< minOutput[0] << "D0 + " << maxOutput[0] << "D0 * VOut;" << endl;
1988 sourcefile << "C --- " << endl;
1989 sourcefile << " RETURN" << endl;
1990 sourcefile << " END" << endl;
1996 * Export the current model as a NeuralNetwork function in a Python file.
1997 * @brief Specific to NeuralNetwork
1998 * @param file Name of the file
1999 * @param functionName Name of the function
2000 * @param header Header of the function
2002 void PMMLlib::ExportNeuralNetworkPython(std::string file,
2003 std::string functionName,
2006 string str(ExportNeuralNetworkPyStr(functionName, header));
2008 ofstream exportfile(file.c_str());
2015 * Export the current model as a function in a Python string.
2016 * @brief Specific to NeuralNetwork
2017 * @param functionName Name of the function
2018 * @param header Header of the function
2019 * @return Function as a string
2021 std::string PMMLlib::ExportNeuralNetworkPyStr(std::string functionName,
2024 CheckNeuralNetwork();
2028 // Get the different values required
2029 int nInput = GetNbInputs();
2030 int nOutput = GetNbOutputs();
2031 int nHidden = GetNbNeuronsAtLayer(0);
2032 int nNeurons = nInput+nOutput+nHidden;
2033 int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
2034 int normType = GetNormalizationType();
2035 // Build min/max input/output vectors
2036 vector<double> minInput(nInput);
2037 vector<double> maxInput(nInput);
2038 vector<double> minOutput(nOutput);
2039 vector<double> maxOutput(nOutput);
2040 vector<double> valW(nWeights);
2041 fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
2043 // Shebang et imports
2044 out << "#!/usr/bin/env python" << endl;
2045 out << "# -*- coding: utf-8 -*-" << endl;
2047 out << "from math import tanh, exp" << endl;
2050 // ActivationFunction
2053 out << "def ActivationFunction(sum): " << endl;
2054 out << " return tanh(sum); " << endl;
2058 out << "def ActivationFunction(sum): " << endl;
2059 out << " return ( 1.0 / ( 1.0 + exp( -1.0 * sum ) ) ); " << endl;
2063 out << "def " << functionName <<"(param):" << endl;
2067 out << " ############################## " << endl;
2068 out << " #" << endl;
2069 // insert comments in header
2070 header = " # " + header;
2072 while ((pos = header.find("\n", pos)) != std::string::npos)
2074 header.replace(pos, 1, "\n #");
2077 out << header << endl;
2078 out << " #" << endl;
2079 out << " ############################## " << endl;
2083 out << " nInput = " << nInput << ";" << endl;
2084 out << " nOutput = " << nOutput << ";" << endl;
2085 out << " nHidden = " << nHidden << ";" << endl;
2086 out << " nNeurones = " << nNeurons << ";" << endl;
2087 out << " " << functionName << "_act = [];" << endl;
2088 out << " res = [];" << endl;
2091 out << " # --- Preprocessing of the inputs and outputs" << endl;
2092 out << " " << functionName << "_minInput = [" << endl << " ";
2094 for(int i=0 ; i<nInput ; i++)
2096 out << minInput[i] << ", ";
2103 out << endl << " ];" << endl;
2105 out << " " << functionName << "_minOutput = [" << endl << " ";
2106 out << " " << minOutput[0] ;
2107 out << endl << " ];" << endl;
2109 out << " " << functionName << "_maxInput = [" << endl << " ";
2110 for(int i=0 ; i<nInput ; i++)
2112 out << maxInput[i] << ", ";
2119 out << endl << " ];" << endl;
2121 out << " " << functionName << "_maxOutput = [" << endl << " ";
2122 out << " " << maxOutput[0] ;
2123 out << endl << " ];" << endl;
2126 out << " # --- Values of the weights" << endl;
2127 out << " " << functionName << "_valW = [" << endl << " ";
2128 for(int i=0 ; i<nWeights ; i++)
2130 out << valW[i] << ", ";
2137 out << endl << " ];"<<endl;
2139 out << " # --- Constants" << endl;
2140 out << " indNeurone = 0;" << endl;
2144 out << " # --- Input Layers" << endl;
2145 out << " for i in range(nInput) :" << endl;
2148 out << " " << functionName << "_act.append( 2.0 * ( param[i] - "
2149 << functionName << "_minInput[i] ) / ( " << functionName << "_maxInput[i] - "
2150 << functionName << "_minInput[i] ) - 1.0 ) ;"
2155 out << " " << functionName << "_act.append( ( param[i] - "
2156 << functionName << "_minInput[i] ) / " << functionName << "_maxInput[i] ) ;"
2159 out << " indNeurone += 1 ;" << endl;
2160 out << " pass" << endl;
2164 out << " # --- Hidden Layers" << endl;
2165 out << " for member in range(nHidden):" << endl;
2166 out << " CrtW = member * ( nInput + 2) + 2;" << endl;
2167 out << " sum = " << functionName << "_valW[CrtW];" << endl;
2168 out << " CrtW += 1 ;" << endl;
2169 out << " for source in range(nInput) :" << endl;
2170 out << " sum += " << functionName << "_act[source] * " << functionName << "_valW[CrtW];" << endl;
2171 out << " CrtW += 1 ;" << endl;
2172 out << " pass" << endl;
2173 out << " " << functionName << "_act.append( ActivationFunction(sum) ) ;" << endl;
2174 out << " indNeurone += 1 ;" << endl;
2175 out << " pass" << endl;
2179 out << " # --- Output"<<endl;
2180 out << " for member in range(nOutput):" << endl;
2181 out << " sum = " << functionName << "_valW[0];" << endl;
2182 out << " for source in range(nHidden):" << endl;
2183 out << " CrtW = source * ( nInput + 2) + 1;"<<endl;
2184 out << " sum += " << functionName << "_act[nInput+source] * " << functionName << "_valW[CrtW];" << endl;
2185 out << " pass" << endl;
2186 out << " " << functionName << "_act.append( sum );" << endl;
2187 out << " indNeurone += 1 ;" << endl;
2190 out << " res[member] = " << functionName
2191 << "_minOutput[member] + 0.5 * ( " << functionName
2192 << "_maxOutput[member] - " << functionName
2193 << "_minOutput[member] ) * ( sum + 1.0);" << endl;
2197 out << " res.append( " << functionName
2198 << "_minOutput[member] + " << functionName
2199 << "_maxOutput[member] * sum );" << endl;
2201 out << " pass" << endl;
2205 out << " return res;" << endl << endl;
2211 //**************************************************************
2215 // méthodes propres au RegressionModel *
2219 //**************************************************************
2222 * Check if the current model type is kLR.
2223 * \brief Called in all methods specific to the RegressionModel model.
2224 * \brief Throw an exception if the model type is not kLR.
2226 void PMMLlib::CheckRegression()
2228 if ( _currentModelType != kLR )
2229 throw string("Use this method with Regression models.");
2233 * Get the pointeur to the regression model node.
2234 * @param name Name of the regression model
2235 * @return Pointer to the XML node
2237 xmlNodePtr PMMLlib::GetRegressionPtr(std::string name)
2239 return GetPtr(name, GetTypeString() );
2243 * Add a RegressionModel to the root node
2244 * @brief Specific to RegressionModel
2245 * @param modelName Name of the model (Value of property "modelName")
2246 * @param functionName Value of property "functionName"
2247 * @param targetFieldName Value of Property "targetFieldName"
2249 void PMMLlib::AddRegressionModel(std::string modelName,
2250 PMMLMiningFunction functionName,
2251 std::string targetFieldName)
2253 _currentModelType = kLR;
2254 _currentModelName = modelName;
2255 // Check regression after setting model type!
2259 switch(functionName)
2262 function = "regression";
2265 xmlNodePtr netNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"RegressionModel", 0);
2266 xmlNewProp(netNode, (const xmlChar*)"functionName", (const xmlChar*)(function.c_str()) );
2267 xmlNewProp(netNode, (const xmlChar*)"modelName", (const xmlChar*)(_currentModelName.c_str()) );
2268 xmlNewProp(netNode, (const xmlChar*)"targetFieldName", (const xmlChar*)(targetFieldName.c_str()) );
2269 _currentModelNode = netNode ;
2273 * Add a RegressionTable to the Regression model.
2274 * @brief No property "intercept" will be set.
2275 * @brief Specific to RegressionModel
2277 void PMMLlib::AddRegressionTable()
2280 xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionModel", 0);
2281 _currentNode = tableNode;
2285 * Add a RegressionTable to the Regression model with a given value of property "intercept".
2286 * @brief Specific to RegressionModel
2287 * @param intercept Value of property "intercept"
2289 void PMMLlib::AddRegressionTable(double intercept)
2294 xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionTable", 0);
2297 ss << scientific << intercept;
2298 xmlNewProp(tableNode, (const xmlChar*)"intercept", (const xmlChar*)(ss.str().c_str()) );
2300 _currentNode = tableNode;
2304 * Add a numeric predictor to the Regression model.
2305 * @brief Specific to RegressionModel
2306 * @param neuronName Value of property "name"
2307 * @param exponent Value of property "exponent"
2308 * @param coefficient Value of property "coefficient"
2310 void PMMLlib::AddNumericPredictor(std::string neuronName,
2316 xmlNodePtr numPrecNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"NumericPredictor", 0);
2317 xmlNewProp(numPrecNode, (const xmlChar*)"name", (const xmlChar*)(neuronName.c_str()) );
2318 ss.str(""); ss << exponent;
2319 xmlNewProp(numPrecNode, (const xmlChar*)"exponent", (const xmlChar*)(ss.str().c_str()) );
2320 ss.str(""); ss << scientific << coefficient;
2321 xmlNewProp(numPrecNode, (const xmlChar*)"coefficient", (const xmlChar*)(ss.str().c_str()) );
2325 * Add a predictor term to the Regression model.
2326 * @brief Specific to RegressionModel
2327 * @param coefficient Value of property "coefficient"
2328 * @param fieldRef List of values for property "field", one per FieldRef to add to the PredictorTerm
2330 void PMMLlib::AddPredictorTerm(double coefficient,
2331 std::vector<std::string> fieldRef)
2335 xmlNodePtr predTermNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"PredictorTerm", 0);
2336 ss.str(""); ss << scientific << coefficient;
2337 xmlNewProp(predTermNode, (const xmlChar*)"coefficient", (const xmlChar*)(ss.str().c_str()) );
2338 vector<string>::iterator it;
2339 for(it=fieldRef.begin() ; it!=fieldRef.end() ; it++)
2341 xmlNodePtr fieldRefNode = xmlNewChild(predTermNode, 0, (const xmlChar*)"FieldRef", 0);
2342 ss.str(""); ss << (*it);
2343 xmlNewProp(fieldRefNode, (const xmlChar*)"field", (const xmlChar*)(ss.str().c_str()) );
2348 * Check if the RegressionTable has a property called "intercept".
2349 * @brief Specific to RegressionModel
2350 * @return true if it has, false otherwise
2352 bool PMMLlib::HasIntercept()
2356 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2357 if ( tableNode == NULL )
2359 xmlChar *xp = _stringToXmlChar("intercept");
2361 attr = xmlGetProp(tableNode, xp);
2373 * Get the value of property "intercept" in the RegressionTable.
2374 * @brief Specific to RegressionModel
2375 * @return Value of property "intercept"
2377 double PMMLlib::GetRegressionTableIntercept()
2381 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2382 if ( tableNode == NULL )
2384 string strValue = _getProp(tableNode, string("intercept") );
2385 return atof(strValue.c_str());
2389 * Get the number of numeric predictors.
2390 * @brief Specific to RegressionModel
2391 * @return Number of numeric predictors
2393 int PMMLlib::GetNumericPredictorNb()
2398 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2399 if ( tableNode == NULL )
2401 xmlNodePtr numPredNodes = tableNode->children;
2402 while (numPredNodes != NULL )
2404 if ( string((const char*)(numPredNodes->name)) == "NumericPredictor" )
2406 numPredNodes = numPredNodes->next;
2412 * Get the number of predictor terms.
2413 * @brief Specific to RegressionModel
2414 * @return Number of predictor terms
2416 int PMMLlib::GetPredictorTermNb()
2420 xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2421 if ( tableNode == NULL )
2423 xmlNodePtr numPredNodes = tableNode->children;
2424 while ( numPredNodes != NULL )
2426 if ( string((const char*)(numPredNodes->name)) == "PredictorTerm" )
2428 numPredNodes = numPredNodes->next;
2434 * Get the name of the numeric predictor given by its index.
2435 * @brief Specific to RegressionModel
2436 * @param num_pred_index Index of the numeric predictor
2437 * @return Name of the numeric predictor
2439 std::string PMMLlib::GetNumericPredictorName(int num_pred_index)
2443 xmlNodePtr numPredNodes = GetChildByName(_currentModelNode,"RegressionTable");
2444 if ( numPredNodes == NULL )
2447 numPredNodes = GetChildByName(numPredNodes,"NumericPredictor");
2448 if ( numPredNodes == NULL )
2450 // Positionnement sur la bonne sortie PredictorTerm
2451 for(int i=0;i<num_pred_index;i++)
2453 numPredNodes = numPredNodes->next;
2454 if ( numPredNodes == NULL ||
2455 string((const char*)(numPredNodes->name)) != "NumericPredictor" )
2458 strName = _getProp(numPredNodes, string("name"));
2463 * Get the name of the predictor term given by its index.
2464 * @brief Specific to RegressionModel
2465 * @param pred_term_index Index of the predictor term
2466 * @return Name of the predictor term
2468 std::string PMMLlib::GetPredictorTermName(int pred_term_index)
2472 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2473 if ( fieldRefNodes == NULL )
2476 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2477 if ( fieldRefNodes == NULL )
2479 // Positionnement sur la bonne sortie
2480 for(int i=0;i<pred_term_index;i++)
2482 fieldRefNodes = fieldRefNodes->next;
2483 if ( fieldRefNodes == NULL ||
2484 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2488 fieldRefNodes = fieldRefNodes->children;
2489 while (fieldRefNodes != NULL)
2491 strName += _getProp(fieldRefNodes, string("field"));
2492 fieldRefNodes = fieldRefNodes->next;
2498 * Get the coefficient of the numeric predictor given by its index.
2499 * @brief (The coefficient is the value of property "coefficient")
2500 * @brief Specific to RegressionModel
2501 * @param num_pred_index Index of the numeric predictor
2502 * @return Coefficient of the numeric predictor
2504 double PMMLlib::GetNumericPredictorCoefficient(int num_pred_index)
2509 xmlNodePtr numPredNodes = GetChildByName(_currentModelNode,"RegressionTable");
2510 if ( numPredNodes == NULL )
2512 numPredNodes = GetChildByName(numPredNodes,"NumericPredictor");
2513 if ( numPredNodes == NULL )
2515 // Positionnement sur la bonne sortie
2516 for(int i=0;i<num_pred_index;i++)
2518 numPredNodes = numPredNodes->next;
2519 if ( numPredNodes == NULL ||
2520 string((const char*)(numPredNodes->name)) != "NumericPredictor" )
2523 string strValue = _getProp(numPredNodes, string("coefficient"));
2524 coef = atof(strValue.c_str());
2529 * Get the coefficient of the predictor term given by its index.
2530 * @brief (The coefficient is the value of property "coefficient")
2531 * @brief Specific to RegressionModel
2532 * @param pred_term_index Index of the predictor term
2533 * @return Coefficient of the predictor term
2535 double PMMLlib::GetPredictorTermCoefficient(int pred_term_index)
2540 xmlNodePtr predTermNodes = GetChildByName(_currentModelNode,"RegressionTable");
2541 if ( predTermNodes == NULL )
2543 predTermNodes = GetChildByName(predTermNodes,"PredictorTerm");
2544 if ( predTermNodes == NULL )
2546 // Positionnement sur la bonne sortie
2547 for(int i=0;i<pred_term_index;i++)
2549 predTermNodes = predTermNodes->next;
2550 if ( predTermNodes == NULL ||
2551 string((const char*)(predTermNodes->name)) != "PredictorTerm" )
2554 string strValue = _getProp(predTermNodes, string("coefficient"));
2555 coef = atof(strValue.c_str());
2560 * Get the number of FieldRef for the predictor term given by its index.
2561 * @brief Specific to RegressionModel
2562 * @param indsex Index of the predictor term
2563 * @return Number of FieldRef
2565 int PMMLlib::GetPredictorTermFieldRefNb(int index)
2570 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2571 if ( fieldRefNodes == NULL )
2573 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2574 if ( fieldRefNodes == NULL )
2576 // Positionnement sur la bonne sortie
2577 for(int i=0;i<index;i++)
2579 fieldRefNodes = fieldRefNodes->next;
2580 if ( fieldRefNodes == NULL ||
2581 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2584 fieldRefNodes = fieldRefNodes->children;
2585 while (fieldRefNodes != NULL)
2588 fieldRefNodes = fieldRefNodes->next;
2594 * Get the name of the field_index-th FieldRef for the pred_term_index-th predictor term.
2595 * @brief (The name is the value of property "field")
2596 * @brief Specific to RegressionModel
2597 * @param pred_term_index Index of the predictor term
2598 * @param field_index Index of the FieldRef
2599 * @return Name of the FieldRef
2601 std::string PMMLlib::GetPredictorTermFieldRefName(int pred_term_index, int field_index)
2606 xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2607 if ( fieldRefNodes == NULL )
2609 fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2610 if ( fieldRefNodes == NULL )
2612 // Positionnement sur la bonne sortie PredictorTerm
2613 for(int i=0;i<pred_term_index;i++)
2615 fieldRefNodes = fieldRefNodes->next;
2616 if ( fieldRefNodes == NULL ||
2617 string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2620 fieldRefNodes = fieldRefNodes->children;
2621 if ( fieldRefNodes == NULL )
2623 // Positionnement sur la bonne sortie FieldRef
2624 for(int i=0;i<field_index;i++)
2626 fieldRefNodes = fieldRefNodes->next;
2627 if ( fieldRefNodes == NULL )
2630 strName = _getProp(fieldRefNodes, string("field"));
2635 * Export the current model as a NeuralNetwork function in a Cpp file.
2636 * @brief Specific to RegressionModel
2637 * @param file Name of the file
2638 * @param functionName Name of the function
2639 * @param header Header of the function
2641 void PMMLlib::ExportLinearRegressionCpp(std::string file,
2642 std::string functionName,
2648 ofstream exportfile(file.c_str());
2650 exportfile << "void " << functionName <<"(double *param, double *res)" << endl;
2651 exportfile << "{" << endl;
2653 exportfile << " ////////////////////////////// " << endl;
2654 exportfile << " //" << endl;
2655 // insert comments in header
2656 header = " // " + header;
2658 while ((pos = header.find("\n", pos)) != std::string::npos)
2660 header.replace(pos, 1, "\n //");
2663 exportfile << header << endl;
2664 exportfile << " //" << endl;
2665 exportfile << " ////////////////////////////// " << endl << endl;
2667 double intercept = 0.0;
2668 if ( HasIntercept() )
2670 exportfile << " // Intercept"<< endl;
2671 intercept = GetRegressionTableIntercept();
2674 exportfile << " // No Intercept"<< endl;
2675 exportfile << " double y = " << intercept << ";";
2676 exportfile << endl << endl;
2678 int nPred = GetNumericPredictorNb();
2679 for (int i=0; i<nPred; i++)
2681 exportfile << " // Attribute : " << GetNumericPredictorName(i) << endl;
2682 exportfile << " y += param["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2683 exportfile << endl << endl;
2685 nPred = GetPredictorTermNb();
2686 for (int i=0; i<nPred; i++)
2688 exportfile << " // Attribute : " << GetPredictorTermName(i) << endl;
2689 exportfile << " y += param["<<(i+nPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2690 exportfile << endl << endl;
2693 exportfile << " // Return the value"<< endl;
2694 exportfile << " res[0] = y;" << endl;
2695 exportfile << "}" << endl;
2700 * Export the current model as a NeuralNetwork function in a Fortran file.
2701 * @brief Specific to Regression
2702 * @param file Name of the file
2703 * @param functionName Name of the function
2704 * @param header Header of the function
2706 void PMMLlib::ExportLinearRegressionFortran(std::string file,
2707 std::string functionName,
2712 int nNumPred = GetNumericPredictorNb();
2713 int nPredTerm = GetPredictorTermNb();
2714 vector<string>strParam(nNumPred+nPredTerm);
2715 for(int i=0; i<(nNumPred+nPredTerm); i++)
2717 strParam[i] = "P" + NumberToString(i) ;
2721 ofstream exportfile(file.c_str());
2723 exportfile << " SUBROUTINE " << functionName <<"(";
2724 for(int i=0; i<(nNumPred+nPredTerm); i++)
2726 exportfile << strParam[i] << ", ";
2728 exportfile << "RES)" << endl;
2731 exportfile << "C --- *********************************************" << endl;
2732 exportfile << "C --- " << endl;
2733 // insert comments in header
2734 header = "C --- " + header;
2736 while ((pos = header.find("\n", pos)) != std::string::npos)
2738 header.replace(pos, 1, "\nC --- ");
2741 exportfile << header << endl;
2742 exportfile << "C --- " << endl;
2743 exportfile << "C --- *********************************************" << endl << endl;
2745 exportfile << " IMPLICIT DOUBLE PRECISION (P)" << endl;
2746 exportfile << " DOUBLE PRECISION RES" << endl;
2747 exportfile << " DOUBLE PRECISION Y" << endl;
2750 double intercept = 0.0;
2751 if ( HasIntercept() )
2753 exportfile << "C --- Intercept"<< endl;
2754 intercept = GetRegressionTableIntercept();
2757 exportfile << "C --- No Intercept"<< endl;
2758 exportfile << " Y = " << intercept << ";";
2759 exportfile << endl << endl;
2761 for (int i=0; i<nNumPred; i++)
2763 exportfile << "C --- Attribute : " << GetNumericPredictorName(i) << endl;
2764 exportfile << " Y += P["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2765 exportfile << endl << endl;
2768 for (int i=0; i<nPredTerm; i++)
2770 exportfile << "C --- Attribute : " << GetPredictorTermName(i) << endl;
2771 exportfile << " Y += P["<<(i+nNumPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2772 exportfile << endl << endl;
2775 exportfile << "C --- Return the value"<< endl;
2776 exportfile << " RES = Y " << endl;
2777 exportfile << " RETURN" << endl;
2778 exportfile << " END" << endl;
2783 * Export the current model as a NeuralNetwork function in a Python file.
2784 * @brief Specific to Regression
2785 * @param file Name of the file
2786 * @param functionName Name of the function
2787 * @param header Header of the function
2789 void PMMLlib::ExportLinearRegressionPython(std::string file,
2790 std::string functionName,
2793 string str(ExportLinearRegressionPyStr(functionName, header));
2795 ofstream exportfile(file.c_str());
2801 * Export the current model as a NeuralNetwork function in a Python string.
2802 * @brief Specific to Regression
2803 * @param functionName Name of the function
2804 * @param header Header of the function
2806 std::string PMMLlib::ExportLinearRegressionPyStr(std::string functionName,
2813 // Shebang et imports
2814 out << "#!/usr/bin/env python" << endl;
2815 out << "# -*- coding: utf-8 -*-" << endl;
2819 out << "def " << functionName <<"(param):" << endl;
2823 out << " ############################## " << endl;
2824 out << " # " << endl;
2825 // insert comments in header
2826 header = " # " + header;
2828 while ((pos = header.find("\n", pos)) != std::string::npos)
2830 header.replace(pos, 1, "\n #");
2833 out << header << endl;
2834 out << " # " << endl;
2835 out << " ############################## " << endl << endl;
2837 double intercept = 0.0;
2838 if ( HasIntercept() )
2840 out << " # Intercept"<< endl;
2841 intercept = GetRegressionTableIntercept();
2844 out << " # No Intercept"<< endl;
2845 out << " y = " << intercept << ";";
2846 out << endl << endl;
2848 int nPred = GetNumericPredictorNb();
2849 for (int i=0; i<nPred; i++)
2851 out << " # Attribute : " << GetNumericPredictorName(i) << endl;
2852 out << " y += param["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2853 out << endl << endl;
2855 nPred = GetPredictorTermNb();
2856 for (int i=0; i<nPred; i++)
2858 out << " # Attribute : " << GetPredictorTermName(i) << endl;
2859 out << " y += param["<<(i+nPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2860 out << endl << endl;
2863 out << " # Return the value"<< endl;
2864 out << " return [y];" << endl;
2870 * Read the structure of the regression model
2871 * @brief Specific to RegressionModel
2872 * @return Structure read
2874 std::string PMMLlib::ReadRegressionStructure()
2878 string structure("");
2879 string structureActive("");
2880 string structurePredicted("@");
2882 xmlNodePtr mNode = GetChildByName(_currentModelNode,"MiningSchema");
2883 if ( mNode != NULL )
2885 xmlNodePtr dNode = GetChildByName(mNode,"MiningField");
2886 while (dNode != NULL)
2888 string name = _getProp(dNode, string("name"));
2889 string usage = _getProp(dNode, string("usageType"));
2890 if ( usage == "active" )
2892 structureActive += name;
2893 structureActive += ":";
2895 else if ( usage == "predicted" )
2897 structurePredicted += name;
2898 structurePredicted += ":";
2901 dNode = dNode->next;
2903 // Delete the last ":"
2904 if ( structureActive.length() > 0 )
2905 structureActive.erase(structureActive.size()-1);
2906 structurePredicted.erase(structurePredicted.size()-1);
2908 std::ostringstream oss;
2910 structure = structureActive + "," + oss.str() + "," + structurePredicted;
2914 } // end of namespace