Version: 9.15.0
PMMLlib.cxx
Go to the documentation of this file.
1 // Copyright (C) 2013-2025 CEA
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU Lesser General Public License as published
5 // by the Free Software Foundation, either version 3 of the License, or any
6 // later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
15 
25 // includes Salomé
26 #include "PMMLlib.hxx"
27 
28 // includes C
29 #include <stdlib.h>
30 
31 // includes C++
32 #include <cstdlib>
33 #include <iostream>
34 #include <fstream>
35 #include <sstream>
36 
37 using namespace std;
38 
39 namespace PMMLlib
40 {
41 
42 //**************************************************************
43 // *
44 // *
45 // *
46 // méthodes communes à tous les types de modèles *
47 // *
48 // *
49 // *
50 //**************************************************************
51 
57 PMMLlib::PMMLlib(std::string file,bool log) :
58  _log(log),
59  _pmmlFile(file),
60  _doc(NULL),
61  _rootNode(NULL),
62  _currentNode(NULL),
63  _nbModels(0),
64  _currentModelName(""),
65  _currentModelType(kUNDEFINED)
66 {
67  try
68  {
69  xmlKeepBlanksDefault(0);
70  xmlInitParser();
71  _doc = xmlParseFile(_pmmlFile.c_str());
72  if ( _doc != NULL )
73  {
74  _rootNode = xmlDocGetRootElement(_doc);
75  CountModels();
76  }
77  else
78  throw string("Unable to read PMML file.");
79  }
80  catch ( std::string msg )
81  {
82  std::cerr << msg;
83  xmlFreeDoc(_doc);
84  xmlCleanupParser();
85  throw;
86  }
87 }
88 
95  _log(log),
96  _pmmlFile(""),
97  _doc(NULL),
98  _rootNode(NULL),
99  _currentNode(NULL),
100  _nbModels(0),
101  _currentModelName(""),
102  _currentModelType(kUNDEFINED)
103 {
104  SetRootNode();
105 }
106 
110 PMMLlib::~PMMLlib()
111 {
112  if (_doc)
113  xmlFreeDoc(_doc);
114  xmlCleanupParser();
115  if ( _log )
116  cout << "~PMMLlib" << endl;
117 }
118 
124 void PMMLlib::SetCurrentModel(std::string modelName,
125  PMMLType type)
126 {
127  _currentModelName = modelName;
128  _currentModelType = type;
129  switch(type)
130  {
131  case kANN:
132  _currentModelNode = GetNeuralNetPtr(modelName);
133  break;
134  case kLR:
135  _currentModelNode = GetRegressionPtr(modelName);
136  break;
137  default:
138  throw string("Unknown PMML type.");
139  break;
140  }
141  if ( _currentModelNode == NULL )
142  throw string("Model not found.");
143 }
144 
150 void PMMLlib::SetCurrentModel(std::string modelName)
151 {
152  if (_rootNode == NULL)
153  throw string("No PMML file set.");
154  xmlNodePtr node = NULL;
155  int nC = 0;
156  node = _rootNode->children;
157  while (node)
158  {
159  string nodeModelName = _getProp(node, string("modelName"));
160  if ( nodeModelName == modelName )
161  {
162  nC++;
163  _currentModelNode = node;
164  _currentModelName = modelName;
165  _currentModelType = GetCurrentModelType();
166  }
167  node = node->next;
168  }
169  if ( nC != 1 )
170  {
171  std::ostringstream oss;
172  oss << nC;
173  string msg = "SetCurrentModel(modelName) : found " + oss.str() + " model(s) in PMML file.\n";
174  msg += "Use SetCurrentModel(modelName,type).";
175  throw msg;
176  }
177 }
178 
183 void PMMLlib::SetCurrentModel()
184 {
185  int nC = _nbModels;
186  if ( nC != 1 )
187  {
188  std::ostringstream oss;
189  oss << nC;
190  string msg = "SetCurrentModel() : found " + oss.str() + " model(s) in PMML file.\n";
191  msg += "Use SetCurrentModel(modelName) or SetCurrentModel(modelName,type).";
192  throw msg;
193  }
194  _currentModelNode = GetChildByName(_rootNode,"NeuralNetwork");
195  _currentModelType = kANN;
196  if (_currentModelNode == NULL)
197  {
198  _currentModelNode = GetChildByName(_rootNode,"RegressionModel");
199  _currentModelType = kLR;
200  }
201  if (_currentModelNode == NULL)
202  {
203  string msg("Couldn't get node in SetCurrentModel().");
204  throw msg;
205  }
206  _currentModelName = _getProp(_currentModelNode, string("modelName"));
207 }
208 
213 std::string PMMLlib::makeLog() const
214 {
215  ostringstream out;
216  out << "**\n**** Display of PMMLlib ****" << endl;
217  out << " ** _pmmlFile[" << _pmmlFile << "]" << endl;
218  out << " ** _log[" << (_log?1:0) << "]" << endl;
219  out << "**\n**** End of display of PMMLlib ****" << endl;
220  return out.str();
221 }
222 
226 void PMMLlib::printLog() const
227 {
228  string log = makeLog();
229  cout << log << endl;
230 }
231 
238 void PMMLlib::SetRootNode()
239 {
240  xmlChar * xs = _stringToXmlChar("1.0");
241  _doc = xmlNewDoc(xs);
242  xmlFree(xs);
243 
244  xmlChar *xp = _stringToXmlChar("PMML");
245  _rootNode = xmlNewNode(0, xp);
246  xmlFree(xp);
247 
248  xmlNewProp(_rootNode, (const xmlChar*)"xmlns", (const xmlChar*)"http://www.dmg.org/PMML-4_1");
249  xmlNewProp(_rootNode, (const xmlChar*)"version", (const xmlChar*)"4.1");
250 
251  xmlDocSetRootElement(_doc, _rootNode);
252 }
253 
254 
263 void PMMLlib::SetHeader(std::string copyright,
264  std::string description,
265  std::string appName,
266  std::string appVersion,
267  std::string annotation)
268 {
269  xmlNodePtr headerNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"Header", 0);
270  xmlNewProp(headerNode, (const xmlChar*)"copyright", (const xmlChar*)(copyright.c_str()));
271  xmlNewProp(headerNode, (const xmlChar*)"description", (const xmlChar*)(description.c_str()));
272 
273  xmlNodePtr appNode = xmlNewChild(headerNode, 0, (const xmlChar*)"Application", 0);
274  xmlNewProp(appNode, (const xmlChar*)"name", (const xmlChar*)(appName.c_str()));
275  xmlNewProp(appNode, (const xmlChar*)"version", (const xmlChar*)(appVersion.c_str()));
276 
277  xmlNewChild(headerNode, 0, (const xmlChar*)"Annotation", (const xmlChar*)(annotation.c_str()));
278 }
279 
286 void PMMLlib::AddMiningSchema(std::string name,
287  std::string usageType)
288 {
289  xmlNodePtr netNode = _currentModelNode;
290 
291  // if 'MiningSchema' node does not exist, create it
292  xmlNodePtr miningSchemaNode = GetChildByName(netNode, "MiningSchema");
293  if(!miningSchemaNode)
294  {
295  miningSchemaNode = xmlNewChild(netNode, 0, (const xmlChar*)"MiningSchema", 0);
296  }
297 
298  // then append the node
299  xmlNodePtr miningFieldNode = xmlNewChild(miningSchemaNode, 0, (const xmlChar*)"MiningField", 0);
300  xmlNewProp(miningFieldNode, (const xmlChar*)"name", (const xmlChar*)(name.c_str()) );
301  xmlNewProp(miningFieldNode, (const xmlChar*)"usageType", (const xmlChar*)(usageType.c_str()) );
302 }
303 
310 xmlNodePtr PMMLlib::GetChildByName(xmlNodePtr node,
311  std::string nodeName)
312 {
313  if ( node == NULL )
314  return node;
315 
316  xmlNodePtr childNode = node->children;
317  if ( childNode == NULL )
318  return childNode;
319 
320  const xmlChar* name = childNode->name;
321  string strName("");
322  if ( name != NULL )
323  strName = _xmlCharToString(name);
324 
325  while( (childNode != NULL) && (strName != nodeName) )
326  {
327  childNode = childNode->next;
328  if ( childNode == NULL )
329  return childNode;
330  name = childNode->name;
331  if ( name != NULL )
332  strName = _xmlCharToString(name);
333  }
334  return childNode;
335 }
336 
341 void PMMLlib::CountModels()
342 {
343  int nCount = 0;
344  nCount = CountNeuralNetModels() + CountRegressionModels();
345  if ( _log)
346  cout << " ** End Of Count Models nCount[" << nCount << "]" << endl;
347  _nbModels = nCount ;
348 }
349 
354 int PMMLlib::CountNeuralNetModels()
355 {
356  int nCount = 0;
357  xmlNodePtr ptr = GetChildByName(_rootNode,"NeuralNetwork");
358  // Count the models
359  while (ptr != NULL && _xmlCharToString(ptr->name) == "NeuralNetwork")
360  {
361  nCount++;
362  if (_log)
363  cout << " ** nCount[" << nCount << "]" << endl;
364  ptr = ptr->next;
365  }
366  if ( _log)
367  cout << " ** End Of CountNetworks nCount[" << nCount << "]" << endl;
368  return nCount;
369 }
370 
375 int PMMLlib::CountRegressionModels()
376 {
377  int nCount = 0;
378  xmlNodePtr ptr = GetChildByName(_rootNode,"RegressionModel");
379  // Count the models
380  while (ptr != NULL && _xmlCharToString(ptr->name) == "RegressionModel")
381  {
382  nCount++;
383  if (_log)
384  cout << " ** nCount[" << nCount << "]" << endl;
385  ptr = ptr->next;
386  }
387  if ( _log)
388  cout << " ** End Of CountRegressions nCount[" << nCount << "]" << endl;
389  return nCount;
390 }
391 
396 int PMMLlib::GetModelsNb()
397 {
398  return _nbModels;
399 }
400 
406 std::string PMMLlib::GetModelName(xmlNodePtr node)
407 {
408  string name("");
409  name = _getProp(node, string("modelName") );
410  return name;
411 }
412 
419 xmlNodePtr PMMLlib::GetPtr(int index,
420  std::string name)
421 {
422  xmlNodePtr node = NULL;
423 
424  if (_doc != NULL)
425  {
426  _rootNode = xmlDocGetRootElement(_doc);
427  node = GetChildByName(_rootNode, name);
428 
429  int i=0;
430  while ((i != index) && (node != NULL))
431  {
432  node = node->next;
433  i++;
434  }
435  }
436  return node;
437 }
438 
445 xmlNodePtr PMMLlib::GetPtr(std::string myModelName,
446  std::string nodeName)
447 {
448  xmlNodePtr node = NULL;
449  if (_doc != NULL)
450  {
451  node = GetChildByName(_rootNode, nodeName);
452  if( node )
453  {
454  string modelName = _getProp(node, string("modelName"));
455 
456  while ( (node != NULL) && modelName != myModelName )
457  {
458  node = node->next;
459  if( node )
460  {
461  modelName = _getProp(node, string("modelName"));
462  }
463  }
464  }
465  }
466  return node;
467 }
468 
473 std::string PMMLlib::GetTypeString()
474 {
475  string name = "";
476  switch(_currentModelType)
477  {
478  case kANN:
479  name = "NeuralNetwork";
480  break;
481  case kLR:
482  name = "RegressionModel";
483  break;
484  default:
485  throw string("Unknown PMML type.");
486  break;
487  }
488  return name;
489 }
490 
496 PMMLType PMMLlib::GetCurrentModelType()
497 {
498  PMMLType type = kUNDEFINED ;
499  if ( ! _currentModelNode )
500  return type;
501  string name = _xmlCharToString(_currentModelNode->name);
502  if ( name == "NeuralNetwork" )
503  type = kANN;
504  else if ( name == "RegressionModel" )
505  type = kLR;
506  return type;
507 }
508 
514 std::string PMMLlib::GetCurrentModelName()
515 {
516  if ( ! _currentModelNode )
517  return string("");
518  string name = _getProp(_currentModelNode, string("modelName"));
519  return name;
520 }
521 
525 void PMMLlib::UnlinkNode()
526 {
527  xmlNodePtr ptr = _currentModelNode ;
528  xmlUnlinkNode( ptr );
529  xmlFreeNode( ptr );
530 }
531 
535 void PMMLlib::BackupNode()
536 {
537  // Node name depending of PMML type
538  string name = GetTypeString();
539  // Find the last save index number
540  int nCrtIndex = 0;
541  stringstream ss;
542  ss << _currentModelName << "_" << nCrtIndex;
543  xmlNodePtr ptr = GetPtr(ss.str(), name);
544  while( ptr )
545  {
546  nCrtIndex++;
547  if (_log)
548  cout << " ** nCrtIndex[" << nCrtIndex << "]" << endl;
549 
550  ss.str("");
551  ss << _currentModelName << "_" << nCrtIndex;
552  ptr = GetPtr(ss.str(), name);
553  }
554  if(_log)
555  cout << " *** Node \"" << _currentModelName << "\" found, then backup it with index [" << nCrtIndex << "]" << endl;
556  // Rename model
557  xmlUnsetProp(_currentModelNode, (const xmlChar*)"modelName");
558  xmlNewProp(_currentModelNode, (const xmlChar*)"modelName", (const xmlChar*)(ss.str().c_str()));
559 }
560 
564 void PMMLlib::Write()
565 {
566  // Enregistrement de l'arbre DOM dans le fichier pmml
567  Write(_pmmlFile);
568  // Mise à jour du nombre de modèles
569  CountModels();
570 }
571 
576 void PMMLlib::Write(std::string file)
577 {
578  // Enregistrement de l'arbre DOM sous forme de fichier pmml
579  int ret = xmlSaveFormatFile( file.c_str(), _doc, 1);
580  if ( ret == -1 )
581  {
582  std::string msg(" *** Error :: unable to write the PMML file \"" + file + "\"") ;
583  cout << msg << endl;
584  throw msg;
585  }
586  if ( _log )
587  cout << " *** Write the PMML file \"" << file <<"\"" << endl;
588 }
589 
596 void PMMLlib::ExportCpp(std::string file,
597  std::string functionName,
598  std::string header)
599 {
600  if ( _currentModelType == kANN )
601  ExportNeuralNetworkCpp(file,functionName, header);
602  else if ( _currentModelType == kLR )
603  {
604  ExportLinearRegressionCpp(file, functionName, header);
605  }
606  else
607  throw string("ExportCpp : PMML type not handled.");
608 }
609 
616 void PMMLlib::ExportFortran(std::string file,
617  std::string functionName,
618  std::string header)
619 {
620  if ( _currentModelType == kANN )
621  ExportNeuralNetworkFortran(file,functionName, header);
622  else if ( _currentModelType == kLR )
623  ExportLinearRegressionFortran(file,functionName, header);
624  else
625  throw string("ExportFortran : PMML type not handled.");
626 }
627 
634 void PMMLlib::ExportPython(std::string file,
635  std::string functionName,
636  std::string header)
637 {
638  if ( _currentModelType == kANN )
639  ExportNeuralNetworkPython(file,functionName, header);
640  else if ( _currentModelType == kLR )
641  ExportLinearRegressionPython(file,functionName, header);
642  else
643  throw string("ExportPython : PMML type not handled.");
644 }
645 
653 std::string PMMLlib::ExportPyStr(std::string functionName,
654  std::string header)
655 {
656  if ( _currentModelType == kANN )
657  return ExportNeuralNetworkPyStr(functionName, header);
658  else if ( _currentModelType == kLR )
659  return ExportLinearRegressionPyStr(functionName, header);
660  else
661  throw string("ExportPyStr : PMML type not handled.");
662 }
663 
669 std::string PMMLlib::_xmlCharToString(const xmlChar *xs) const
670 {
671  size_t i, L = xmlStrlen(xs);
672  std::string s;
673  s.resize(L);
674  for (i=0; *xs; s[i++] = *xs++);
675  return s;
676 }
677 
683 xmlChar * PMMLlib::_stringToXmlChar(const std::string &s) const
684 {
685  return xmlCharStrdup(s.c_str());
686 }
687 
694 std::string PMMLlib::_getProp(const xmlNodePtr node,
695  std::string const & prop ) const
696 {
697  std::string name("");
698  if (_doc != NULL)
699  {
700  xmlChar *xp = _stringToXmlChar(prop);
701  xmlChar * attr ;
702  attr = xmlGetProp(node, xp );
703  if ( attr )
704  {
705  name = _xmlCharToString(attr );
706  xmlFree(attr);
707  }
708  xmlFree(xp);
709  }
710  return name;
711 }
712 
713 //**************************************************************
714 // *
715 // *
716 // *
717 // méthodes propres au NeuralNetwork *
718 // *
719 // *
720 // *
721 //**************************************************************
722 
728 void PMMLlib::CheckNeuralNetwork()
729 {
730  if ( _currentModelType != kANN )
731  throw string("Use this method with NeuralNetwork models.");
732 }
733 
739 xmlNodePtr PMMLlib::GetNeuralNetPtr(int index)
740 {
741  return GetPtr(index, GetTypeString() );
742 }
743 
749 xmlNodePtr PMMLlib::GetNeuralNetPtr(std::string name)
750 {
751  return GetPtr(name, GetTypeString() );
752 }
753 
759 std::string PMMLlib::ReadNetworkStructure()
760 {
761  CheckNeuralNetwork();
762 
763  string structure("");
764  // Treatment of the input
765  xmlNodePtr inputNodes = GetChildByName(_currentModelNode,"NeuralInputs");
766  if ( inputNodes != NULL )
767  {
768  xmlNodePtr inputNode = GetChildByName(inputNodes,"NeuralInput");
769  if ( inputNode != NULL )
770  {
771  while (inputNode != NULL)
772  {
773  xmlNodePtr child = GetChildByName(inputNode,"DerivedField");
774  if ( child != NULL )
775  {
776  xmlNodePtr fieldName = child->children; // NormContinuous
777  if ( fieldName != NULL )
778  {
779  string field = _getProp(fieldName, string("field"));
780  structure += field;
781  structure += ":";
782  }
783  }
784  inputNode = inputNode->next;
785  }
786  // Delete the last comma
787  structure.erase(structure.size()-1);
788  }
789  }
790  // Intermediary layers
791  xmlNodePtr node_layer = GetChildByName(_currentModelNode,"NeuralLayer");
792  if ( node_layer != NULL )
793  {
794  string name = string((const char*)(node_layer->name));
795  structure += ",";
796 
797  while ( node_layer != NULL &&
798  (string((const char*)(node_layer->name)) == "NeuralLayer") &&
799  node_layer->next != NULL &&
800  (string((const char*)(node_layer->next->name)) != "NeuralOutputs") )
801  {
802  // Get the number of neurons of the current layer
803  string nbneurons = _getProp(node_layer, string("numberOfNeurons"));
804  structure += nbneurons;
805  structure += ",";
806  node_layer = node_layer->next;
807  }
808  }
809  // Output layers
810  xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
811  if ( node_outputs != NULL )
812  {
813  xmlNodePtr node_output = GetChildByName(node_outputs,"NeuralOutput");
814  if ( node_output != NULL )
815  {
816  while (node_output != NULL)
817  {
818  // Get the input of the current layer
819  xmlNodePtr child = GetChildByName(node_output,"DerivedField");
820  if ( child != NULL )
821  {
822  xmlNodePtr fieldName = child->children; // NormContinuous
823  if ( fieldName != NULL )
824  {
825  if (string((const char*)(fieldName->name)) == "NormContinuous")
826  structure += "@";
827 
828  string field = _getProp(fieldName, string("field"));
829  structure += field;
830  structure += ":";
831  }
832  }
833  node_output = node_output->next;
834  }
835  // Delete the last comma
836  structure.erase(structure.size()-1);
837  }
838  }
839  return structure;
840 }
841 
847 int PMMLlib::GetNbInputs()
848 {
849  CheckNeuralNetwork();
850 
851  int nb=0;
852  xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
853  if ( node_inputs == NULL )
854  return nb;
855 
856  node_inputs = node_inputs->children;
857  while (node_inputs != NULL)
858  {
859  nb++;
860  node_inputs = node_inputs->next;
861  }
862 
863  return nb;
864 }
865 
871 int PMMLlib::GetNbOutputs()
872 {
873  CheckNeuralNetwork();
874 
875  int nb=0;
876  xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
877  if ( node_outputs == NULL )
878  return nb;
879 
880  node_outputs = node_outputs->children;
881 
882  while (node_outputs != NULL)
883  {
884  nb++;
885  node_outputs = node_outputs->next;
886  }
887 
888  return nb;
889 }
890 
897 std::string PMMLlib::GetNameInput(int index)
898 {
899  CheckNeuralNetwork();
900 
901  string name("");
902  xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
903  if ( node_inputs == NULL )
904  return name;
905 
906  node_inputs = node_inputs->children;
907  if ( node_inputs == NULL )
908  return name;
909 
910  for(int i = 0;i<index;i++)
911  {
912  node_inputs = node_inputs->next;
913  if ( node_inputs == NULL )
914  return name;
915  }
916 
917  node_inputs = node_inputs->children;
918  if ( node_inputs == NULL )
919  return name;
920 
921  node_inputs = node_inputs->children;
922  if ( node_inputs == NULL )
923  return name;
924 
925  name = _getProp(node_inputs, string("field"));
926 
927  return name;
928 }
929 
936 std::string PMMLlib::GetNameOutput(int index)
937 {
938  CheckNeuralNetwork();
939 
940  string name("");
941  xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
942  if ( node_outputs == NULL )
943  return name;
944  node_outputs = node_outputs->children;
945  if ( node_outputs == NULL )
946  return name;
947  for(int i = 0;i<index;i++)
948  {
949  node_outputs = node_outputs->next;
950  if ( node_outputs == NULL )
951  return name;
952  }
953 
954  node_outputs = node_outputs->children;
955  if ( node_outputs == NULL )
956  return name;
957  node_outputs = node_outputs->children;
958  if ( node_outputs == NULL )
959  return name;
960 
961  name = _getProp(node_outputs, string("field") );
962 
963  return name;
964 }
965 
971 int PMMLlib::GetNormalizationType()
972 {
973  CheckNeuralNetwork();
974 
975  xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
976  node_inputs = GetChildByName(node_inputs,"NeuralInput");
977  xmlNodePtr nodeTmp = GetChildByName(node_inputs,"DerivedField");
978  xmlNodePtr node_field = nodeTmp->children;
979  xmlNodePtr node_linearnorm;
980  string str_tmp;
981  double dorig1, dnorm1;
982  double dorig2, dnorm2;
983  if (string((const char*)(node_field->name)) == "NormContinuous")
984  {
985  // Get mean and standard deviation
986  node_linearnorm = node_field->children;
987  str_tmp = _getProp(node_linearnorm, string("orig"));
988  dorig1 = atof(str_tmp.c_str());
989  str_tmp = _getProp(node_linearnorm, string("norm"));
990  dnorm1 = atof(str_tmp.c_str());
991  node_linearnorm = node_linearnorm->next;
992  str_tmp = _getProp(node_linearnorm, string("orig"));
993  dorig2 = atof(str_tmp.c_str());
994  str_tmp = _getProp(node_linearnorm, string("norm"));
995  dnorm2 = atof(str_tmp.c_str());
996  if ( dnorm1 * dnorm2 < -0.5 )
997  { // case of kMinusOneOne
998  return 0;
999  }
1000  else
1001  { // case of kCR, kZeroOne
1002  return 1;
1003  }
1004  }
1005  string msg("Unable to retrieve the normalization type.");
1006  throw msg;
1007 }
1008 
1016 void PMMLlib::GetNormalisationInput(int index,
1017  double *dnorm)
1018 {
1019  CheckNeuralNetwork();
1020  dnorm[0] = 0.0;
1021  dnorm[1] = 0.0;
1022  xmlNodePtr node_inputs = GetChildByName(_currentModelNode,"NeuralInputs");
1023  if ( node_inputs == NULL )
1024  return ;
1025  node_inputs = GetChildByName(node_inputs,"NeuralInput");
1026  if ( node_inputs == NULL )
1027  return ;
1028  // Positionnement sur la bonne entree
1029  for(int i=0;i<index;i++)
1030  {
1031  node_inputs = node_inputs->next;
1032  if ( node_inputs == NULL )
1033  return ;
1034  }
1035  xmlNodePtr tmpNode = GetChildByName(node_inputs,"DerivedField");
1036  if ( tmpNode == NULL )
1037  return ;
1038  xmlNodePtr node_field = GetChildByName(tmpNode,"NormContinuous");
1039  if ( node_field == NULL )
1040  return ;
1041  if (string((const char*)(node_field->name)) == "NormContinuous")
1042  {
1043  //Get mean and standard deviation
1044  string str_tmp;
1045  xmlNodePtr node_linearnorm = node_field->children;
1046  str_tmp = _getProp(node_linearnorm, string("orig"));
1047  double dorig1 = atof(str_tmp.c_str());
1048  str_tmp = _getProp(node_linearnorm, string("norm"));
1049  double dnorm1 = atof(str_tmp.c_str());
1050  node_linearnorm = node_linearnorm->next;
1051  str_tmp = _getProp(node_linearnorm, string("orig"));
1052  double dorig2 = atof(str_tmp.c_str());
1053  str_tmp = _getProp(node_linearnorm, string("norm"));
1054  double dnorm2 = atof(str_tmp.c_str());
1055  if ( dnorm1 * dnorm2 < -0.5 ) // <=> GetNormalizationType == 0
1056  {
1057  // case of kMinusOneOne
1058  dnorm[0] = dorig1;
1059  dnorm[1] = dorig2;
1060  }
1061  else // <=> GetNormalizationType == 1
1062  {
1063  // case of kCR, kZeroOne
1064  dnorm[0] = dorig2;
1065  dnorm[1] = -1.0 * dnorm1 * dorig2; //dorig2 / dnorm1;
1066  }
1067  }
1068 }
1069 
1076 void PMMLlib::GetNormalisationOutput(int index,
1077  double *dnorm)
1078 {
1079  CheckNeuralNetwork();
1080  dnorm[0] = 0.0;
1081  dnorm[1] = 0.0;
1082 
1083  xmlNodePtr node_outputs = GetChildByName(_currentModelNode,"NeuralOutputs");
1084  if ( node_outputs == NULL )
1085  return ;
1086  node_outputs = GetChildByName(node_outputs,"NeuralOutput");
1087  if ( node_outputs == NULL )
1088  return ;
1089  // Positionnement sur la bonne sortie
1090  for(int i=0;i< index;i++)
1091  {
1092  node_outputs = node_outputs->next;
1093  if ( node_outputs == NULL )
1094  return ;
1095  }
1096  xmlNodePtr tmpNode = GetChildByName(node_outputs,"DerivedField");
1097  if ( tmpNode == NULL )
1098  return ;
1099  xmlNodePtr node_field = GetChildByName(tmpNode,"NormContinuous");
1100  if ( node_field == NULL )
1101  return ;
1102 
1103  if (string((const char*)(node_field->name)) == "NormContinuous")
1104  {
1105  // Recuperation de la moyenne et de l'ecart type
1106  string str_tmp;
1107  xmlNodePtr node_linearnorm = node_field->children;
1108  str_tmp = _getProp(node_linearnorm, string("orig"));
1109  double dorig1 = atof(str_tmp.c_str());
1110  str_tmp = _getProp(node_linearnorm, string("norm"));
1111  double dnorm1 = atof(str_tmp.c_str());
1112  node_linearnorm = node_linearnorm->next;
1113  str_tmp = _getProp(node_linearnorm,string("orig"));
1114  double dorig2 = atof(str_tmp.c_str());
1115  str_tmp = _getProp(node_linearnorm, string("norm"));
1116  double dnorm2 = atof(str_tmp.c_str());
1117  if ( dnorm1 * dnorm2 < -0.5 )
1118  {
1119  // case of kMinusOneOne
1120  dnorm[0] = dorig1;
1121  dnorm[1] = dorig2;
1122  }
1123  else
1124  {
1125  // case of kCR, kZeroOne
1126  dnorm[0] = dorig2;
1127  dnorm[1] = -1.0 * dorig2 * dnorm1; //-1.0 * dorig2 / dnorm1;
1128  }
1129  }
1130 }
1131 
1137 int PMMLlib::GetNbHiddenLayers()
1138 {
1139  CheckNeuralNetwork();
1140 
1141  int nb_layers = 0;
1142  xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1143  if ( node_layers == NULL )
1144  return nb_layers;
1145 
1146  while (string((const char*)(node_layers->name)) == "NeuralLayer")
1147  {
1148  nb_layers++;
1149  node_layers = node_layers->next;
1150  if ( node_layers == NULL )
1151  return nb_layers;
1152  }
1153  return nb_layers;
1154 }
1155 
1160 int PMMLlib::GetNbLayers()
1161 {
1162  return (GetNbHiddenLayers() + 2);
1163 }
1164 
1170 int PMMLlib::GetNbNeuronsAtLayer(int index)
1171 {
1172  CheckNeuralNetwork();
1173 
1174  int nb_neurons = 0;
1175  xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1176  if ( node_layers == NULL )
1177  return nb_neurons;
1178 
1179  // Positionnement à la bonne couche
1180  for(int i=0;i<index;i++)
1181  {
1182  node_layers = node_layers->next;
1183  if ( node_layers == NULL )
1184  return nb_neurons;
1185  }
1186 
1187  xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1188  while(node_neurons != NULL)
1189  {
1190  nb_neurons++;
1191  node_neurons = node_neurons->next;
1192  }
1193 
1194  return nb_neurons;
1195 }
1196 
1204 double PMMLlib::GetNeuronBias(int layer_index,
1205  int neu_index)
1206 {
1207  CheckNeuralNetwork();
1208 
1209  double bias = 0.;
1210  xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1211  if ( node_layers == NULL )
1212  return bias;
1213  // Positionnement a la bonne couche
1214  for(int i=0;i<layer_index;i++)
1215  {
1216  node_layers = node_layers->next;
1217  if ( node_layers == NULL )
1218  return bias;
1219  }
1220  xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1221  // Positionnement sur le bon neurone
1222  for(int j=0;j<neu_index;j++)
1223  {
1224  node_neurons = node_neurons->next;
1225  if ( node_neurons == NULL )
1226  return bias;
1227  }
1228  string str_tmp = _getProp(node_neurons, string("bias"));
1229  bias = atof(str_tmp.c_str());
1230  return bias;
1231 }
1232 
1241 double PMMLlib::GetPrecNeuronSynapse(int layer_index,
1242  int neu_index,
1243  int prec_index)
1244 {
1245  CheckNeuralNetwork();
1246 
1247  double weight = 0.;
1248  xmlNodePtr node_layers = GetChildByName(_currentModelNode,"NeuralLayer");
1249  if ( node_layers == NULL )
1250  return weight;
1251  // Positionnement a la bonne couche
1252  for(int i=0;i<layer_index;i++)
1253  {
1254  node_layers = node_layers->next;
1255  if ( node_layers == NULL )
1256  return weight;
1257  }
1258  xmlNodePtr node_neurons = GetChildByName(node_layers,"Neuron");
1259  // Positionnement sur le bon neurone
1260  for(int i=0;i<neu_index;i++)
1261  {
1262  node_neurons = node_neurons->next;
1263  if ( node_neurons == NULL )
1264  return weight;
1265  }
1266  xmlNodePtr node_con = GetChildByName(node_neurons,"Con");
1267  // Positionnement sur la bonne synapse
1268  for(int i=0;i<prec_index;i++)
1269  {
1270  node_con = node_con->next;
1271  if ( node_con == NULL )
1272  return weight;
1273  }
1274  string str_tmp = _getProp(node_con, string("weight"));
1275  weight = atof(str_tmp.c_str());
1276  return weight;
1277 }
1278 
1285 // LCOV_EXCL_START
1286 void PMMLlib::SetNeuralNetName(int index,
1287  std::string name)
1288 {
1289  CheckNeuralNetwork();
1290 
1291  int i=0;
1292  if (_doc != NULL)
1293  {
1294  xmlNodePtr node_ann = GetChildByName(_rootNode,"NeuralNetwork");
1295  while ((i != index) && (node_ann != NULL))
1296  {
1297  node_ann = node_ann->next;
1298  i++;
1299  }
1300  xmlNewProp(node_ann, (const xmlChar*)"modelName", (const xmlChar*)(name.c_str()));
1301  }
1302  xmlSaveFormatFile( string(_pmmlFile+".pmml").c_str(), _doc, 1);
1303 }
1304 // LCOV_EXCL_STOP
1305 
1317 void PMMLlib::AddDataField(std::string fieldName,
1318  std::string displayName,
1319  std::string optype,
1320  std::string dataType,
1321  std::string closure,
1322  double leftMargin,
1323  double rightMargin,
1324  bool interval)
1325 {
1326  // if 'DataDictionary' node does not exist, create it
1327  xmlNodePtr dataDictNode = GetChildByName(_rootNode, "DataDictionary");
1328  if(!dataDictNode)
1329  {
1330  dataDictNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"DataDictionary", 0);
1331  }
1332 
1333  // then append the node
1334  xmlNodePtr dataFieldNode = xmlNewChild(dataDictNode, 0, (const xmlChar*)"DataField", 0);
1335  xmlNewProp(dataFieldNode, (const xmlChar*)"name", (const xmlChar*)(fieldName.c_str()) );
1336  xmlNewProp(dataFieldNode, (const xmlChar*)"displayName", (const xmlChar*)(displayName.c_str()) );
1337  xmlNewProp(dataFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1338  xmlNewProp(dataFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1339 
1340  if ( interval )
1341  {
1342  xmlNodePtr intervalNode = xmlNewChild(dataFieldNode, 0, (const xmlChar*)"Interval", 0);
1343  xmlNewProp(intervalNode, (const xmlChar*)"closure", (const xmlChar*)(closure.c_str()) );
1344  stringstream ss;
1345  ss << scientific << leftMargin;
1346  xmlNewProp(intervalNode, (const xmlChar*)"leftMargin", (const xmlChar*)(ss.str().c_str()) );
1347  ss.str("");
1348  ss << scientific << rightMargin;
1349  xmlNewProp(intervalNode, (const xmlChar*)"rightMargin", (const xmlChar*)(ss.str().c_str()) );
1350  }
1351 }
1352 
1359 void PMMLlib::AddNeuralNetwork(std::string modelName,
1360  PMMLMiningFunction functionName)
1361 {
1362  _currentModelType = kANN;
1363  _currentModelName = modelName;
1364 
1365  CheckNeuralNetwork();
1366 
1367  string function;
1368  switch(functionName)
1369  {
1370  case kREGRESSION:
1371  function = "regression";
1372  break;
1373  }
1374 
1375  xmlNodePtr netNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"NeuralNetwork", 0);
1376  xmlNewProp(netNode, (const xmlChar*)"modelName", (const xmlChar*)(_currentModelName.c_str()) );
1377  xmlNewProp(netNode, (const xmlChar*)"functionName", (const xmlChar*)(function.c_str()) );
1378  xmlNewProp(netNode, (const xmlChar*)"numberOfLayers", (const xmlChar*)"0" );
1379  _currentModelNode = netNode;
1380 }
1381 
1394 void PMMLlib::AddNeuralInput(int id,
1395  std::string inputName,
1396  std::string optype,
1397  std::string dataType,
1398  double orig1, double norm1,
1399  double orig2, double norm2)
1400 {
1401  CheckNeuralNetwork();
1402 
1403  xmlNodePtr netNode = _currentModelNode;
1404  // if 'NeuralInputs' node does not exist, create it
1405  xmlNodePtr neuralInputsNode = GetChildByName(netNode, "NeuralInputs");
1406  if(!neuralInputsNode)
1407  {
1408  neuralInputsNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralInputs", 0);
1409  xmlNewProp(neuralInputsNode, (const xmlChar*)"numberOfInputs", (const xmlChar*)"0" );
1410  }
1411  // increment the number of inputs
1412  string numberOfInputsStr = _getProp(neuralInputsNode, string("numberOfInputs"));
1413  int numberOfInputs;
1414  istringstream( numberOfInputsStr ) >> numberOfInputs;
1415  numberOfInputs++;
1416  stringstream ss;
1417  ss << numberOfInputs;
1418  xmlSetProp(neuralInputsNode, (const xmlChar*)"numberOfInputs", (const xmlChar*)(ss.str().c_str()) );
1419  // then append the node and its children
1420  xmlNodePtr neuralInputNode = xmlNewChild(neuralInputsNode, 0, (const xmlChar*)"NeuralInput", 0);
1421  ss.str(""); ss << id;
1422  xmlNewProp(neuralInputNode, (const xmlChar*)"id", (const xmlChar*)(ss.str().c_str()) );
1423 
1424  xmlNodePtr derivedFieldNode = xmlNewChild(neuralInputNode, 0, (const xmlChar*)"DerivedField", 0);
1425  xmlNewProp(derivedFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1426  xmlNewProp(derivedFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1427 
1428  xmlNodePtr normcontNode = xmlNewChild(derivedFieldNode, 0, (const xmlChar*)"NormContinuous", 0);
1429  xmlNewProp(normcontNode, (const xmlChar*)"field", (const xmlChar*)(inputName.c_str()) );
1430 
1431  xmlNodePtr node_linearnorm1 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1432  ss.str(""); ss << scientific << orig1;
1433  xmlNewProp(node_linearnorm1, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1434  ss.str(""); ss << scientific << norm1;
1435  xmlNewProp(node_linearnorm1, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1436  xmlNodePtr node_linearnorm2 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1437  ss.str(""); ss << scientific << orig2;
1438  xmlNewProp(node_linearnorm2, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1439  ss.str(""); ss << scientific << norm2;
1440  xmlNewProp(node_linearnorm2, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1441 }
1442 
1455 void PMMLlib::AddNeuralOutput(int outputNeuron,
1456  std::string outputName,
1457  std::string optype,
1458  std::string dataType,
1459  double orig1, double norm1,
1460  double orig2, double norm2)
1461 {
1462  CheckNeuralNetwork();
1463 
1464  xmlNodePtr netNode = _currentModelNode;
1465  // if 'NeuralOutputs' node does not exist, create it
1466  xmlNodePtr neuralOutputsNode = GetChildByName(netNode, "NeuralOutputs");
1467  if(!neuralOutputsNode)
1468  {
1469  neuralOutputsNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralOutputs", 0);
1470  xmlNewProp(neuralOutputsNode, (const xmlChar*)"numberOfOutputs", (const xmlChar*)"0" );
1471  }
1472  // increment the number of inputs
1473  string numberOfOutputsStr = _getProp(neuralOutputsNode, string("numberOfOutputs"));
1474  int numberOfOutputs;
1475  istringstream( numberOfOutputsStr ) >> numberOfOutputs;
1476  numberOfOutputs++;
1477  stringstream ss;
1478  ss << numberOfOutputs;
1479  xmlSetProp(neuralOutputsNode, (const xmlChar*)"numberOfOutputs", (const xmlChar*)(ss.str().c_str()) );
1480 
1481  // then append the node and its children
1482  xmlNodePtr neuralOutputNode = xmlNewChild(neuralOutputsNode, 0, (const xmlChar*)"NeuralOutput", 0);
1483  ss.str(""); ss << outputNeuron;
1484  xmlNewProp(neuralOutputNode, (const xmlChar*)"outputNeuron", (const xmlChar*)(ss.str().c_str()) );
1485 
1486  xmlNodePtr derivedFieldNode = xmlNewChild(neuralOutputNode, 0, (const xmlChar*)"DerivedField", 0);
1487  xmlNewProp(derivedFieldNode, (const xmlChar*)"optype", (const xmlChar*)(optype.c_str()) );
1488  xmlNewProp(derivedFieldNode, (const xmlChar*)"dataType", (const xmlChar*)(dataType.c_str()) );
1489 
1490  xmlNodePtr normcontNode = xmlNewChild(derivedFieldNode, 0, (const xmlChar*)"NormContinuous", 0);
1491  xmlNewProp(normcontNode, (const xmlChar*)"field", (const xmlChar*)(outputName.c_str()) );
1492 
1493  xmlNodePtr node_linearnorm1 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1494  ss.str(""); ss << scientific << orig1;
1495  xmlNewProp(node_linearnorm1, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1496  ss.str(""); ss << scientific << norm1;
1497  xmlNewProp(node_linearnorm1, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1498  xmlNodePtr node_linearnorm2 = xmlNewChild(normcontNode, 0, (const xmlChar*)"LinearNorm", 0);
1499  ss.str(""); ss << scientific << orig2;
1500  xmlNewProp(node_linearnorm2, (const xmlChar*)"orig", (const xmlChar*)(ss.str().c_str()) );
1501  ss.str(""); ss << scientific << norm2;
1502  xmlNewProp(node_linearnorm2, (const xmlChar*)"norm", (const xmlChar*)(ss.str().c_str()) );
1503 }
1504 
1510 void PMMLlib::AddNeuralLayer(PMMLActivationFunction activationFunction)
1511 {
1512  CheckNeuralNetwork();
1513 
1514  string functionName;
1515  switch(activationFunction)
1516  {
1517  case kIDENTITY:
1518  functionName = "identity";
1519  break;
1520  case kTANH:
1521  functionName = "tanh";
1522  break;
1523  case kLOGISTIC:
1524  functionName = "logistic";
1525  break;
1526  }
1527  xmlNodePtr netNode = _currentModelNode;
1528  // Increment the number of layers
1529  string numberOfLayersStr = _getProp(_currentModelNode, string("numberOfLayers"));
1530  int numberOfLayers;
1531  istringstream( numberOfLayersStr ) >> numberOfLayers;
1532  numberOfLayers++;
1533  stringstream ss;
1534  ss << numberOfLayers;
1535  xmlSetProp(netNode, (const xmlChar*)"numberOfLayers", (const xmlChar*)(ss.str().c_str()) );
1536  // Add the neural layer node
1537  xmlNodePtr neuralLayerNode = xmlNewChild(netNode, 0, (const xmlChar*)"NeuralLayer", 0);
1538  xmlNewProp(neuralLayerNode, (const xmlChar*)"activationFunction", (const xmlChar*)(functionName.c_str()) );
1539  xmlNewProp(neuralLayerNode, (const xmlChar*)"numberOfNeurons", (const xmlChar*)"0" );
1540  // Save the current layer in the _currentNode attribute
1541  _currentNode = neuralLayerNode;
1542 }
1543 
1553 void PMMLlib::AddNeuron(int id,
1554  double bias,
1555  int conNb,
1556  int firstFrom,
1557  vector<double> weights)
1558 {
1559  CheckNeuralNetwork();
1560 
1561  stringstream ss;
1562 
1563  // increment the number of neurons
1564  string numberOfNeuronsStr = _getProp(_currentNode, string("numberOfNeurons"));
1565  int numberOfNeurons;
1566  istringstream( numberOfNeuronsStr ) >> numberOfNeurons;
1567  numberOfNeurons++;
1568  ss << numberOfNeurons;
1569  xmlSetProp(_currentNode, (const xmlChar*)"numberOfNeurons", (const xmlChar*)(ss.str().c_str()) );
1570 
1571  // append a neuron
1572  xmlNodePtr neuronNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"Neuron", 0);
1573  ss.str(""); ss << id;
1574  xmlNewProp(neuronNode, (const xmlChar*)"id", (const xmlChar*)(ss.str().c_str()) );
1575  ss.str(""); ss << scientific << bias;
1576  xmlNewProp(neuronNode, (const xmlChar*)"bias", (const xmlChar*)(ss.str().c_str()) );
1577 
1578  // append multiple 'Con' to the neuron
1579  for(int k=0 ; k<conNb ; k++)
1580  {
1581  xmlNodePtr conNode = xmlNewChild(neuronNode, 0, (const xmlChar*)"Con", 0);
1582  ss.str(""); ss << firstFrom+k;
1583  xmlNewProp(conNode, (const xmlChar*)"from", (const xmlChar*)(ss.str().c_str()) ); // !!! ce n'est pas k !!!
1584  ss.str(""); ss << scientific << weights[k];
1585  xmlNewProp(conNode, (const xmlChar*)"weight", (const xmlChar*)(ss.str().c_str()) );
1586  }
1587 }
1588 
1602 void PMMLlib::fillVectorsForExport(int nInput,
1603  int nOutput,
1604  int nHidden,
1605  int normType,
1606  vector<double> &minInput,
1607  vector<double> &maxInput,
1608  vector<double> &minOutput,
1609  vector<double> &maxOutput,
1610  vector<double> &valW )
1611 {
1612  CheckNeuralNetwork();
1613 
1614  xmlNodePtr netNode = _currentModelNode ;
1615  // Get the different values required
1616  // Build min/max input/output vectors
1617  for(int i=0 ; i<nInput ; i++)
1618  {
1619  xmlNodePtr node_inputs = GetChildByName(netNode,"NeuralInputs");
1620  node_inputs = node_inputs->children;
1621  for(int j = 0;j<i;j++)
1622  {
1623  node_inputs = node_inputs->next;
1624  }
1625  node_inputs = node_inputs->children; // DerivedField
1626  node_inputs = node_inputs->children; // NormContinuous
1627  node_inputs = node_inputs->children; // LinearNorm
1628  string strOrig1 = _getProp(node_inputs, string("orig") );
1629  double orig1 = atof( strOrig1.c_str() );
1630  string strNorm1 = _getProp(node_inputs, string("norm") );
1631  double norm1 = atof( strNorm1.c_str() );
1632  node_inputs = node_inputs->next;
1633  string strOrig2 = _getProp(node_inputs, string("orig") );
1634  double orig2 = atof( strOrig2.c_str() );
1635  string strNorm2 = _getProp(node_inputs, string("norm") );
1636  if( normType==0 )
1637  { // kMinusOneOne
1638  minInput[i] = orig1;
1639  maxInput[i] = orig2;
1640  }
1641  else
1642  { // kCR, kZeroOne
1643  minInput[i] = orig2;
1644  maxInput[i] = -1.0*norm1*orig2;
1645  }
1646  }
1647  xmlNodePtr node_outputs = GetChildByName(netNode,"NeuralOutputs");
1648  node_outputs = node_outputs->children;
1649  node_outputs = node_outputs->children; // DerivedField
1650  node_outputs = node_outputs->children; // NormContinuous
1651  node_outputs = node_outputs->children; // LinearNorm
1652  string strOrig1 = _getProp(node_outputs, string("orig") );
1653  double orig1 = atof( strOrig1.c_str() );
1654  string strNorm1 = _getProp(node_outputs, string("norm") );
1655  double norm1 = atof( strNorm1.c_str() );
1656  node_outputs = node_outputs->next;
1657  string strOrig2 = _getProp(node_outputs, string("orig") );
1658  double orig2 = atof( strOrig2.c_str() );
1659  if( normType==0 )
1660  { // kMinusOneOne
1661  minOutput[0] = orig1;
1662  maxOutput[0] = orig2;
1663  }
1664  else
1665  { // kCR, kZeroOne
1666  minOutput[0] = orig2;
1667  maxOutput[0] = -1.0*norm1*orig2;
1668  }
1669  // Build weight vector
1670  for(int j=0 ; j<nHidden ; j++) // hidden layers
1671  {
1672  valW[j*(nInput+nOutput+1)+2] = GetNeuronBias( 0, j);
1673  for(int i=0 ; i<nInput ; i++)
1674  {
1675  valW[j*(nInput+nOutput+1)+3+i] = GetPrecNeuronSynapse( 0, j, i);
1676  }
1677  }
1678  for(int j=0 ; j<nOutput ; j++) // output layers
1679  {
1680  valW[0] = GetNeuronBias( 1, j);
1681  for(int i=0 ; i<nHidden ; i++)
1682  {
1683  valW[i*(nInput+nOutput+1)+1] = GetPrecNeuronSynapse( 1, j, i);
1684  }
1685  }
1686 }
1687 
1695 void PMMLlib::ExportNeuralNetworkCpp(std::string file,
1696  std::string functionName,
1697  std::string header)
1698 {
1699  CheckNeuralNetwork();
1700 
1701  // Get the different values required
1702  int nInput = GetNbInputs();
1703  int nOutput = GetNbOutputs();
1704  int nHidden = GetNbNeuronsAtLayer(0);
1705  int nNeurons = nInput+nOutput+nHidden;
1706  int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
1707  int normType = GetNormalizationType();
1708  // Build min/max input/output vectors
1709  vector<double> minInput(nInput);
1710  vector<double> maxInput(nInput);
1711  vector<double> minOutput(nOutput);
1712  vector<double> maxOutput(nOutput);
1713  vector<double> valW(nWeights);
1714  fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
1715  // Write the file
1716  ofstream sourcefile(file.c_str());
1717  // ActivationFunction
1718  if( normType==0 )
1719  { // kMinusOneOne
1720  sourcefile << "#define ActivationFunction(sum) ( tanh(sum) )" << endl;
1721  }
1722  else
1723  { // kCR, kZeroOne
1724  sourcefile << "#define ActivationFunction(sum) ( 1.0 / ( 1.0 + exp( -1.0 * sum )) )" << endl;
1725  }
1726  //
1727  sourcefile << "void " << functionName <<"(double *param, double *res)" << endl;
1728  sourcefile << "{" << endl;
1729  // header
1730  sourcefile << " ////////////////////////////// " << endl;
1731  sourcefile << " //" << endl;
1732  // insert comments in header
1733  header = " // " + header;
1734  size_t pos = 0;
1735  while ((pos = header.find("\n", pos)) != std::string::npos)
1736  {
1737  header.replace(pos, 1, "\n //");
1738  pos += 5;
1739  }
1740  sourcefile << header << endl;
1741  sourcefile << " //" << endl;
1742  sourcefile << " ////////////////////////////// " << endl;
1743  sourcefile << endl;
1744  sourcefile << " int nInput = " << nInput << ";" << endl;
1745  sourcefile << " int nOutput = " << nOutput << ";" << endl;
1746  // sourcefile << " int nWeights = " << _nWeight << ";" << endl;
1747  sourcefile << " int nHidden = " << nHidden << ";" << endl;
1748  sourcefile << " const int nNeurones = " << nNeurons << ";" << endl;
1749  sourcefile << " double " << functionName << "_act[nNeurones];" << endl;
1750  sourcefile << endl;
1751  sourcefile << " // --- Preprocessing of the inputs and outputs" << endl;
1752  sourcefile << " double " << functionName << "_minInput[] = {" << endl << " ";
1753  for(int i=0 ; i<nInput ; i++)
1754  {
1755  sourcefile << minInput[i] << ", ";
1756  if( (i+1)%5==0 )
1757  sourcefile << "\n ";
1758  }
1759  if( nInput%5 != 0 )
1760  sourcefile << endl;
1761  sourcefile << " };" << endl;
1762  //
1763  sourcefile << " double " << functionName << "_minOutput[] = {" << endl << " ";
1764  sourcefile << minOutput[0] << ", ";
1765  sourcefile << " };" << endl;
1766  //
1767  sourcefile << " double " << functionName << "_maxInput[] = {" << endl << " ";
1768  for(int i=0 ; i<nInput ; i++)
1769  {
1770  sourcefile << maxInput[i] << ", ";
1771  if( (i+1)%5==0 )
1772  sourcefile << "\n ";
1773  }
1774  if( nInput%5 != 0 )
1775  sourcefile << endl;
1776  sourcefile << " };" << endl;
1777  //
1778  sourcefile << " double " << functionName << "_maxOutput[] = {" << endl << " ";
1779  sourcefile << maxOutput[0] << ", ";
1780  sourcefile << " };" << endl;
1781  // Weights vector
1782  sourcefile << endl;
1783  sourcefile << " // --- Values of the weights" << endl;
1784  sourcefile << " double " << functionName << "_valW[] = {" << endl << " ";
1785  for(int i=0 ; i<nWeights ; i++)
1786  {
1787  sourcefile << valW[i] << ", ";
1788  if ( (i+1)%5 == 0 )
1789  sourcefile << endl << " ";
1790  }
1791  sourcefile << endl << " };"<<endl;
1792  //
1793  sourcefile << " // --- Constants";
1794  sourcefile << endl;
1795  sourcefile << " int indNeurone = 0;"<<endl;
1796  sourcefile << " int CrtW;"<<endl;
1797  sourcefile << " double sum;"<<endl;
1798 
1799  // couche entree
1800  sourcefile << endl;
1801  sourcefile << " // --- Input Layers"<<endl;
1802  sourcefile << " for(int i = 0; i < nInput; i++) {"<<endl;
1803  if( normType==0 )
1804  { // kMinusOneOne
1805  sourcefile << " " << functionName << "_act[indNeurone++] = 2.0 * ( param[i] - "
1806  << functionName << "_minInput[i] ) / ( " << functionName << "_maxInput[i] - "
1807  << functionName << "_minInput[i] ) - 1.0;"<<endl;
1808  }
1809  else
1810  { // kCR, kZeroOne
1811  sourcefile << " " << functionName << "_act[indNeurone++] = ( param[i] - "
1812  << functionName << "_minInput[i] ) / " << functionName << "_maxInput[i];"
1813  << endl;
1814  }
1815  sourcefile << " }"<<endl;
1816 
1817 
1818  // couche cachee
1819  sourcefile << endl;
1820  sourcefile << " // --- Hidden Layers"<<endl;
1821  sourcefile << " for (int member = 0; member < nHidden; member++) {"<<endl;
1822  sourcefile << " int CrtW = member * ( nInput + 2) + 2;" << endl;
1823  sourcefile << " sum = " << functionName << "_valW[CrtW++];" << endl;
1824  sourcefile << " for (int source = 0; source < nInput; source++) {" << endl;
1825  sourcefile << " sum += " << functionName << "_act[source] * " << functionName << "_valW[CrtW++];" << endl;
1826  sourcefile << " }" << endl;
1827  sourcefile << " " << functionName << "_act[indNeurone++] = ActivationFunction(sum);" << endl;
1828  sourcefile << " }"<<endl;
1829  // couche sortie
1830  sourcefile << endl;
1831  sourcefile << " // --- Output"<<endl;
1832  sourcefile << " for (int member = 0; member < nOutput; member++) {"<<endl;
1833  sourcefile << " sum = " << functionName << "_valW[0];"<<endl;
1834  sourcefile << " for (int source = 0; source < nHidden; source++) {"<<endl;
1835  sourcefile << " CrtW = source * ( nInput + 2) + 1;"<<endl;
1836  sourcefile << " sum += " << functionName << "_act[nInput+source] * " << functionName << "_valW[CrtW];"<<endl;
1837  sourcefile << " }"<<endl;
1838  sourcefile << " " << functionName << "_act[indNeurone++] = sum;"<<endl;
1839  if( normType==0 )
1840  { // kMinusOneOne
1841  sourcefile << " res[member] = " << functionName
1842  << "_minOutput[member] + 0.5 * ( " << functionName
1843  << "_maxOutput[member] - " << functionName
1844  << "_minOutput[member] ) * ( sum + 1.0);" << endl;
1845  }
1846  else
1847  { // kCR, kZeroOne
1848  sourcefile << " res[member] = " << functionName
1849  << "_minOutput[member] + " << functionName
1850  << "_maxOutput[member] * sum;" << endl;
1851  }
1852  sourcefile << " }"<<endl;
1853  //
1854  sourcefile << "}" << endl;
1855  sourcefile.close();
1856 }
1857 
1865 void PMMLlib::ExportNeuralNetworkFortran(std::string file,
1866  std::string functionName,
1867  std::string header)
1868 {
1869  CheckNeuralNetwork();
1870 
1871  // Get the different values required
1872  int nInput = GetNbInputs();
1873  int nOutput = GetNbOutputs();
1874  int nHidden = GetNbNeuronsAtLayer(0);
1875  int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
1876  int normType = GetNormalizationType();
1877  // Build min/max input/output vectors
1878  vector<double> minInput(nInput);
1879  vector<double> maxInput(nInput);
1880  vector<double> minOutput(nOutput);
1881  vector<double> maxOutput(nOutput);
1882  vector<double> valW(nWeights);
1883  fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
1884  // Write the file
1885  ofstream sourcefile(file.c_str());
1886 
1887  sourcefile << " SUBROUTINE " << functionName << "(";
1888  for(int i=0 ; i<GetNbInputs() ; i++)
1889  {
1890  sourcefile << GetNameInput(i) << ",";
1891  }
1892  sourcefile << GetNameOutput(0) << ")" << endl;
1893  // header
1894  sourcefile << "C --- *********************************************" << endl;
1895  sourcefile << "C --- " << endl;
1896  // insert comments in header
1897  header = "C --- " + header;
1898  size_t pos = 0;
1899  while ((pos = header.find("\n", pos)) != std::string::npos)
1900  {
1901  header.replace(pos, 1, "\nC --- ");
1902  pos += 5;
1903  }
1904  sourcefile << header << endl;
1905  sourcefile << "C --- " << endl;
1906  sourcefile << "C --- *********************************************" << endl;
1907 
1908  sourcefile << " IMPLICIT DOUBLE PRECISION (V)" << endl;
1909  for(int i=0 ; i<GetNbInputs() ; i++)
1910  {
1911  sourcefile << " DOUBLE PRECISION " << GetNameInput(i) << endl;
1912  }
1913  sourcefile << " DOUBLE PRECISION " << GetNameOutput(0) << endl;
1914  sourcefile << endl;
1915 
1916  sourcefile << "C --- Preprocessing of the inputs" << endl;
1917  for(int i=0 ; i<GetNbInputs() ; i++)
1918  {
1919  sourcefile << " VXN" << GetNameInput(i) << " = ";
1920 
1921  if( normType==0 )
1922  { // kMinusOneOne
1923  sourcefile << "2.D0 * ( " << GetNameInput(i) << " - " << minInput[i] << "D0 ) / " << maxInput[i] - minInput[i] << "D0 - 1.0" << endl;
1924  }
1925  else
1926  { // kCR, kZeroOne
1927  sourcefile << "( " << GetNameInput(i) << " - " << minInput[i] << "D0 ) / " << maxInput[i] << "D0" << endl;
1928  }
1929  }
1930 
1931  // Weights vector
1932  sourcefile << endl;
1933  sourcefile << "C --- Values of the weights" << endl;
1934  for(int i=0 ; i<nWeights ; i++)
1935  {
1936  sourcefile << " VW" << i+1 << " = " << valW[i] << endl;
1937  }
1938  // Loop on hidden neurons
1939  sourcefile << endl;
1940  for(int member = 0; member < nHidden; member++)
1941  {
1942  sourcefile << "C --- hidden neural number " << member+1 << endl;
1943  int CrtW = member * ( nInput + 2) + 3;
1944  sourcefile << " VAct" << member+1 << " = VW" << CrtW++ << endl;
1945  for (int source = 0; source < nInput; source++)
1946  {
1947  sourcefile << " 1 + VW"<< CrtW++ << " * VXN" << GetNameInput(source) << endl;
1948  }
1949  sourcefile << endl;
1950 
1951 
1952  if( normType==0 )
1953  { // kMinusOneOne
1954  sourcefile << " VPot" << member+1 << " = 2.D0 / (1.D0 + DEXP(-2.D0 * VAct" << member+1 <<")) - 1.D0" << endl;
1955  }
1956  else
1957  { // kCR, kZeroOne
1958  sourcefile << " VPot" << member+1 << " = 1.D0 / (1.D0 + DEXP(-1.D0 * VAct" << member+1 <<"))" << endl;
1959  }
1960  sourcefile << endl;
1961  }
1962 
1963  // Ouput of the model
1964  sourcefile << "C --- Output" << endl;
1965  sourcefile << " VOut = VW1" << endl;
1966  for(int source=0 ; source < nHidden ; source++)
1967  {
1968  int CrtW = source * ( nInput + 2) + 2;
1969  sourcefile << " 1 + VW"<< CrtW << " * VPot" << source+1 << endl;
1970  }
1971 
1972  // Denormalize Output
1973  sourcefile << endl;
1974  sourcefile << "C --- Pretraitment of the output" << endl;
1975  if( normType==0 )
1976  { // kMinusOneOne
1977  sourcefile << " VDelta = " << 0.5*(maxOutput[0]-minOutput[0]) << "D0 * ( VOut + 1.0D0)" << endl;
1978  sourcefile << " " << GetNameOutput(0) << " = " << minOutput[0] << "D0 + VDelta" << endl;
1979 
1980  }
1981  else
1982  { // kCR, kZeroOne
1983  sourcefile << " " << GetNameOutput(0) << " = "<< minOutput[0] << "D0 + " << maxOutput[0] << "D0 * VOut;" << endl;
1984  }
1985 
1986  sourcefile << endl;
1987  sourcefile << "C --- " << endl;
1988  sourcefile << " RETURN" << endl;
1989  sourcefile << " END" << endl;
1990 
1991  sourcefile.close();
1992 }
1993 
2001 void PMMLlib::ExportNeuralNetworkPython(std::string file,
2002  std::string functionName,
2003  std::string header)
2004 {
2005  string str(ExportNeuralNetworkPyStr(functionName, header));
2006  // Write the file
2007  ofstream exportfile(file.c_str());
2008  exportfile << str;
2009  exportfile.close();
2010 }
2011 
2012 
2020 std::string PMMLlib::ExportNeuralNetworkPyStr(std::string functionName,
2021  std::string header)
2022 {
2023  CheckNeuralNetwork();
2024 
2025  ostringstream out;
2026 
2027  // Get the different values required
2028  int nInput = GetNbInputs();
2029  int nOutput = GetNbOutputs();
2030  int nHidden = GetNbNeuronsAtLayer(0);
2031  int nNeurons = nInput+nOutput+nHidden;
2032  int nWeights = nHidden*(nInput+nOutput+1)+nOutput;
2033  int normType = GetNormalizationType();
2034  // Build min/max input/output vectors
2035  vector<double> minInput(nInput);
2036  vector<double> maxInput(nInput);
2037  vector<double> minOutput(nOutput);
2038  vector<double> maxOutput(nOutput);
2039  vector<double> valW(nWeights);
2040  fillVectorsForExport(nInput,nOutput,nHidden,normType,minInput,maxInput,minOutput,maxOutput,valW);
2041 
2042  // Shebang et imports
2043  out << "#!/usr/bin/env python3" << endl;
2044  out << "# -*- coding: utf-8 -*-" << endl;
2045  out << endl;
2046  out << "from math import tanh, exp" << endl;
2047  out << endl;
2048 
2049  // ActivationFunction
2050  if( normType==0 )
2051  { // kMinusOneOne
2052  out << "def ActivationFunction(sum): " << endl;
2053  out << " return tanh(sum); " << endl;
2054  }
2055  else
2056  { // kCR, kZeroOne
2057  out << "def ActivationFunction(sum): " << endl;
2058  out << " return ( 1.0 / ( 1.0 + exp( -1.0 * sum ) ) ); " << endl;
2059  }
2060 
2061  out << endl;
2062  out << "def " << functionName <<"(param):" << endl;
2063  out << endl;
2064 
2065  // header
2066  out << " ############################## " << endl;
2067  out << " #" << endl;
2068  // insert comments in header
2069  header = " # " + header;
2070  size_t pos = 0;
2071  while ((pos = header.find("\n", pos)) != std::string::npos)
2072  {
2073  header.replace(pos, 1, "\n #");
2074  pos += 5;
2075  }
2076  out << header << endl;
2077  out << " #" << endl;
2078  out << " ############################## " << endl;
2079  out << endl;
2080 
2081  // Initialisations
2082  out << " nInput = " << nInput << ";" << endl;
2083  out << " nOutput = " << nOutput << ";" << endl;
2084  out << " nHidden = " << nHidden << ";" << endl;
2085  out << " nNeurones = " << nNeurons << ";" << endl;
2086  out << " " << functionName << "_act = [];" << endl;
2087  out << " res = [];" << endl;
2088  out << endl;
2089 
2090  out << " # --- Preprocessing of the inputs and outputs" << endl;
2091  out << " " << functionName << "_minInput = [" << endl << " ";
2092  out << " " ;
2093  for(int i=0 ; i<nInput ; i++)
2094  {
2095  out << minInput[i] << ", ";
2096  if( (i+1)%5==0 )
2097  {
2098  out << endl ;
2099  out << " " ;
2100  }
2101  }
2102  out << endl << " ];" << endl;
2103 
2104  out << " " << functionName << "_minOutput = [" << endl << " ";
2105  out << " " << minOutput[0] ;
2106  out << endl << " ];" << endl;
2107 
2108  out << " " << functionName << "_maxInput = [" << endl << " ";
2109  for(int i=0 ; i<nInput ; i++)
2110  {
2111  out << maxInput[i] << ", ";
2112  if( (i+1)%5==0 )
2113  {
2114  out << endl;
2115  out << " " ;
2116  }
2117  }
2118  out << endl << " ];" << endl;
2119 
2120  out << " " << functionName << "_maxOutput = [" << endl << " ";
2121  out << " " << maxOutput[0] ;
2122  out << endl << " ];" << endl;
2123 
2124  // Weights vector
2125  out << " # --- Values of the weights" << endl;
2126  out << " " << functionName << "_valW = [" << endl << " ";
2127  for(int i=0 ; i<nWeights ; i++)
2128  {
2129  out << valW[i] << ", ";
2130  if ( (i+1)%5 == 0 )
2131  {
2132  out << endl;
2133  out << " " ;
2134  }
2135  }
2136  out << endl << " ];"<<endl;
2137 
2138  out << " # --- Constants" << endl;
2139  out << " indNeurone = 0;" << endl;
2140  out << endl;
2141 
2142  // couche entree
2143  out << " # --- Input Layers" << endl;
2144  out << " for i in range(nInput) :" << endl;
2145  if( normType==0 )
2146  { // kMinusOneOne
2147  out << " " << functionName << "_act.append( 2.0 * ( param[i] - "
2148  << functionName << "_minInput[i] ) / ( " << functionName << "_maxInput[i] - "
2149  << functionName << "_minInput[i] ) - 1.0 ) ;"
2150  << endl;
2151  }
2152  else
2153  { // kCR, kZeroOne
2154  out << " " << functionName << "_act.append( ( param[i] - "
2155  << functionName << "_minInput[i] ) / " << functionName << "_maxInput[i] ) ;"
2156  << endl;
2157  }
2158  out << " indNeurone += 1 ;" << endl;
2159  out << " pass" << endl;
2160 
2161  // couche cachee
2162  out << endl;
2163  out << " # --- Hidden Layers" << endl;
2164  out << " for member in range(nHidden):" << endl;
2165  out << " CrtW = member * ( nInput + 2) + 2;" << endl;
2166  out << " sum = " << functionName << "_valW[CrtW];" << endl;
2167  out << " CrtW += 1 ;" << endl;
2168  out << " for source in range(nInput) :" << endl;
2169  out << " sum += " << functionName << "_act[source] * " << functionName << "_valW[CrtW];" << endl;
2170  out << " CrtW += 1 ;" << endl;
2171  out << " pass" << endl;
2172  out << " " << functionName << "_act.append( ActivationFunction(sum) ) ;" << endl;
2173  out << " indNeurone += 1 ;" << endl;
2174  out << " pass" << endl;
2175  out << endl;
2176 
2177  // couche sortie
2178  out << " # --- Output"<<endl;
2179  out << " for member in range(nOutput):" << endl;
2180  out << " sum = " << functionName << "_valW[0];" << endl;
2181  out << " for source in range(nHidden):" << endl;
2182  out << " CrtW = source * ( nInput + 2) + 1;"<<endl;
2183  out << " sum += " << functionName << "_act[nInput+source] * " << functionName << "_valW[CrtW];" << endl;
2184  out << " pass" << endl;
2185  out << " " << functionName << "_act.append( sum );" << endl;
2186  out << " indNeurone += 1 ;" << endl;
2187  if( normType==0 )
2188  { // kMinusOneOne
2189  out << " res[member] = " << functionName
2190  << "_minOutput[member] + 0.5 * ( " << functionName
2191  << "_maxOutput[member] - " << functionName
2192  << "_minOutput[member] ) * ( sum + 1.0);" << endl;
2193  }
2194  else
2195  { // kCR, kZeroOne
2196  out << " res.append( " << functionName
2197  << "_minOutput[member] + " << functionName
2198  << "_maxOutput[member] * sum );" << endl;
2199  }
2200  out << " pass" << endl;
2201  out << endl;
2202 
2203  // return result
2204  out << " return res;" << endl << endl;
2205  out << endl;
2206 
2207  return out.str();
2208 }
2209 
2210 //**************************************************************
2211 // *
2212 // *
2213 // *
2214 // méthodes propres au RegressionModel *
2215 // *
2216 // *
2217 // *
2218 //**************************************************************
2219 
2225 void PMMLlib::CheckRegression()
2226 {
2227  if ( _currentModelType != kLR )
2228  throw string("Use this method with Regression models.");
2229 }
2230 
2236 xmlNodePtr PMMLlib::GetRegressionPtr(std::string name)
2237 {
2238  return GetPtr(name, GetTypeString() );
2239 }
2240 
2248 void PMMLlib::AddRegressionModel(std::string modelName,
2249  PMMLMiningFunction functionName,
2250  std::string targetFieldName)
2251 {
2252  _currentModelType = kLR;
2253  _currentModelName = modelName;
2254  // Check regression after setting model type!
2255  CheckRegression();
2256 
2257  string function;
2258  switch(functionName)
2259  {
2260  case kREGRESSION:
2261  function = "regression";
2262  break;
2263  }
2264  xmlNodePtr netNode = xmlNewChild(_rootNode, 0, (const xmlChar*)"RegressionModel", 0);
2265  xmlNewProp(netNode, (const xmlChar*)"functionName", (const xmlChar*)(function.c_str()) );
2266  xmlNewProp(netNode, (const xmlChar*)"modelName", (const xmlChar*)(_currentModelName.c_str()) );
2267  xmlNewProp(netNode, (const xmlChar*)"targetFieldName", (const xmlChar*)(targetFieldName.c_str()) );
2268  _currentModelNode = netNode ;
2269 }
2270 
2276 void PMMLlib::AddRegressionTable()
2277 {
2278  CheckRegression();
2279  xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionModel", 0);
2280  _currentNode = tableNode;
2281 }
2282 
2288 void PMMLlib::AddRegressionTable(double intercept)
2289 {
2290  CheckRegression();
2291 
2292  stringstream ss;
2293  xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionTable", 0);
2294  if(intercept!=0.0)
2295  {
2296  ss << scientific << intercept;
2297  xmlNewProp(tableNode, (const xmlChar*)"intercept", (const xmlChar*)(ss.str().c_str()) );
2298  }
2299  _currentNode = tableNode;
2300 }
2301 
2309 void PMMLlib::AddNumericPredictor(std::string neuronName,
2310  int exponent,
2311  double coefficient)
2312 {
2313  CheckRegression();
2314  stringstream ss;
2315  xmlNodePtr numPrecNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"NumericPredictor", 0);
2316  xmlNewProp(numPrecNode, (const xmlChar*)"name", (const xmlChar*)(neuronName.c_str()) );
2317  ss.str(""); ss << exponent;
2318  xmlNewProp(numPrecNode, (const xmlChar*)"exponent", (const xmlChar*)(ss.str().c_str()) );
2319  ss.str(""); ss << scientific << coefficient;
2320  xmlNewProp(numPrecNode, (const xmlChar*)"coefficient", (const xmlChar*)(ss.str().c_str()) );
2321 }
2322 
2329 void PMMLlib::AddPredictorTerm(double coefficient,
2330  std::vector<std::string> fieldRef)
2331 {
2332  CheckRegression();
2333  stringstream ss;
2334  xmlNodePtr predTermNode = xmlNewChild(_currentNode, 0, (const xmlChar*)"PredictorTerm", 0);
2335  ss.str(""); ss << scientific << coefficient;
2336  xmlNewProp(predTermNode, (const xmlChar*)"coefficient", (const xmlChar*)(ss.str().c_str()) );
2337  vector<string>::iterator it;
2338  for(it=fieldRef.begin() ; it!=fieldRef.end() ; it++)
2339  {
2340  xmlNodePtr fieldRefNode = xmlNewChild(predTermNode, 0, (const xmlChar*)"FieldRef", 0);
2341  ss.str(""); ss << (*it);
2342  xmlNewProp(fieldRefNode, (const xmlChar*)"field", (const xmlChar*)(ss.str().c_str()) );
2343  }
2344 }
2345 
2351 bool PMMLlib::HasIntercept()
2352 {
2353  CheckRegression();
2354  bool b = false;
2355  xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2356  if ( tableNode == NULL )
2357  return b;
2358  xmlChar *xp = _stringToXmlChar("intercept");
2359  xmlChar * attr ;
2360  attr = xmlGetProp(tableNode, xp);
2361  if ( attr )
2362  {
2363  xmlFree(attr);
2364  xmlFree(xp);
2365  return true;
2366  }
2367  xmlFree(xp);
2368  return false;
2369 }
2370 
2376 double PMMLlib::GetRegressionTableIntercept()
2377 {
2378  CheckRegression();
2379  double reg = 0.;
2380  xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2381  if ( tableNode == NULL )
2382  return reg;
2383  string strValue = _getProp(tableNode, string("intercept") );
2384  return atof(strValue.c_str());
2385 }
2386 
2392 int PMMLlib::GetNumericPredictorNb()
2393 {
2394  CheckRegression();
2395 
2396  int nb=0;
2397  xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2398  if ( tableNode == NULL )
2399  return nb;
2400  xmlNodePtr numPredNodes = tableNode->children;
2401  while (numPredNodes != NULL )
2402  {
2403  if ( string((const char*)(numPredNodes->name)) == "NumericPredictor" )
2404  nb++;
2405  numPredNodes = numPredNodes->next;
2406  }
2407  return nb;
2408 }
2409 
2415 int PMMLlib::GetPredictorTermNb()
2416 {
2417  CheckRegression();
2418  int nb=0;
2419  xmlNodePtr tableNode = GetChildByName(_currentModelNode,"RegressionTable");
2420  if ( tableNode == NULL )
2421  return nb;
2422  xmlNodePtr numPredNodes = tableNode->children;
2423  while ( numPredNodes != NULL )
2424  {
2425  if ( string((const char*)(numPredNodes->name)) == "PredictorTerm" )
2426  nb++;
2427  numPredNodes = numPredNodes->next;
2428  }
2429  return nb;
2430 }
2431 
2438 std::string PMMLlib::GetNumericPredictorName(int num_pred_index)
2439 {
2440  CheckRegression();
2441  string strName("");
2442  xmlNodePtr numPredNodes = GetChildByName(_currentModelNode,"RegressionTable");
2443  if ( numPredNodes == NULL )
2444  return strName;
2445 
2446  numPredNodes = GetChildByName(numPredNodes,"NumericPredictor");
2447  if ( numPredNodes == NULL )
2448  return strName;
2449  // Positionnement sur la bonne sortie PredictorTerm
2450  for(int i=0;i<num_pred_index;i++)
2451  {
2452  numPredNodes = numPredNodes->next;
2453  if ( numPredNodes == NULL ||
2454  string((const char*)(numPredNodes->name)) != "NumericPredictor" )
2455  return strName;
2456  }
2457  strName = _getProp(numPredNodes, string("name"));
2458  return strName;
2459 }
2460 
2467 std::string PMMLlib::GetPredictorTermName(int pred_term_index)
2468 {
2469  CheckRegression();
2470  string strName("");
2471  xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2472  if ( fieldRefNodes == NULL )
2473  return strName;
2474 
2475  fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2476  if ( fieldRefNodes == NULL )
2477  return strName;
2478  // Positionnement sur la bonne sortie
2479  for(int i=0;i<pred_term_index;i++)
2480  {
2481  fieldRefNodes = fieldRefNodes->next;
2482  if ( fieldRefNodes == NULL ||
2483  string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2484  return strName;
2485  }
2486 
2487  fieldRefNodes = fieldRefNodes->children;
2488  while (fieldRefNodes != NULL)
2489  {
2490  strName += _getProp(fieldRefNodes, string("field"));
2491  fieldRefNodes = fieldRefNodes->next;
2492  }
2493  return strName;
2494 }
2495 
2503 double PMMLlib::GetNumericPredictorCoefficient(int num_pred_index)
2504 {
2505  CheckRegression();
2506 
2507  double coef = 0.;
2508  xmlNodePtr numPredNodes = GetChildByName(_currentModelNode,"RegressionTable");
2509  if ( numPredNodes == NULL )
2510  return coef;
2511  numPredNodes = GetChildByName(numPredNodes,"NumericPredictor");
2512  if ( numPredNodes == NULL )
2513  return coef;
2514  // Positionnement sur la bonne sortie
2515  for(int i=0;i<num_pred_index;i++)
2516  {
2517  numPredNodes = numPredNodes->next;
2518  if ( numPredNodes == NULL ||
2519  string((const char*)(numPredNodes->name)) != "NumericPredictor" )
2520  return coef;
2521  }
2522  string strValue = _getProp(numPredNodes, string("coefficient"));
2523  coef = atof(strValue.c_str());
2524  return coef;
2525 }
2526 
2534 double PMMLlib::GetPredictorTermCoefficient(int pred_term_index)
2535 {
2536  CheckRegression();
2537 
2538  double coef = 0.;
2539  xmlNodePtr predTermNodes = GetChildByName(_currentModelNode,"RegressionTable");
2540  if ( predTermNodes == NULL )
2541  return coef;
2542  predTermNodes = GetChildByName(predTermNodes,"PredictorTerm");
2543  if ( predTermNodes == NULL )
2544  return coef;
2545  // Positionnement sur la bonne sortie
2546  for(int i=0;i<pred_term_index;i++)
2547  {
2548  predTermNodes = predTermNodes->next;
2549  if ( predTermNodes == NULL ||
2550  string((const char*)(predTermNodes->name)) != "PredictorTerm" )
2551  return coef;
2552  }
2553  string strValue = _getProp(predTermNodes, string("coefficient"));
2554  coef = atof(strValue.c_str());
2555  return coef;
2556 }
2557 
2564 int PMMLlib::GetPredictorTermFieldRefNb(int index)
2565 {
2566  CheckRegression();
2567 
2568  int nb=0;
2569  xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2570  if ( fieldRefNodes == NULL )
2571  return nb;
2572  fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2573  if ( fieldRefNodes == NULL )
2574  return nb;
2575  // Positionnement sur la bonne sortie
2576  for(int i=0;i<index;i++)
2577  {
2578  fieldRefNodes = fieldRefNodes->next;
2579  if ( fieldRefNodes == NULL ||
2580  string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2581  return nb;
2582  }
2583  fieldRefNodes = fieldRefNodes->children;
2584  while (fieldRefNodes != NULL)
2585  {
2586  nb++;
2587  fieldRefNodes = fieldRefNodes->next;
2588  }
2589  return nb;
2590 }
2591 
2600 std::string PMMLlib::GetPredictorTermFieldRefName(int pred_term_index, int field_index)
2601 {
2602  CheckRegression();
2603 
2604  string strName("");
2605  xmlNodePtr fieldRefNodes = GetChildByName(_currentModelNode,"RegressionTable");
2606  if ( fieldRefNodes == NULL )
2607  return strName;
2608  fieldRefNodes = GetChildByName(fieldRefNodes,"PredictorTerm");
2609  if ( fieldRefNodes == NULL )
2610  return strName;
2611  // Positionnement sur la bonne sortie PredictorTerm
2612  for(int i=0;i<pred_term_index;i++)
2613  {
2614  fieldRefNodes = fieldRefNodes->next;
2615  if ( fieldRefNodes == NULL ||
2616  string((const char*)(fieldRefNodes->name)) != "PredictorTerm" )
2617  return strName;
2618  }
2619  fieldRefNodes = fieldRefNodes->children;
2620  if ( fieldRefNodes == NULL )
2621  return strName;
2622  // Positionnement sur la bonne sortie FieldRef
2623  for(int i=0;i<field_index;i++)
2624  {
2625  fieldRefNodes = fieldRefNodes->next;
2626  if ( fieldRefNodes == NULL )
2627  return strName;
2628  }
2629  strName = _getProp(fieldRefNodes, string("field"));
2630  return strName;
2631 }
2632 
2640 void PMMLlib::ExportLinearRegressionCpp(std::string file,
2641  std::string functionName,
2642  std::string header)
2643 {
2644  CheckRegression();
2645 
2646  // Write the file
2647  ofstream exportfile(file.c_str());
2648 
2649  exportfile << "void " << functionName <<"(double *param, double *res)" << endl;
2650  exportfile << "{" << endl;
2651  // header
2652  exportfile << " ////////////////////////////// " << endl;
2653  exportfile << " //" << endl;
2654  // insert comments in header
2655  header = " // " + header;
2656  size_t pos = 0;
2657  while ((pos = header.find("\n", pos)) != std::string::npos)
2658  {
2659  header.replace(pos, 1, "\n //");
2660  pos += 5;
2661  }
2662  exportfile << header << endl;
2663  exportfile << " //" << endl;
2664  exportfile << " ////////////////////////////// " << endl << endl;
2665 
2666  double intercept = 0.0;
2667  if ( HasIntercept() )
2668  {
2669  exportfile << " // Intercept"<< endl;
2670  intercept = GetRegressionTableIntercept();
2671  }
2672  else
2673  exportfile << " // No Intercept"<< endl;
2674  exportfile << " double y = " << intercept << ";";
2675  exportfile << endl << endl;
2676 
2677  int nPred = GetNumericPredictorNb();
2678  for (int i=0; i<nPred; i++)
2679  {
2680  exportfile << " // Attribute : " << GetNumericPredictorName(i) << endl;
2681  exportfile << " y += param["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2682  exportfile << endl << endl;
2683  }
2684  nPred = GetPredictorTermNb();
2685  for (int i=0; i<nPred; i++)
2686  {
2687  exportfile << " // Attribute : " << GetPredictorTermName(i) << endl;
2688  exportfile << " y += param["<<(i+nPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2689  exportfile << endl << endl;
2690  }
2691 
2692  exportfile << " // Return the value"<< endl;
2693  exportfile << " res[0] = y;" << endl;
2694  exportfile << "}" << endl;
2695  exportfile.close();
2696 }
2697 
2705 void PMMLlib::ExportLinearRegressionFortran(std::string file,
2706  std::string functionName,
2707  std::string header)
2708 {
2709  CheckRegression();
2710 
2711  int nNumPred = GetNumericPredictorNb();
2712  int nPredTerm = GetPredictorTermNb();
2713  vector<string>strParam(nNumPred+nPredTerm);
2714  for(int i=0; i<(nNumPred+nPredTerm); i++)
2715  {
2716  strParam[i] = "P" + NumberToString(i) ;
2717  }
2718 
2719  // Write the file
2720  ofstream exportfile(file.c_str());
2721 
2722  exportfile << " SUBROUTINE " << functionName <<"(";
2723  for(int i=0; i<(nNumPred+nPredTerm); i++)
2724  {
2725  exportfile << strParam[i] << ", ";
2726  }
2727  exportfile << "RES)" << endl;
2728 
2729  // header
2730  exportfile << "C --- *********************************************" << endl;
2731  exportfile << "C --- " << endl;
2732  // insert comments in header
2733  header = "C --- " + header;
2734  size_t pos = 0;
2735  while ((pos = header.find("\n", pos)) != std::string::npos)
2736  {
2737  header.replace(pos, 1, "\nC --- ");
2738  pos += 5;
2739  }
2740  exportfile << header << endl;
2741  exportfile << "C --- " << endl;
2742  exportfile << "C --- *********************************************" << endl << endl;
2743 
2744  exportfile << " IMPLICIT DOUBLE PRECISION (P)" << endl;
2745  exportfile << " DOUBLE PRECISION RES" << endl;
2746  exportfile << " DOUBLE PRECISION Y" << endl;
2747  exportfile << endl;
2748 
2749  double intercept = 0.0;
2750  if ( HasIntercept() )
2751  {
2752  exportfile << "C --- Intercept"<< endl;
2753  intercept = GetRegressionTableIntercept();
2754  }
2755  else
2756  exportfile << "C --- No Intercept"<< endl;
2757  exportfile << " Y = " << intercept << ";";
2758  exportfile << endl << endl;
2759 
2760  for (int i=0; i<nNumPred; i++)
2761  {
2762  exportfile << "C --- Attribute : " << GetNumericPredictorName(i) << endl;
2763  exportfile << " Y += P["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2764  exportfile << endl << endl;
2765  }
2766 
2767  for (int i=0; i<nPredTerm; i++)
2768  {
2769  exportfile << "C --- Attribute : " << GetPredictorTermName(i) << endl;
2770  exportfile << " Y += P["<<(i+nNumPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2771  exportfile << endl << endl;
2772  }
2773 
2774  exportfile << "C --- Return the value"<< endl;
2775  exportfile << " RES = Y " << endl;
2776  exportfile << " RETURN" << endl;
2777  exportfile << " END" << endl;
2778  exportfile.close();
2779 }
2780 
2788 void PMMLlib::ExportLinearRegressionPython(std::string file,
2789  std::string functionName,
2790  std::string header)
2791 {
2792  string str(ExportLinearRegressionPyStr(functionName, header));
2793  // Write the file
2794  ofstream exportfile(file.c_str());
2795  exportfile << str;
2796  exportfile.close();
2797 }
2798 
2805 std::string PMMLlib::ExportLinearRegressionPyStr(std::string functionName,
2806  std::string header)
2807 {
2808  CheckRegression();
2809 
2810  ostringstream out;
2811 
2812  // Shebang et imports
2813  out << "#!/usr/bin/env python3" << endl;
2814  out << "# -*- coding: utf-8 -*-" << endl;
2815  out << endl;
2816 
2817  // Function
2818  out << "def " << functionName <<"(param):" << endl;
2819  out << endl;
2820 
2821  // header
2822  out << " ############################## " << endl;
2823  out << " # " << endl;
2824  // insert comments in header
2825  header = " # " + header;
2826  size_t pos = 0;
2827  while ((pos = header.find("\n", pos)) != std::string::npos)
2828  {
2829  header.replace(pos, 1, "\n #");
2830  pos += 5;
2831  }
2832  out << header << endl;
2833  out << " # " << endl;
2834  out << " ############################## " << endl << endl;
2835 
2836  double intercept = 0.0;
2837  if ( HasIntercept() )
2838  {
2839  out << " # Intercept"<< endl;
2840  intercept = GetRegressionTableIntercept();
2841  }
2842  else
2843  out << " # No Intercept"<< endl;
2844  out << " y = " << intercept << ";";
2845  out << endl << endl;
2846 
2847  int nPred = GetNumericPredictorNb();
2848  for (int i=0; i<nPred; i++)
2849  {
2850  out << " # Attribute : " << GetNumericPredictorName(i) << endl;
2851  out << " y += param["<<i<<"]*" << GetNumericPredictorCoefficient(i) << ";";
2852  out << endl << endl;
2853  }
2854  nPred = GetPredictorTermNb();
2855  for (int i=0; i<nPred; i++)
2856  {
2857  out << " # Attribute : " << GetPredictorTermName(i) << endl;
2858  out << " y += param["<<(i+nPred)<<"]*" << GetPredictorTermCoefficient(i) << ";";
2859  out << endl << endl;
2860  }
2861 
2862  out << " # Return the value"<< endl;
2863  out << " return [y];" << endl;
2864 
2865  return out.str() ;
2866 }
2867 
2873 std::string PMMLlib::ReadRegressionStructure()
2874 {
2875  CheckRegression();
2876 
2877  string structure("");
2878  string structureActive("");
2879  string structurePredicted("@");
2880  int nPred = 0;
2881  xmlNodePtr mNode = GetChildByName(_currentModelNode,"MiningSchema");
2882  if ( mNode != NULL )
2883  {
2884  xmlNodePtr dNode = GetChildByName(mNode,"MiningField");
2885  while (dNode != NULL)
2886  {
2887  string name = _getProp(dNode, string("name"));
2888  string usage = _getProp(dNode, string("usageType"));
2889  if ( usage == "active" )
2890  {
2891  structureActive += name;
2892  structureActive += ":";
2893  }
2894  else if ( usage == "predicted" )
2895  {
2896  structurePredicted += name;
2897  structurePredicted += ":";
2898  nPred++;
2899  }
2900  dNode = dNode->next;
2901  }
2902  // Delete the last ":"
2903  if ( structureActive.length() > 0 )
2904  structureActive.erase(structureActive.size()-1);
2905  structurePredicted.erase(structurePredicted.size()-1);
2906  }
2907  std::ostringstream oss;
2908  oss << nPred;
2909  structure = structureActive + "," + oss.str() + "," + structurePredicted;
2910  return structure;
2911 }
2912 
2913 } // end of namespace
2914 
2915 
Header de la classe PMMLlib.
@ kANN
Definition: PMMLlib.hxx:54
@ kUNDEFINED
Definition: PMMLlib.hxx:54
PMMLMiningFunction
Definition: PMMLlib.hxx:66
@ kREGRESSION
Definition: PMMLlib.hxx:66
PMMLActivationFunction
Definition: PMMLlib.hxx:60
@ kIDENTITY
Definition: PMMLlib.hxx:60
@ kTANH
Definition: PMMLlib.hxx:60
@ kLOGISTIC
Definition: PMMLlib.hxx:60
std::string NumberToString(T Number)
Definition: PMMLlib.hxx:39
string log
Definition: logview.py:23