Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner el enlace http://www.chuidiang.org

Reconocedor de Idiomas

El algoritmo

Hace tiempo leí en una revista "Scientific American" la forma en que se podía reconocer un idioma.

Cada idioma tienen una frecuencia con que salen determinadas letras. Por ejemplo, en muchos idiomas la "e" es la letra más frecuente, en español aparece la "ñ", en inglés hay muchas más "w" que en español, etc.

Una forma de reconocer un idioma es tener varios idomas de muestra, con un texto suficientemente largo y para cada uno de ellos extraer el número de veces que sale cada letra. Luego, cuando queremos reconocer en qué idioma está un texto nuevo que encontremos, contamos cuántas veces sale cada letra y comparamos con los otros, a ver a cual se parece más.

También se puede complicar un poco el asunto. En vez de comprobar letras sueltas, podemos comprobar parejas de letras consecutivas. Por ejemplo, la palabra "hola" tiene las parejas "ho", "ol" y "la". Estas parejas de letras también son muy concretas del idioma que tratemos. En inglés hay muchas "th", de cosas como "the", "this", etc. Esta pareja "th" en español, por ejemplo, apenas sale.

Por supuesto, podemos complicar el asunto y usar trios de letras, etc, etc.

Otra apliación curiosa de estas estadísticas de caracteres es la de generar un texto aleatorio que puede dar el pego de ser en un idioma. No tendrá sentido ninguno, pero engañará a una persona que no conozca el idioma, identificándolo como tal. A mi, por ejemplo, no me cabe duda de que el texto generado en alemán por esta aplicación es efectivamente alemán, pero porque no tengo ni idea de alemán.

En este articulillo hay un pequeño programa java que permite reconocer el idioma de un texto entre varios disponibles. Si te bajas el jar, también puedes usar las clases sueltas para hacerte tu propio programa. Al final lo tienes en forma de Applet y puedes jugar un poco con él.

La clase EstadisticaCaracteres

La clase EstadisticaCaracteres es la encargada de contar las parejas de caracteres. Se la instancia pasándole un nombre de idioma en formato de String y el texto en ese idioma. El texto se pasa como una clase que implemente Reader de java (por ejemplo, un FileReader). La clase se encarga de leer el Reader y recordar las parejas de letras de ese texto.

Esta clase también sabe compararse con otras de su misma especie, devolviendo el porcentaje de parecido entre ella y la otra. Si devuelve un 1.0 entonces es que los grupos de letras son los mismos y aparecen el mismo número de veces en cada texto. Si devuelve 0.0 es que no hay ningún grupo de letras repetido en ambas. Esta comparación se hace llamado al método correla().

Para los que gusten de las matemáticas, cada texto queda representado como un vector de n dimensiones. Cada dimensión es una pareja de letras. Los dos vectores, el del idioma a probar y el del idioma de muestra, se normalizan para que tengan módulo 1 y se hace el producto escalar. Si el producto escalar es 1, es que ambos vectores coinciden. Si es 0 es que no tienen nada que ver el uno con el otro.

Es posible hacer que la clase recuerde letras simples, trios o cualquier número llamando al método setNumeroCaracteres(). Por defecto está fijado a 2. Puedes hacer tus pruebas con varios números a ver cómo varían los resultados según el número de caracteres que elijas.

La clase CorreladorIdiomas

Esta clase se instancia y se le añaden varios idiomas. Cada idioma se le pasa añadiéndole un nombre y un texto por medio del método addIdioma(). Este texto puede ser directamente un Reader o un nombre de fichero. La clase se encarga de instanciar una EstadisticaCaracteres y guardarla.

Una vez que tenemos guardados varios idiomas en esta clase, podemos pedirle que nos compare un texto con todos ellos. Llamando al método analizaIdioma(), pasándole bien un nombre de fichero con el texto a analizar o bien un Reader. Este método nos devolverá un array ordenado de PorcentajeCorrelacion de menor a mayor. Esta última es una clase tonta que sólo tiene el nombre del idioma y el porcentaje de parecido entre el texto de muestra y el idioma. Dentro del array, el último elemento es el idioma más probable para el texto analizado.

La clase GeneradorTexto

La clase GeneradorTexto permite, dándole un texto en un idioma de muestra, generar otro texto aleatorio que mantiene las probabilidades de que una letra concreta siga a dos letras. Es decir, en inglés, depués de "th" es muy probable que vaya una vocal, en concreto "e" o "i". En español, después de "cr" es casi imposible que vaya una consonante.

Con esto lo que conseguimos es un texto que para alguien que no conozca el idioma, le parecerá en dicho idioma. A mi un texto en alemán generado por esta herramienta me parece efectivamente alemán, pero un texto en español o bable no me lo parece, aunque hay que reconocer que le da un aire.

Como curiosidad he puesto ejemplos y posiblidad de generar texto en formato xml y texto en formato java. Verás que no tienen ni pies ni cabeza, pero que los hace, incluidos los sangrados.

En cuanto al algoritmo, para no complicarme la vida pensando una estructura de datos que a cada pareja de letras, por ejemplo la "th"le asocie un grupo de letras con su probabilidad, por ejemplo, la "e" va detras de la "th" en un 35% de los casos, la "i" en un 29%, ... he optado por cargar el texto entero y buscar en cada ocasión. Es decir, para una pareja de letras dada como la "th", se recorre todo el texto buscándola y se mira la letra que va detrás. Esto consume más tiempo de cpu, pero posiblemente (seguro) gasta menos memoria.

El applet de ejemplo

Antes de nada, ten en cuenta que esto es sólo un pequeño programa de ejemplo, sin pretensiones, para ilustrar un poco un posible algoritmo de reconocimiento de idiomas. Tampoco me he matado a depurar el algoritmo o a hacer análisis más complejos, por lo que es posible (casi seguro) que con textos cortos te salgan resultados malos. Tómatelo como un juego y no demasiado en serio.

Puedes bajarte los fuentes de idiomas.zip y el jar ejecutable de idiomas.jar. Los textos de muestra están dentro del mismo jar. Puedes ejecutar el jar como aplicación independiente con

$ java -jar idiomas.jar

También puedes ver y jugar aquí mismo con el applet. Pon o copia en la caja de texto superior algún texto en algún idioma y luego pulsa "analizar idioma", a ver qué sale. Mete un texto de longitud adecuada. Si es muy corto posiblemente el programa se equivoque de idioma. Si es muy largo, puedes ir a tomar un café mientras esperas el resultado.

Pincha también en el "deja, ya escribo yo" y elige un idioma que no conozcas en absoluto, para que te engañe. Luego elige un idioma que sí conozcas, para que veas que no tiene sentido ninguno. Finalmente, si tienes curiosidad, prueba a generar o escribir un texto en java o xml.

 

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007: