Es una técnica que consiste en representar palabras como vectores numéricos, lo cual se ha descubierto que potencia las tareas de descubrimiento de conocimiento y de recomendación de contenido. Si bien la teoría sobre esta técnica ya era conocida desde los años 90, fue hasta el 2013 que se popularizó con el método para crear words embeddings llamado word2vec.
Word2vec es una técnica para el procesamiento de lenguaje natural publicada en 2013. El algoritmo Word2vec utiliza un modelo de red neuronal para aprender asociaciones de palabras a partir de un gran corpus de texto. Una vez entrenado, dicho modelo puede detectar palabras sinónimas o sugerir palabras adicionales para una frase sin terminar. Como su nombre indica, Word2vec representa cada palabra distinta con una lista particular de números llamada vector. Los vectores están escogidos cuidadosamente de forma que una función matemática sencilla (la similitud coseno entre los vectores) indica el nivel de la similitud semántica entre las palabras representadas por dichos vectores.
Por otro lado, veamos la siguiente imagen
el cual representa un espacio (espacio vectorial) compuesto de palabras, donde el lugar que ocupan las palabras en dicho espacio es de suma importancia pues determina su significado. Dentro de dicho espacio podremos encontrar grupos de palabras que comparte característica en común; por ejemplo podemos hallar grupos que sean sólo números, grupos de animales, etcétera. Otro ejemplo de asociaciones interesantes que podremos ver es que la distancia entre las palabras rey y hombre es la misma que la distancia entre las palabras mujer y reina.
Al entrenar al algorítmo word2vec se usaron una gran cantidad de documentos que contenían texto de todo tipo de vocabulario, consiguieron además representar palabras como vectores para determinar su lugar en el espacio y hacer aritmética con ellas, esto es, la representación que consigue word2vec mantiene las relaciones semánticas y sintácticas de las palabras, lo que permite operar con ellas. Por ejemplo, si tenemos la suma de las palabras hombre y rey, le restamos hombre y le sumamos mujer, obtendremos como resultado la palabra reina.
Gensim es una librería para diversas aplicaciones del NLP, como la indexación de documentos, la recuperación por similitud, entre otras. Está diseñado para manejar grandes colecciones de texto utilizando la transmisión de datos. Además, utiliza los mejores modelos académicos para la realización de tareas complejas como la creación de documentos o llevar acabo el proceso de word embedding o la creación de corpus. Asimismo, ayuda para la identificación de temas y comparación de documentos.
Utilizaremos particularmente la función Dictionary()
para crear una asignación con identificadores numéricos únicos para cada token, asimismo, esta función realizará un procedimiento como el de la función Counter()
al contar el número de apariciones de cada token en el documento en cuestión, lo cual nos permitirá representar documentos completos usando solo una lista de sus identificadores de token y la frecuencia de aparición de cada token. Recordemos que, antes de lo que haremos a continuación, se realiza primero la limpieza o el preprocesamiento.
# Importaciones necesarias
from gensim.corpora.dictionary import Dictionary
from nltk.tokenize import word_tokenize
# Cada elemento de la lista representa un documento
documents = ['The movie was about a spaceship and aliens.',
'I really liked the movie!',
'Awesome action scenes, but boring characters.',
'The movie was awful! I hate aliens films',
'More space films, please!']
# Tokenizamos cada documento
docs_tokenized = [word_tokenize(doc.lower()) for doc in documents]
# Creamos la asignacion con una identificacion para cada token y la
# frecuencia de aparicion de cada token para cada documento
dictionary = Dictionary(docs_tokenized)
# Podemos ver los tokens y sus identificadores de todos los documentos
# utilizando el atributo token2id
dictionary.token2id
{'.': 0, 'a': 1, 'about': 2, 'aliens': 3, 'and': 4, 'movie': 5, 'spaceship': 6, 'the': 7, 'was': 8, '!': 9, 'i': 10, 'liked': 11, 'really': 12, ',': 13, 'action': 14, 'awesome': 15, 'boring': 16, 'but': 17, 'characters': 18, 'scenes': 19, 'awful': 20, 'films': 21, 'hate': 22, 'more': 23, 'please': 24, 'space': 25}
Con base en lo anterior podemos crear un corpus de Gensim, el cual es un poco diferente a un corpus normal (el cual es una colección de documentos), y que transforma cada documento en una "bolsa de palabras" utilizando para ello los identificadores de los tokens y la frecuencia de cada token en el documento.
# Creamos el corpus Gensim para cada documento tokenizado
# mediante el metodo doc2bow() aplicado al diccionario
# dictionary que habiamos creado antes
corpus = [dictionary.doc2bow(doc) for doc in docs_tokenized]
corpus
[[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1)], [(5, 1), (7, 1), (9, 1), (10, 1), (11, 1), (12, 1)], [(0, 1), (13, 1), (14, 1), (15, 1), (16, 1), (17, 1), (18, 1), (19, 1)], [(3, 1), (5, 1), (7, 1), (8, 1), (9, 1), (10, 1), (20, 1), (21, 1), (22, 1)], [(9, 1), (13, 1), (21, 1), (23, 1), (24, 1), (25, 1)]]
donde vemos una lista de listas, cada lista de la lista grande representa un documento, y donde cada lista está conformada por tuplas; la primer entrada de dicha tupla corresponde al identificador del token (denominémoslo token id) y el segundo elemento la frecuencia del token en cuestión en el documento.
La ventaja de este modelo, a diferencia de lo que haciamos antes con la función Counter()
, es que podemos guardar, actualizar y reutilizar fácilmente gracias a las herramientas adicionales de la librería Gensim. Además, podemos actualizar con nuevos textos o extraer solo las palabras que cumplen determinados umbrales.
Es un modelo de NLP de uso común que nos ayuda a determinar las palabras más importantes en cada documento del corpus. Es una medida numérica que expresa cuan relevante es una palabra para un documento en una colección. Dicho valor que mencionamos aumenta proporcionalmente al número de veces que una palabra aparece en el documento, pero es compensada por la frecuencia de la palabra en la colección de documentos, lo que permite manejar el hecho de que algunas palabras son generalmente más comunes que otras. Este modelo puede utilizarse para el filtrado de las denominadas stopswords.
En resumen, podemos filtrar algunas palabras comunes pero irrelevantes, mientras retenemos palabras importantes que afectan todo el texto.
Para calcular la medida numérica del modelo tf-idf requerimos calcular la medida de frecuencia de término $tf(t,d)$ , donde $t$ es la frecuencia bruta del término en cuestión en el documento $d$, es decir, el número de veces que el término $t$ ocurre en el documento $d$. Si denominamos $f(t,d)$ a la frecuencia bruta de $t$ en el documento $d$, entonces $tf(t,d)=f(t,d)$. Otras posibilidades son donde $tf(t,d)$ hace alusión a las frecuencias booleanas, a las frecuencias de escala lograrítmica, frecuencias normalizadas, entre otras. La frecuencia inversa de documento es una medida de si el término es común o no en la colección de documentos. Se obtiene dividiendo el número total de documentos por el número de documentos que contienen el término, y se toma el logarítmo de ese cociente, esto es:
$$ idf(t, D)=log\left(\frac{|D|}{1+|\{d\in D: t\in d\}|}\right) $$donde $|D|$ es el número de documentos en la colección o corpus y $|\{d\in D: t\in d\}|$ es el número de documentos donde aparece el término $t$. Finalmente: $tfidf(t,d,D)=tf(tmd)\cdot idf(t,D)$. De donde un peso alto en tf-idf se alcanza con una elevada frecuencia de término (en el documento dado) y una pequeña frecuencia de ocurrencia del término en la colección completa de documentos. Cuando un término aparece en muchos documentos, el cociente dentro del logarítmo se acerca a 1, por lo cual el valor de tf-idf se acercará a 0.
De tal manera, tfidf tomará textos que comparten un lenguaje en común y ayudará a mantener en el documento en específico las palabras más frecuentes, a las cuales se les asignará un peso alto, y a las palabras comunes se les asignará un peso bajo. Por ejemplo
# Importacion necesaria
from gensim.models.tfidfmodel import TfidfModel
# Aplicamos el modelo tfidf al corpus que habiamos
# creado antes
tfidf = TfidfModel(corpus)
# Accedemos a los pesos dados por el modelo tfidf
# a nuestro corpus, especificamente para
# el primer documento
tfidf[corpus[1]]
[(5, 0.19584951664054379), (7, 0.19584951664054379), (9, 0.19584951664054379), (10, 0.35130402350758305), (11, 0.6170552582882589), (12, 0.6170552582882589)]
donde dichos pesos representan una herramienta para determinar buenos temas y palabras claves para un corpus con un vocabulario compartido, es decir, un corpus de varios documentos los cuales comparten vocabulario. Lo anterior también nos dice, por ejemplo, que las palabras movie, the, la letra i y el símbolo ! son comunes y que las palabras liked y really son frecuentes.
Podemos almacenar los número obtenidos por el modelo tf-idf y guardarlos en un dataframe
import pandas as pd
list_auxiliar = []
# Recorremos i sobre el numero total de documentos
for i in range(len(documents)):
# Creamos un dataframe con los valores obtenidos (token id, frecuencia tf-idf)
# para el documento i del corpus
df = pd.DataFrame(tfidf[corpus[i]])
# Agremos dicho dataframe a la lista auxiliar
list_auxiliar.append(df)
# concatenamos los dataframes de la lista auxiliar
df = pd.concat(list_auxiliar).rename(columns={0: 'Token ID', 1: 'Medida tf-idf'})
# Ordenamos de manera descendiente
df.sort_values('Medida tf-idf', ascending=False)[0:8]
Token ID | Medida tf-idf | |
---|---|---|
4 | 11 | 0.617055 |
5 | 12 | 0.617055 |
8 | 22 | 0.527139 |
6 | 20 | 0.527139 |
5 | 25 | 0.516467 |
4 | 24 | 0.516467 |
3 | 23 | 0.516467 |
2 | 2 | 0.439635 |
Lo cual parece indicar que las palabras de token id 11,12,22,20,25,24 y 23 son las más importantes de nuestro corpus y nos ayudan a describir la idea o ideas detrás del contenido del corpus en general. Podemos crear un diccionario auxiliar donde voltearemos las keys-values del diccionario dictionary.token2id
para ver de manera más directa las palabras de los índices que mencionamos antes
# tokens id de interes
ids = [11, 12, 22, 20, 25, 24, 23]
# diccionario auxiliar
dic_aux = {}
for key, value in dictionary.token2id.items():
dic_aux[value] = key
# veamos las palabras con los tokens id de interes
for i in ids:
print(dic_aux[i])
liked really hate awful space please more
Asimismo, podemos ver las palabras con un valor tf-idf menor:
df.sort_values('Medida tf-idf')[0:31]
Token ID | Medida tf-idf | |
---|---|---|
5 | 5 | 0.139537 |
7 | 7 | 0.139537 |
0 | 9 | 0.163923 |
1 | 5 | 0.167311 |
2 | 7 | 0.167311 |
4 | 9 | 0.167311 |
1 | 7 | 0.195850 |
0 | 5 | 0.195850 |
2 | 9 | 0.195850 |
1 | 13 | 0.220803 |
0 | 0 | 0.220803 |
0 | 0 | 0.250295 |
8 | 8 | 0.250295 |
3 | 3 | 0.250295 |
1 | 13 | 0.294037 |
2 | 21 | 0.294037 |
5 | 10 | 0.300113 |
7 | 21 | 0.300113 |
3 | 8 | 0.300113 |
0 | 3 | 0.300113 |
3 | 10 | 0.351304 |
7 | 19 | 0.387834 |
3 | 15 | 0.387834 |
5 | 17 | 0.387834 |
4 | 16 | 0.387834 |
2 | 14 | 0.387834 |
6 | 18 | 0.387834 |
6 | 6 | 0.439635 |
4 | 4 | 0.439635 |
2 | 2 | 0.439635 |
1 | 1 | 0.439635 |
Vemos que tenemos en cuestión varias palabras repetidas, pues puede ser que encontremos la misma palabra en más de un documento.
# Eliminamos las palabras repetidas
lista_aux = list(set(df.sort_values('Medida tf-idf')[0:31]['Token ID']))
# Veamos cuales son las palabras de menor importancia o que son muy comunes
for i in lista_aux:
print(dic_aux[i])
. a about aliens and movie spaceship the was ! i , action awesome boring but characters scenes films
vemos también que varias palabras vistas antes son stopswords o símbolos como punto, coma y !.
El análisis de las palabras hecho antes es sobre todo el corpus en general, y no sobre algún documento de éste en particular.
Extraído de: Link
En este ejemplo utilizaremos un conjunto de datos de uno de los populares concursos automatizados de puntuación de ensayos financiados por la Fundación Hewlett: puntuación de respuestas cortas. El conjunto de datos incluye las respuestas de los estudiantes a diez conjuntos diferentes de elementos de respuesta corta y puntajes asignados por dos evaluadores humanos. El conjunto de datos consta de las siguientes variables:
Para este ejemplo utilizaremos el "Conjunto de ensayos 3", en el que se pide a los estudiantes que expliquen en qué se parecen los pandas de China a los koalas de Australia y en qué se diferencian de las pitones. También deben respaldar sus respuestas con información de los artículos proporcionados en el pasaje de lectura incluido en el ítem. Hay tres categorías de puntuación (0, 1 o 2 puntos). Cada categoría de puntaje contiene una variedad de respuestas de los estudiantes que reflejan las descripciones que se dan a continuación:
Puntuación 2 : La respuesta demuestra una exploración o desarrollo de las ideas presentadas en el texto, una sólida comprensión conceptual mediante la inclusión de información relevante específica del texto, una extensión de ideas que puede incluir inferencias extensas y/o perspicaces, conexiones entre ideas en el texto, y referencias a conocimientos y/o experiencias previas.
Puntuación 1 : La respuesta demuestra alguna exploración o desarrollo de las ideas presentadas en el texto una comprensión fundamental mediante la inclusión de alguna información relevante del texto una extensión de ideas que carece de profundidad, aunque puede incluir algunas inferencias, conexiones entre ideas en el texto, o referencias a conocimientos y/o experiencias previas.
Puntaje 0 : La respuesta demuestra exploración o desarrollo limitado o nulo de las ideas presentadas en el texto Comprensión limitada o nula del texto, puede ser ilógica, vaga o irrelevante Posibles inferencias incompletas o limitadas, conexiones entre ideas en el texto o referencias a conocimientos y/o experiencias previas.
Ahora, comencemos nuestro análisis importando los datos a Python y seleccionando el Conjunto de ensayos 3.
# Realizamos la importacion de la base de datos desde el siguiente link
link = 'https://raw.githubusercontent.com/okanbulut/blog/master/data_and_codes/train_rel_2.tsv'
# Dado que es un archivo tsv la separacion sera por \t
df = pd.read_csv(link, sep = '\t')
# Veamos el dataframe creado
df
Id | EssaySet | Score1 | Score2 | EssayText | |
---|---|---|---|---|---|
0 | 1 | 1 | 1 | 1 | Some additional information that we would need... |
1 | 2 | 1 | 1 | 1 | After reading the expirement, I realized that ... |
2 | 3 | 1 | 1 | 1 | What you need is more trials, a control set up... |
3 | 4 | 1 | 0 | 0 | The student should list what rock is better an... |
4 | 5 | 1 | 2 | 2 | For the students to be able to make a replicat... |
... | ... | ... | ... | ... | ... |
17038 | 27584 | 10 | 1 | 1 | white :: white becuase if you live in a hot pl... |
17039 | 27585 | 10 | 1 | 1 | light gray :: This color will affect the dogho... |
17040 | 27586 | 10 | 1 | 1 | light gray :: i think light gray would work th... |
17041 | 27587 | 10 | 1 | 0 | dark gray :: if they painted the doghouse dar... |
17042 | 27588 | 10 | 0 | 1 | white :: the black would affect the doghouse b... |
17043 rows × 5 columns
Pero sólo trabajaremos con el conjunto de ensayos 3, además solo consideraremos las columnas Score1 y EssayText, esto es:
df_3 = df[df['EssaySet'] == 3].reset_index()[['Score1', 'EssayText']]
df_3 = df_3.rename(columns={'Score1': 'Score', 'EssayText': 'Response'})
df_3
Score | Response | |
---|---|---|
0 | 1 | China's panda and Australia's koala are two an... |
1 | 1 | Pandas and koalas are similar because they are... |
2 | 1 | Pandas in China and Koalas in Australia are si... |
3 | 2 | Pandas in China only eat bamboo and Koalas in ... |
4 | 0 | Pandas in China and koalas from Australia are ... |
... | ... | ... |
1803 | 2 | Pandas in China must live these because they e... |
1804 | 0 | They are similar because they are not as visio... |
1805 | 1 | Pandas in china are similar to Australia's kol... |
1806 | 1 | The China's panda and the Eustralia's koala ar... |
1807 | 1 | Pandas a koalas are similar because both have ... |
1808 rows × 2 columns
df_3.shape
(1808, 2)
Consideraremos a cada respuesta, o cada fila, como un documento, donde cada documento incluye un conjunto de palabras que contribuyen al significado de la oración, así como palabras vacías (p. ej., artículos, preposiciones, pronombres y conjunciones) que no agregan mucha información al texto.
Dado que las palabras vacías son muy comunes y, sin embargo, solo brindan información de bajo nivel, eliminarlas del texto puede ayudarnos a resaltar las palabras que son más importantes para cada documento. Además, la presencia de palabras vacías conduce a una alta escasez y alta dimensionalidad en los datos. Además, los textos en mayúsculas y minúsculas y la lematización son otros factores que pueden afectar la vectorización del texto. Por lo tanto, antes de realizar la vectorización TF-IDF del texto, un proceso de preprocesamiento que implica la eliminación de palabras vacías, la conversión de letras mayúsculas a minúsculas y la lematización, se puede implementar de la siguiente manera:
# Importaciones necesarias
import re
import nltk
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
# Stopwords del ingles
stopwords = stopwords.words('english')
# Instanciamos el lematizador
lemmatizer = WordNetLemmatizer()
# Lista auxiliar para almacenar los textos sin stopwords
data_without_stopwords = []
# Preprocesamiento
for i in range(df_3.shape[0]):
# quitamos todos los caracteres que no sean alfanumericos
# de cada documento (fila del dataframe)
doc = re.sub('\W+', ' ', df_3.iloc[i][1])
# convertimos todo el texto a minusculas
doc = doc.lower()
# partimos el texto por palabras
doc = doc.split()
# lematizamos cada palabra para las palabras que no sean stopwords
doc = [lemmatizer.lemmatize(word) for word in doc if word not in set(stopwords)]
# unimos de nuevo las palabras para formar el documento ya "limpio"
doc = ' '.join(doc)
# agregamos cada documento a la lista
data_without_stopwords.append(doc)
# documento 1
data_without_stopwords[0]
'china panda australia koala two animal arent predator panda eat bamboo koala eat eucalyptus leaf therefore harmless different python python potentialy dangerous considering swallow entire alligator could conceivably python shacking upto potomac'
# Comparamos
df_3.iloc[0][1]
"China's panda and Australia's koala are two animals that arent predator, pandas eat bamboo and koala's eat eucalyptus leaves. Therefore, they are harmless. They are both different from pythons because pythons are potentialy dangerous considering they can swallow an entire alligator you could conceivably have pythons shacking upto the Potomac"
Podemos ver que después del preprocesamiento, las palabras vacías se han eliminado, todas las palabras se han transformado en minúsculas y las palabras se han lematizado. Continuando, indagaremos en otra alternativa de código utilizando la librería sklearn
# Importamos Tfidf vectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
# Instanciamos
vectorizer = TfidfVectorizer()
# Creamos una matriz aplicando el modelo tf-idf a
# nuestros documentos limpios en data_without_stopwords
vectors = vectorizer.fit_transform(data_without_stopwords)
# Veamos cuantas filas y columnas tiene la matriz TF-IDF que creamos
print("n_muestras: %d, n_características: %d" % vectors.shape)
n_muestras: 1808, n_características: 1995
El resultado muestra que se ha creado un nuevo vector que consta de 1978 entidades pertenecientes a 1808 participantes. La matriz TF-IDF es una matriz grande, que incluye numerosas filas y columnas. En aras de la brevedad, nos centraremos en las primeras cinco respuestas de los estudiantes y las diez palabras más frecuentes en la matriz TF-IDF .
# Seleccionamos las primeras 5 filas (documentos) de nuestro conjunto de
# datos
tf_idf = pd.DataFrame(vectors.todense()).iloc[:5]
# Configuramos los nombres de las columnas
tf_idf.columns = vectorizer.get_feature_names()
# Convertimos a una matriz el dataframe tf_idf
tfidf_matrix = tf_idf.T
# Configuramos el nombre de las columnas de la matriz
tfidf_matrix.columns = ['response' + str(i) for i in range(1, 6)]
tfidf_matrix['count'] = tfidf_matrix.sum(axis=1)
# Top 10 palabras
tfidf_matrix = tfidf_matrix.sort_values(by ='count', ascending=False)[:10]
# Imprimimos las 10 primeras palabras
print(tfidf_matrix.drop(columns=['count']).head(10))
response1 response2 response3 response4 response5 python 0.129319 0.124885 0.083783 0.066513 0.467525 koala 0.079249 0.172196 0.154030 0.061140 0.214879 panda 0.078464 0.170490 0.152505 0.060535 0.212752 eat 0.105059 0.076093 0.204196 0.243159 0.000000 australia 0.056927 0.000000 0.110645 0.087838 0.308710 china 0.054376 0.000000 0.105687 0.083902 0.294878 generalist 0.000000 0.113179 0.000000 0.000000 0.423700 similar 0.000000 0.077710 0.104268 0.000000 0.290917 different 0.059878 0.086738 0.000000 0.000000 0.324715 specialist 0.000000 0.099279 0.000000 0.000000 0.371665
C:\ProgramData\Miniconda3\lib\site-packages\sklearn\utils\deprecation.py:87: FutureWarning: Function get_feature_names is deprecated; get_feature_names is deprecated in 1.0 and will be removed in 1.2. Please use get_feature_names_out instead. warnings.warn(msg, category=FutureWarning)
En la matriz podemos ver que cada palabra tiene un peso diferente ( valor TF-IDF ) para cada documento y que los valores TF-IDF de las palabras no incluidas en el documento son cero. Por ejemplo, la palabra "specialist" no está incluida en el documento 1 (es decir, la respuesta 1) y, por lo tanto, su valor TF-IDF es cero.
En este ejemplo se quería demostrar cómo usar la vectorización TF-IDF para crear vectores de texto más allá de la matriz término-documento (es decir, bolsa de palabras). La vectorización TF-IDF transforma datos textuales en vectores numéricos considerando la frecuencia de cada palabra en el documento, el número total de palabras en el documento, el número total de documentos y el número de documentos que incluyen cada palabra única. Por lo tanto, a diferencia de la matriz de término-documento (bolsa de palabras) que solo muestra la presencia, ausencia o conteo de una palabra en un documento, crea vectores de texto más significativos que se enfocan en el peso de las palabras que representan su contribución única al documento.
Otra manera de implementar la vectorización es como habíamos visto mediante la librería gensim, para lo cual:
data_without_stopwords
y creamos las asignaciones de los Tokens ID:# Importaciones necesarias
from gensim.corpora.dictionary import Dictionary
from nltk.tokenize import word_tokenize
from gensim.models.tfidfmodel import TfidfModel
# Tokenizamos cada documento
docs_tokenized = [word_tokenize(doc) for doc in data_without_stopwords]
# Creamos la asignacion con una identificacion para cada token y la
# frecuencia de aparicion de cada token para cada documento
dictionary = Dictionary(docs_tokenized)
# Podemos ver algunos tokens y sus identificadores de todos los documentos
# utilizando el atributo token2id
print(f'Palabra: lligator. Token ID: {dictionary.token2id["alligator"]}')
print(f'Palabra: conceivably. Token ID: {dictionary.token2id["conceivably"]}')
Palabra: lligator. Token ID: 0 Palabra: conceivably. Token ID: 6
# Importacion necesaria
from gensim.models.tfidfmodel import TfidfModel
# Creamos el corpus Gensim para cada documento tokenizado
# mediante el metodo doc2bow() aplicado al diccionario
# dictionary que habiamos creado antes
corpus = [dictionary.doc2bow(doc) for doc in docs_tokenized]
# Aplicamos el modelo tfidf al corpus que habiamos
# creado antes
tfidf = TfidfModel(corpus)
# Accedemos a los pesos dados por el modelo tfidf
# a nuestro corpus, especificamente para
# al segundo documento (a la segunda respuesta dada)
tfidf[corpus[1]]
[(1, 0.1895153816342581), (10, 0.038659697867352356), (11, 0.025206774914059624), (15, 0.004758003947315047), (17, 0.002603719738617299), (21, 0.015917550395519342), (27, 0.14836165486824207), (28, 0.1907143960013259), (29, 0.27196844677260285), (30, 0.2096030193696955), (31, 0.18136363651128223), (32, 0.3842687834462787), (33, 0.11362618613064965), (34, 0.07428895097327756), (35, 0.07208718077158), (36, 0.5316831016964588), (37, 0.4175879526518721), (38, 0.27196844677260285), (39, 0.07760811692218253), (40, 0.027250220531026277), (41, 0.05451246500204112), (42, 0.2010858326795001)]
tfidf[corpus[1]]
y el otro que tenga una columna para los tokens id y otra con su palabra correspondiente# Creamos un dataframe con los valores obtenidos (token id, frecuencia tf-idf)
# para el documento 1 del corpus
df_i1 = pd.DataFrame(tfidf[corpus[1]]).rename(columns={0: 'Token ID', 1: 'Medida tf-idf'})
# Vemos el dataframe
df_i1.sort_values('Token ID')
Token ID | Medida tf-idf | |
---|---|---|
0 | 1 | 0.189515 |
1 | 10 | 0.038660 |
2 | 11 | 0.025207 |
3 | 15 | 0.004758 |
4 | 17 | 0.002604 |
5 | 21 | 0.015918 |
6 | 27 | 0.148362 |
7 | 28 | 0.190714 |
8 | 29 | 0.271968 |
9 | 30 | 0.209603 |
10 | 31 | 0.181364 |
11 | 32 | 0.384269 |
12 | 33 | 0.113626 |
13 | 34 | 0.074289 |
14 | 35 | 0.072087 |
15 | 36 | 0.531683 |
16 | 37 | 0.417588 |
17 | 38 | 0.271968 |
18 | 39 | 0.077608 |
19 | 40 | 0.027250 |
20 | 41 | 0.054512 |
21 | 42 | 0.201086 |
# Consideramos los ids de los token para el documento de indice 1
lista_aux = list(df_i1['Token ID'])
# Creamos un diccionario vacio
dict_aux = {}
# Volteamos las keys-values de dictionary.token2id
# y los almacenamos en el diccionario auxiliar
for key, value in dictionary.token2id.items():
dict_aux[value] = key
# Creamos otro diccionario auxiliar
dict_aux2 = {}
# Consideraremos ahora solo los elementos que nos interesan de
# los tokens id de la lista lista_aux
for i in lista_aux:
dict_aux2[i] = dict_aux[i]
# Creamos el dataframe y transponemos
df_aux = pd.DataFrame([dict_aux2]).transpose().reset_index()
# Cambiamos el nombre de las columnas
df_aux = df_aux.rename(columns={'index': 'Token ID', 0: 'Palabra'})
# Vemos el dataframe
df_aux
Token ID | Palabra | |
---|---|---|
0 | 1 | animal |
1 | 10 | different |
2 | 11 | eat |
3 | 15 | koala |
4 | 17 | panda |
5 | 21 | python |
6 | 27 | adapt |
7 | 28 | bear |
8 | 29 | can |
9 | 30 | change |
10 | 31 | climate |
11 | 32 | described |
12 | 33 | exclusively |
13 | 34 | food |
14 | 35 | generalist |
15 | 36 | lower |
16 | 37 | migrate |
17 | 38 | not |
18 | 39 | one |
19 | 40 | similar |
20 | 41 | specialist |
21 | 42 | state |
# Unimos df_i1 con el dataframe df_aux
df_union = pd.merge(df_i1, df_aux, on='Token ID')
df_union
Token ID | Medida tf-idf | Palabra | |
---|---|---|---|
0 | 1 | 0.189515 | animal |
1 | 10 | 0.038660 | different |
2 | 11 | 0.025207 | eat |
3 | 15 | 0.004758 | koala |
4 | 17 | 0.002604 | panda |
5 | 21 | 0.015918 | python |
6 | 27 | 0.148362 | adapt |
7 | 28 | 0.190714 | bear |
8 | 29 | 0.271968 | can |
9 | 30 | 0.209603 | change |
10 | 31 | 0.181364 | climate |
11 | 32 | 0.384269 | described |
12 | 33 | 0.113626 | exclusively |
13 | 34 | 0.074289 | food |
14 | 35 | 0.072087 | generalist |
15 | 36 | 0.531683 | lower |
16 | 37 | 0.417588 | migrate |
17 | 38 | 0.271968 | not |
18 | 39 | 0.077608 | one |
19 | 40 | 0.027250 | similar |
20 | 41 | 0.054512 | specialist |
21 | 42 | 0.201086 | state |
df_union.sort_values('Medida tf-idf', ascending=False)
Token ID | Medida tf-idf | Palabra | |
---|---|---|---|
15 | 36 | 0.531683 | lower |
16 | 37 | 0.417588 | migrate |
11 | 32 | 0.384269 | described |
8 | 29 | 0.271968 | can |
17 | 38 | 0.271968 | not |
9 | 30 | 0.209603 | change |
21 | 42 | 0.201086 | state |
7 | 28 | 0.190714 | bear |
0 | 1 | 0.189515 | animal |
10 | 31 | 0.181364 | climate |
6 | 27 | 0.148362 | adapt |
12 | 33 | 0.113626 | exclusively |
18 | 39 | 0.077608 | one |
13 | 34 | 0.074289 | food |
14 | 35 | 0.072087 | generalist |
20 | 41 | 0.054512 | specialist |
1 | 10 | 0.038660 | different |
19 | 40 | 0.027250 | similar |
2 | 11 | 0.025207 | eat |
5 | 21 | 0.015918 | python |
3 | 15 | 0.004758 | koala |
4 | 17 | 0.002604 | panda |