【问题标题】:getting primal form from CvSVM trained file从 CvSVM 训练的文件中获取原始形式
【发布时间】:2014-09-29 07:20:26
【问题描述】:

我正在尝试基于 HOG 特征训练我自己的检测器,并使用 opencv 的 CvSVM 实用程序训练了一个检测器。现在要在 HOGDescriptor.SetSVM(myDetector) 中使用此检测器,我需要以行向量(原始)形式获取经过训练的检测器来馈送。为此,我使用this 代码。我的实现如下所示:

vector<float>primal;

void LinearSVM::getSupportVector(std::vector<float>& support_vector)  {

    CvSVM svm;
    svm.load("Classifier.xml");
    cin.get();
    int sv_count = svm.get_support_vector_count();
    const CvSVMDecisionFunc* df = decision_func;
    const double* alphas = df[0].alpha;
    double rho = df[0].rho;
    int var_count = svm.get_var_count();
    support_vector.resize(var_count, 0);
    for (unsigned int r = 0; r < (unsigned)sv_count; r++) {
      float myalpha = alphas[r];
      const float* v = svm.get_support_vector(r);
      for (int j = 0; j < var_count; j++,v++) {
        support_vector[j] += (-myalpha) * (*v);
      }
    }
    support_vector.push_back(rho);
}

int main()
{

    LinearSVM s;
    s.getSupportVector(primal);

    return 0;
}

当我使用内置 CvSVM 时,它显示 SV 为 3,因为我保存的文件中只有 3 个 SV,但由于 decision_func 处于保护模式,因此我无法访问它。这就是为什么我尝试使用该包装器但仍然没有用。也许你们可以在这里帮助我...非常感谢!

【问题讨论】:

    标签: opencv svm


    【解决方案1】:

    再次您好 :) 请扩展 cvsm 类而不是封装它,因为您需要访问受保护的成员。

    //header
    class mySVM : public CvSVM
    {
    
    public:
        vector<float>
        getWeightVector(const int descriptorSize);
    };
    
    //cpp
    vector<float>
    mySVM::getWeightVector(const int descriptorSize)
    {
        vector<float> svmWeightsVec(descriptorSize+1);
        int numSupportVectors = get_support_vector_count();
    
        //this is protected, but can access due to inheritance rules 
        const CvSVMDecisionFunc *dec = CvSVM::decision_func;
    
        const float *supportVector;
        float* svmWeight = &svmWeightsVec[0];
    
        for (int i = 0; i < numSupportVectors; ++i)
        {
            float alpha = *(dec[0].alpha + i);
            supportVector = get_support_vector(i);
            for(int j=0;j<descriptorSize;j++)
            {
                *(svmWeight + j) += alpha * *(supportVector+j);
            }
        }
        *(svmWeight + descriptorSize) = - dec[0].rho;
    
        return svmWeightsVec;
    }
    

    类似的东西。

    学分: Obtaining weights in CvSVM, the SVM implementation of OpenCV

    【讨论】:

    • 嗨。我不知道为什么,但我收到一个错误,即头文件和源文件声明不兼容。我从标题中复制了函数名称并在源中复制但仍然错误。另一个问题是在 params_ 说“标识符 params_ 未识别”
    • 是的,它是给你一个想法,现在应该是复制和粘贴给你
    • 好的。但我在第一个循环中遇到错误,即 float alpha = *(dec[0].alpha+1);我不明白原因。请耐心等待我....
    • 您是否训练了 mySVM?如果不是,您将需要将复制/移动构造器添加到将 CvSVm 转换为 mySVM。我这么说是因为我预计 dec 是空的,因为你没有训练它。
    • 我不这么认为,因为当我 "cout
    【解决方案2】:

    使用测试工具来回答。我输入了新的答案,因为它会给原始答案增加混乱,可能会让人有点混乱。

    //dummy features
    std:: vector<float> 
    dummyDerReaderForOneDer(const vector<float> &pattern)
    {
        int i = std::rand() % pattern.size();
        int j = std::rand() % pattern.size();
        vector<float> patternPulNoise(pattern);
        std::random_shuffle(patternPulNoise.begin()+std::min(i,j),patternPulNoise.begin()+std::max(i,j));
        return patternPulNoise;
    };
    
    //extend CvSVM to get access to weights
    class mySVM : public CvSVM
    {
    public:
        vector<float>
        getWeightVector(const int descriptorSize);
    };
    
    //get the weights
    vector<float>
    mySVM::getWeightVector(const int descriptorSize)
    {
        vector<float> svmWeightsVec(descriptorSize+1);
        int numSupportVectors = get_support_vector_count();
    
        //this is protected, but can access due to inheritance rules 
        const CvSVMDecisionFunc *dec = CvSVM::decision_func;
    
        const float *supportVector;
        float* svmWeight = &svmWeightsVec[0];
    
        for (int i = 0; i < numSupportVectors; ++i)
        {
            float alpha = *(dec[0].alpha + i);
            supportVector = get_support_vector(i);
            for(int j=0;j<descriptorSize;j++)
            {
                *(svmWeight + j) += alpha * *(supportVector+j);
            }
        }
        *(svmWeight + descriptorSize) = - dec[0].rho;
    
        return svmWeightsVec;
    }
    
    
    // main harness entry point for detector test
    int main (int argc, const char * argv[])
    {
    
    
        //dummy variables for example
        int posFiles = 10;
        int negFiles = 10;
        int dims = 1000;
        int randomFactor = 4;
    
        //setup some dummy data
        vector<float> dummyPosPattern;
        dummyPosPattern.assign(int(dims/randomFactor),1.f);
        dummyPosPattern.resize(dims );
        random_shuffle(dummyPosPattern.begin(),dummyPosPattern.end());
    
        vector<float> dummyNegPattern;
        dummyNegPattern.assign(int(dims/randomFactor),1.f);
        dummyNegPattern.resize(dims );
        random_shuffle(dummyNegPattern.begin(),dummyNegPattern.end());
    
        // the labels and lables mat
        float posLabel = 1.f;
        float negLabel = 2.f;
        cv::Mat cSvmLabels;
    
        //the data mat
        cv::Mat cSvmTrainingData;
    
        //dummy linear svm parmas
        SVMParams cSvmParams;
        cSvmParams.svm_type = cv::SVM::C_SVC;
        cSvmParams.C = 0.0100;
        cSvmParams.kernel_type = cv::SVM::LINEAR;
        cSvmParams.term_crit =  cv::TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000000, FLT_EPSILON);
    
    
    
    
        cout << "creating training data. please wait" << endl;
        int i;
        for(i=0;i<posFiles;i++)
        {
            //your feature for one box from file
            vector<float> d = dummyDerReaderForOneDer(dummyPosPattern);
    
            //push back a new mat made from the vectors data, with copy  data flag on
            //this shows the format of the mat for a single example, (1 (row) X dims(col) ), as  training mat has each **row** as an example;
            //the push_back works like vector add adds each example to the bottom of the matrix
            cSvmTrainingData.push_back(cv::Mat(1,dims,CV_32FC1,d.data(),true));
    
            //push back a pos label to the labels mat
            cSvmLabels.push_back(posLabel);
        }
    
        //do same with neg files;
        for(i=0;i<negFiles;i++)
        {
            float a =  rand(); 
            vector<float> d = dummyDerReaderForOneDer(dummyNegPattern);
            cSvmTrainingData.push_back(cv::Mat(1,dims,CV_32FC1,d.data(),true));
            cSvmLabels.push_back(negLabel);
        }
    
        //have a look
        cv::Mat viz;
        cSvmTrainingData.convertTo(viz,CV_8UC3);
        viz = viz*255;
        cv::imshow("svmData", viz);
        cv::waitKey(10);
        cout << "press any key to continue" << endl;
        getchar();
    
        viz.release();
    
        //create the svm;
        cout << "training, please wait" << endl;
    
        mySVM svm;
        svm.train(cSvmTrainingData,cSvmLabels,cv::Mat(),cv::Mat(),cSvmParams);
    
    
        cout << "get weights" << endl; 
        vector<float> svmWeights = svm.getWeightVector(dims);
        for(i=0; i<dims+1; i++)
        {
            cout << svmWeights[i] << ", ";
            if(i==dims)
            {
                cout << endl << "bias: "  << svmWeights[i]  << endl;
            }
        }
    
        cout << "press any key to continue" << endl;
        getchar();
    
    
    
        cout << "testing, please wait" << endl;
        //test the svm with a large amount of new unseen fake one at a time
        int totExamples = 10;
        int k;
        for(i=0;i<totExamples; i++)
        {
            cout << endl << endl;
            vector<float> dPos = dummyDerReaderForOneDer(dummyPosPattern);
            cv::Mat dMatPos(1,dims,CV_32FC1,dPos.data(),true);
            float predScoreFromDual = svm.predict(dMatPos,true);
            float predScoreBFromPrimal = svmWeights[dims];
    
            for( k = 0; k <= dims - 4; k += 4 )
                    predScoreBFromPrimal += dPos[k]*svmWeights[k] + dPos[k+1]*svmWeights[k+1] +
                        dPos[k+2]*svmWeights[k+2] + dPos[k+3]*svmWeights[k+3];
                for( ; k < dims; k++ )
                    predScoreBFromPrimal += dPos[k]*svmWeights[k];
    
             cout << "Dual Score:\t" << predScoreFromDual << "\tPrimal Score:\t" <<  predScoreBFromPrimal << endl; 
    
        }
    
    
    
        cout << "press any key to continue" << endl;
        getchar();
        return(0);
    } 
    

    【讨论】:

    • 现在可以工作了。也许我有错误是因为我只是尝试加载保存的文件并尝试访问其元素?
    • 实际上我创建了错误的 CvSVM 实例。当我更改 CvSVM svm 时;到 mySVM svm,一切顺利。这也是你所做的!干杯!
    猜你喜欢
    • 2018-10-03
    • 2019-06-23
    • 2015-03-28
    • 2015-10-06
    • 2012-08-04
    • 2013-08-29
    • 1970-01-01
    • 2014-04-01
    • 1970-01-01
    相关资源
    最近更新 更多