Corrección ortográfica en Python con TextBlob

En este tutorial, veremos cómo crear un script de corrección ortográfica simple y potente en Python usando TextBlob. Repasaremos la corrección ortográfica estándar y entrenaremos el modelo con datos personalizados.

Introducción

Los errores de ortografía son comunes y la mayoría de las personas están acostumbradas a que el software indique si se cometió un error. Desde la autocorrección en nuestros teléfonos hasta el subrayado en rojo en los editores de texto, la revisión ortográfica es una función esencial para muchos productos diferentes.

El primer programa que implementó el corrector ortográfico se escribió en 1971 para el DEC PDP-10. Llamado SPELL, era capaz de realizar solo comparaciones simples de palabras y detectar diferencias de una o dos letras. A medida que el hardware y el software avanzaron, también lo hicieron los correctores ortográficos. Los correctores ortográficos modernos son capaces de manejar la morfología y usar estadísticas para mejorar las sugerencias.

Python ofrece muchos módulos para usar con este propósito, lo que hace que escribir un corrector ortográfico simple sea una prueba fácil de 20 minutos.

Una de estas bibliotecas es TextBlob, que se utiliza para el procesamiento de lenguaje natural que proporciona una API intuitiva para trabajar.

En este artículo, veremos cómo implementar corrección ortográfica en Python con TextBlob.

Instalación

Primero, necesitaremos instalar TextBlob, ya que no viene preinstalado. Abra una consola e instálela usando pip:

1
$ pip install textblob

Esto debería instalar todo lo que necesitamos para este proyecto. Al finalizar la instalación, la salida de la consola debería incluir algo como:

1
Successfully installed click-7.1.2 joblib-0.17.0 nltk-3.5 regex-2020.11.13 textblob-0.15.3

TextBlob se basa en NLTK, por lo que también viene con la instalación.

La función correct()

La forma más sencilla de corregir el texto de entrada es usar el método correct(). El texto de ejemplo que usaremos es un párrafo de "Sobre el origen de las especies" de Charles Darwin, que es parte del dominio público, empaquetado en un archivo llamado text.txt.

Además, agregaremos algunos errores de ortografía deliberados:

1
As far as I am abl to judg, after long attnding to the sbject, the condiions of lfe apear to act in two waysdirectly on the whle organsaton or on certin parts alne and indirectly by afcting the reproducte sstem. Wit respct to te dirct action, we mst bea in mid tht in every cse, as Profesor Weismann hs latly insistd, and as I have inidently shwn in my wrk on "Variatin undr Domesticcation," thcere arae two factrs: namly, the natre of the orgnism and the natture of the condiions. The frmer sems to be much th mre importannt; foor nealy siimilar variations sometimes aris under, as far as we cn juddge, disimilar conditios; annd, on te oter hannd, disssimilar variatioons arise undder conditions which aappear to be nnearly uniiform. The efffects on tthe offspring arre ieither definnite or in definite. They maay be considdered as definnite whhen allc or neearly all thhe ofefspring off inadividuals exnposed tco ceertain conditionas duriing seveal ggenerations aree moodified in te saame maner.

Está lleno de faltas de ortografía, en casi todas las palabras. Escribamos un script simple, usando TextBlob, para corregir estos errores e imprimirlos de nuevo en la consola:

1
2
3
4
5
6
7
from textblob import TextBlob

with open("text.txt", "r") as f:        # Opening the test file with the intention to read
    text = f.read()                     # Reading the file
    textBlb = TextBlob(text)            # Making our first textblob
    textCorrected = textBlb.correct()   # Correcting the text
    print(textCorrected)

Si ha trabajado anteriormente con TextBlob, este flujo le resultará familiar. Hemos leído el archivo y el contenido dentro de él, y construimos una instancia TextBlob pasando el contenido al constructor.

Luego, ejecutamos la función correct() en esa instancia para realizar la corrección ortográfica.

Después de ejecutar el script anterior, debería obtener un resultado similar a:

1
Is far as I am all to judge, after long attending to the subject, the conditions of life appear to act in two waysdirectly on the while organisation or on certain parts alone and indirectly by acting the reproduce system. It respect to te direct action, we must be in mid the in every case, as Professor Weismann he lately insisted, and as I have evidently shown in my work on "Variation under Domesticcation," there are two facts: namely, the nature of the organism and the nature of the conditions. The former seems to be much th are important; for nearly similar variations sometimes arms under, as far as we in judge, similar condition; and, on te other hand, disssimilar variations arise under conditions which appear to be nearly uniform. The effects on the offspring are either definite or in definite. They may be considered as definite when all or nearly all the offspring off individuals exposed to certain conditions during several generations are modified in te same manner.

¿Qué tan correcta es la corrección ortográfica de TextBlob?

Como podemos ver, el texto todavía tiene algunos errores ortográficos. Se suponía que palabras como "abl" eran "capaz", no "todos". Aunque, incluso con estos, sigue siendo mejor que el original.

Ahora viene la pregunta, ¿cuánto mejor es?

El siguiente fragmento de código es un script simple que prueba qué tan bueno es TextBlob para corregir errores, según este ejemplo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from textblob import TextBlob

# A function that compares two texts and returns 
# the number of matches and differences
def compare(text1, text2):  
    l1 = text1.split()
    l2 = text2.split()
    good = 0
    bad = 0
    for i in range(0, len(l1)):
        if l1[i] != l2[i]:
            bad += 1
        else:
            good += 1
    return (good, bad)

# Helper function to calculate the percentage of misspelled words
def percentageOfBad(x):
    return (x[1] / (x[0] + x[1])) * 100

Ahora, con esas dos funciones, hagamos un análisis rápido:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
with open("test.txt", "r") as f1: # test.txt contains the same typo-filled text from the last example 
    t1 = f1.read()

with open("original.txt", "r") as f2: # original.txt contains the text from the actual book 
    t2 = f2.read()

t3 = TextBlob(t1).correct()

mistakesCompOriginal = compare(t1, t2)
originalCompCorrected = compare(t2, t3)
mistakesCompCorrected = compare(t1, t3)

print("Mistakes compared to original ", mistakesCompOriginal)
print("Original compared to corrected ", originalCompCorrected)
print("Mistakes compared to corrected ", mistakesCompCorrected, "\n")

print("Percentage of mistakes in the test: ", percentageOfBad(mistakesCompOriginal), "%")
print("Percentage of mistakes in the corrected: ", percentageOfBad(originalCompCorrected), "%")
print("Percentage of fixed mistakes: ", percentageOfBad(mistakesCompCorrected), "%", "\n")

Ejecutarlo imprimirá:

1
2
3
4
5
6
7
Mistakes compared to original  (126, 194)
Original compared to corrected  (269, 51)
Mistakes compared to corrected  (145, 175) 

Percentage of mistakes in the test:  60.62499999999999 %
Percentage of mistakes in the corrected:  15.937499999999998 %
Percentage of fixed mistakes:  54.6875 % 

Como podemos ver, el método correcto logró que nuestro porcentaje de errores ortográficos pasara del 60,6% al 15,9%, lo cual es bastante decente, sin embargo, hay un pequeño inconveniente. Corrigió el 54,7% de las palabras, entonces, ¿por qué todavía hay una tasa de error del 15,9%?

La respuesta es sobrecorrección. A veces, puede cambiar una palabra que está escrita correctamente, como la primera palabra en nuestro texto de ejemplo donde "Como" se corrigió a "Es". Otras veces, simplemente no tiene suficiente información sobre la palabra y el contexto para saber qué palabra intenta escribir el usuario, por lo que supone que debe reemplazar "whl" con "while" en lugar de "entero".

No existe un corrector ortográfico perfecto porque gran parte del lenguaje hablado es contextual, así que tenlo en cuenta. En la mayoría de los casos de uso, hay muchos menos errores que en nuestro ejemplo, por lo que TextBlob debería poder funcionar lo suficientemente bien para el usuario promedio.

Entrenamiento TextBlob con conjuntos de datos personalizados

¿Qué sucede si desea revisar la ortografía de otro idioma que no es compatible con TextBlob de forma inmediata? ¿O tal vez quieres ser un poco más preciso? Bueno, podría haber una manera de lograr esto. Todo se reduce a la forma en que funciona la revisión ortográfica en TextBlob.

TextBlob usa estadísticas de uso de palabras en inglés para hacer sugerencias inteligentes sobre qué palabras corregir. Mantiene estas estadísticas en un archivo llamado en-spelling.txt, pero también le permite crear su propio archivo de estadísticas de uso de palabras.

Intentemos hacer uno para nuestro ejemplo de Darwin. Usaremos todas las palabras del "Sobre el origen de las especies" para entrenar. Puede usar cualquier texto, solo asegúrese de que tenga suficientes palabras que sean relevantes para el texto que desea corregir.

En nuestro caso, el resto del libro proporcionará un gran contexto e información adicional que TextBlob necesitaría para ser más preciso en la corrección.

Reescribamos el guión:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from textblob.en import Spelling        
import re

textToLower = ""

with open("originOfSpecies.txt","r") as f1:           # Open our source file
    text = f1.read()                                  # Read the file                 
    textToLower = text.lower()                        # Lower all the capital letters

words = re.findall("[a-z]+", textToLower)             # Find all the words and place them into a list    
oneString = " ".join(words)                           # Join them into one string

pathToFile = "train.txt"                              # The path we want to store our stats file at
spelling = Spelling(path = pathToFile)                # Connect the path to the Spelling object
spelling.train(oneString, pathToFile)                 # Train

Si miramos en el archivo train.txt, veremos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
a 3389
abdomen 3
aberrant 9
aberration 5
abhorrent 1
abilities 1
ability 4
abjectly 1
able 54
ably 5
abnormal 17
abnormally 2
abodes 2
...

Esto indica que la palabra "a" aparece como palabra 3389 veces, mientras que "ably" aparece solo 5 veces. Para probar este modelo entrenado, usaremos suggest(text) en lugar de correct(text), que es una lista de tuplas de confianza de palabras. Los primeros elementos de la lista serán la palabra en la que tenga más confianza, por lo que podemos acceder a ella a través de suggest(text)[0][0].

Tenga en cuenta que esto podría ser más lento, así que vaya palabra por palabra mientras revisa la ortografía, ya que descargar grandes cantidades de datos puede provocar un bloqueo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from textblob.en import Spelling        
from textblob import TextBlob

pathToFile = "train.txt" 
spelling = Spelling(path = pathToFile)
text = " "

with open("test.txt", "r") as f: 
    text = f.read()

words = text.split()
corrected = " "
for i in words :
    corrected = corrected +" "+ spelling.suggest(i)[0][0] # Spell checking word by word

print(corrected)

Y ahora, esto resultará en:

1
As far as I am all to judge after long attending to the subject the conditions of life appear to act in two waysdirectly on the whole organisation or on certain parts alone and indirectly by acting the reproduce system It respect to the direct action we most be in mid the in every case as Professor Weismann as lately insisted and as I have incidently shown in my work on "Variatin under Domesticcation," there are two facts namely the nature of the organism and the nature of the conditions The former seems to be much th are important for nearly similar variations sometimes arise under as far as we in judge dissimilar conditions and on the other hand dissimilar variations arise under conditions which appear to be nearly uniform The effects on the offspring are either definite or in definite They may be considered as definite when all or nearly all the offspring off individuals exposed to certain conditions during several generations are modified in the same manner.

Esto corrige alrededor de 2 de 3 palabras mal escritas, lo cual es bastante bueno, considerando la ejecución sin mucho contexto.

Conclusión

En este artículo, usaremos TextBlob para implementar un corrector ortográfico básico, tanto con el modelo de predicción de acciones como con uno personalizado.

La corrección de errores ortográficos creados por el hombre se ha convertido en una tarea común para los desarrolladores de software. Aunque se ha vuelto más fácil y eficiente a través de la minería de datos, muchos errores ortográficos necesitan que se corrija el contexto.

En conclusión, es probable que los correctores de pruebas no se queden sin trabajo en el corto plazo, aunque se pueden automatizar algunas correcciones básicas para ahorrar tiempo y esfuerzo.