使用OpenCV随机森林,是否有办法获取分类的“置信度”水平?

7
如果我有一个训练好的随机森林,有没有办法让我得到森林在测试样本上获得的每个类别的票数?更好的是能得到百分比。
类似于CVRTrees::predict,但同时获得原始输出和预测类别。
谢谢
编辑:为了进一步解释我的目标,这样我就可以潜在地得到解决我的问题而不是我的问题的答案。
回答我知道多少,很少。
这是一个现实世界的应用程序,我正在尽快使自己了解所有这些内容。
基本上,我正在研究判别分类器,并要求我能够比较2(或更多)独立分类器之间的输出。我指的是它们可能或可能不知道整个类别集合的意义,但是存在一个类别集合,其中所有分类器都包含此类别的子集。
我的最初想法是从每个分类器收集关于分类的元信息,理想情况下,这些信息将包含某种形式的(有15%的可能性是A,有78%的可能性是B)[我知道“可能性”是一个不好的词,但我会留下它]。如果我能得到那个输出,我就能根据分配给每个分类器的动态性能权重进行最终分类。
这个想法是我可以使用非常简单的基于规则的分类器来进行初始分类,而更奇特的分类器有时间进行训练。理想情况下,学习分类器可能支持比规则分类器更多的类别,并且随着时间的推移,它主要用于分类。

你看过randomforest.cpp吗? - karlphillip
@karlphillip 是的,我看过了。它没有展示任何从分类中获取元信息的例子,这正是我所寻找的。我对结果为什么是一个类别和实际结果同样感兴趣。如果随机森林不适合提供这些信息,我也愿意尝试其他能够提供此类信息的学习结构。 - Mranz
  1. RF非常容易实现自己的功能。由于实际上有很高的自由度,例如测试强度、随机性,如果您自己完成,您将更好地掌握所做的事情。
  2. 如果您只有准确性而没有分布,您是否可以更好地解释?
- guinny
我想要进行分类器的混合方法,所以我需要了解分布情况,以便正确给予分类结果权重。 - Mranz
你想从判别分类器中得到一个概率吗?正如Shambool建议的那样,请告诉我们你的项目规模是多少。 - guinny
3个回答

6

我曾遇到相同的问题并想在此分享我的解决方案。我从CvRTrees派生了一个类,并添加了一个具有所需行为的函数。我使用现有的predict()函数作为起点。以下是我的代码:

class CvRTreesMultiClass : public CvRTrees
{
    public:
    int predict_multi_class( const CvMat* sample, 
                             cv::AutoBuffer<int>& out_votes, 
                             const CvMat* missing = 0) const;
};

使用:

int CvRTreesMultiClass::predict_multi_class( const CvMat* sample, 
                                             cv::AutoBuffer<int>& out_votes, 
                                             const CvMat* missing ) const
{
int result = 0;
int k;

if( nclasses > 0 ) //classification
{
    int max_nvotes = 0;
    int* votes = out_votes;
    memset( votes, 0, sizeof(*votes)*nclasses );
    for( k = 0; k < ntrees; k++ )
    {
        CvDTreeNode* predicted_node = trees[k]->predict( sample, missing );
        int nvotes;
        int class_idx = predicted_node->class_idx;
        CV_Assert( 0 <= class_idx && class_idx < nclasses );

        nvotes = ++votes[class_idx];

    }

    result = ntrees;
}
else // regression
{
    throw std::runtime_error(__FUNCTION__ "can only be used classification");
}

return result;
}

在调用此函数后,我只需从每个类别接收到的投票数计算概率(prob = out_votes[class_index] / result)。我认为这就是OP要求的(至少我是这么认为的)。


太棒了!感谢您的见解。由于某种原因,我没有想到可以对树进行子类化。 - Mranz

2
您正在进行二元分类吗?如果是的话,您可以使用CvRTrees::predict_prob()。这应该返回一个值在0到1之间,表示决策树中判定给定点属于第二类的比例。
如果您有多个类别,那么将给定点分类为特定类别的树的比例并不是真正的置信度指标。更好的方法是使用CvRTrees::get_proximity()。它的使用方式取决于您的应用程序。假设您有一个来自每个类的点,这些点很可能属于它们的类。然后您首先对给定点进行分类。为了检查分类的质量,您可以通过使用get_proximity来测量投票给给定点和高概率属于该类的点的树的比例。
注意:
你的问题非常有限,而且不清楚你对于测量判别分类器置信度的了解程度。但如果你正在处理一个真实世界的重要项目,那么这个问题还涉及到更多方面。如果只是一份作业或练习,那么这就足够了。

回答我知道多少,其实很少。这是一个真实的应用程序,我正在尽快让自己了解所有这些内容。基本上,我正在研究判别分类,需要能够比较2个(或更多)独立分类器之间的输出。我所说的独立是指它们可能知道或不知道整个类集,但是存在一组类,其中所有分类器都包含这样的类的子集。我的最初想法是收集有关分类的元信息(继续...) - Mranz
从每个分类器中返回一些形式的输出(有15%的可能性是A,78%的可能性是B),如果我能得到这样的输出,我就能根据分配给每个分类器的动态性能权重执行最终分类。这个想法是,我可以使用一个非常简单的基于规则的分类器来进行初始分类,而更奇特的分类器则有时间进行训练。理想情况下,学习分类器可能支持比规则分类器更多的类,并且随着时间的推移,它主要用于分类。 - Mranz

0
特征向量x的分类置信度可以直接计算出来,对于某些分类器而言:对于线性和二次判别分类器(参见麦克拉克兰的《判别分析与统计模式识别》第11章第378页),已经推导出了公式。这些公式相当复杂,但确实能够给出你问题的正确答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接