私は非常に不均衡なデータセットで特定のバイナリ分類問題に取り組んでおり、不均衡なデータセットを処理するための特定の技術を実装しようとする人がいるかどうか疑問に思っていました( [〜#〜] smote [〜#〜 ] )SparkのMLlibを使用した分類問題。
私はMLLibのランダムフォレスト実装を使用しており、より大きなクラスをランダムにアンダーサンプリングする最も単純なアプローチを既に試しましたが、期待どおりに機能しませんでした。
同様の問題についてのあなたの経験に関するフィードバックをお願いします。
おかげで、
この時点で、Random Forestアルゴリズムのクラスの重み付けはまだ開発中です( here を参照)
しかし、他の分類子を試してみたい場合は、この機能 Logistic Regression に既に追加されています。
データセットに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-961
確認する必要がある別の問題-予測しようとしているラベルに対して、フィーチャに「予測力」があるかどうか。アンダーサンプリング後も精度が低い場合、データセットが本質的に不均衡であるという事実とはおそらく関係ありません。
私は探索的データ分析を行います-分類器がランダムな選択よりもうまくいかない場合、機能とクラスの間に単に関係がないというリスクがあります。
オーバーフィッティング-トレーニングセットでの低いエラーとテストセットでの高いエラーは、過度に柔軟な機能セットを使用してオーバーフィットしていることを示している可能性があります。
バイアス分散-分類器が高バイアスまたは高分散の問題を抱えているかどうかを確認します。
@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")
を使用して重みで回帰をトレーニングできます(引用記事を参照重みに設定する必要がある値を計算します)。