如何在没有 StringIndexer 的情况下在 Spark ML 中进行二进制分类
How to make binary classication in Spark ML without StringIndexer
我尝试在没有 StringIndexer 的管道中使用 Spark ML DecisionTreeClassifier,因为我的特征已经被索引为 (0.0; 1.0)。 DecisionTreeClassifier 作为标签需要双值,所以这段代码应该有效:
def trainDecisionTreeModel(training: RDD[LabeledPoint], sqlc: SQLContext): Unit = {
import sqlc.implicits._
val trainingDF = training.toDF()
//format of this dataframe: [label: double, features: vector]
val featureIndexer = new VectorIndexer()
.setInputCol("features")
.setOutputCol("indexedFeatures")
.setMaxCategories(4)
.fit(trainingDF)
val dt = new DecisionTreeClassifier()
.setLabelCol("label")
.setFeaturesCol("indexedFeatures")
val pipeline = new Pipeline()
.setStages(Array(featureIndexer, dt))
pipeline.fit(trainingDF)
}
但实际上我得到了
java.lang.IllegalArgumentException:
DecisionTreeClassifier was given input with invalid label column label,
without the number of classes specified. See StringIndexer.
当然,我可以只放置 StringIndexer 并让它为我的双 "label" 字段工作,但我想使用 DecisionTreeClassifier 的输出 rawPrediction 列来获得每行 0.0 和 1.0 的概率,例如...
val predictions = model.transform(singletonDF)
val zeroProbability = predictions.select("rawPrediction").asInstanceOf[Vector](0)
val oneProbability = predictions.select("rawPrediction").asInstanceOf[Vector](1)
如果我将 StringIndexer 放入管道 - 我将不知道 rawPrediction 向量中我的输入标签“0.0”和“1.0”的索引,因为字符串索引器将按值的频率进行索引,这可能会有所不同。
请帮助在不使用 StringIndexer 的情况下为 DecisionTreeClassifier 准备数据,或者建议一些其他方法来获取每行原始标签 (0.0; 1.0) 的概率。
您始终可以手动设置所需的元数据:
import sqlContext.implicits._
import org.apache.spark.ml.attribute.NominalAttribute
val meta = NominalAttribute
.defaultAttr
.withName("label")
.withValues("0.0", "1.0")
.toMetadata
val dfWithMeta = df.withColumn("label", $"label".as("label", meta))
pipeline.fit(dfWithMeta)
我尝试在没有 StringIndexer 的管道中使用 Spark ML DecisionTreeClassifier,因为我的特征已经被索引为 (0.0; 1.0)。 DecisionTreeClassifier 作为标签需要双值,所以这段代码应该有效:
def trainDecisionTreeModel(training: RDD[LabeledPoint], sqlc: SQLContext): Unit = {
import sqlc.implicits._
val trainingDF = training.toDF()
//format of this dataframe: [label: double, features: vector]
val featureIndexer = new VectorIndexer()
.setInputCol("features")
.setOutputCol("indexedFeatures")
.setMaxCategories(4)
.fit(trainingDF)
val dt = new DecisionTreeClassifier()
.setLabelCol("label")
.setFeaturesCol("indexedFeatures")
val pipeline = new Pipeline()
.setStages(Array(featureIndexer, dt))
pipeline.fit(trainingDF)
}
但实际上我得到了
java.lang.IllegalArgumentException:
DecisionTreeClassifier was given input with invalid label column label,
without the number of classes specified. See StringIndexer.
当然,我可以只放置 StringIndexer 并让它为我的双 "label" 字段工作,但我想使用 DecisionTreeClassifier 的输出 rawPrediction 列来获得每行 0.0 和 1.0 的概率,例如...
val predictions = model.transform(singletonDF)
val zeroProbability = predictions.select("rawPrediction").asInstanceOf[Vector](0)
val oneProbability = predictions.select("rawPrediction").asInstanceOf[Vector](1)
如果我将 StringIndexer 放入管道 - 我将不知道 rawPrediction 向量中我的输入标签“0.0”和“1.0”的索引,因为字符串索引器将按值的频率进行索引,这可能会有所不同。
请帮助在不使用 StringIndexer 的情况下为 DecisionTreeClassifier 准备数据,或者建议一些其他方法来获取每行原始标签 (0.0; 1.0) 的概率。
您始终可以手动设置所需的元数据:
import sqlContext.implicits._
import org.apache.spark.ml.attribute.NominalAttribute
val meta = NominalAttribute
.defaultAttr
.withName("label")
.withValues("0.0", "1.0")
.toMetadata
val dfWithMeta = df.withColumn("label", $"label".as("label", meta))
pipeline.fit(dfWithMeta)