python - sklearn - Interpretación de la suma de las puntuaciones de palabras TF-IDF en los documentos
tf idf python (4)
Si queremos encontrar la "prominencia" o la "importancia" de las palabras dentro de este corpus, ¿podemos simplemente hacer la suma de las puntuaciones de tf-idf en todos los documentos y dividirla por el número de documentos? Si es así, ¿cuál es la interpretación matemática de la suma de los puntajes de palabras de TF-IDF en los documentos?
Si sumó los puntajes td-idf en todos los documentos, los términos que de otra manera tendrían puntajes bajos podrían obtener un impulso y los términos con puntajes más altos podrían tener sus puntajes deprimidos.
No creo que simplemente dividir por el número total de documentos sea una normalización suficiente para abordar esto. ¿Tal vez incorporar la longitud del documento en el factor de normalización? De cualquier manera, creo que todos estos métodos aún deberían ajustarse por dominio.
Entonces, en términos generales, matemáticamente espero que obtengas un efecto de promedio no deseado.
Primero, extraigamos los puntajes TF-IDF por término por documento:
from gensim import corpora, models, similarities
documents = ["Human machine interface for lab abc computer applications",
"A survey of user opinion of computer system response time",
"The EPS user interface management system",
"System and human system engineering testing of EPS",
"Relation of user perceived response time to error measurement",
"The generation of random binary unordered trees",
"The intersection graph of paths in trees",
"Graph minors IV Widths of trees and well quasi ordering",
"Graph minors A survey"]
stoplist = set(''for a of the and to in''.split())
texts = [[word for word in document.lower().split() if word not in stoplist] for document in documents]
dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]
tfidf = models.TfidfModel(corpus)
corpus_tfidf = tfidf[corpus]
Imprimiéndolo
for doc in corpus_tfidf:
print doc
[afuera]:
[(0, 0.4301019571350565), (1, 0.4301019571350565), (2, 0.4301019571350565), (3, 0.4301019571350565), (4, 0.2944198962221451), (5, 0.2944198962221451), (6, 0.2944198962221451)]
[(4, 0.3726494271826947), (7, 0.27219160459794917), (8, 0.3726494271826947), (9, 0.27219160459794917), (10, 0.3726494271826947), (11, 0.5443832091958983), (12, 0.3726494271826947)]
[(6, 0.438482464916089), (7, 0.32027755044706185), (9, 0.32027755044706185), (13, 0.6405551008941237), (14, 0.438482464916089)]
[(5, 0.3449874408519962), (7, 0.5039733231394895), (14, 0.3449874408519962), (15, 0.5039733231394895), (16, 0.5039733231394895)]
[(9, 0.21953536176370683), (10, 0.30055933182961736), (12, 0.30055933182961736), (17, 0.43907072352741366), (18, 0.43907072352741366), (19, 0.43907072352741366), (20, 0.43907072352741366)]
[(21, 0.48507125007266594), (22, 0.48507125007266594), (23, 0.48507125007266594), (24, 0.48507125007266594), (25, 0.24253562503633297)]
[(25, 0.31622776601683794), (26, 0.31622776601683794), (27, 0.6324555320336759), (28, 0.6324555320336759)]
[(25, 0.20466057569885868), (26, 0.20466057569885868), (29, 0.2801947048062438), (30, 0.40932115139771735), (31, 0.40932115139771735), (32, 0.40932115139771735), (33, 0.40932115139771735), (34, 0.40932115139771735)]
[(8, 0.6282580468670046), (26, 0.45889394536615247), (29, 0.6282580468670046)]
Si queremos encontrar la "prominencia" o la "importancia" de las palabras dentro de este corpus, ¿podemos simplemente hacer la suma de las puntuaciones de tf-idf en todos los documentos y dividirla por el número de documentos? Es decir
>>> tfidf_saliency = Counter()
>>> for doc in corpus_tfidf:
... for word, score in doc:
... tfidf_saliency[word] += score / len(corpus_tfidf)
...
>>> tfidf_saliency
Counter({7: 0.12182694202050007, 8: 0.11121194156107769, 26: 0.10886469856464989, 29: 0.10093919463036093, 9: 0.09022272408985754, 14: 0.08705221175200946, 25: 0.08482488519466996, 6: 0.08143359568202602, 10: 0.07480097322359022, 12: 0.07480097322359022, 4: 0.07411881371164887, 13: 0.07117278898823597, 5: 0.07104525967490458, 27: 0.07027283689263066, 28: 0.07027283689263066, 11: 0.060487023243988705, 15: 0.055997035904387725, 16: 0.055997035904387725, 21: 0.05389680556362955, 22: 0.05389680556362955, 23: 0.05389680556362955, 24: 0.05389680556362955, 17: 0.048785635947490406, 18: 0.048785635947490406, 19: 0.048785635947490406, 20: 0.048785635947490406, 0: 0.04778910634833961, 1: 0.04778910634833961, 2: 0.04778910634833961, 3: 0.04778910634833961, 30: 0.045480127933079706, 31: 0.045480127933079706, 32: 0.045480127933079706, 33: 0.045480127933079706, 34: 0.045480127933079706})
En cuanto a la salida, podríamos suponer que la palabra más "prominente" en el corpus es:
>>> dictionary[7]
u''system''
>>> dictionary[8]
u''survey''
>>> dictionary[26]
u''graph''
Si es así, ¿cuál es la interpretación matemática de la suma de los puntajes de palabras de TF-IDF en los documentos?
Esta es una gran discusión. Gracias por comenzar este hilo. La idea de incluir la longitud del documento por @avip parece interesante. Habrá que experimentar y comprobar los resultados. Mientras tanto, permítame tratar de hacer la pregunta un poco diferente. ¿Qué estamos tratando de interpretar al consultar las puntuaciones de relevancia de TF-IDF?
- Posiblemente tratando de entender la relevancia de la palabra a nivel de documento
- Posiblemente tratando de entender la relevancia de la palabra por clase.
Posiblemente tratando de entender la relevancia de la palabra en general (en todo el cuerpo)
# # features, corpus = 6 documents of length 3 counts = [[3, 0, 1], [2, 0, 0], [3, 0, 0], [4, 0, 0], [3, 2, 0], [3, 0, 2]] from sklearn.feature_extraction.text import TfidfTransformer transformer = TfidfTransformer(smooth_idf=False) tfidf = transformer.fit_transform(counts) print(tfidf.toarray()) # lambda for basic stat computation summarizer_default = lambda x: np.sum(x, axis=0) summarizer_mean = lambda x: np.mean(x, axis=0) print(summarizer_default(tfidf)) print(summarizer_mean(tfidf))
Resultado:
# Result post computing TF-IDF relevance scores
array([[ 0.81940995, 0. , 0.57320793],
[ 1. , 0. , 0. ],
[ 1. , 0. , 0. ],
[ 1. , 0. , 0. ],
[ 0.47330339, 0.88089948, 0. ],
[ 0.58149261, 0. , 0.81355169]])
# Result post aggregation (Sum, Mean)
[[ 4.87420595 0.88089948 1.38675962]]
[[ 0.81236766 0.14681658 0.2311266 ]]
Si observamos detenidamente, nos damos cuenta de que la característica 1 que ocurrió en todo el documento no se ignora completamente porque la implementación sklearn de idf = log [n / df (d, t)] + 1. +1 se agrega para que la palabra importante lo que ocurre en todos los documentos no se ignora. Por ejemplo, la palabra "bicicleta" aparece con mucha frecuencia al clasificar un documento en particular como "motocicleta" (conjunto de datos de 20_newsgroup).
Ahora, en lo que respecta a las primeras 2 preguntas, una está tratando de interpretar y comprender las principales características comunes que pueden estar ocurriendo en el documento. En ese caso, agregar de alguna forma, incluida toda la posible aparición de la palabra en un documento, no es quitar nada, ni siquiera matemáticamente. En mi opinión, esta consulta es muy útil para explorar el conjunto de datos y ayudar a comprender de qué trata el conjunto de datos. La lógica podría aplicarse a la vectorización utilizando también Hashing.
relevance_score = mean (tf (t, d) * idf (t, d)) = mean ((sesgo + inital_wt * F (t, d) / max {F (t '', d)}) * log (N / df (d, t)) + 1))
La pregunta 3 es muy importante ya que también podría contribuir a la selección de características para construir un modelo predictivo. El solo hecho de usar las puntuaciones de TF-IDF de forma independiente para la selección de características puede ser engañoso en múltiples niveles. Adoptar una prueba estadística más teórica como la pareja ''chi2'' con puntuaciones de relevancia TF-IDF podría ser un mejor enfoque. Dicha prueba estadística también evalúa la importancia de la característica en relación con la clase objetivo respectiva.
Y, por supuesto, combinar dicha interpretación con las ponderaciones de las características aprendidas del modelo sería muy útil para comprender completamente la importancia de las características derivadas del texto.
** El problema es un poco más complejo de cubrir en detalle aquí. Pero, esperando lo anterior ayuda. ¿Qué sienten los demás?
Referencia: https://arxiv.org/abs/1707.05261
Hay dos contextos en los que se puede calcular la prominencia en ellos.
- prominencia en el corpus
- prominencia en un solo documento
la prominencia en el corpus puede calcularse simplemente contando las apariencias de una palabra en particular en el corpus o invirtiendo el conteo de los documentos en los que aparece esa palabra (IDF = Frecuencia de documentos invertida). Porque las palabras que contienen el significado específico no aparecen en todas partes.
La salencia en el documento se calcula por tf_idf. Porque eso se compone de dos tipos de información. La información global (basada en el corpus) y la información local (basada en el documento). La reclamación de que "la palabra con mayor frecuencia en el documento es más importante en el documento actual" no es completamente verdadera o falsa porque depende de la prominencia global de la palabra. En un documento en particular, tiene muchas palabras como "it, is, am, are, ..." con frecuencias grandes. ¡Pero esta palabra no es importante en ningún documento y puede tomarlas como palabras de parada!
---- editar ---
El denominador (= len (corpus_tfidf)) es un valor constante y podría ignorarse si se quiere tratar con la ordinalidad en lugar de la cardinalidad de la medición. Por otro lado, sabemos que IDF significa Frecuencia de Documento Invertida, por lo que IDF puede ser reorientada por 1 / DF. Sabemos que el DF es un valor de nivel de corpus y TF es el valor de nivel de documento. TF-IDF Summation convierte TF a nivel de documento en TF a nivel de Corpus. De hecho, la suma es igual a esta fórmula:
recuento ( palabra ) / recuento (documentos contienen palabra )
Esta medida se puede llamar valor de dispersión inversa . Cuando el valor aumenta, las palabras se agrupan en un subconjunto más pequeño de documentos y viceversa.
Creo que esta fórmula no es tan útil.
La interpretación de TF-IDF en corpus es la mayor TF-IDF en corpus para un término dado.
Encuentra las palabras principales en corpus_tfidf.
topWords = {}
for doc in corpus_tfidf:
for iWord, tf_idf in doc:
if iWord not in topWords:
topWords[iWord] = 0
if tf_idf > topWords[iWord]:
topWords[iWord] = tf_idf
for i, item in enumerate(sorted(topWords.items(), key=lambda x: x[1], reverse=True), 1):
print("%2s: %-13s %s" % (i, dictionary[item[0]], item[1]))
if i == 6: break
Carro de comparación de salida:
NOTA : Podría usar gensim
para crear un dictionary
coincida con corpus_tfidf
.
Solo puede mostrar palabras indias.
Question tfidf_saliency topWords(corpus_tfidf) Other TF-IDF implentation
---------------------------------------------------------------------------
1: Word(7) 0.121 1: Word(13) 0.640 1: paths 0.376019
2: Word(8) 0.111 2: Word(27) 0.632 2: intersection 0.376019
3: Word(26) 0.108 3: Word(28) 0.632 3: survey 0.366204
4: Word(29) 0.100 4: Word(8) 0.628 4: minors 0.366204
5: Word(9) 0.090 5: Word(29) 0.628 5: binary 0.300815
6: Word(14) 0.087 6: Word(11) 0.544 6: generation 0.300815
El cálculo de TF-IDF siempre tiene en cuenta el corpus.
Probado con Python: 3.4.2