Spark,MLlib:调整分类器识别阈值
Posted
技术标签:
【中文标题】Spark,MLlib:调整分类器识别阈值【英文标题】:Spark, MLlib: Adjusting classifier descrimination threshold 【发布时间】:2015-10-25 21:20:04 【问题描述】:我尝试使用 Spark MLlib 逻辑回归 (LR) 和/或随机森林 (RF) 分类器来创建模型来区分由基数差异很大的集合表示的两个类。 一组有 150 000 000 个负例,而另一组只有 50 000 个正例。
在使用默认参数训练 LR 和 RF 分类器后,我得到两个分类器的非常相似的结果,例如,对于以下测试集:
Test instances: 26842
Test positives = 433.0
Test negatives = 26409.0
分类器检测到:
truePositives = 0.0
trueNegatives = 26409.0
falsePositives = 433.0
falseNegatives = 0.0
Precision = 0.9838685641904478
Recall = 0.9838685641904478
看起来分类器根本无法检测到任何正面实例。
此外,无论数据如何拆分为训练集和测试集,分类器提供的 false positives
equal 数量与测试集实际拥有的 positives
数量完全相同。
LR 分类器默认阈值设置为 0.5 将阈值设置为 0.8 没有任何区别。
val model = new LogisticRegressionWithLBFGS().run(training)
model.setThreshold(0.8)
问题:
1) 请告知如何操纵分类器阈值,以使分类器对具有少量正实例的类与具有大量负实例的类更有意义?
2) 任何其他 MLlib 分类器来解决这个问题?
3) itercept
参数对逻辑回归算法有什么作用?
val model = new LogisticRegressionWithSGD().setIntercept(true).run(training)
【问题讨论】:
您可以尝试对参数执行网格搜索并交叉验证您的模型以查看最适合的模型。你应该小心过度拟合的想法!关于截距,它是您添加到权重向量的常数值,可以帮助您拟合函数 @eliasah 对于像这里这样极度偏斜的分布不太可能有帮助。 @zork 应该是falsePositives = 0.0
,falseNegatives = 433.0
,不是吗?
理想情况下应该是truePositives = 433
和falsePositives = falseNegatives = 0
scikit-learn 很好地解释了grid search,它主要是搜索估计器参数。你也可以阅读它here。我正在向您指出这些方向,因为我不知道您的数据是什么样的,也不知道它代表什么,这在优化过程的某些情况下可能是必不可少的。
【参考方案1】:
好吧,我认为你这里有一个非常不平衡的数据集问题: 150 000 000 1 类 50 000 类 2。小3000倍。
因此,如果您训练一个假设所有都是 Class1 的分类器,您将拥有: 0.999666 精度。所以最好的分类器总是 ALL are Class1。这就是您的模型在这里学习的内容。
有不同的方法来评估这些情况,通常你可以做,对较大的类进行下采样,或者对较小的类进行上采样,或者你可以对随机森林做一些其他的事情,例如当你在采样时做一种平衡的方式(分层),或添加权重:
http://statistics.berkeley.edu/sites/default/files/tech-reports/666.pdf
还存在其他方法,例如 SMOTE 等(也正在做示例),您可以在此处阅读更多详细信息:
https://www3.nd.edu/~dial/papers/SPRINGER05.pdf
您可以为逻辑回归更改的阈值将是概率,您可以在此处尝试在逻辑回归示例的参数中使用“probabilityCol”:
http://spark.apache.org/docs/latest/ml-guide.html
但是现在 MLlib 的一个问题是,并非所有分类器都返回概率,我问过他们这个问题,这在他们的路线图中。
【讨论】:
以上是关于Spark,MLlib:调整分类器识别阈值的主要内容,如果未能解决你的问题,请参考以下文章
在 spark mllib 分类器中处理 null/NaN 值
PySpark MLlib:AssertionError:分类器未从 HasRawPredictionCol 扩展