大多数机器学习分类器遇到一个实例,该实例没有以前见过的功能时,会使用训练数据中最频繁的类对示例进行分类。

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。这是为什么?

最佳答案

我相信这就是liblinear命令行版本的“ -B”(偏差)参数要解决的问题。如果直接创建FeatureNode,则该参数不可用,但实际上与在每个new FeatureNode(1, 1)的开头添加FeatureNode[]相同。如果我遵循这种方法,并且在训练和分类过程中都添加了额外的偏见功能,则一切正常。该代码如下所示:

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的偏爱。

09-11 05:38