Spark.ml LogisticRegression是否仅假定数字特征?

Nik*_*shi 3 apache-spark apache-spark-sql apache-spark-ml apache-spark-mllib

我正在查看Spark 1.5 dataframe/row api和逻辑回归的实现.据我所知,train其中的方法首先将其转换dataframeRDD[LabeledPoint]as,

override protected def train(dataset: DataFrame): LogisticRegressionModel = {
     // Extract columns from data.  If dataset is persisted, do not persist oldDataset.
     val instances = extractLabeledPoints(dataset).map {
           case LabeledPoint(label: Double, features: Vector) => (label, features)
     }
...
Run Code Online (Sandbox Code Playgroud)

然后它继续进行功能标准化等.

我很困惑与是,该DataFrame类型是RDD[Row]Row允许有任何valueTypes,对于例如(1, true, "a string", null)似乎是一个数据帧的有效行.如果是这样,extractLabeledPoints以上是什么意思?它似乎只选择Array[Double]作为特征值Vector.如果数据框中的列是什么,会发生什么strings?此外,整数分类值会发生什么?

提前谢谢,Nikhil

zer*_*323 5

让我们暂时忽略Spark.一般而言,包括逻辑回归在内的线性模型期望数值自变量.它与Spark/MLlib没有任何特定的关系.如果输入包含分类或有序变量,则必须首先对其进行编码.有些语言,比如R,以透明的方式处理:

> df <- data.frame(x1 = c("a", "b",  "c", "d"), y=c("aa", "aa", "bb", "bb"))
> glm(y ~ x1, df, family="binomial")

Call:  glm(formula = y ~ x1, family = "binomial", data = df)

Coefficients:
(Intercept)          x1b          x1c          x1d  
 -2.357e+01   -4.974e-15    4.713e+01    4.713e+01  
...
Run Code Online (Sandbox Code Playgroud)

但幕后真正使用的是所谓的设计矩阵:

> model.matrix( ~ x1, df)
  (Intercept) x1b x1c x1d
1           1   0   0   0
2           1   1   0   0
3           1   0   1   0
4           1   0   0   1
...
Run Code Online (Sandbox Code Playgroud)

跳过细节,它与OneHotEncoderSpark中执行的转换类型相同.

import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.ml.feature.{OneHotEncoder, StringIndexer}

val df = sqlContext.createDataFrame(Seq(
    Tuple1("a"), Tuple1("b"), Tuple1("c"), Tuple1("d")
)).toDF("x").repartition(1)

val indexer = new StringIndexer()
  .setInputCol("x")
  .setOutputCol("xIdx")
  .fit(df)

val indexed = indexer.transform(df)

val encoder = new OneHotEncoder()
    .setInputCol("xIdx")
    .setOutputCol("xVec")

val encoded = encoder.transform(indexed)

encoded
    .select($"xVec")
    .map(_.getAs[Vector]("xVec").toDense)
    .foreach(println)
Run Code Online (Sandbox Code Playgroud)

Spark更进一步,所有功能,即使算法允许名义/序数自变量,也必须存储为Double使用a spark.mllib.linalg.Vector.如果spark.ml它是一个DataFrame列,在spark.mllib一个字段中spark.mllib.regression.LabeledPoint.

根据模型,特征向量的解释可以是不同的.如上所述,对于线性模型,这些将被解释为数值变量.因为Naive Bayes论文被认为是名义上的.如果模型接受数值和名义变量Spark并以不同的方式处理每个组,例如决策/回归树,则可以提供categoricalFeaturesInfo参数.

值得指出的是,因变量应该被编码,Double但与自变量不同,可能需要正确处理其他元数据.如果您查看indexedDataFrame,您将看到StringIndexer不仅可以转换x,还可以添加属性:

scala> org.apache.spark.ml.attribute.Attribute.fromStructField(indexed.schema(1))
res12: org.apache.spark.ml.attribute.Attribute = {"vals":["d","a","b","c"],"type":"nominal","name":"xIdx"}
Run Code Online (Sandbox Code Playgroud)

最后一些TransformersML,如VectorIndexer,可以自动检测和编码基于不同值的数目分类变量.