¿Cuál es la diferencia entre un vectorizador hash y un vectorizador tfidf

11

Estoy convirtiendo un corpus de documentos de texto en vectores de palabras para cada documento. He intentado esto usando un TfidfVectorizer y un HashingVectorizer

Entiendo que a HashingVectorizerno toma en cuenta los IDFpuntajes como lo TfidfVectorizerhace. La razón por la que todavía estoy trabajando con a HashingVectorizeres la flexibilidad que brinda al tratar con grandes conjuntos de datos, como se explica aquí y aquí . (Mi conjunto de datos original tiene 30 millones de documentos)

Actualmente, estoy trabajando con una muestra de 45339 documentos, por lo tanto, tengo la capacidad de trabajar TfidfVectorizertambién. Cuando uso estos dos vectorizadores en los mismos documentos 45339, las matrices que obtengo son diferentes.

hashing = HashingVectorizer()
with LSM('corpus.db')) as corpus:
    hashing_matrix = hashing.fit_transform(corpus)
print(hashing_matrix.shape) 

forma de matriz de hashing (45339, 1048576)

tfidf = TfidfVectorizer()
with LSM('corpus.db')) as corpus:
    tfidf_matrix = tfidf.fit_transform(corpus)
print(tfidf_matrix.shape) 

Forma de matriz tfidf (45339, 663307)

Quiero comprender mejor las diferencias entre ay HashingVectorizera TfidfVectorizer, y la razón por la cual estas matrices están en diferentes tamaños, particularmente en el número de palabras / términos.

Minu
fuente
¿Puedes por favor compartir el conjunto de datos conmigo? (respuesta a eliminar)
nKarza

Respuestas:

7

La principal diferencia es que HashingVectorizeraplica una función hash a los recuentos de frecuencia de términos en cada documento, donde TfidfVectorizerescala esos recuentos de frecuencia de términos en cada documento penalizando los términos que aparecen más ampliamente en el corpus. Aquí hay un gran resumen: https://spark.apache.org/docs/latest/mllib-feature-extraction.html

  • Las funciones hash son una forma eficiente de asignar términos a características; no necesariamente debe aplicarse solo a las frecuencias de término, pero así HashingVectorizeres como se emplea aquí. Junto con los documentos 45339, sospecho que el vector de características tiene una longitud de 1048576 porque es el valor predeterminado 2 ^ 20 n_features; podría reducir esto y hacerlo menos costoso de procesar pero con un mayor riesgo de colisión, donde la función asigna diferentes términos a la misma característica: http://preshing.com/20110504/hash-collision-probabilities/

  • Dependiendo del caso de uso de los vectores de palabras, puede ser posible reducir la longitud del vector de características hash (y, por lo tanto, la complejidad) significativamente con una pérdida aceptable de precisión / efectividad (debido a una mayor colisión). Scikit-learn tiene algunos parámetros de hashing que pueden ayudar, por ejemplo alternate_sign.

  • Si la matriz de hash es más ancha que el diccionario, significará que muchas de las entradas de columna en la matriz de hash estarán vacías, y no solo porque un documento dado no contiene un término específico sino porque están vacías en todo matriz. Si no es así, podría enviar varios términos al mismo hash de la característica: esta es la 'colisión' de la que hemos estado hablando. HashingVectorizertiene una configuración que funciona para mitigar esta llamada alternate_signque está activada de manera predeterminada, descrita aquí: en.wikipedia.org/wiki/Feature_hashing#Properties

  • 'Frecuencia de término - frecuencia de documento inversa' toma las frecuencias de término en cada documento y las pondera penalizando las palabras que aparecen con mayor frecuencia en todo el corpus. La intuición es que los términos que se encuentran situacionalmente tienen más probabilidades de ser representativos del tema de un documento específico. Esto es diferente a una función de hash en que es necesario tener un diccionario completo de palabras en el corpus para calcular la frecuencia inversa del documento. Espero que sus dimensiones de matriz tf.idf sean 45339 documentos por 663307 palabras en el corpus; Manning et al proporcionan más detalles y ejemplos de cálculo: https://nlp.stanford.edu/IR-book/html/htmledition/term-frequency-and-weighting-1.html

'Minería de conjuntos de datos masivos' de Leskovec et al tiene un montón de detalles sobre el hashing de características y tf.idf, los autores hicieron que el pdf estuviera disponible aquí: http://www.mmds.org/

redhqs
fuente
1
Si tfidf vectorizernecesita un diccionario completo de palabras para los cálculos de idf, ¿no deberían los términos en la matriz tfidf ser más que los términos en la matriz hash?
Minu
2
Si la matriz de hash es más ancha que el diccionario, significará que muchas de las entradas de columna en la matriz de hash estarán vacías, y no solo porque un documento dado no contiene un término específico sino porque están vacías en todo matriz. Ligeramente fuera de tema, pero ¿está procesando las palabras en sus documentos antes de vectorizar? Stopwords, stemming, etc.
redhqs
Sí, estoy procesando Estoy usando espacioso.
Minu
1
Confirmación: Entonces, ¿1048576 es la longitud predeterminada de cualquier matriz de hashing si no se menciona n_features? Si realmente solo hay 663307 palabras en el corpus, las 385269 características restantes están vacías. ¿Cómo puede hacer que esta matriz de hash se ajuste sin todas las características vacías?
Minu
1
Así es: puede cambiar el tamaño de la cantidad de características cambiando el parámetro n_features=1048576, si tiene tiempo intente 640k, 320k y vea si tiene un gran impacto en su precisión. Debería acelerar tu tiempo de entrenamiento al menos. ¡Mira la respuesta de @ Nathan n_features=5!
redhqs
5

El HashingVectorizertiene un parámetro n_featuresque es 1048576de forma predeterminada. Cuando usan hash, en realidad no calculan los términos de mapeo de un diccionario en un índice único para usar en cada uno. En su lugar, simplemente hash de cada término y utiliza un tamaño suficientemente grande para que no se espera que haya demasiadas colisiones: hash(term) mod table_size. Puede hacer que la matriz devuelta tenga el tamaño que desee mediante la configuración n_features. Debes ajustar esto para que esté en el estadio correcto para tu corpus si no crees que el valor predeterminado es razonable (tenerlo más grande causará menos colisiones, aunque requiere más memoria).

from sklearn.feature_extraction.text import HashingVectorizer
vectorizer = HashingVectorizer()
print(vectorizer.transform(['a very small document']).shape)
(1, 1048576)

small_vectorizer = HashingVectorizer(n_features=5)
print(small_vectorizer.transform(['a very small document']).shape)    
(1, 5)
Nathan
fuente
0

HashingVectorizer y CountVectorizer (nota no Tfidfvectorizer) están destinados a hacer lo mismo. Que consiste en convertir una colección de documentos de texto en una matriz de ocurrencias de tokens.

Si está buscando obtener frecuencias de término ponderadas por su importancia relativa (IDF), entonces Tfidfvectorizer es lo que debe usar. Si necesita los recuentos sin procesar o los recuentos normalizados (frecuencia de término), entonces debe usar CountVectorizer o HashingVectorizer.

Para obtener información sobre HashingVectorizer, consulte este artículo sobre HashingVectorizer vs. CountVectorizer .

Para obtener más información sobre Tfidfvectorizer, consulte este artículo sobre Cómo usar Tfidftransformer y Tfidfvectorizer .

kavgan
fuente