source: orange/source/orange/libsvm_interface.cpp @ 10389:8d7ba785b51c

Revision 10389:8d7ba785b51c, 22.8 KB checked in by Ales Erjavec <ales.erjavec@…>, 2 years ago (diff)

Removed redundant slist includes

Line 
1/*
2    This file is part of Orange.
3
4    Copyright 1996-2011 Faculty of Computer and Information Science, University of Ljubljana
5    Contact: janez.demsar@fri.uni-lj.si
6
7    Orange is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11
12    Orange is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Orange.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include <iostream>
22#include <sstream>
23
24#include "libsvm_interface.ppp"
25
26// Defined in svm.cpp. If new svm or kernel types are added this should be updated.
27
28static const char *svm_type_table[] =
29{
30    "c_svc","nu_svc","one_class","epsilon_svr","nu_svr",NULL
31};
32
33static const char *kernel_type_table[]=
34{
35    "linear","polynomial","rbf","sigmoid","precomputed",NULL
36};
37
38#define Malloc(type,n) (type *)malloc((n)*sizeof(type))
39
40/*
41 * Save load functions for use with orange pickling.
42 * They are a copy of the standard libSVM save-load functions
43 * except that they read/write from/to std::iostream objects.
44 */
45
46int svm_save_model_alt(std::ostream& stream, const svm_model *model){
47    const svm_parameter& param = model->param;
48    stream.precision(17);
49
50    stream << "svm_type " << svm_type_table[param.svm_type] << endl;
51    stream << "kernel_type " << kernel_type_table[param.kernel_type] << endl;
52
53    if(param.kernel_type == POLY)
54        stream << "degree " << param.degree << endl;
55
56    if(param.kernel_type == POLY || param.kernel_type == RBF || param.kernel_type == SIGMOID)
57        stream << "gamma " << param.gamma << endl;
58
59    if(param.kernel_type == POLY || param.kernel_type == SIGMOID)
60        stream << "coef0 " << param.coef0 << endl;
61
62    int nr_class = model->nr_class;
63    int l = model->l;
64    stream << "nr_class " << nr_class << endl;
65    stream << "total_sv " << l << endl;
66    {
67        stream << "rho";
68        for(int i=0;i<nr_class*(nr_class-1)/2;i++)
69            stream << " " << model->rho[i];
70        stream << endl;
71    }
72
73    if(model->label)
74    {
75        stream << "label";
76        for(int i=0;i<nr_class;i++)
77            stream << " " << model->label[i];
78        stream << endl;
79    }
80
81    if(model->probA) // regression has probA only
82    {
83        stream << "probA";
84        for(int i=0;i<nr_class*(nr_class-1)/2;i++)
85            stream << " " << model->probA[i];
86        stream << endl;
87    }
88    if(model->probB)
89    {
90        stream << "probB";
91        for(int i=0;i<nr_class*(nr_class-1)/2;i++)
92            stream << " " << model->probB[i];
93        stream << endl;
94    }
95
96    if(model->nSV)
97    {
98        stream << "nr_sv";
99        for(int i=0;i<nr_class;i++)
100            stream << " " << model->nSV[i];
101        stream << endl;
102    }
103
104    stream << "SV" << endl;
105    const double * const *sv_coef = model->sv_coef;
106    const svm_node * const *SV = model->SV;
107
108    for(int i=0;i<l;i++)
109    {
110        for(int j=0;j<nr_class-1;j++)
111            stream << sv_coef[j][i] << " ";
112
113        const svm_node *p = SV[i];
114
115        if(param.kernel_type == PRECOMPUTED)
116            stream << "0:" << (int)(p->value) << " ";
117        else
118            while(p->index != -1)
119            {
120                stream << (int)(p->index) << ":" << p->value << " ";
121                p++;
122            }
123        stream << endl;
124    }
125
126    if (!stream.fail())
127        return 0;
128    else
129        return 1;
130}
131
132int svm_save_model_alt(std::string& buffer, const svm_model *model){
133    std::ostringstream strstream;
134    int ret = svm_save_model_alt(strstream, model);
135    buffer = strstream.rdbuf()->str();
136    return ret;
137}
138
139
140#include <algorithm>
141
142svm_model *svm_load_model_alt(std::istream& stream)
143{
144    svm_model *model = Malloc(svm_model,1);
145    svm_parameter& param = model->param;
146    model->rho = NULL;
147    model->probA = NULL;
148    model->probB = NULL;
149    model->label = NULL;
150    model->nSV = NULL;
151
152    char cmd[81];
153    stream.width(80);
154    while (stream.good())
155    {
156        stream >> cmd;
157
158        if(strcmp(cmd, "svm_type") == 0)
159        {
160            stream >> cmd;
161            int i;
162            for(i=0; svm_type_table[i]; i++)
163            {
164                if(strcmp(cmd, svm_type_table[i]) == 0)
165                {
166                    param.svm_type=i;
167                    break;
168                }
169            }
170            if(svm_type_table[i] == NULL)
171            {
172                fprintf(stderr, "unknown svm type.\n");
173                free(model->rho);
174                free(model->label);
175                free(model->nSV);
176                free(model);
177                return NULL;
178            }
179        }
180        else if(strcmp(cmd, "kernel_type") == 0)
181        {
182            stream >> cmd;
183            int i;
184            for(i=0;kernel_type_table[i];i++)
185            {
186                if(strcmp(kernel_type_table[i], cmd)==0)
187                {
188                    param.kernel_type=i;
189                    break;
190                }
191            }
192            if(kernel_type_table[i] == NULL)
193            {
194                fprintf(stderr,"unknown kernel function.\n");
195                free(model->rho);
196                free(model->label);
197                free(model->nSV);
198                free(model);
199                return NULL;
200            }
201        }
202        else if(strcmp(cmd,"degree")==0)
203            stream >> param.degree;
204        else if(strcmp(cmd,"gamma")==0)
205            stream >> param.gamma;
206        else if(strcmp(cmd,"coef0")==0)
207            stream >> param.coef0;
208        else if(strcmp(cmd,"nr_class")==0)
209            stream >> model->nr_class;
210        else if(strcmp(cmd,"total_sv")==0)
211            stream >> model->l;
212        else if(strcmp(cmd,"rho")==0)
213        {
214            int n = model->nr_class * (model->nr_class-1)/2;
215            model->rho = Malloc(double,n);
216            string rho_str;
217            for(int i=0;i<n;i++){
218                // Read the number into a string and then use strtod
219                // for proper handling of NaN's
220                stream >> rho_str;
221                model->rho[i] = strtod(rho_str.c_str(), NULL);
222            }
223        }
224        else if(strcmp(cmd,"label")==0)
225        {
226            int n = model->nr_class;
227            model->label = Malloc(int,n);
228            for(int i=0;i<n;i++)
229                stream >> model->label[i];
230        }
231        else if(strcmp(cmd,"probA")==0)
232        {
233            int n = model->nr_class * (model->nr_class-1)/2;
234            model->probA = Malloc(double,n);
235            for(int i=0;i<n;i++)
236                stream >> model->probA[i];
237        }
238        else if(strcmp(cmd,"probB")==0)
239        {
240            int n = model->nr_class * (model->nr_class-1)/2;
241            model->probB = Malloc(double,n);
242            for(int i=0;i<n;i++)
243                stream >> model->probB[i];
244        }
245        else if(strcmp(cmd,"nr_sv")==0)
246        {
247            int n = model->nr_class;
248            model->nSV = Malloc(int,n);
249            for(int i=0;i<n;i++)
250                stream >> model->nSV[i];
251        }
252        else if(strcmp(cmd,"SV")==0)
253        {
254            while(1)
255            {
256                int c = stream.get();
257                if(stream.eof() || c=='\n') break;
258            }
259            break;
260        }
261        else
262        {
263            fprintf(stderr,"unknown text in model file: [%s]\n",cmd);
264            free(model->rho);
265            free(model->label);
266            free(model->nSV);
267            free(model);
268            return NULL;
269        }
270    }
271    if (stream.fail()){
272        free(model->rho);
273        free(model->label);
274        free(model->nSV);
275        free(model);
276        return NULL;
277
278    }
279
280    // read sv_coef and SV
281
282    int elements = 0;
283    long pos = stream.tellg();
284
285    char *p,*endptr,*idx,*val;
286    string str_line;
287    while (!stream.eof() && !stream.fail())
288    {
289        getline(stream, str_line);
290        elements += std::count(str_line.begin(), str_line.end(), ':');
291    }
292
293    elements += model->l;
294
295    stream.clear();
296    stream.seekg(pos, ios::beg);
297
298    int m = model->nr_class - 1;
299    int l = model->l;
300    model->sv_coef = Malloc(double *,m);
301    int i;
302    for(i=0;i<m;i++)
303        model->sv_coef[i] = Malloc(double,l);
304    model->SV = Malloc(svm_node*,l);
305    svm_node *x_space = NULL;
306    if(l>0) x_space = Malloc(svm_node,elements);
307
308    int j=0;
309    char *line;
310    for(i=0;i<l;i++)
311    {
312        getline(stream, str_line);
313        if (str_line.size() == 0)
314            continue;
315
316        line = (char *) Malloc(char, str_line.size() + 1);
317        // Copy the line for strtok.
318        strcpy(line, str_line.c_str());
319
320        model->SV[i] = &x_space[j];
321
322        p = strtok(line, " \t");
323        model->sv_coef[0][i] = strtod(p,&endptr);
324        for(int k=1;k<m;k++)
325        {
326            p = strtok(NULL, " \t");
327            model->sv_coef[k][i] = strtod(p,&endptr);
328        }
329
330        while(1)
331        {
332            idx = strtok(NULL, ":");
333            val = strtok(NULL, " \t");
334
335            if(val == NULL)
336                break;
337            x_space[j].index = (int) strtol(idx,&endptr,10);
338            x_space[j].value = strtod(val,&endptr);
339
340            ++j;
341        }
342        x_space[j++].index = -1;
343        free(line);
344    }
345
346    if (stream.fail())
347        return NULL;
348
349    model->free_sv = 1; // XXX
350    return model;
351}
352
353svm_model *svm_load_model_alt(std::string& stream)
354{
355    std::istringstream strstream(stream);
356    return svm_load_model_alt(strstream);
357}
358
359svm_node* example_to_svm(const TExample &ex, svm_node* node, float last=0.0, int type=0){
360    if(type==0){
361        int index=1;
362        for(TExample::iterator i=ex.begin(); i!=ex.end(); i++){
363            if(i->isRegular() && i!=&ex.getClass()){
364                if(i->varType==TValue::FLOATVAR)
365                    node->value=float(*i);
366                else
367                    node->value=int(*i);
368                node->index=index++;
369                if(node->value==numeric_limits<float>::signaling_NaN() ||
370                    node->value==numeric_limits<int>::max())
371                    node--;
372                node++;
373            }
374        }
375    }
376    if(type == 1){ /*one dummy attr so we can pickle the classifier and keep the SV index in the training table*/
377        node->index=1;
378        node->value=last;
379        node++;
380    }
381    //cout<<(node-1)->index<<endl<<(node-2)->index<<endl;
382    node->index=-1;
383    node->value=last;
384    node++;
385    return node;
386}
387
388class SVM_NodeSort{
389public:
390    bool operator() (const svm_node &lhs, const svm_node &rhs){
391        return lhs.index < rhs.index;
392    }
393};
394
395svm_node* example_to_svm_sparse(const TExample &ex, svm_node* node, float last=0.0, bool useNonMeta=false){
396    svm_node *first=node;
397    int j=1;
398    int index=1;
399    if(useNonMeta)
400        for(TExample::iterator i=ex.begin(); i!=ex.end(); i++){
401            if(i->isRegular() && i!=&ex.getClass()){
402                if(i->varType==TValue::FLOATVAR)
403                    node->value=float(*i);
404                else
405                    node->value=int(*i);
406                node->index=index;
407                if(node->value==numeric_limits<float>::signaling_NaN() ||
408                    node->value==numeric_limits<int>::max())
409                    node--;
410                node++;
411            }
412            index++;
413        }
414    for(TMetaValues::const_iterator i=ex.meta.begin(); i!=ex.meta.end();i++,j++){
415        if(i->second.isRegular()){
416            if(i->second.varType==TValue::FLOATVAR)
417                node->value=float(i->second);
418            else
419                node->value=int(i->second);
420            node->index=index-i->first;
421            if(node->value==numeric_limits<float>::signaling_NaN() ||
422                node->value==numeric_limits<int>::max())
423                node--;
424            node++;
425        }
426    }
427    sort(first, node, SVM_NodeSort());
428    //cout<<first->index<<endl<<(first+1)->index<<endl;
429    node->index=-1;
430    node->value=last;
431    node++;
432    return node;
433}
434
435/*
436 * Precompute Gram matrix row for ex.
437 * Used for prediction when using the PRECOMPUTED kernel.
438 */
439svm_node* example_to_svm_precomputed(const TExample &ex, PExampleGenerator examples, PKernelFunc kernel, svm_node* node){
440    node->index = 0;
441    node->value = 0.0;
442    node++;
443    int k = 0;
444    PEITERATE(iter, examples){
445        node->index = ++k;
446        node->value = kernel.getReference()(*iter, ex);
447        node++;
448    }
449    node->index = -1; // sentry
450    node++;
451    return node;
452}
453
454int getNumOfElements(const TExample &ex, bool meta=false, bool useNonMeta=false){
455    if(!meta)
456        return std::max(ex.domain->attributes->size()+1, 2);
457    else{
458        int count=1; //we need one to indicate the end of a sequence
459        if(useNonMeta)
460            count+=ex.domain->attributes->size();
461        for(TMetaValues::const_iterator i=ex.meta.begin(); i!=ex.meta.end();i++)
462            if(i->second.isRegular())
463                count++;
464        return std::max(count,2);
465    }
466}
467
468int getNumOfElements(PExampleGenerator &examples, bool meta=false, bool useNonMeta=false){
469    if(!meta)
470        return getNumOfElements(*(examples->begin()), meta)*examples->numberOfExamples();
471    else{
472        int count=0;
473        for(TExampleGenerator::iterator ex(examples->begin()); ex!=examples->end(); ++ex){
474            count+=getNumOfElements(*ex, meta, useNonMeta);
475        }
476        return count;
477    }
478}
479
480#include "symmatrix.hpp"
481svm_node* init_precomputed_problem(svm_problem &problem, PExampleTable examples, TKernelFunc &kernel){
482    int n_examples = examples->numberOfExamples();
483    int i,j;
484    PSymMatrix matrix = mlnew TSymMatrix(n_examples, 0.0);
485    for (i = 0; i < n_examples; i++)
486        for (j = 0; j <= i; j++){
487            matrix->getref(i, j) = kernel(examples->at(i), examples->at(j));
488//          cout << i << " " << j << " " << matrix->getitem(i, j) << endl;
489        }
490    svm_node *x_space = Malloc(svm_node, n_examples * (n_examples + 2));
491    svm_node *node = x_space;
492
493    problem.l = n_examples;
494    problem.x = Malloc(svm_node*, n_examples);
495    problem.y = Malloc(double, n_examples);
496
497    for (i = 0; i < n_examples; i++){
498        problem.x[i] = node;
499        if (examples->domain->classVar->varType == TValue::FLOATVAR)
500            problem.y[i] = examples->at(i).getClass().floatV;
501        else
502            problem.y[i] = examples->at(i).getClass().intV;
503
504        node->index = 0;
505        node->value = i + 1; // instance indices are 1 based
506        node++;
507        for (j = 0; j < n_examples; j++){
508            node->index = j + 1;
509            node->value = matrix->getitem(i, j);
510            node++;
511        }
512        node->index = -1; // sentry
513        node++;
514    }
515    return x_space;
516}
517
518static void print_string_null(const char* s) {}
519
520TSVMLearner::TSVMLearner(){
521    //sparse=false; //if this learners supports sparse datasets (set to true in TSMVLearnerSparse subclass)
522    svm_type = NU_SVC;
523    kernel_type = RBF;
524    degree = 3;
525    gamma = 0;
526    coef0 = 0;
527    nu = 0.5;
528    cache_size = 250;
529    C = 1;
530    eps = 1e-3f;
531    p = 0.1f;
532    shrinking = 1;
533    probability = 0;
534    verbose = false;
535    nr_weight = 0;
536    weight_label = NULL;
537    weight = NULL;
538};
539
540PClassifier TSVMLearner::operator ()(PExampleGenerator examples, const int&){
541    svm_parameter param;
542    svm_problem prob;
543    svm_model* model;
544    svm_node* x_space;
545
546//  PExampleTable table = dynamic_cast<TExampleTable *>(examples.getUnwrappedPtr());
547
548    param.svm_type = svm_type;
549    param.kernel_type = kernel_type;
550    param.degree = degree;
551    param.gamma = gamma;
552    param.coef0 = coef0;
553    param.nu = nu;
554    param.C = C;
555    param.eps = eps;
556    param.p = p;
557    param.cache_size=cache_size;
558    param.shrinking=shrinking;
559    param.probability=probability;
560    param.nr_weight = nr_weight;
561    if (nr_weight > 0) {
562        param.weight_label = Malloc(int, nr_weight);
563        param.weight = Malloc(double, nr_weight);
564        int i;
565        for (i=0; i<nr_weight; i++) {
566            param.weight_label[i] = weight_label[i];
567            param.weight[i] = weight[i];
568        }
569    } else {
570        param.weight_label = NULL;
571        param.weight = NULL;
572    }
573
574    int classVarType;
575    if(examples->domain->classVar)
576        classVarType=examples->domain->classVar->varType;
577    else{
578        classVarType=TValue::NONE;
579        if(svm_type!=ONE_CLASS)
580            raiseError("Domain has no class variable");
581    }
582    if(classVarType==TValue::FLOATVAR && !(svm_type==EPSILON_SVR || svm_type==NU_SVR ||svm_type==ONE_CLASS))
583        raiseError("Domain has continuous class");
584
585    if(kernel_type==PRECOMPUTED && !kernelFunc)
586        raiseError("Custom kernel function not supplied");
587
588    int numElements=getNumOfElements(examples);
589
590    if(kernel_type != PRECOMPUTED)
591        x_space = init_problem(prob, examples, numElements);
592    else // Compute the matrix using the kernelFunc
593        x_space = init_precomputed_problem(prob, examples, kernelFunc.getReference());
594
595    if(param.gamma==0)
596        param.gamma=1.0f/(float(numElements)/float(prob.l)-1);
597
598    const char* error=svm_check_parameter(&prob,&param);
599    if(error){
600        free(x_space);
601        free(prob.y);
602        free(prob.x);
603        raiseError("LibSVM parameter error: %s", error);
604    }
605
606//  svm_print_string = (verbose)? &print_string_stdout : &print_string_null;
607
608    // If a probability model was requested LibSVM uses 5 fold
609    // cross-validation to estimate the prediction errors. This includes a
610    // random shuffle of the data. To make the results reproducible and
611    // consistent with 'svm-train' (which always learns just on one dataset
612    // in a process run) we reset the random seed. This could have unintended
613    // consequences.
614    if (param.probability)
615    {
616        srand(1);
617    }
618    svm_set_print_string_function((verbose)? NULL : &print_string_null);
619    model=svm_train(&prob,&param);
620
621  if ((svm_type==C_SVC || svm_type==NU_SVC) && !model->nSV) {
622    svm_free_and_destroy_model(&model);
623    if (x_space)
624      free(x_space);
625      raiseError("LibSVM returned no support vectors");
626  }
627
628    //cout<<"end training"<<endl;
629    svm_destroy_param(&param);
630    free(prob.y);
631    free(prob.x);
632//  tempExamples=NULL;
633    return PClassifier(createClassifier((param.svm_type==ONE_CLASS)?  \
634        mlnew TFloatVariable("one class") : examples->domain->classVar, examples, model, x_space));
635}
636
637svm_node* TSVMLearner::example_to_svm(const TExample &ex, svm_node* node, float last, int type){
638    return ::example_to_svm(ex, node, last, type);
639}
640
641svm_node* TSVMLearner::init_problem(svm_problem &problem, PExampleTable examples, int n_elements){
642    problem.l = examples->numberOfExamples();
643    problem.y = Malloc(double ,problem.l);
644    problem.x = Malloc(svm_node*, problem.l);
645    svm_node *x_space = Malloc(svm_node, n_elements);
646    svm_node *node = x_space;
647
648    for (int i = 0; i < problem.l; i++){
649        problem.x[i] = node;
650        node = example_to_svm(examples->at(i), node, i);
651        if (examples->domain->classVar)
652            if (examples->domain->classVar->varType == TValue::FLOATVAR)
653                problem.y[i] = examples->at(i).getClass().floatV;
654            else if (examples->domain->classVar->varType == TValue::INTVAR)
655                problem.y[i] = examples->at(i).getClass().intV;
656    }
657    return x_space;
658}
659
660int TSVMLearner::getNumOfElements(PExampleGenerator examples){
661    return ::getNumOfElements(examples);
662}
663
664TSVMClassifier* TSVMLearner::createClassifier(PVariable var, PExampleTable ex, svm_model* model, svm_node* x_space){
665    return mlnew TSVMClassifier(var, ex, model, x_space, kernelFunc);
666}
667
668TSVMLearner::~TSVMLearner(){
669    if(weight_label)
670        free(weight_label);
671
672    if(weight)
673            free(weight);
674}
675
676svm_node* TSVMLearnerSparse::example_to_svm(const TExample &ex, svm_node* node, float last, int type){
677    return ::example_to_svm_sparse(ex, node, last, useNonMeta);
678}
679
680int TSVMLearnerSparse::getNumOfElements(PExampleGenerator examples){
681    return ::getNumOfElements(examples, true, useNonMeta);
682}
683
684TSVMClassifier* TSVMLearnerSparse::createClassifier(PVariable var, PExampleTable ex, svm_model* model, svm_node *x_space){
685    return mlnew TSVMClassifierSparse(var, ex, model, x_space, useNonMeta, kernelFunc);
686}
687
688TSVMClassifier::TSVMClassifier(const PVariable &var, PExampleTable examples, svm_model* model, svm_node* x_space, PKernelFunc kernelFunc){
689    this->classVar = var;
690    this->model = model;
691    this->x_space = x_space;
692    this->examples = examples;
693    domain = examples->domain;
694    svm_type = svm_get_svm_type(model);
695    kernel_type = model->param.kernel_type;
696    this->kernelFunc = kernelFunc;
697
698    computesProbabilities = model && svm_check_probability_model(model) && \
699            (svm_type != NU_SVR && svm_type != EPSILON_SVR); // Disable prob. estimation for regression
700
701    int nr_class = svm_get_nr_class(model);
702    int i = 0;
703    supportVectors = mlnew TExampleTable(examples->domain);
704    if(x_space){
705        for(i = 0;i < model->l; i++){
706            svm_node *node = model->SV[i];
707            int sv_index = 0;
708            if(model->param.kernel_type != PRECOMPUTED){
709                // The value of the last node (with index == -1) holds the index of the training example.
710                while(node->index != -1)
711                    node++;
712                sv_index = int(node->value);
713            }
714            else
715                sv_index = int(node->value) - 1; // The indices for precomputed kernels are 1 based.
716            supportVectors->addExample(mlnew TExample(examples->at(sv_index)));
717        }
718    }
719   
720    if (svm_type == C_SVC || svm_type == NU_SVC){
721        nSV = mlnew TIntList(nr_class); // num of SVs for each class (sum = model->l)
722        for(i = 0;i < nr_class; i++)
723            nSV->at(i) = model->nSV[i];
724    }
725
726    coef = mlnew TFloatListList(nr_class-1);
727    for(i = 0; i < nr_class - 1; i++){
728        TFloatList *coefs = mlnew TFloatList(model->l);
729        for(int j = 0;j < model->l; j++)
730            coefs->at(j) = model->sv_coef[i][j];
731        coef->at(i)=coefs;
732    }
733    rho = mlnew TFloatList(nr_class*(nr_class-1)/2);
734    for(i = 0; i < nr_class*(nr_class-1)/2; i++)
735        rho->at(i) = model->rho[i];
736    if(model->probA){
737        probA = mlnew TFloatList(nr_class*(nr_class-1)/2);
738        if (model->param.svm_type != NU_SVR && model->param.svm_type != EPSILON_SVR && model->probB) // Regression has only probA
739            probB = mlnew TFloatList(nr_class*(nr_class-1)/2);
740        for(i=0; i<nr_class*(nr_class-1)/2; i++){
741            probA->at(i) = model->probA[i];
742            if (model->param.svm_type != NU_SVR && model->param.svm_type != EPSILON_SVR && model->probB)
743                probB->at(i) = model->probB[i];
744        }
745    }
746}
747
748TSVMClassifier::~TSVMClassifier(){
749    if (model)
750        svm_free_and_destroy_model(&model);
751    if(x_space)
752        free(x_space);
753}
754
755PDistribution TSVMClassifier::classDistribution(const TExample & example){
756    if(!model)
757        raiseError("No Model");
758
759    if(!computesProbabilities)
760        return TClassifierFD::classDistribution(example);
761
762    int n_elements;
763    if (model->param.kernel_type != PRECOMPUTED)
764        n_elements = getNumOfElements(example);
765    else
766        n_elements = examples->numberOfExamples() + 2;
767
768    int svm_type = svm_get_svm_type(model);
769    int nr_class = svm_get_nr_class(model);
770
771    svm_node *x = Malloc(svm_node, n_elements);
772    try{
773        if (model->param.kernel_type != PRECOMPUTED)
774            example_to_svm(example, x, -1.0);
775        else
776            example_to_svm_precomputed(example, examples, kernelFunc, x);
777    } catch (...) {
778        free(x);
779        throw;
780    }
781
782    int *labels=(int *) malloc(nr_class*sizeof(int));
783    svm_get_labels(model, labels);
784
785    double *prob_estimates = (double *) malloc(nr_class*sizeof(double));;
786    svm_predict_probability(model, x, prob_estimates);
787
788    PDistribution dist = TDistribution::create(example.domain->classVar);
789    for(int i=0; i<nr_class; i++)
790        dist->setint(labels[i], prob_estimates[i]);
791    free(x);
792    free(prob_estimates);
793    free(labels);
794    return dist;
795}
796
797TValue TSVMClassifier::operator()(const TExample & example){
798    if(!model)
799        raiseError("No Model");
800
801    int n_elements;
802    if (model->param.kernel_type != PRECOMPUTED)
803        n_elements = getNumOfElements(example); //example.domain->attributes->size();
804    else
805        n_elements = examples->numberOfExamples() + 2;
806
807    int svm_type = svm_get_svm_type(model);
808    int nr_class = svm_get_nr_class(model);
809
810    svm_node *x = Malloc(svm_node, n_elements);
811    try {
812        if (model->param.kernel_type != PRECOMPUTED)
813            example_to_svm(example, x);
814        else
815            example_to_svm_precomputed(example, examples, kernelFunc, x);
816    } catch (...) {
817        free(x);
818        throw;
819    }
820
821    double v;
822
823    if(svm_check_probability_model(model)){
824        double *prob = (double *) malloc(nr_class*sizeof(double));
825        v = svm_predict_probability(model, x, prob);
826        free(prob);
827    } else
828        v = svm_predict(model, x);
829
830    free(x);
831    if(svm_type==NU_SVR || svm_type==EPSILON_SVR || svm_type==ONE_CLASS)
832        return TValue(v);
833    else
834        return TValue(int(v));
835}
836
837PFloatList TSVMClassifier::getDecisionValues(const TExample &example){
838    if(!model)
839        raiseError("No Model");
840
841    int n_elements;
842        if (model->param.kernel_type != PRECOMPUTED)
843            n_elements = getNumOfElements(example); //example.domain->attributes->size();
844        else
845            n_elements = examples->numberOfExamples() + 2;
846
847    int svm_type=svm_get_svm_type(model);
848    int nr_class=svm_get_nr_class(model);
849
850    svm_node *x = Malloc(svm_node, n_elements);
851    try {
852        if (model->param.kernel_type != PRECOMPUTED)
853            example_to_svm(example, x);
854        else
855            example_to_svm_precomputed(example, examples, kernelFunc, x);
856    } catch (...) {
857        free(x);
858        throw;
859    }
860
861    int nDecValues = nr_class*(nr_class-1)/2;
862    double *dec = (double*) malloc(sizeof(double)*nDecValues);
863    svm_predict_values(model, x, dec);
864    PFloatList res = mlnew TFloatList(nDecValues);
865    for(int i=0; i<nDecValues; i++){
866        res->at(i) = dec[i];
867    }
868    free(x);
869    free(dec);
870    return res;
871}
872
873svm_node *TSVMClassifier::example_to_svm(const TExample &ex, svm_node *node, float last, int type){
874    return ::example_to_svm(ex, node, last, type);
875}
876
877int TSVMClassifier::getNumOfElements(const TExample& example){
878    return ::getNumOfElements(example);
879}
880svm_node *TSVMClassifierSparse::example_to_svm(const TExample &ex, svm_node *node, float last, int type){
881    return ::example_to_svm_sparse(ex, node, last, useNonMeta);
882}
883
884int TSVMClassifierSparse::getNumOfElements(const TExample& example){
885    return ::getNumOfElements(example, true, useNonMeta);
886}
887
888
Note: See TracBrowser for help on using the repository browser.