Datos personales

Estudiante de la UNMSM - Facultad de Matemática - EAP Computación Cientifica

lunes, 25 de junio de 2012

Corrector Ortografico (Español) en Python


Empecemos conociendo un poco la parte teórica :


¿Cómo funciona?
Dada una palabra, estamos tratando de elegir la corrección ortográfica más probable para esa palabra(puede darse el caso en que la "corrección", sea la palabra original). No hay manera de saber con seguridad (ejemplo: "abarar" debe ser corregido por :"abarrar" o "abarraz"), lo que sugiere que usemos probabilidades. Vamos a decir que estamos tratando de encontrar la corrección C, de todas las correcciones posibles, tal corrección bebe tener la mayor probabilidad dada la palabra original W.
Max P(C|W) (1)

Usando el Teorema de Bayes, la expresión (1) es equivalente a :
Max P(C|W)= Max P(W|C)*P(C)/P(W) (2)


como P(w) es el mismo para todos los C posibles, se puede obviar, obteniendo de (2):
Max P(C|W)= Max P(W|C)*P(C) (3)

Entendamos a mayor detalle la expresión (3):

  • P(W), ¿cual es la probabilidad de que sea exactamente lo que se escribió?
  • P(C), dado un remplazo C, ¿cual es la probabilidad de que sea esa?, ejemplo: P ("la") tendría una probabilidad relativamente alta, mientras que P ("zxzxzxzyyy") sería cercano a cero.
  • P(W|C), ¿Cual es la probabilidad de que haya puesto W queriendo poner C?

Queremos la palabra C mas probable que se parezca a W

  • Si es muy distinta de W, C no nos sirve (ejem : W=berde, C=hola)
  • Si es muy rara, no nos sirve (ejem: W=verdo, C=bardo)
  • Si es común y parecida, C es genial (ejm: W=verda, C= verde)



Código Completo



#! /usr/bin/env python26
#-*- coding: utf-8 -*-
import re, collections

def words(text):
    """
    Escoje todas las palabras del text
    """
    return re.findall(u'[\xf1\xe1\xe9\xed\xf3\xfaa-z]+', unicode(text.lower(), 'utf-8'))


def train(features):
    """
   
calcula el P(C)
    """
    model = collections.defaultdict(lambda: 1)
    for f in features:
        model[f] += 1 
    list = []
    return model

NWORDS = train(words(file('DicEspaniol.txt').read()))
alphabet = u'abcdefghijklmnopqrstuvwxyz\xf1\xe1\xe9\xed\xf3\xfa'

def edits1(word):
 
    """
    Calcula el P(W/C) ----- distancia=1
    """
    s = [(word[:i], word[i:]) for i in range(len(word) + 1)]
    deletes= [a + b[1:] for
a, b in s if b]
    transposes = [a + b[1] + b[0] + b[2:] for a, b in s if len(b) > 1]
    replaces= [a + c + b[1:] for a, b in s for c in alphabet if b]
    inserts= [a + c + b for a, b in s for c in alphabet]
    return set(deletes + transposes + replaces + inserts)


def known_edits2(word):
    """
        Calcula el P(W/C) ----- distancia=2 y se descarta si P(C)=0
    """
    return set(e2 for e1 in edits1(word) for
e2 in edits1(e1) if e2 in NWORDS)


def known(words):
    """
        Descarta si P(C)=0
    """
    return set(w for w in words if w in NWORDS)

def correct(word):
    """
    funcion principal
    """
    word = unicode(word.lower(), 'utf-8')
    candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word] 
    return max(candidates, key = NWORDS.get)
.encode('utf-8')

print correct("categoria")