spark machine learning docs apache-spark apache-spark-mllib apache-spark-ml

apache spark - machine - ¿Cuál es la diferencia entre HashingTF y CountVectorizer en Spark?



spark documentation (3)

Tratando de hacer clasificación de doc en Spark. No estoy seguro de lo que hace el hashing en HashingTF; ¿Sacrifica alguna precisión? Lo dudo, pero no lo sé. La doctora Spark dice que usa el "truco de hash" ... solo otro ejemplo de un nombre realmente malo / confuso usado por los ingenieros (también soy culpable). CountVectorizer también requiere configurar el tamaño del vocabulario, pero tiene otro parámetro, un parámetro de umbral que se puede usar para excluir palabras o tokens que aparecen debajo de algún umbral en el cuerpo del texto. No entiendo la diferencia entre estos dos transformadores. Lo que hace que esto sea importante son los pasos posteriores en el algoritmo. Por ejemplo, si quisiera realizar una SVD en la matriz tfidf resultante, entonces el tamaño del vocabulario determinará el tamaño de la matriz para la SVD, lo que afecta el tiempo de ejecución del código y el rendimiento del modelo, etc. Tengo una dificultad en general Encontrar cualquier fuente sobre Spark Mllib más allá de la documentación de la API y ejemplos realmente triviales sin profundidad.


Algunas diferencias importantes:

  • parcialmente reversible ( CountVectorizer ) vs irreversible ( HashingTF ): dado que el hashing no es reversible, no puede restaurar la entrada original de un vector hash. Por otro lado, el vector de conteo con modelo (índice) se puede usar para restaurar la entrada no ordenada. Como consecuencia, los modelos creados con entrada hash pueden ser mucho más difíciles de interpretar y monitorear.
  • memoria y sobrecarga computacional : HashingTF requiere solo un escaneo de datos y no memoria adicional más allá de la entrada original y el vector. CountVectorizer requiere un escaneo adicional sobre los datos para construir un modelo y una memoria adicional para almacenar vocabulario (índice). En el caso del modelo de lenguaje Unigram, por lo general no es un problema, pero en el caso de n-gramas más altos, puede ser prohibitivamente costoso o no factible.
  • El hashing depende del tamaño del vector, la función de hashing y el documento. El conteo depende del tamaño del vector, el cuerpo de entrenamiento y un documento.
  • Una fuente de la pérdida de información : en el caso de HashingTF es la reducción de la dimensionalidad con posibles colisiones. CountVectorizer descarta tokens infrecuentes. La forma en que afecta a los modelos posteriores depende de un caso de uso particular y de los datos.

El truco del hashing es en realidad el otro nombre del hashing de características.

Estoy citando la definición de Wikipedia:

En el aprendizaje automático, el hash de características, también conocido como truco de hashing, por analogía con el truco del kernel, es una forma rápida y eficiente en el espacio de vectorizar características, es decir, convertir características arbitrarias en índices en un vector o matriz. Funciona aplicando una función de hash a las funciones y utilizando sus valores de hash como índices directamente, en lugar de buscar los índices en una matriz asociativa.

Puedes leer más sobre esto en este documento .

Así que, en realidad, para las funciones de espacio eficiente vectorización

Mientras que CountVectorizer realiza solo una extracción de vocabulario y se transforma en vectores.


Según la documentación de Spark 2.1.0,

Tanto HashingTF como CountVectorizer se pueden usar para generar el término vectores de frecuencia.

HashingTF

HashingTF es un transformador que toma conjuntos de términos y los convierte en vectores de características de longitud fija. En el procesamiento de texto, un "conjunto de términos" puede ser una bolsa de palabras. HashingTF utiliza el truco de hashing. Una característica en bruto se asigna a un índice (término) mediante la aplicación de una función hash. La función hash utilizada aquí es MurmurHash 3. Luego, las frecuencias de los términos se calculan en función de los índices asignados. Este enfoque evita la necesidad de calcular un mapa de término a índice global, que puede ser costoso para un gran corpus, pero sufre de posibles colisiones de hash, donde diferentes características en bruto pueden convertirse en el mismo término después del hashing.

Para reducir la posibilidad de colisión, podemos aumentar la dimensión de la característica de destino, es decir, el número de cubos de la tabla hash. Dado que se utiliza un módulo simple para transformar la función hash en un índice de columna, es recomendable utilizar una potencia de dos como dimensión de la característica, de lo contrario, las características no se asignarán de manera uniforme a las columnas. La dimensión de la característica predeterminada es 2 ^ 18 = 262,144. Un parámetro de alternancia binario opcional controla el término conteos de frecuencia. Cuando se establece en verdadero, todos los conteos de frecuencia distintos de cero se establecen en 1. Esto es especialmente útil para modelos probabilísticos discretos que modelan conteos binarios, en lugar de números enteros.

CountVectorizer

CountVectorizer y CountVectorizerModel pretenden ayudar a convertir una colección de documentos de texto en vectores de conteos de tokens. Cuando no está disponible un diccionario a priori, CountVectorizer se puede usar como un Estimador para extraer el vocabulario y genera un CountVectorizerModel. El modelo produce representaciones dispersas para los documentos sobre el vocabulario , que luego pueden pasarse a otros algoritmos como LDA .

Durante el proceso de ajuste, CountVectorizer seleccionará las principales palabras de tamaño de voz ordenadas por frecuencia de término en todo el corpus. Un parámetro opcional minDF también afecta el proceso de adaptación al especificar el número mínimo (o fracción si <1.0) de los documentos en los que debe aparecer un término para incluirlo en el vocabulario. Otro parámetro opcional de alternar binario controla el vector de salida. Si se establece en verdadero, todos los conteos distintos de cero se establecen en 1. Esto es especialmente útil para modelos probabilísticos discretos que modelan conteos binarios, en lugar de números enteros.

Código de muestra

from pyspark.ml.feature import HashingTF, IDF, Tokenizer from pyspark.ml.feature import CountVectorizer sentenceData = spark.createDataFrame([ (0.0, "Hi I heard about Spark"), (0.0, "I wish Java could use case classes"), (1.0, "Logistic regression models are neat")], ["label", "sentence"]) tokenizer = Tokenizer(inputCol="sentence", outputCol="words") wordsData = tokenizer.transform(sentenceData) hashingTF = HashingTF(inputCol="words", outputCol="Features", numFeatures=100) hashingTF_model = hashingTF.transform(wordsData) print "Out of hashingTF function" hashingTF_model.select(''words'',col(''Features'').alias(''Features(vocab_size,[index],[tf])'')).show(truncate=False) # fit a CountVectorizerModel from the corpus. cv = CountVectorizer(inputCol="words", outputCol="Features", vocabSize=20) cv_model = cv.fit(wordsData) cv_result = model.transform(wordsData) print "Out of CountVectorizer function" cv_result.select(''words'',col(''Features'').alias(''Features(vocab_size,[index],[tf])'')).show(truncate=False) print "Vocabulary from CountVectorizerModel is /n" + str(cv_model.vocabulary)

La salida es la siguiente

Hashing TF pierde el vocabulario que es esencial para técnicas como LDA. Para esto hay que usar la función CountVectorizer. Independientemente del tamaño del vocabulario, la función CountVectorizer estima el término frecuencia sin ninguna aproximación involucrada a diferencia de HashingTF.

Referencia:

https://spark.apache.org/docs/latest/ml-features.html#tf-idf

https://spark.apache.org/docs/latest/ml-features.html#countvectorizer