Ignore:
Timestamp:
07/01/13 16:24:25 (10 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Changed TSVMClassifier constructor interface.

It no longer requires "examples" table unless using a custom kernel
and no longer keeps the training "x_space" array (the passed svm_model
needs to 'own' the *(model->SV) array).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • source/orange/libsvm_interface.cpp

    r10389 r11606  
    357357} 
    358358 
     359 
     360/* 
     361 * Return a formated string representing a svm data instance (svm_node *) 
     362 * (useful for debugging) 
     363 */ 
     364string svm_node_to_string(svm_node * node) { 
     365    std::ostringstream strstream; 
     366    strstream.precision(17); 
     367    while (node->index != -1) { 
     368        strstream << node->index << ":" << node->value << " "; 
     369        node++; 
     370    } 
     371    strstream << node->index << ":" << node->value << " "; 
     372    return strstream.rdbuf()->str(); 
     373} 
     374 
     375 
    359376svm_node* example_to_svm(const TExample &ex, svm_node* node, float last=0.0, int type=0){ 
    360377    if(type==0){ 
     
    418435            else 
    419436                node->value=int(i->second); 
    420             node->index=index-i->first; 
     437            node->index = index - i->first; 
     438 
    421439            if(node->value==numeric_limits<float>::signaling_NaN() || 
    422440                node->value==numeric_limits<int>::max()) 
     
    439457svm_node* example_to_svm_precomputed(const TExample &ex, PExampleGenerator examples, PKernelFunc kernel, svm_node* node){ 
    440458    node->index = 0; 
    441     node->value = 0.0; 
     459    node->value = 0.0; // Can be any value. 
    442460    node++; 
    443461    int k = 0; 
     
    516534} 
    517535 
     536/* 
     537 * Extract an ExampleTable corresponding to the support vectors from the 
     538 * trained model. 
     539 */ 
     540PExampleTable extract_support_vectors(svm_model * model, PExampleTable train_instances) 
     541{ 
     542    PExampleTable vectors = mlnew TExampleTable(train_instances->domain); 
     543 
     544    for (int i = 0; i < model->l; i++) { 
     545        svm_node *node = model->SV[i]; 
     546        int sv_index = -1; 
     547        if(model->param.kernel_type != PRECOMPUTED){ 
     548            /* The value of the last node (with index == -1) holds the 
     549             * index of the training example. 
     550             */ 
     551            while(node->index != -1) { 
     552                node++; 
     553            } 
     554            sv_index = int(node->value); 
     555        } else { 
     556            /* The value of the first node contains the training instance 
     557             * index (indices 1 based). 
     558             */ 
     559            sv_index = int(node->value) - 1; 
     560        } 
     561        vectors->addExample(mlnew TExample(train_instances->at(sv_index))); 
     562    } 
     563 
     564    return vectors; 
     565} 
     566 
     567 
     568/* 
     569 * Consolidate model->SV[1] .. SV[l] vectors into a single contiguous 
     570 * memory block. The model will 'own' the new *(model->SV) array and 
     571 * will be freed in destroy_svm_model (model->free_sv == 1). Note that 
     572 * the original 'x_space' is left intact, it is the caller's 
     573 * responsibility to free it. However the model->SV array itself is 
     574 * reused (overwritten). 
     575 */ 
     576 
     577void svm_model_consolidate_SV(svm_model * model) { 
     578    int count = 0; 
     579    svm_node * x_space = NULL; 
     580    svm_node * ptr = NULL; 
     581    svm_node * ptr_source = NULL; 
     582 
     583    // Count the number of elements. 
     584    for (int i = 0; i < model->l; i++) { 
     585        ptr = model->SV[i]; 
     586        while (ptr->index != -1){ 
     587            count++; 
     588            ptr++; 
     589        } 
     590    } 
     591    // add the sentinel count 
     592    count += model->l; 
     593 
     594    x_space = Malloc(svm_node, count); 
     595    ptr = x_space; 
     596    for (int i = 0; i < model->l; i++) { 
     597        ptr_source = model->SV[i]; 
     598        model->SV[i] = ptr; 
     599        while (ptr_source->index != -1) { 
     600            *(ptr++) = *(ptr_source++); 
     601        } 
     602        // copy the sentinel 
     603        *(ptr++) = *(ptr_source++); 
     604    } 
     605    model->free_sv = 1; // XXX 
     606} 
     607 
    518608static void print_string_null(const char* s) {} 
    519609 
     610 
    520611TSVMLearner::TSVMLearner(){ 
    521     //sparse=false; //if this learners supports sparse datasets (set to true in TSMVLearnerSparse subclass) 
    522612    svm_type = NU_SVC; 
    523613    kernel_type = RBF; 
     
    538628}; 
    539629 
     630 
    540631PClassifier TSVMLearner::operator ()(PExampleGenerator examples, const int&){ 
    541632    svm_parameter param; 
     
    543634    svm_model* model; 
    544635    svm_node* x_space; 
    545  
    546 //  PExampleTable table = dynamic_cast<TExampleTable *>(examples.getUnwrappedPtr()); 
    547636 
    548637    param.svm_type = svm_type; 
     
    559648    param.probability=probability; 
    560649    param.nr_weight = nr_weight; 
     650 
    561651    if (nr_weight > 0) { 
    562652        param.weight_label = Malloc(int, nr_weight); 
     
    603693        raiseError("LibSVM parameter error: %s", error); 
    604694    } 
    605  
    606 //  svm_print_string = (verbose)? &print_string_stdout : &print_string_null; 
    607695 
    608696    // If a probability model was requested LibSVM uses 5 fold 
     
    617705    } 
    618706    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; 
     707 
     708    model = svm_train(&prob, &param); 
     709 
     710    if ((svm_type==C_SVC || svm_type==NU_SVC) && !model->nSV) { 
     711        svm_free_and_destroy_model(&model); 
     712        if (x_space) { 
     713            free(x_space); 
     714        } 
     715        raiseError("LibSVM returned no support vectors"); 
     716    } 
     717 
    629718    svm_destroy_param(&param); 
    630719    free(prob.y); 
    631720    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)); 
     721 
     722    // Consolidate the SV so x_space can be safely freed 
     723    svm_model_consolidate_SV(model); 
     724 
     725    free(x_space); 
     726 
     727    PExampleTable supportVectors = extract_support_vectors(model, examples); 
     728 
     729    PVariable classVar; 
     730 
     731    if (param.svm_type == ONE_CLASS) { 
     732        classVar = mlnew TFloatVariable("one class"); 
     733    } else { 
     734        classVar = examples->domain->classVar; 
     735    } 
     736 
     737    return PClassifier(createClassifier(classVar, examples, supportVectors, model)); 
    635738} 
    636739 
     
    662765} 
    663766 
    664 TSVMClassifier* TSVMLearner::createClassifier(PVariable var, PExampleTable ex, svm_model* model, svm_node* x_space){ 
    665     return mlnew TSVMClassifier(var, ex, model, x_space, kernelFunc); 
     767TSVMClassifier* TSVMLearner::createClassifier( 
     768        PVariable classVar, PExampleTable examples, PExampleTable supportVectors, svm_model* model) { 
     769    if (kernel_type != PRECOMPUTED) { 
     770        examples = NULL; 
     771    } 
     772    return mlnew TSVMClassifier(classVar, examples, supportVectors, model, kernelFunc); 
    666773} 
    667774 
     
    682789} 
    683790 
    684 TSVMClassifier* 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  
    688 TSVMClassifier::TSVMClassifier(const PVariable &var, PExampleTable examples, svm_model* model, svm_node* x_space, PKernelFunc kernelFunc){ 
     791TSVMClassifier* TSVMLearnerSparse::createClassifier( 
     792        PVariable classVar, PExampleTable examples, PExampleTable supportVectors, svm_model* model) { 
     793    if (kernel_type != PRECOMPUTED) { 
     794        examples = NULL; 
     795    } 
     796    return mlnew TSVMClassifierSparse(classVar, examples, supportVectors, model, useNonMeta, kernelFunc); 
     797} 
     798 
     799 
     800TSVMClassifier::TSVMClassifier( 
     801        const PVariable &var, 
     802        PExampleTable examples, 
     803        PExampleTable supportVectors, 
     804        svm_model* model, 
     805        PKernelFunc kernelFunc) { 
    689806    this->classVar = var; 
     807    this->examples = examples; 
     808    this->supportVectors = supportVectors; 
    690809    this->model = model; 
    691     this->x_space = x_space; 
    692     this->examples = examples; 
    693     domain = examples->domain; 
     810    this->kernelFunc = kernelFunc; 
     811 
     812    domain = supportVectors->domain; 
    694813    svm_type = svm_get_svm_type(model); 
    695814    kernel_type = model->param.kernel_type; 
    696     this->kernelFunc = kernelFunc; 
    697815 
    698816    computesProbabilities = model && svm_check_probability_model(model) && \ 
     
    701819    int nr_class = svm_get_nr_class(model); 
    702820    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      
     821 
     822    /* Expose (copy) the model data (coef, rho, probA) to public 
     823     * class interface. 
     824     */ 
    720825    if (svm_type == C_SVC || svm_type == NU_SVC){ 
    721826        nSV = mlnew TIntList(nr_class); // num of SVs for each class (sum = model->l) 
     
    747852 
    748853TSVMClassifier::~TSVMClassifier(){ 
    749     if (model) 
     854    if (model) { 
    750855        svm_free_and_destroy_model(&model); 
    751     if(x_space) 
    752         free(x_space); 
     856    } 
    753857} 
    754858 
     
    801905    int n_elements; 
    802906    if (model->param.kernel_type != PRECOMPUTED) 
    803         n_elements = getNumOfElements(example); //example.domain->attributes->size(); 
     907        n_elements = getNumOfElements(example); 
    804908    else 
    805909        n_elements = examples->numberOfExamples() + 2; 
     
    840944 
    841945    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; 
     946    if (model->param.kernel_type != PRECOMPUTED) 
     947        n_elements = getNumOfElements(example); 
     948    else 
     949        n_elements = examples->numberOfExamples() + 2; 
    846950 
    847951    int svm_type=svm_get_svm_type(model); 
     
    878982    return ::getNumOfElements(example); 
    879983} 
    880 svm_node *TSVMClassifierSparse::example_to_svm(const TExample &ex, svm_node *node, float last, int type){ 
     984svm_node *TSVMClassifierSparse::example_to_svm(const TExample &ex, svm_node *node, float last, int){ 
    881985    return ::example_to_svm_sparse(ex, node, last, useNonMeta); 
    882986} 
Note: See TracChangeset for help on using the changeset viewer.