Apache spark Spark.ml LogisticReturnal是否仅假设数字特征?
我在查看Spark 1.5和逻辑回归的数据。据我所知,其中的Apache spark Spark.ml LogisticReturnal是否仅假设数字特征?,apache-spark,apache-spark-sql,apache-spark-ml,apache-spark-mllib,Apache Spark,Apache Spark Sql,Apache Spark Ml,Apache Spark Mllib,我在查看Spark 1.5和逻辑回归的数据。据我所知,其中的train方法首先将dataframe转换为RDD[LabeledPoint]As override protected def train(dataset: DataFrame): LogisticRegressionModel = { // Extract columns from data. If dataset is persisted, do not persist oldDataset. val ins
train
方法首先将dataframe
转换为RDD[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)
}
...
然后进行特征标准化等
我感到困惑的是,数据帧
的类型是RDD[Row]
,行
可以有任何值类型
,例如(1,true,“a string”,null)
似乎是数据帧的有效行。如果是这样的话,上面的提取标记点是什么意思?它似乎只选择了Array[Double]
作为Vector
中的特征值。如果数据框中的列是字符串
,会发生什么情况?另外,整型分类值会发生什么变化
提前感谢,,
Nikhil在评论中复制zero323的澄清:
在传递给MLlib/ML估计器之前,分类值必须编码为Double
。这里有很多内置的转换器,比如StringIndexer
或onehotcoder
,这些都很有用。如果算法以与数字特征不同的方式处理分类特征,例如DecisionTree
,您可以使用categoricalFeaturesInfo
识别哪些变量是分类的
最后,一些转换器在列上使用特殊属性来区分不同类型的属性。让我们暂时忽略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
...
跳过细节,这与Spark中的OneHotEncoder执行的转换类型相同
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)
Spark更进一步,所有特征,即使算法允许标称/顺序自变量,也必须使用Spark.mllib.linalg.Vector
存储为Double
。在spark.ml
的情况下,它是spark.mllib
中的DataFrame
列,spark.mllib.regression.LabeledPoint
中的字段
但是,根据模型的不同,特征向量的解释可能会有所不同。如上所述,对于线性模型,这些将被解释为数值变量。对于朴素贝叶斯
而言,这些被认为是名义上的。若模型同时接受数值变量和名义变量,并以不同的方式处理每个组,如决策树/回归树,则可以提供参数
值得指出的是,因变量也应编码为Double
,但与自变量不同,可能需要正确处理额外的元数据。如果查看索引的
数据帧,您将看到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"}
最后,来自ML
的一些转换器可以根据不同值的数量自动检测和编码分类变量。分类值在传递给MLlib/ML估计器之前必须编码为双
。有相当多的内置变压器,如或,可以在这里有所帮助。如果算法以与数字特征不同的方式处理分类特征,例如DecisionTree
,您可以使用categoricalFeaturesInfo
来确定哪些变量是分类变量。最后,一些转换器在列上使用特殊属性来区分不同类型的属性。@zero323我认为您的这两个答案是公认的答案。介意回答吗(不是评论)?@zero323,因此似乎用户有责任在处理之前调整数据帧。这是有意义的,因为没有特别的方法可以知道某个变量是否是分类变量(特别是在整数类标签的情况下)。只是他们的API并不清楚。在一个地方,他们展示了一个带有任何valueType列的行示例,在其他地方,他们只说train(dataset)
@NikhilJJoshi这是可能的,ML的一些工具可以为您处理这一点,但这不是应该隐式完成的事情。
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"}