我试图了解 spark.ml 如何处理字符串分类自变量。我知道在 Spark 中我必须使用StringIndexer将字符串转换为双精度。
例如,“a”/“b”/“c” => 0.0/1.0/2.0。
但我真正想避免的是必须在双打列上使用OneHotEncoder。这似乎使管道不必要地混乱。特别是因为 Spark 知道数据是分类的。希望下面的示例代码使我的问题更清楚。
import org.apache.spark.ml.feature.StringIndexer
import org.apache.spark.ml.feature.VectorAssembler
import org.apache.spark.ml.classification.LogisticRegression
val df = sqlContext.createDataFrame(Seq(
Tuple2(0.0,"a"), Tuple2(1.0, "b"), Tuple2(1.0, "c"), Tuple2(0.0, "c")
)).toDF("y", "x")
// index the string column "x"
val indexer = new StringIndexer().setInputCol("x").setOutputCol("xIdx").fit(df)
val indexed = indexer.transform(df)
// build a data frame of label, vectors
val assembler = (new VectorAssembler()).setInputCols(List("xIdx").toArray).setOutputCol("features")
val assembled = assembler.transform(indexed)
// build a logistic regression model and fit it
val logreg = (new LogisticRegression()).setFeaturesCol("features").setLabelCol("y")
val model = logreg.fit(assembled)
逻辑回归将其视为只有一个自变量的模型。
model.coefficients
res1: org.apache.spark.mllib.linalg.Vector = [0.7667490491775728]
但是自变量是分类的,具有三个类别 = [“a”、“b”、“c”]。我知道我从未做过 k 编码之一,但数据帧的元数据知道特征向量是名义上的。
import org.apache.spark.ml.attribute.AttributeGroup
AttributeGroup.fromStructField(assembled.schema("features"))
res2: org.apache.spark.ml.attribute.AttributeGroup = {"ml_attr":{"attrs":
{"nominal":[{"vals":["c","a","b"],"idx":0,"name":"xIdx"}]},
"num_attrs":1}}
如何将此信息传递给LogisticRegression?这不是保留数据帧元数据的重点吗?SparkML中似乎没有CategoricalFeaturesInfo。我真的需要对每个分类特征进行 1 of k 编码吗?