huc*_*cko 7 scala svm apache-flink flinkml
我尝试用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()
Run Code Online (Sandbox Code Playgroud)
绘制的数据如下所示:
SVM 分类器不会提供到原点的距离(又称偏差或阈值),因为这是预测器的参数。不同的阈值将导致不同的精度和召回指标,并且最佳值取决于具体用例。通常我们使用ROC(接受者操作特征)曲线来找到它。
相关属性SVM有(来自Flink 文档):
true为输出到分离平面的距离而不是二元分类。如何找到最佳阈值本身就是一门艺术。在不了解有关问题的更多信息的情况下,您始终可以做的就是针对不同的阈值绘制 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
}
Run Code Online (Sandbox Code Playgroud)
然后循环改变它,测量测试数据的 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)))
}
Run Code Online (Sandbox Code Playgroud)
这里有一个关于为什么你不应该这样做的很好的讨论。基本上问题是偏差会参与正则化。但在机器学习中,没有绝对的真理。