为啥 liblinear 不能预测多数派?

Posted

技术标签:

【中文标题】为啥 liblinear 不能预测多数派?【英文标题】:why doesn't liblinear predict the majority class?为什么 liblinear 不能预测多数派? 【发布时间】:2013-02-03 16:18:11 【问题描述】:

大多数机器学习分类器在遇到没有以前见过的特征的​​实例时,会将示例与训练数据中最常见的类进行分类。

liblinear-java 似乎不是这种情况,我想知道为什么会这样。这是一些示例代码,我在其中构造了一个示例问题,其中有两个特征,并且训练数据的 0 标签是 1 标签的 4 倍:

Problem problem = new Problem();
problem.l = 5;
problem.n = 2;
problem.x = new FeatureNode[][] 
  new FeatureNode[]  new FeatureNode(1, 1) ,  
  new FeatureNode[]  new FeatureNode(1, 1) ,  
  new FeatureNode[]  new FeatureNode(1, 1) ,  
  new FeatureNode[]  new FeatureNode(1, 1) ,  
  new FeatureNode[]  new FeatureNode(2, 1) ,  
;
problem.y = new int[] 0, 0, 0, 0, 1;

Parameter parameter = new Parameter(SolverType.L2R_L2LOSS_SVC, 1.0, 0.01);
Model model = Linear.train(problem, parameter);

现在让我们在训练数据中没有的新功能3 上对此进行测试。由于经过训练的模型对特征 3 一无所知,因此我预计预测的类别将是 0,这是训练数据中最常见的类别。

FeatureNode[] instance = new FeatureNode[]  new FeatureNode(3, 1) ;
int prediction = Linear.predict(model, instance);
System.err.println(prediction);

然而,最后一行打印出1。这是为什么呢?

【问题讨论】:

这取决于分隔线的设置位置,您可以添加模型的学习参数吗?我相信它在 1/1 和 2/1 之间,因此 2/1 以上的所有内容都将归类为 1,所有内容都归类为 0。 只是猜测:是的,您的假设是正确的,它应该分配具有最高存在的类。问题是算法如何处理看不见的特征:a)代码中可能存在错误(看不见的分配给第一类),或b)求解器被定义为以这种方式进行(出于某种理论原因)。我会检查求解器应该如何工作,或者我会在其他一些软件(R、Weka、...)中尝试相同的 ML 算法 似乎未指定的特征值默认为零。因此,您的测试实例在分类器中显示为(0,0)。如果不使用偏差,则分隔线穿过该点,因此两个输出同样可能(无论训练集如何)。毕竟,我看不出这样的测试有什么意义。如果您的数据中有缺失值,则在使用 SVM 时将它们设置为零(隐式)可能不是最佳策略。尝试找到一些可以解决缺失数据的学习算法。 您对分隔线的分析是正确的,但并不是我的数据中缺少值 - 只是我在训练期间看到的所有二进制特征的值都是 0。 【参考方案1】:

我相信这是 liblinear 命令行版本的“-B”(偏差)参数旨在解决的问题。如果您直接创建FeatureNodes,则该参数不可用,但这与在每个FeatureNode[] 的开头添加new FeatureNode(1, 1) 基本相同。如果我遵循这种方法,并在训练和分类期间添加一个额外的偏差特征,那么一切正常。这段代码是这样的:

Problem problem = new Problem();
problem.l = 5;
problem.n = 3;
problem.x = new FeatureNode[][] 
  new FeatureNode[]  new FeatureNode(1, 1), new FeatureNode(2, 1) ,  
  new FeatureNode[]  new FeatureNode(1, 1), new FeatureNode(2, 1) ,  
  new FeatureNode[]  new FeatureNode(1, 1), new FeatureNode(2, 1) ,  
  new FeatureNode[]  new FeatureNode(1, 1), new FeatureNode(2, 1) ,  
  new FeatureNode[]  new FeatureNode(1, 1), new FeatureNode(3, 1) ,  
;
problem.y = new int[] 0, 0, 0, 0, 1;

Parameter parameter = new Parameter(SolverType.L2R_L2LOSS_SVC, 1.0, 0.01);
Model model = Linear.train(problem, parameter);
FeatureNode[] instance = new FeatureNode[]  new FeatureNode(1, 1), new FeatureNode(4, 1) ;
int prediction = Linear.predict(model, instance);

为了弄清楚为什么需要偏置功能,我深入研究了 liblinear-java 代码。预测代码如下所示:

for (int i = 0; i < nr_w; i++)
    dec_values[i] = 0;

for (FeatureNode lx : x) 
    int idx = lx.index;
    // the dimension of testing data may exceed that of training
    if (idx <= n) 
        for (int i = 0; i < nr_w; i++) 
            dec_values[i] += w[(idx - 1) * nr_w + i] * lx.value;
         
    

因此,在训练期间从未见过特征的情况下,我们只得到一个全为零的dec_values(决策值)数组,这意味着所有类的概率相等。因此,在分类过程中看到的每个实例中至少存在一个训练过程中看到的特征是至关重要的。

添加具有恒定值的“偏差”特征(例如1)解决了这个问题,允许模型学习默认权重以应用于任何新实例。在上面的代码中,模型为偏差特征学习了0.0869565217391306 的权重,这意味着模型正确地学会了偏爱类0 而不是类1

【讨论】:

以上是关于为啥 liblinear 不能预测多数派?的主要内容,如果未能解决你的问题,请参考以下文章

是否有原因为啥仅存在于给定类中的特征没有被强烈预测到该类中?

机器学习逻辑回归对肿瘤预测

为啥我不能直接使用特征矩阵进行预测?

简单分析实现运维利器---webssh终端libl

liblinear简介

LibSVM 和 LibLinear 有啥区别