spark one hot apache-spark categorical-data apache-spark-ml apache-spark-mllib

apache-spark - one - spark ml pca



¿Cómo manejar las características categóricas con spark-ml? (4)

Hay un componente de la línea ML llamado StringIndexer que puede usar para convertir sus cadenas a Double de manera razonable. http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.ml.feature.StringIndexer tiene más documentación, y http://spark.apache.org/docs/latest/ml-guide.html muestra cómo construir tuberías.

¿Cómo manejo datos categóricos con spark-ml y no spark-mllib ?

Aunque la documentación no es muy clara, parece que los clasificadores, por ejemplo RandomForestClassifier , LogisticRegression , tienen un argumento featuresCol , que especifica el nombre de la columna de características en el DataFrame , y un argumento labelCol , que especifica el nombre de la columna de clases etiquetadas en el DataFrame

Obviamente, quiero usar más de una característica en mi predicción, así que traté de usar el VectorAssembler para poner todas mis características en un único vector en featuresCol .

Sin embargo, VectorAssembler solo acepta tipos numéricos, tipo booleano y tipo de vector (de acuerdo con el sitio web de Spark), por lo que no puedo poner cadenas en mi vector de características.

¿Cómo debo proceder?


Puede convertir un tipo de columna de cadena en un marco de datos de chispa en un tipo de datos numéricos utilizando la función de conversión.

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()))

En el ejemplo anterior, leemos en un archivo csv como un marco de datos, convertimos los tipos de datos de cadena por defecto en enteros y dobles, y sobrescribimos el marco de datos original. Luego podemos usar el VectorAssembler para combinar las características en un solo vector y aplicar su algoritmo favorito de Spark ML.


Solo quería completar la respuesta de Holden.

Desde Spark 1.4.0 , MLLib también proporciona la función OneHotEncoder , que asigna una columna de índices de etiquetas a una columna de vectores binarios, con un valor único como máximo.

Esta codificación permite algoritmos que esperan funciones continuas, como la Regresión logística, para usar características categóricas

Consideremos el siguiente DataFrame :

val df = Seq((0, "a"),(1, "b"),(2, "c"),(3, "a"),(4, "a"),(5, "c")) .toDF("id", "category")

El primer paso sería crear el DataFrame indexado con el StringIndexer :

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| // +---+--------+-------------+

A continuación, puede codificar el categoryIndex con OneHotEncoder :

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])| // +---+-------------+


Voy a proporcionar una respuesta desde otra perspectiva, ya que también me preguntaba sobre las características categóricas con respecto a los modelos basados ​​en árboles en Spark ML (no MLlib), y la documentación no es tan clara sobre cómo funciona todo.

Cuando transforma una columna en su marco de datos utilizando pyspark.ml.feature.StringIndexer los metadatos adicionales se almacenan en el marco de datos que marca específicamente la característica transformada como una característica categórica.

Cuando imprima el marco de datos, verá un valor numérico (que es un índice que se corresponde con uno de sus valores categóricos) y, si observa el esquema, verá que su nueva columna transformada es de tipo double . Sin embargo, esta nueva columna que creó con pyspark.ml.feature.StringIndexer.transform no es solo una doble columna normal, sino que tiene meta-datos adicionales asociados que son muy importantes. Puede inspeccionar estos metadatos mirando la propiedad de metadata del campo apropiado en el esquema de su marco de datos (puede acceder a los objetos de esquema de su marco de datos mirando su esquema de marco de datos)

Este metadato adicional tiene dos implicaciones importantes:

  1. Cuando llame a .fit() cuando utilice un modelo basado en árbol, escaneará los metadatos de su marco de datos y reconocerá los campos codificados como categóricos con transformadores como pyspark.ml.feature.StringIndexer (como se indicó anteriormente, hay otros transformadores que también tendrán este efecto, como pyspark.ml.feature.VectorIndexer ). Debido a esto, NO es necesario codificar sus características en caliente después de haberlas transformado con StringIndxer cuando se usan modelos basados ​​en árboles en spark ML (sin embargo, aún tiene que realizar una codificación en caliente cuando se usan otros modelos que no lo hacen). Manejar categóricamente categorías como la regresión lineal, etc.).

  2. Debido a que estos metadatos se almacenan en el marco de datos, puede usar pyspark.ml.feature.IndexToString para revertir los índices numéricos a los valores categóricos originales (que a menudo son cadenas) en cualquier momento.