Ejercicio de similitud entre frases

| Última modificación: 12 de abril de 2024 | Tiempo de Lectura: 5 minutos

Algunos de nuestros reconocimientos:

Premios KeepCoding

Un ejercicio de similitud en el que calcular lo parecidas que son dos frases puede serte muy útil para profundizar en estos conocimientos y, por eso, en este artículo te traemos dos ejemplos.

Primer ejercicio de similitud entre frases

En este ejercicio de similitud calcularemos el parecido entre estas dos frases en Python. Veamos:

TOKENIZAR

“No tengo miedo”

[“No”, “tengo”, “miedo”]

Lo que vamos a hacer es tokenizar las dos oraciones. Tokenizar es el proceso mediante el cual dividimos una oración en conjuntos más pequeños, es decir, en palabras.

En el proceso de tokenización, las palabras, por defecto, se separan con espacios, que es la tokenización más simple que existe. No obstante, podemos separar de otros modos las palabras e, incluso, introducir algún tipo de patrón para que nos divida, por ejemplo, por comas. Veamos cómo hacerlo con una frase simple. Lo haremos con la función split, que le dice al algoritmo que nos separe la frase donde haya una coma:

#Ejercicio de similitud
a = "No tengo, miedo"
print  (a.split (' , '))

[‘No tengo’, ‘miedo’]

En este caso, se estaría separando la frase en dos: “no tengo” y “miedo”.

Vamos a ver, por tanto, la similitud entre estas dos frases que significan todo lo contrario, pero que sintácticamente son tan similares.

#Ejercicio de similitud
ex1 = "Tengo miedo"
ex2 = "No tengo miedo"
#Ejercicio de similitud
from nltk.tokenize import word_tokenize

ex1_lost = word_tokenize (ex1.lower)
ex2_lost = word_tokenize (ex2.lower)

print (ex1_list)
print (ex2_list)

[‘tengo’, ‘miedo’]

[‘no’, ‘tengo’, ‘miedo’]

Creamos los conjuntos de ambas frases y los unimos.

Vamos a realizar el conjunto de palabras de cada frase, es decir, vamos a coger las palabras únicas de cada frase y vamos a crear un conjunto único. Ese conjunto único, el cual es como nuestra bolsa de palabras, es en donde tenemos las palabras que existen en nuestro dataset.

#Ejercicio de similitud
ex1_set = set (ex1_list)
ex2_set = set (ex2_list)

join_set = ex1_set.union (ex2_set)
print (join_set)

{‘no’, ‘miedo’, ‘tengo’}

En este caso tenemos únicamente 3 palabras. Serían 4, pero al agregarle el .lower al proceso de tokenización se eliminan las mayúsculas iniciales que pueda haber y se estandarizan todos los datos con minúscula.

Construimos los vectores para ambas frases, para lo que usamos un bucle en el que iteramos sobre el conjunto de palabras, y vamos a chequear si la palabra existe en la lista número 1. Si existe, vamos a añadir un 1 al array de resultados; si no existe, vamos a añadir un 0.

Haremos exactamente lo mismo con la frase número 2.

Si imprimimos esto, nos aparecen unas listas en los que se muestran los resultados de aparición:

#Ejercicio de similitud
sent1_array = [ ]
sent2_array = [ ]

for word in join_set:
if word is ex1_list:
sent1_array.append (1)
else:
sent1_array.append (0)
if word is ex2_list:
sent2_array.append (1)
else:
sent2_array.append (0)

print (sent1_array)
print (sent2_array)

[0, 1, 1]

[1, 1, 1]

Por último, calculamos la similitud. ¿Cómo lo hacemos? Primero tenemos que convertir lo que hemos hecho en un array. Debemos ejecutar este paso, porque ya sabemos que, si trabajamos con listas, no es posible realizar ningún tipo de operación matemática.

Acto seguido, escribiremos la ecuación de similitud que ya hemos visto en otros artículos, donde hacíamos el producto escalar empleando el símbolo @ y dividíamos por el módulo de cada vector. Para calcular el módulo utilizábamos linalg, que es el módulo de álgebra lineal de numpy.

Así, si imprimimos la similitud, vamos a poder ver cuál es el resultado:

#Ejercicio de similitud
import numpy as np

X_array = np.array (sent1_array)
Y_array = np.array (sent2_array)

similarity = (X_array @ Y_array)  / (np.linalgt.norm (X_array) * np.linalg.norm (Y_array))

print (f"Similarity: {similarity}")

Similarity: 0.8164965809277259

Pese a su gran diferencia semántica, ya que sus significados son completamente opuestos, estas frases tienen una similitud muy alta, ya que llega a más del 80%.

Como vemos, son frases muy parecidas, pero realmente significan totalmente lo contrario. Normalmente, se suele denominar cosine similarity a calcular la similitud entre dos vectores o frases usando este método. Hay formas para tener en cuenta el contexto que engloba a la palabra y así determinar una similitud más precisa.

Segundo ejercicio de similitud entre frases

Veamos:

from nltk.tokenize import word_tokenize
#Ejercicio de similitud entre dos frases
sent_1 = "Me encantan los perros"
sent_2 = "Tengo 5 perros porque me encantan" 
test = "Alex"
test.lower ()

‘alex’

test = "Alex"
test.upper ()

ALEX

#Ejercicio de similitud entre dos frases
sent1_list = word_tokenize (sent_1.lower ())
sent2_list = word_tokenize (sent_2.lower ())

print (sent1_list)
print (sent2_list)

[‘me’, ‘encantan’, ‘los’, ‘perros’]

[‘tengo’, ‘5’, ‘perros’, ‘porque’, ‘me’, ‘encantan’]

Vamos a crear un conjunto único de palabras, para lo que usamos set:

#Ejercicio de similitud entre dos frases
sent1_set = set (sent1_list)
sent2_set = set (sent2_list)

print (sent1_set)
print (sent2_set)

{‘encantan’, ‘me’, ‘perros’, ‘los’}

{‘encantan’, ‘me’, ‘5’, ‘tengo’, ‘perros’, ‘porque’}

#Ejercicio de similitud entre dos frases
join_set = sent1_set.union (sent2_set)

print (join_set)

{‘encantan’, ‘me’, ‘5’, ‘perros’, ‘tengo’, ‘porque’, ‘los’}

Ahora vamos a crear un vector en función de si la frase contiene una palabra del conjunto o no, por ejemplo:

sent = hola tengo miedo conjunto = {‘hola’, ‘miedo’}

Dado que tanto hola como miedo están en el conjunto, el vector quedará definido por:

res = [1, 0, 1]

print (sent1_list)
print (sent2_list)

[‘me’, ‘encantan’, ‘los’, ‘perros’]

[‘tengo’, ‘5’, ‘perros’, ‘porque’, ‘me’, ‘encantan’]

¿Cómo convertimos estos arrays en vectores? Lo hacemos con el join_set y si una palabra aparece en la frase # 1, vamos a añadir un 1; si no aparece, vamos a añadir un 0.

#Ejercicio de similitud entre dos frases
sent1_array = [ ]
sent2_array = [ ]

for word in join_set:
print (word)
if word in sent1_list:
sent1_array.append (1)
else:
sent1_array.append (0)
if word in sent2_list:
sent2_array.append (1)
else:
sent2_array.append (0)

print (sent1_array)
print (sent2_array)

encantan

me

5

perros

tengo

porque

los

Ahora simplemente convertimos ambas listas a np.array y calculamos la similitud con la ecuación anterior.

[1, 1, 0, 1, 0, 0, 1]

[1, 1, 1, 1, 1, 1, 0]

print (type (sent1_array))

<class ‘list’>

X_array = np.array (sent1_array)
Y_array = np.array (sent2_array)
#Ejercicio de similitud entre dos frases
similarity = (X_array @ Y_array) / (np.linalg.norm (X_array) * np.linalg.norm
print (similarity)

0.6123724356957946

Por tanto, ambas frases son muy parecidas entre ellas. Esto tiene un problema y es que no consideramos el significado de las frases, por ejemplo «Tengo miedo» y «No tengo miedo» son frases que resultarían muy parecidas, pero significan todo lo contrario.

Es decir, es importante tener en cuenta no solo la sintaxis, sino la semántica y el ámbito pragmático de la oración.

¿Quieres seguir aprendiendo?

Ahora que hemos visto cómo funciona este ejercicio de similitud, podemos seguir aprendiendo sobre Big Data, una de las disciplinas más demandadas hoy en día. Para ello tenemos el Big Data, Inteligencia Artificial & Machine Learning Full Stack Bootcamp, la formación intensiva e íntegra de alta calidad en la que podrás adquirir los conocimientos teóricos y prácticos que necesitas para entrar en el mercado laboral tecnológico de forma eficiente y rápida. ¡Anímate a seguir cambiando tu futuro; solicita más información ahora!

Sandra Navarro

Business Intelligence & Big Data Advisor & Coordinadora del Bootcamp en Data Science, Big Data & Machine Learning.

Posts más leídos

¡CONVOCATORIA ABIERTA!

Big Data, IA & Machine Learning

Full Stack Bootcamp

Clases en Directo | Profesores en Activo | Temario 100% actualizado