Medición de la similitud del documento en Python

La similitud del documento, como sugiere el nombre, determina qué tan similares son los dos documentos dados. Por «documentos», nos referimos a una colección de strings. Por ejemplo, un ensayo o un archivo .txt. Muchas organizaciones utilizan este principio de similitud de documentos para comprobar el plagio. También lo utilizan muchas instituciones que realizan exámenes para verificar si un estudiante hizo trampa al otro. Por lo tanto, es muy importante a la vez que interesante saber cómo funciona todo esto.

similarity-python

La similitud del documento se calcula calculando la distancia del documento. La distancia del documento es un concepto en el que las palabras (documentos) se tratan como vectores y se calcula como el ángulo entre dos vectores de documentos dados. Los vectores de documentos son la frecuencia de aparición de palabras en un documento dado. Veamos un ejemplo:

Digamos que nos dan dos documentos D1 y D2 como:

D1 : “Esto es un geek”
D2 : “Esto era una cosa de geek”

Las palabras similares en ambos documentos se convierten en:

"This a geek"

Si hacemos una representación tridimensional de esto como vectores tomando D1, D2 y palabras similares en geometría de 3 ejes, entonces obtenemos:

similarity-python-2

Ahora, si tomamos el producto escalar de D1 y D2 ,

D1.D2 = "This"."This"+"is"."was"+"a"."a"+"geek"."geek"+"thing".0
D1.D2 = 1+0+1+1+0
D1.D2 = 3

Ahora que sabemos cómo calcular el producto escalar de estos documentos, ahora podemos calcular el ángulo entre los vectores del documento:

cos d = D1.D2/|D1||D2|

Aquí d es la distancia del documento. Su valor oscila entre 0 y 90 grados. Donde 0 grados significa que los dos documentos son exactamente idénticos y 90 grados indican que los dos documentos son muy diferentes.

Ahora que sabemos acerca de la similitud y la distancia del documento, veamos un programa de Python para calcular lo mismo:

Programa de similitud de documentos:

Nuestro algoritmo para confirmar la similitud de los documentos constará de tres pasos fundamentales:

  • Divide los documentos en palabras.
  • Calcule las frecuencias de las palabras.
  • Calcule el producto escalar de los vectores del documento.

Para el primer paso, primero usaremos el .read()método para abrir y leer el contenido de los archivos. A medida que leamos los contenidos, los dividiremos en una lista. A continuación, calcularemos la lista de frecuencia de palabras de la lectura en el archivo. Por lo tanto, se cuenta la aparición de cada palabra y la lista se ordena alfabéticamente.

import math
import string
import sys
  
# reading the text file
# This functio will return a 
# list of the lines of text 
# in the file.
def read_file(filename): 
      
    try:
        with open(filename, 'r') as f:
            data = f.read()
        return data
      
    except IOError:
        print("Error opening or reading input file: ", filename)
        sys.exit()
  
# splitting the text lines into words
# translation table is a global variable
# mapping upper case to lower case and
# punctuation to spaces
translation_table = str.maketrans(string.punctuation+string.ascii_uppercase,
                                     " "*len(string.punctuation)+string.ascii_lowercase)
       
# returns a list of the words
# in the file
def get_words_from_line_list(text): 
      
    text = text.translate(translation_table)
    word_list = text.split()
      
    return word_list

Ahora que tenemos la lista de palabras, calcularemos la frecuencia de aparición de las palabras.

# counts frequency of each word
# returns a dictionary which maps
# the words to  their frequency.
def count_frequency(word_list): 
      
    D = {}
      
    for new_word in word_list:
          
        if new_word in D:
            D[new_word] = D[new_word] + 1
              
        else:
            D[new_word] = 1
              
    return D
  
# returns dictionary of (word, frequency)
# pairs from the previous dictionary.
def word_frequencies_for_file(filename): 
      
    line_list = read_file(filename)
    word_list = get_words_from_line_list(line_list)
    freq_mapping = count_frequency(word_list)
  
    print("File", filename, ":", )
    print(len(line_list), "lines, ", )
    print(len(word_list), "words, ", )
    print(len(freq_mapping), "distinct words")
  
    return freq_mapping

Por último, calcularemos el producto punto para dar la distancia del documento.

# returns the dot product of two documents
def dotProduct(D1, D2): 
    Sum = 0.0
      
    for key in D1:
          
        if key in D2:
            Sum += (D1[key] * D2[key])
              
    return Sum
  
# returns the angle in radians 
# between document vectors
def vector_angle(D1, D2): 
    numerator = dotProduct(D1, D2)
    denominator = math.sqrt(dotProduct(D1, D1)*dotProduct(D2, D2))
      
    return math.acos(numerator / denominator)

¡Eso es todo! Es hora de ver la función de similitud de documentos:

def documentSimilarity(filename_1, filename_2):
      
   # filename_1 = sys.argv[1]
   # filename_2 = sys.argv[2]
    sorted_word_list_1 = word_frequencies_for_file(filename_1)
    sorted_word_list_2 = word_frequencies_for_file(filename_2)
    distance = vector_angle(sorted_word_list_1, sorted_word_list_2)
      
    print("The distance between the documents is: % 0.6f (radians)"% distance)

Aquí está el código fuente completo.

import math
import string
import sys
  
# reading the text file
# This functio will return a 
# list of the lines of text 
# in the file.
def read_file(filename): 
      
    try:
        with open(filename, 'r') as f:
            data = f.read()
        return data
      
    except IOError:
        print("Error opening or reading input file: ", filename)
        sys.exit()
  
# splitting the text lines into words
# translation table is a global variable
# mapping upper case to lower case and
# punctuation to spaces
translation_table = str.maketrans(string.punctuation+string.ascii_uppercase,
                                     " "*len(string.punctuation)+string.ascii_lowercase)
       
# returns a list of the words
# in the file
def get_words_from_line_list(text): 
      
    text = text.translate(translation_table)
    word_list = text.split()
      
    return word_list
  
  
# counts frequency of each word
# returns a dictionary which maps
# the words to  their frequency.
def count_frequency(word_list): 
      
    D = {}
      
    for new_word in word_list:
          
        if new_word in D:
            D[new_word] = D[new_word] + 1
              
        else:
            D[new_word] = 1
              
    return D
  
# returns dictionary of (word, frequency)
# pairs from the previous dictionary.
def word_frequencies_for_file(filename): 
      
    line_list = read_file(filename)
    word_list = get_words_from_line_list(line_list)
    freq_mapping = count_frequency(word_list)
  
    print("File", filename, ":", )
    print(len(line_list), "lines, ", )
    print(len(word_list), "words, ", )
    print(len(freq_mapping), "distinct words")
  
    return freq_mapping
  
  
# returns the dot product of two documents
def dotProduct(D1, D2): 
    Sum = 0.0
      
    for key in D1:
          
        if key in D2:
            Sum += (D1[key] * D2[key])
              
    return Sum
  
# returns the angle in radians 
# between document vectors
def vector_angle(D1, D2): 
    numerator = dotProduct(D1, D2)
    denominator = math.sqrt(dotProduct(D1, D1)*dotProduct(D2, D2))
      
    return math.acos(numerator / denominator)
  
  
def documentSimilarity(filename_1, filename_2):
      
   # filename_1 = sys.argv[1]
   # filename_2 = sys.argv[2]
    sorted_word_list_1 = word_frequencies_for_file(filename_1)
    sorted_word_list_2 = word_frequencies_for_file(filename_2)
    distance = vector_angle(sorted_word_list_1, sorted_word_list_2)
      
    print("The distance between the documents is: % 0.6f (radians)"% distance)
      
# Driver code
documentSimilarity('GFG.txt', 'file.txt')

Producción:

File GFG.txt :
15 lines, 
4 words, 
4 distinct words
File file.txt :
22 lines, 
5 words, 
5 distinct words
The distance between the documents is:  0.835482 (radians)

Publicación traducida automáticamente

Artículo escrito por agarwalkeshav8399 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *