如何处理spark-ml的分类function?
如何处理分类数据 spark-ml
而不 spark-mllib
?
认为文档不是很清楚,看起来像RandomForestClassifier
, LogisticRegression
这样的分类器有一个featuresCol
参数,它指定DataFrame
列的名称,以及一个labelCol
参数,它指定了标签类的列名在DataFrame
。
很显然,我想在预测中使用多个特征,所以我尝试使用VectorAssembler
将所有特征放在featuresCol下的单个vector中。
然而, VectorAssembler
只接受数字types,布尔types和向量types(根据Spark网站),所以我不能把string放入我的特征向量中。
我应该如何继续?
我只是想完成Holden的回答。
自Spark 1.4.0以来,MLLib还提供了OneHotEncoderfunction,它将一列标签索引映射到一列二进制向量,最多只有一个单值。
该编码允许期望连续特征的algorithm(例如Logistic回归)使用分类特征
我们来考虑下面的DataFrame
:
val df = Seq((0, "a"),(1, "b"),(2, "c"),(3, "a"),(4, "a"),(5, "c")) .toDF("id", "category")
第一步是使用StringIndexer
创build索引的DataFrame
:
import org.apache.spark.ml.feature.StringIndexer val indexer = new StringIndexer() .setInputCol("category") .setOutputCol("categoryIndex") .fit(df) val indexed = indexer.transform(df) indexed.show // +---+--------+-------------+ // | id|category|categoryIndex| // +---+--------+-------------+ // | 0| a| 0.0| // | 1| b| 2.0| // | 2| c| 1.0| // | 3| a| 0.0| // | 4| a| 0.0| // | 5| c| 1.0| // +---+--------+-------------+
然后,您可以使用OneHotEncoder
对categoryIndex
进行编码:
import org.apache.spark.ml.feature.OneHotEncoder val encoder = new OneHotEncoder() .setInputCol("categoryIndex") .setOutputCol("categoryVec") val encoded = encoder.transform(indexed) encoded.select("id", "categoryVec").show // +---+-------------+ // | id| categoryVec| // +---+-------------+ // | 0|(2,[0],[1.0])| // | 1| (2,[],[])| // | 2|(2,[1],[1.0])| // | 3|(2,[0],[1.0])| // | 4|(2,[0],[1.0])| // | 5|(2,[1],[1.0])| // +---+-------------+
我将从另一个angular度提供一个答案,因为我也想知道关于Spark ML(而不是MLlib)中基于树的模型的分类特征,而且文档并不清楚一切是如何工作的。
当您使用pyspark.ml.feature.StringIndexer
转换数据pyspark.ml.feature.StringIndexer
的列时,额外的元数据将被存储在专门将转换后的要素标记为分类要素的数据pyspark.ml.feature.StringIndexer
。
当您打印数据框时,您将看到一个数值(这是一个与您的某个分类值相对应的索引),如果您查看该模式,您将看到新的变换列是double
types的。 但是,使用pyspark.ml.feature.StringIndexer.transform
创build的这个新列不仅仅是一个普通的双列,它还有额外的与之关联的元数据,这非常重要。 您可以通过查看metadata
框模式中相应字段的metadata
属性来检查此元数据(您可以通过查看yourdataframe.schema来访问数据框的模式对象)
这额外的元数据有两个重要的含义:
-
在使用基于树的模型时调用
.fit()
时,它将扫描数据框的元数据,并将您编码的字段与转换器(如pyspark.ml.feature.StringIndexer
(如上所述,还有其他的变形金刚也将有这种效果,如pyspark.ml.feature.VectorIndexer
)。 正因为如此,在Spark ML中使用基于树的模型时,您不必对自己的要素进行一次性编码,但是在使用其他不需要编码的模型时自然处理线性回归等分类)。 -
由于此元数据存储在数据框中,因此可以使用
pyspark.ml.feature.IndexToString
将数字索引随时反转回原始分类值(通常是string)。
有一个称为StringIndexer
的MLpipe道组件,可以用来以合理的方式将string转换为Double。 http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.ml.feature.StringIndexer有更多的文档和http://spark.apache.org/docs/最新/ ml-guide.html显示了如何构buildpipe道。
您可以使用cast函数将火花数据框中的string列types转换为数字数据types。
from pyspark.sql import SQLContext from pyspark.sql.types import DoubleType, IntegerType sqlContext = SQLContext(sc) dataset = sqlContext.read.format('com.databricks.spark.csv').options(header='true').load('./data/titanic.csv') dataset = dataset.withColumn("Age", dataset["Age"].cast(DoubleType())) dataset = dataset.withColumn("Survived", dataset["Survived"].cast(IntegerType()))
在上面的例子中,我们读取一个csv文件作为一个dataframe,将默认的string数据types转换为整型和双精度型,并覆盖原始dataframe。 然后,我们可以使用VectorAssembler将特征合并到一个vector中,并应用您最喜欢的Spark MLalgorithm。