Flink SVM 90%错误分类

时间:2017-12-01 16:33:32

标签: scala svm apache-flink flinkml

我尝试使用flink-ml svm实现进行二进制分类。 当我评估分类时,我在训练数据集上得到了大约85%的错误率。我绘制了3D数据,看起来你可以用超平面很好地分离数据。

当我试图从svm中获取权重向量时,我只看到了获取权重向量而没有截取超平面的选项​​。所以只是一架超平面经过(0,0,0)。

我不知道错误可能是什么,并欣赏每一条线索。

TreeView

绘制的数据如下所示:

Plot of the Data

1 个答案:

答案 0 :(得分:2)

SVM分类器不会给你到原点的距离(也就是偏差或阈值),因为这是预测变量的参数。阈值的不同值将导致不同的精度和召回度量,并且最佳是特定于用例的。通常我们会使用ROC (Receiver Operating Characteristic) curve来查找它。

SVM上的相关属性(来自Flink docs):

  • ThresholdValue - 设置测试/预测的阈值。以下产出归类为负数,上述产出归类为正数。默认值为0.
  • OutputDecisionFunction - 将其设置为true以输出到分离平面的距离,而不是二进制分类。

ROC曲线

如何找到最佳阈值本身就是一门艺术。在不知道更多关于问题的情况下,您可以随时做的是针对阈值的不同值绘制ROC曲线(真阳性率与假阳性率),并寻找与随机猜测距离最大的点( 0.5斜率线)。但最终阈值的选择还取决于假阳性的成本与您域中假阴性的成本。以下是来自维基百科的三种不同分类器的示例ROC曲线:

要选择初始阈值,您可以对训练数据(或其样本)进行平均:

  // weights is a DataSet of size 1
  val weights = svm.weightsOption.get.collect().head
  val initialThreshold = trainLV.map { lv =>
    (lv.label - (weights dot lv.vector), 1l)
  }.reduce { (avg1, avg2) =>
    (avg1._1 + avg2._1, avg1._2 + avg2._2)
  }.collect() match { case Seq((sum, len)) =>
    sum / len
  }

然后在循环中改变它,测量测试数据上的TPR和FPR。

其他超参数

请注意,SVM培训师还需要调整Parameters(称为超参数),以获得最佳预测效果。有很多技术可以做到这一点,这篇文章会变得太长而无法列出。我只是想引起你的注意。如果您感到懒惰,请点击维基百科上的链接:Hyperparameter optimization

其他方面?

如果您现在不想处理阈值,则存在(某种程度上)黑客攻击。您可以将偏差卡入特征向量的另一个维度,如下所示:

val bias = 10 // choose a large value
val inputLV = input.map { t =>
  LabeledVector(
    if (t._3) 1.0 else -1.0,
    DenseVector(Array(t._4, t._5, t._6, bias)))
}

以下是nice discussion为什么不应该执行此操作。基本上问题是偏见会参与正规化。但在机器学习中并没有绝对的真理。