Version: 9.16.0
PMMLlib.cxx
Go to the documentation of this file.
1// Copyright (C) 2013-2026 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
37using namespace std;
38
39namespace PMMLlib
40{
41
42//**************************************************************
43// *
44// *
45// *
46// méthodes communes à tous les types de modèles *
47// *
48// *
49// *
50//**************************************************************
51
57PMMLlib::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
110PMMLlib::~PMMLlib()
111{
112 if (_doc)
113 xmlFreeDoc(_doc);
114 xmlCleanupParser();
115 if ( _log )
116 cout << "~PMMLlib" << endl;
117}
118
124void 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
150void 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
183void 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
213std::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
226void PMMLlib::printLog() const
227{
228 string log = makeLog();
229 cout << log << endl;
230}
231
238void 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
263void 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
286void 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
310xmlNodePtr 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
341void 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
354int 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
375int 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
396int PMMLlib::GetModelsNb()
397{
398 return _nbModels;
399}
400
406std::string PMMLlib::GetModelName(xmlNodePtr node)
407{
408 string name("");
409 name = _getProp(node, string("modelName") );
410 return name;
411}
412
419xmlNodePtr 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
445xmlNodePtr 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
473std::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
496PMMLType 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
514std::string PMMLlib::GetCurrentModelName()
515{
516 if ( ! _currentModelNode )
517 return string("");
518 string name = _getProp(_currentModelNode, string("modelName"));
519 return name;
520}
521
525void PMMLlib::UnlinkNode()
526{
527 xmlNodePtr ptr = _currentModelNode ;
528 xmlUnlinkNode( ptr );
529 xmlFreeNode( ptr );
530}
531
535void 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
564void 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
576void 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
596void 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
616void 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
634void 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
653std::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
669std::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
683xmlChar * PMMLlib::_stringToXmlChar(const std::string &s) const
684{
685 return xmlCharStrdup(s.c_str());
686}
687
694std::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
728void PMMLlib::CheckNeuralNetwork()
729{
730 if ( _currentModelType != kANN )
731 throw string("Use this method with NeuralNetwork models.");
732}
733
739xmlNodePtr PMMLlib::GetNeuralNetPtr(int index)
740{
741 return GetPtr(index, GetTypeString() );
742}
743
749xmlNodePtr PMMLlib::GetNeuralNetPtr(std::string name)
750{
751 return GetPtr(name, GetTypeString() );
752}
753
759std::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
847int 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
871int 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
897std::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
936std::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
971int 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
1016void 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
1076void 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
1137int 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
1160int PMMLlib::GetNbLayers()
1161{
1162 return (GetNbHiddenLayers() + 2);
1163}
1164
1170int 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
1204double 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
1241double 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
1286void 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
1317void 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
1359void 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
1394void 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
1455void 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
1510void 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
1553void 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
1602void 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
1695void 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
1865void 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
2001void 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
2020std::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
2225void PMMLlib::CheckRegression()
2226{
2227 if ( _currentModelType != kLR )
2228 throw string("Use this method with Regression models.");
2229}
2230
2236xmlNodePtr PMMLlib::GetRegressionPtr(std::string name)
2237{
2238 return GetPtr(name, GetTypeString() );
2239}
2240
2248void 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
2276void PMMLlib::AddRegressionTable()
2277{
2278 CheckRegression();
2279 xmlNodePtr tableNode = xmlNewChild(_currentModelNode, 0, (const xmlChar*)"RegressionModel", 0);
2280 _currentNode = tableNode;
2281}
2282
2288void 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
2309void 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
2329void 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
2351bool 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
2376double 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
2392int 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
2415int 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
2438std::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
2467std::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
2503double 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
2534double 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
2564int 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
2600std::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
2640void 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
2705void 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
2788void 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
2805std::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
2873std::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