flink支持向量机90%错误分类

koaltpgm  于 2021-06-25  发布在  Flink
关注(0)|答案(1)|浏览(370)

我试着用flink-ml-svm实现一些二进制分类。当我评估分类时,我在训练数据集上得到了大约85%的错误率。我绘制了三维数据,看起来你可以用超平面很好地分离数据。
当我试图从支持向量机中得到权重向量时,我只看到了不截取超平面而得到权重向量的选项。就是一个超平面穿过(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()

绘制的数据如下所示:

a14dhokn

a14dhokn1#

svm分类器不会给出到原点的距离(aka。偏差或阈值),因为这是预测器的一个参数。阈值的不同值将导致不同的精确度和召回度量,并且最佳值是特定于用例的。通常我们使用roc(receiver operating characteristic)曲线来寻找它。
上的相关属性 SVM 是(来自flink文档):
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 培训师还有一些参数(称为超参数),需要对这些参数进行调整,以获得最佳的预测性能。有很多技巧可以做到这一点,这篇文章将变得太长,无法列出它们。我只是想引起你的注意。如果你觉得懒惰,这里有一个维基百科的链接:超参数优化。

其他尺寸?

如果你现在不想处理这个门槛,那就有(某种程度上)黑客攻击了。可以将偏差塞入特征向量的另一个维度,如下所示:

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)))
}

这里有一个很好的讨论,你为什么不应该这样做。基本上,问题是偏见会参与正则化。但是在机器学习中没有绝对的真理。

相关问题