【问题标题】:Flink SVM 90% misclassificationFlink SVM 90% 错误分类
【发布时间】:2018-05-15 19:23:34
【问题描述】:

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

当我试图从 svm 中获取权重向量时,我只看到了在不拦截超平面的情况下获取权重向量的选项。所以只是一个通过 (0,0,0) 的超平面。

我不知道错误可能出在哪里,并感谢每一个线索。

val env = ExecutionEnvironment.getExecutionEnvironment
val input: DataSet[(Int, Int, Boolean, Double, Double, Double)] = env.readCsvFile(filepathTraining, ignoreFirstLine = true, fieldDelimiter = ";")


val inputLV = input.map(
  t => { LabeledVector({if(t._3) 1.0 else -1.0}, DenseVector(Array(t._4, t._5, t._6)))}
)


val trainTestDataSet = Splitter.trainTestSplit(inputLV, 0.8, precise = true, seed = 100)
val trainLV = trainTestDataSet.training
val testLV = trainTestDataSet.testing

val svm = SVM()

svm.fit(trainLV)

val testVD = testLV.map(lv => (lv.vector, lv.label))
val evalSet = svm.evaluate(testVD)

// groups the data in false negatives, false positives, true negatives, true positives
evalSet.map(t => (t._1, t._2, 1)).groupBy(0,1).reduce((x1,x2) => (x1._1, x1._2, x1._3 + x2._3)).print()

此处显示绘制的数据:

【问题讨论】:

  • 你能发布绘制的数据集吗?

标签: scala svm apache-flink flinkml


【解决方案1】:

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

其他维度?

如果您现在不想处理阈值,则存在(有点)hack。您可以将偏差塞入特征向量的另一个维度,如下所示:

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,说明您不应该这样做的原因。基本上问题是偏差会参与正则化。但在机器学习中,没有绝对的真理。

【讨论】:

    猜你喜欢
    • 2023-04-08
    • 2020-06-12
    • 1970-01-01
    • 2015-06-28
    • 2020-06-01
    • 2012-01-07
    • 2013-12-08
    • 2021-10-14
    • 2013-06-07
    相关资源
    最近更新 更多