Introducción al topic modeling con Gensim (III): similitud de textos

Abr 17, 2021 | Machine Learning, NLP | 0 Comentarios

Introducción a la similitud entre textos

Existen un sinfín de técnicas para obtener la similitud entre textos y tienen muchas aplicaciones interesantes que pueden facilitarnos la vida. Por ejemplo, puede usarse para elegir los resultados en un motor de búsqueda o como sistema de recomendación que proporciona al usuario contenido que sea de su interés a partir de otros contenidos que le han gustado previamente. Este contenido puede tratarse de libros, artículos, noticias, etc.

Las técnicas más básicas para calcular la similitud entre textos solo tienen en cuenta la similitud léxica, esto es la semejanza en las palabras contenidas en los textos comparados.

Una de estas técnicas consiste en representar los textos como bolsas de palabras (BOW) y aplicar la similitud de coseno para comparar la similitud entre dos documentos. En este caso, la semejanza entre los dos textos dependerá del número de palabras que compartan.

Hay varios problemas evidentes con este tipo de técnicas. Por ejemplo, una palabra puede tener varios significados completamente diferentes y, al carecer de contexto estos métodos, no pueden saber a que significado se refiere. Además, es posible que dos frases que no compartan ninguna palabra tengan un significado muy similar, como, por ejemplo: “Fui en coche a su casa y compramos algo para comer” y “El otro día conduje hacia su piso y pedimos unas hamburguesas». Mirando solamente las palabras de las frases anteriores, concluiríamos que esas frases no tienen nada que ver. Sin embargo, las dos frases tienen un alto grado de similitud y el modelo que utilizamos debería ser capaz de detectarlo.

Por ello, es importante que los modelos tengan también en cuenta la similitud semántica, es decir, que puedan entender el significado real de las palabras o de la frase en cada contexto. Existen varios métodos para extraer esta similitud semántica de los textos, como los ampliamente utilizados modelos de word embeddings que permiten representar cada palabra como un vector de números reales y capturar de esta forma su información semántica.

Sin embargo, en esta tercera publicación sobre el topic modeling se enseñará como calcular la similitud de textos aplicando la métrica de distancia de Jensen-Shannon a las distribuciones de los tópicos del modelo LDA, que aprendimos a calcular en la anterior publicación. De esta forma, estaremos teniendo en cuenta las estructuras semánticas de los documentos extraídas mediante el modelo LDA.

En caso de que no recordéis como asignar estos tópicos a un conjunto de documentos, recomendamos que os paséis por las anteriores entregas de la serie donde aprendimos como aplicar el preprocesamento necesario (tokenización de los textos, eliminación de stopwords…) a los textos y como entrenar el modelo LDA con estos.

En el caso práctico que encontrareis en esta publicación seguiremos utilizando el mismo corpus que consiste en 5665 noticias extraídas de distintos periódicos digitales españoles y que podéis descargar aquí. Realizaremos dos pruebas distintas. En primer lugar, calcularemos las noticas más similares a otra noticia nueva sobre violencia de género. En la segunda prueba vamos a obtener las más similiares a una noticas sobre el ex presidente Trump.

 

Usando la métrica Jensen Shannon para calcular la distancia entre textos

El procedimiento a seguir es sencillo. Primero obtenemos la distribución de tópicos del texto nuevo del cual queremos obtener los textos más similares. Después, solo nos queda calcular la distancia entre ese texto nuevo y el resto comparando sus distribuciones de tópicos.

Para calcular la distancia entre dos distribuciones utilizaremos la métrica de distancia de Jensen-Shannon, una medida de distancia estadística entre distribuciones de probabilidad. Esta métrica nos devolverá un valor comprendido entre 0 y 1, donde cuanto menor sea este valor significa una mayor similitud entre las dos distribuciones.

La distancia de Jensen-Shannon se calcula mediante la raíz cuadrada de la divergencia de Jensen-Shannon, métrica basada en la divergencia de Kullback-Leiber. La diferencia entre ambas es que Jensen-Shannon es simétrica y siempre tiene un valor finito. Su fórmula es la siguiente:

formulajensen

Donde P y Q son las dos distribuciones a comparar, M = (P+Q)/2 y D(P || M) es la divergencia de Kullback-Leiber entre Q y M.

En este artículo no entraremos en más detalles sobre esta métrica.

Una vez ya sabemos lo que tenemos que hacer, pongámonos manos a la obra.

 

Noticas más similares a una noticia sobre violencia de género

En este caso práctico, utilizamos como corpus las 5665 noticias mencionadas previamente. Como siempre, empezamos importando las librerías que vamos a necesitar:

In [1]:
from gensim.matutils import jensen_shannon

Después, le aplicamos el modelo LDA a una nueva noticia para obtener su distribución de tópicos con las proporciones de pertenencia de cada tópico en el documento.

Usamos la misma notica sobre violencia de género en Cantabria que ya usamos en la anterior publicación (noticia1.txt). Para la obtención de los tópicos debemos realizar el preprocesamiento al texto de la noticia y obtener su representación BOW. En el siguiente código podeís ver como abrimos la noticia en Python y realizamos las anterior dos operaciones:

In [2]:
texto_articulo = open("noticia1.txt")
articulo_nuevo = texto_articulo.read().replace("\\n", " ")
texto_articulo.close()
In [3]:
articulo_nuevo = limpiar_texto(articulo_nuevo)
articulo_nuevo = tokenizer.tokenize(articulo_nuevo)
articulo_nuevo = filtrar_stopword_digitos(articulo_nuevo)
articulo_nuevo = stem_palabras(articulo_nuevo)
In [4]:
bow_articulo_nuevo = diccionario.doc2bow(articulo_nuevo)

Con el método get_document_topics de Gensim obtenemos la distribución de tópicos y ajustando el parámetro minimum_probability a 0 nos aseguraremos de que ningún tópico sea descartado.

In [5]:
distribucion_noticia = lda.get_document_topics(bow_articulo_nuevo, 
                                               minimum_probability=0)

Esa será la distribución que necesitamos para comparar las noticias. Seguidamente creamos un método que se encarga de calcular la distancia entre dos distribuciones. De nuevo gensim nos facilitará el trabajo al contar con la función jensen_shannon que hará este cálculo por nosotros.

In [6]:
def calcular_jensen_shannon_sim_doc_doc(doc_dist1, doc_dist2):
    """Calcula la distancia Jensen Shannon entre dos documentos.
    """
    return jensen_shannon(doc_dist1, doc_dist2)

También implementamos un método que se encarga de calcular las distancias entre las distribuciones de tópicos de nuestra noticia con las del resto y mostrar el titular de aquellas más similares, es decir, las que tengan la distancia más baja, junto con el valor de esta.

In [7]:
def mostrar_n_mas_similares(distribucion_noticia, n):
    """Muestra las n noticias mas similares a partir 
       de una distribucion de tópicos.
    """
    distancias = [calcular_jensen_shannon_sim_doc_doc(
        distribucion_noticia, lda[noticia]) for noticia in corpus]
    mas_similares = np.argsort(distancias)
    for i in range(0,n):
        titular = df.iloc[int(mas_similares[i])].Titular
        print(f'{i + 1}: {titular} ({distancias[mas_similares[i]]})')

Ahora simplemente usamos el método implementado pasándole como entrada la distribución de nuestra noticia y el número de noticias más similares que queremos mostrar.

In [8]:
mostrar_n_mas_similares(distribucion_noticia, 10)
1: El año arranca con el reto de reconocer la violencia machista fuera de la pareja tras los 47 asesinatos contabilizados en 2018 (0.09249553084373474)
2: La violencia machista deja mil mujeres asesinadas por hombres en los últimos dieciséis años (0.11838279664516449)
3: Más de 40 ciudades acogen manifestaciones contra la sentencia de la violación grupal de Manresa (0.1389278918504715)
4: Obligan a una niña argentina de 11 años violada a someterse a una cesárea en lugar de un aborto (0.16407731175422668)
5: La Fiscalía no probó ninguna denuncia falsa por violencia de género el año pasado (0.1668342649936676)
6: La atención sanitaria a las personas trans en Catalunya dejará de estar basada en un diagnóstico psiquiátrico (0.171798974275589)
7: El Parlamento de Navarra solicita por unanimidad medios para esclarecer los casos de abusos en la Iglesia (0.17249423265457153)
8: Por una ley integral contra la trata de personas (0.18349292874336243)
9: Fue violación: el Supremo condena a quince años de cárcel a los cinco miembros de 'la manada' por agresión sexual (0.1846129298210144)
10: Asesinada por su marido una mujer de 78 años en Las Palmas de Gran Canaria (0.18781311810016632)

Como podemos ver, las 10 noticias más similares calculadas mediante la distancia Jensen-Shannon son, en efecto, bastante similares a nuestra noticia. Esto lo podemos ver fácilmente observando los titulares de las noticias, que tienen que ver sobre la violencia de género en su gran mayoría.

 

Noticas más similares a una noticia sobre Trump

A continuación, realizamos una segunda prueba y esta vez usamos para evaluar el modelo una noticia del ex presidente Trump y las elecciones de 2020 en Estados Unidos. Empezamos, como siempre, cargando la noticia que se encuentra en formato texto (noticia2.txt).

In [9]:
texto_articulo = open("noticia2.txt")
articulo_nuevo = texto_articulo.read().replace("\\n", " ")
texto_articulo.close()
articulo_nuevo
Out[1]:
' El Servicio Postal de Estados Unidos (USPS, por sus siglas en inglés) se ha convertido en los últimos días en protagonista de la pelea entre Donald Trump y los demócratas de cara a las elecciones del próximo 3 de noviembre.  El presidente clama contra "los riesgos de fraude... '

Realizamos el preprocesamiento del texto y obtenemos la distribución de tópicos:

In [10]:
articulo_nuevo = limpiar_texto(articulo_nuevo)
articulo_nuevo = tokenizer.tokenize(articulo_nuevo)
articulo_nuevo = filtrar_stopword_digitos(articulo_nuevo)
articulo_nuevo = stem_palabras(articulo_nuevo)
articulo_nuevo
In [11]:
bow_articulo_nuevo = diccionario.doc2bow(articulo_nuevo)
distribucion_noticia = lda.get_document_topics(bow_articulo_nuevo, 
                                               minimum_probability=0)

Ya solo nos queda mostrar las 10 noticias más similares a la nuestra:

In [12]:
mostrar_n_mas_similares(distribucion_noticia, 10)
1: Trump contra el sistema democrático: "La única manera de perder estas elecciones es si están amañadas" (0.08675152063369751)
2: Trump redobla los ataques al voto por correo y Twitter alerta de datos engañosos (0.1108022928237915)
3: Trump, obligado a suspender las polémicas reformas del servicio postal en medio de su guerra contra el voto por correo (0.12227611988782883)
4: Trump desafía las restricciones de afluencia por el coronavirus con un mitin multitudinario en Nevada (0.12261532992124557)
5: Trump desacredita las encuestas y carga nuevamente contra el voto por correo: "Creo que va a amañar las elecciones" (0.13689066469669342)
6: Michelle Obama, protagonista en la apertura de la convención demócrata: "Trump no puede ser quien necesitamos que sea. Es lo que es" (0.138019859790802)
7: Elecciones disputadas, polarización y crisis constitucional en EEUU... La lección de 1876 para los comicios de 2020 (0.15536248683929443)
8: Obama advierte de que Trump está dispuesto a "derribar la democracia para ganar" y ve el cargo como un "reality show" (0.15747606754302979)
9: Trump promete vacunas para todos en abril y alerta del voto por correo en EE.UU. (0.1696244478225708)
10: Facebook bloqueará los mensajes políticos antes de las elecciones en EE UU (0.17046895623207092)

¡De nuevo vemos un buen resultado de nuestro modelo! Todas las noticias obtenidas son de Trump y la gran mayoría sobre las elecciones en Estados Unidos.

Con este post, hemos aprendido a utilizar la técnica de topic modeling para obtener la similitud entre textos teniendo en cuenta la semántica. Si queréis repasar todas las publicaciones sobre topic modeling, no dudes en echar un vistazo a nuestra serie completa:

Esperamos que este tutorial os haya resultado interesante y recordad que el notebook con el código utilizado hasta ahora lo podéis descargar aquí.

 

También te puede interesar:

Diferencias entre inferencia y predicción

Entiende las diferencias entre inferencia y predicción, dos conceptos de la estadística y el machine learning que pueden resultar confusos.

Libros recomendados para adentrarse en el machine learning

Lista de cinco libros recomendables para principiantes que quieran aprender machine learning y ciencia de datos.

Introducción al topic modeling con Gensim (I): fundamentos y preprocesamiento de textos

En esta publicación entenderéis los fundamentos del topic modeling (modelo LDA) y se mostrará como realizar el preprocesamento necesario a los textos: tokenización, eliminación de stopwords, etc.

Introducción al topic modeling con Gensim (II): asignación de tópicos

En esta publicación aprenderás como entrenar un modelo LDA con noticias periodísticas para la asignación de tópicos, usando para ello la librería Gensim de Python.

Extracción de datos de Twitter con Python (sin consumir la API)

En esta publicación os enseñaremos como poder extraer datos de Twitter en Python mediante la librería Twint. De esta forma, podremos obtener facilmente los últimos tweets que contengan cierta palabra o que pertenezcan a un determinado usuario y aplicar varios filtros.

Sentiment analysis en críticas de películas mediante regresión logística

El sentimiento de análisis es una técnica que nos permite identificar la opinión emocional que hay detrás de un textol. En este artículo mostramos como construir un modelo de predicción capaz de distinguir entre críticas positivas y negativas. Estas críticas han sido descargadas previamente de la web de filmaffinity.

AutoML: creación de un modelo de análisis de sentimiento con Google Cloud AutoML

Descubre en que consiste el AutoML, que nos permite automatizar varias partes del proceso de Machine Learning y aprende a utilizar Google Cloud AutoML para realizar una tarea de sentiment analysis y construir un clasificador capaz de identificar si una crítica de película es positiva o negativa.

Introducción al clustering (I): algoritmo k-means

En este artículo explicamos el algoritmo de clustering k-means, el cual busca instancias centradas en un punto determinado, llamado centroide. Después de explicar su funcionamiento, lo aplicaremos en Python a un conjunto de datos y visualizaremos los resultados obtenidos.

Machine Learning vs. Deep Learning: Comprendiendo las diferencias en la inteligencia artificial

Explora las diferencias entre Machine Learning y Deep Learning en este artículo y comprende cuándo utilizar cada enfoque en la inteligencia artificial

Dominando Apache Spark (I): Introducción y ventajas en el procesamiento de grandes volúmenes de datos

En el artículo, exploramos la historia y ventajas de Apache Spark como un marco de procesamiento de datos de código abierto. Destacamos su evolución y las razones para su popularidad en el procesamiento de datos a gran escala, incluyendo su velocidad y capacidad de procesamiento en memoria.

Ads Blocker Image Powered by Code Help Pro

Por favor, permite que se muestren anuncios en nuestro sitio web

Querido lector,

Esperamos que estés disfrutando de nuestro contenido. Entendemos la importancia de la experiencia sin interrupciones, pero también queremos asegurarnos de que podamos seguir brindándote contenido de alta calidad de forma gratuita. Desactivar tu bloqueador de anuncios en nuestro sitio nos ayuda enormemente a lograrlo.

¡Gracias por tu comprensión y apoyo!