我正在处理一个高度不平衡的二分类问题,想知道是否有人尝试过使用特定技术来处理不平衡数据集(例如 SMOTE),并应用于Spark的MLlib分类问题。
我正在使用MLlib的随机森林实现,并已经尝试了最简单的方法——对较大类别进行随机欠采样,但效果不如我预期。
如果您有类似问题的经验,请提供任何反馈。
谢谢。
我正在处理一个高度不平衡的二分类问题,想知道是否有人尝试过使用特定技术来处理不平衡数据集(例如 SMOTE),并应用于Spark的MLlib分类问题。
我正在使用MLlib的随机森林实现,并已经尝试了最简单的方法——对较大类别进行随机欠采样,但效果不如我预期。
如果您有类似问题的经验,请提供任何反馈。
谢谢。
目前,随机森林算法的类权重仍在开发中(请参见此处)。
但是,如果您愿意尝试其他分类器,这个功能已经被添加到了逻辑回归中(点此查看)。
考虑一个数据集中有80%的正例(标签==1),理论上我们想要“欠采样”正类。逻辑损失目标函数应该以更高的权重处理负类(标签==0)。
以下是在Scala中生成这个权重的示例,我们为数据集中的每条记录添加一个新列:
def balanceDataset(dataset: DataFrame): DataFrame = {
// Re-balancing (weighting) of records to be used in the logistic loss objective function
val numNegatives = dataset.filter(dataset("label") === 0).count
val datasetSize = dataset.count
val balancingRatio = (datasetSize - numNegatives).toDouble / datasetSize
val calculateWeights = udf { d: Double =>
if (d == 0.0) {
1 * balancingRatio
}
else {
(1 * (1.0 - balancingRatio))
}
}
val weightedDataset = dataset.withColumn("classWeightCol", calculateWeights(dataset("label")))
weightedDataset
}
然后,我们按照以下方式创建分类器:
new LogisticRegression().setWeightCol("classWeightCol").setLabelCol("label").setFeaturesCol("features")
更多详情请查看:https://issues.apache.org/jira/browse/SPARK-9610
你应该检查的一个不同问题-您的特征是否对您尝试预测的标签具有"预测能力"。在进行欠采样后仍然具有低精度的情况下,也许这与您的数据集本质上不平衡无关。
我会进行探索性数据分析 - 如果分类器不能比随机选择做得更好,则存在一种风险,即特征和类别之间根本没有联系。
过度拟合- 训练集上的误差较小,测试集上的误差较大可能表明您使用过于灵活的特征集过度拟合了。
偏差方差- 检查您的分类器是否存在高偏差或高方差问题。
我使用了@Serendipity提供的解决方案,但我们可以优化balanceDataset函数,避免使用udf。我还添加了更改标签列的功能。这是我最终得到的函数版本:
def balanceDataset(dataset: DataFrame, label: String = "label"): DataFrame = {
// Re-balancing (weighting) of records to be used in the logistic loss objective function
val (datasetSize, positives) = dataset.select(count("*"), sum(dataset(label))).as[(Long, Double)].collect.head
val balancingRatio = positives / datasetSize
val weightedDataset = {
dataset.withColumn("classWeightCol", when(dataset(label) === 0.0, balancingRatio).otherwise(1.0 - balancingRatio))
}
weightedDataset
}
new LogisticRegression().setWeightCol("classWeightCol").setLabelCol("label").setFeaturesCol("features")
@dbakr 你在不平衡的数据集上进行偏见预测时得到了答案吗?
虽然我不确定这是否是你最初的计划,但请注意,如果你首先按比例r对数据集的多数类进行子采样,那么为了获得Spark逻辑回归的无偏预测,你可以选择:
- 使用transform()
函数提供的rawPrediction,并使用log(r)
调整截距
- 或者你可以使用.setWeightCol("classWeightCol")
训练带权重的回归(请参阅此处引用的文章以找出必须设置的权重值)。