【问题标题】:Convert LibSVM output to vector of floats将 LibSVM 输出转换为浮点向量
【发布时间】:2023-03-17 02:18:01
【问题描述】:

我需要形成HOGDescriptor::setSVMDetector() 输入。

我使用 openCV 计算描述符,然后使用 libSVM 获取模型文件。 要形成输入,我知道我需要获取支持向量的值并使用 alpha 对它们进行元素 mul(然后在末尾添加 -rho),但是 我不知道从哪里获得这些 alpha

我有一个 SV 列表,例如:

1 1:-0.0434783 2:0.153846 3:0.194444 4:-0.353712 5:-0.45054
1 1:-0.2173916 2:-0.38461 3:0.222262 4:-0.676686 5:-0.78062

但是从哪里获得 alphas?

【问题讨论】:

    标签: c++ opencv machine-learning computer-vision libsvm


    【解决方案1】:

    好的,现在事情似乎很清楚了。 在我的例子中,Alpha 是第一列。 由于在我的测试模型中它们都等于 -1 或 1(不知道为什么),我认为这些是标签。

    无论如何,这是我的解析器(但您只需要在文件中保留 SV):

    std::ifstream ifs("cars_model.model");
    
        const int nsv = 90;
        const int nfeatures = 144;
    
        float rho = 12.5459;
    
        char ts[4000] = ""; // !
    
        std::vector<float> res(nfeatures,0);
    
        std::vector<float> alphas;
    
        Mat_<float> temp(nsv, nfeatures);
    
        int c = 0;
    
        std::cout << "Loading model file...\n";
    
        for (int i=0; i<nsv; i++) {
    
            float al = 0;
            ifs >> al;
            alphas.push_back(al);
    
            for (int j=0; j<nfeatures; j++) {
    
                float ind, s;
                char junk;
    
                ifs >> ind >> junk >> s;
    
                temp.at<float>(c, j) = s;
    
                //std::cout << f << ' ' << s << '\n';
    
            }
    
            c++;
    
        }
    
        ifs.close();
    
        std::cout << "Computing primal form...\n";
    
        for (int i=0; i<nsv; i++) {
    
            float alpha = alphas[i];
    
            for (int j=0; j<nfeatures; j++) {
                res[j] += (temp.at<float>(i,j) * alpha);
            }
    
        }
    
        //res.push_back(-rho);
    
        std::ofstream ofs("primal.txt");
    
        for (int i=0; i<res.size(); i++)
            ofs << res[i] << ' ';
    
        ofs.close();
    

    你知道,它有效。您可以将 rho 设置为检测器的阈值。

    【讨论】:

      【解决方案2】:

      但是为什么要“手动”分类呢? OpenCv has a classification routine 调用 predict,它使用找到的 SVs' 和 alphas'

      float response = SVM.predict(sampleMat);
      

      如果你真的想自己做,你不仅需要 SV 和 alpha,还需要一个用于训练和计算的核函数

      SUM alpha_i K( support_vector_i , data_point ) - rho
      

      我不确定是否可以在不扩展 SVM 类的情况下“手动”提取 alpha,正如在 sources 中看到的那样 - alpha 存储在 CvSVMDecisionFunc 结构中:

      struct CvSVMDecisionFunc
      {
          double rho;
          int sv_count;
          double* alpha;
          int* sv_index;
      };
      

      而对这个结构的唯一引用是在protected 部分:

      protected:
      
          (...)
      
          CvSVMDecisionFunc* decision_func;
      

      svm.cpp 的源代码我们可以发现,它只能通过save 例程公开访问。所以一些“hack”是保存模型并从那里提取 alpha(它将位于“决策函数”部分,以人类可读的格式编写)。

      最简单的提取技术似乎扩展CvSVM 类并包含类似方法

      public:
      
          CvSVMDecisionFunc* get_decision_function() { return decision_func; }
      

      更新

      经过澄清,OP 实际上是在尝试在 opencv 中使用外部训练模型 - 最简单的方法是将由其他方法(libsvm、linearsvm 等)创建的 libsvm 模型转换为 opencv 兼容格式并使用read 加载它方法

      void CvSVM::read( CvFileStorage* fs, CvFileNode* svm_node )
      

      see source for more details.

      【讨论】:

      • 据我了解,您可以使用 .predict(),但您必须为它提供一个已经计算的 HOG,以获得与您训练 CvSVM 的完全相同大小的图像,这很不方便。如果您想使用扫描给定图像并返回一个点数组的例程,并在其中找到答案,您应该使用 .detectMultiScale()。
      • 我不太明白你的评论。 SVM 将总是要求与训练中使用的输入大小完全相同。不管你是提取 alpha 还是使用 predict 方法,它的工作方式都是一样的。
      • 好吧,首先,我决定不使用openCV进行训练,因为我查了很多资料,有人说最好使用svmlight或libsvm,所以我不能使用CvSVMDecisionFunc。我要谈论的第二件事是,detectMultiScale() 获取任意大小的图像,并为您完成所有工作,在图像的每个点计算 HOG,并返回匹配点。我说的对吗?
      • 因此您可以简单地将使用 libsvm 或 svmlight 训练的 SVM 模型转换为 opencv 可以使用 read 方法读取的格式。虽然有人可以说,它的训练过程有些故障(?)分类过程是正确实现的,所以只需从外部源加载模型并使用 CvSVM 对象作为你的 detectMultiScale() 的检测器。
      • 哦,谢谢,我不知道 .read()。顺便说一句,我现在弄清楚了一些事情,所以我将发布我的解析器代码,并尝试您的方法,然后比较结果。
      猜你喜欢
      • 2014-02-06
      • 2019-09-09
      • 1970-01-01
      • 2023-04-09
      • 2012-11-04
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      • 2017-06-08
      相关资源
      最近更新 更多