Su tarea es simple: le indica en qué lenguaje se escriben algunos datos textuales proporcionados. Esto es muy útil como un paso de preprocesamiento para los datos lingüísticos en aplicaciones de procesamiento del lenguaje natural, como la clasificación de texto y la verificación de hechizos. Otros casos de uso, por ejemplo, pueden incluir correos electrónicos de enrutamiento al departamento de servicio al cliente geográficamente ubicado geográficamente, según los idiomas de los correos electrónicos.
La detección de idiomas a menudo se realiza como parte de grandes marcos de aprendizaje automático o aplicaciones de procesamiento de lenguaje natural. En los casos en que no necesita la funcionalidad completa de esos sistemas o no quiere aprender las cuerdas de ellos, una pequeña biblioteca flexible es útil.
Hasta ahora, otras tres bibliotecas integrales de código abierto que trabajan en el JVM para esta tarea son Apache Tika, Apache OpenNLP y Optimaize Language Detector. Desafortunadamente, especialmente este último tiene tres inconvenientes principales:
Lingua tiene como objetivo eliminar estos problemas. Casi no necesita ninguna configuración y produce resultados bastante precisos en el texto largo y corto, incluso en palabras y frases individuales. Se basa en métodos basados en reglas y estadísticos, pero no utiliza ningún diccionarios de palabras. Tampoco necesita una conexión a ninguna API o servicio externo. Una vez que se ha descargado la biblioteca, se puede usar completamente fuera de línea.
En comparación con otras bibliotecas de detección de idiomas, el enfoque de Lingua está en la calidad sobre la cantidad , es decir, obtener la detección adecuada para un pequeño conjunto de idiomas primero antes de agregar otros nuevos. Actualmente, los siguientes 75 idiomas son compatibles:
Lingua puede informar estadísticas de precisión para algunos datos de prueba agrupados disponibles para cada idioma compatible. Los datos de prueba para cada idioma se dividen en tres partes:
Tanto los modelos de idiomas como los datos de prueba se han creado a partir de documentos separados de los corpus wortschatz ofrecidos por la Universidad de Leipzig, Alemania. Los datos rastreados de varios sitios web de noticias se han utilizado para la capacitación, cada corpus comprende un millón de oraciones. Para las pruebas, se han utilizado corpus hechos de sitios web elegidos arbitrariamente, cada uno comprende diez mil oraciones. De cada corpus de prueba, se ha extraído un subconjunto aleatorio no organizado de 1000 palabras individuales, 1000 pares de palabras y 1000 oraciones, respectivamente.
Dados los datos de prueba generados, he comparado los resultados de detección de Lingua , Apache Tika , Apache OpenNLP y el detector de lenguaje de Optimaize utilizando pruebas JUNIT parametrizadas que se ejecutan sobre los datos de los 75 lenguajes compatibles con Lingua . Los idiomas que no son compatibles con las otras bibliotecas simplemente se ignoran para aquellos durante el proceso de detección.
Cada una de las siguientes secciones contiene dos parcelas. La trama de barra muestra los resultados de precisión detallados para cada idioma compatible. La gráfica de cuadros ilustra las distribuciones de los valores de precisión para cada clasificador. Las cajas en sí representan las áreas en las que se encuentran el 50 % de los datos medios. Dentro de las cajas de colores, las líneas horizontales marcan la mediana de las distribuciones.
La siguiente tabla muestra estadísticas detalladas para cada idioma y clasificador, incluida la media, la mediana y la desviación estándar.
| Idioma | Promedio | Palabras individuales | Pares de palabras | Oraciones | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Lengua (Modo de alta precisión) | Lengua (modo de baja precisión) | Tika | OpenNLP | Optimizar | Lengua (Modo de alta precisión) | Lengua (modo de baja precisión) | Tika | OpenNLP | Optimizar | Lengua (Modo de alta precisión) | Lengua (modo de baja precisión) | Tika | OpenNLP | Optimizar | Lengua (Modo de alta precisión) | Lengua (modo de baja precisión) | Tika | OpenNLP | Optimizar | |
| africaans | 79 | 64 | 71 | 72 | 39 | 58 | 38 | 44 | 41 | 3 | 81 | 62 | 70 | 75 | 22 | 97 | 93 | 98 | 99 | 93 |
| albanés | 88 | 80 | 79 | 71 | 70 | 69 | 54 | 54 | 40 | 38 | 95 | 86 | 84 | 73 | 73 | 100 | 99 | 99 | 100 | 98 |
| árabe | 98 | 94 | 97 | 84 | 89 | 96 | 88 | 94 | 65 | 72 | 99 | 96 | 99 | 88 | 94 | 100 | 99 | 100 | 99 | 100 |
| armenio | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - |
| Azerbaiyano | 90 | 82 | - | 82 | - | 77 | 71 | - | 60 | - | 92 | 78 | - | 86 | - | 99 | 96 | - | 99 | - |
| vasco | 84 | 74 | 83 | 77 | 66 | 71 | 56 | 64 | 56 | 33 | 87 | 76 | 86 | 82 | 70 | 93 | 91 | 98 | 92 | 95 |
| Bielorruso | 97 | 92 | 96 | 91 | 87 | 92 | 80 | 92 | 78 | 69 | 99 | 95 | 98 | 95 | 92 | 100 | 100 | 100 | 100 | 99 |
| bengalí | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| Bokmal | 58 | 49 | - | 66 | - | 39 | 27 | - | 42 | - | 59 | 47 | - | 69 | - | 75 | 74 | - | 87 | - |
| bosnio | 35 | 29 | - | 26 | - | 29 | 23 | - | 12 | - | 35 | 29 | - | 22 | - | 40 | 36 | - | 44 | - |
| búlgaro | 87 | 78 | 73 | 83 | 48 | 70 | 56 | 52 | 62 | 18 | 91 | 81 | 69 | 87 | 36 | 99 | 96 | 96 | 100 | 91 |
| catalán | 70 | 58 | 58 | 42 | 31 | 51 | 33 | 32 | 11 | 2 | 74 | 60 | 57 | 32 | 16 | 86 | 81 | 84 | 81 | 77 |
| Chino | 100 | 100 | 69 | 78 | 31 | 100 | 100 | 20 | 40 | 0 | 100 | 100 | 86 | 94 | 2 | 100 | 100 | 100 | 100 | 91 |
| croata | 72 | 60 | 74 | 50 | 41 | 53 | 36 | 54 | 23 | 8 | 74 | 57 | 72 | 44 | 24 | 90 | 85 | 97 | 81 | 91 |
| checo | 80 | 71 | 72 | 67 | 49 | 66 | 54 | 54 | 42 | 21 | 84 | 72 | 75 | 70 | 46 | 91 | 87 | 88 | 90 | 81 |
| danés | 81 | 70 | 83 | 60 | 55 | 61 | 45 | 63 | 34 | 19 | 84 | 70 | 86 | 52 | 51 | 98 | 95 | 99 | 94 | 96 |
| Holandés | 77 | 64 | 60 | 61 | 39 | 55 | 36 | 31 | 31 | 6 | 81 | 61 | 52 | 57 | 19 | 96 | 94 | 98 | 97 | 91 |
| Inglés | 81 | 62 | 64 | 52 | 41 | 55 | 29 | 30 | 10 | 2 | 89 | 62 | 62 | 46 | 23 | 99 | 96 | 99 | 99 | 97 |
| esperanto | 84 | 66 | - | 76 | - | 67 | 44 | - | 50 | - | 85 | 61 | - | 78 | - | 98 | 92 | - | 100 | - |
| Estoniano | 92 | 83 | 84 | 59 | 61 | 80 | 62 | 66 | 29 | 23 | 96 | 88 | 88 | 60 | 63 | 100 | 99 | 100 | 88 | 98 |
| finlandés | 96 | 91 | 94 | 86 | 79 | 90 | 77 | 86 | 68 | 51 | 98 | 95 | 96 | 91 | 86 | 100 | 100 | 100 | 100 | 100 |
| Francés | 89 | 77 | 78 | 59 | 54 | 74 | 52 | 55 | 25 | 18 | 94 | 83 | 80 | 55 | 48 | 99 | 97 | 99 | 98 | 97 |
| Ganda | 91 | 84 | - | - | - | 79 | 65 | - | - | - | 95 | 87 | - | - | - | 100 | 100 | - | - | - |
| georgiano | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - |
| Alemán | 89 | 80 | 74 | 67 | 55 | 74 | 57 | 50 | 38 | 21 | 94 | 84 | 71 | 66 | 46 | 100 | 99 | 100 | 98 | 99 |
| Griego | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| Gujarati | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| hebreo | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| hindi | 73 | 33 | 80 | 58 | 51 | 61 | 11 | 65 | 28 | 16 | 64 | 20 | 75 | 49 | 38 | 93 | 67 | 99 | 99 | 98 |
| húngaro | 95 | 90 | 88 | 78 | 77 | 87 | 77 | 75 | 53 | 51 | 98 | 94 | 91 | 82 | 82 | 100 | 100 | 100 | 100 | 99 |
| islandés | 93 | 88 | 90 | 76 | 78 | 83 | 72 | 76 | 53 | 53 | 97 | 92 | 94 | 76 | 82 | 100 | 99 | 100 | 99 | 99 |
| indonesio | 60 | 48 | 60 | 29 | 18 | 39 | 25 | 37 | 10 | 0 | 61 | 46 | 62 | 25 | 1 | 81 | 72 | 82 | 52 | 54 |
| irlandés | 91 | 85 | 90 | 78 | 80 | 82 | 70 | 80 | 56 | 58 | 94 | 90 | 92 | 82 | 85 | 96 | 95 | 99 | 97 | 98 |
| italiano | 87 | 71 | 80 | 64 | 51 | 69 | 42 | 58 | 31 | 12 | 92 | 74 | 84 | 61 | 43 | 100 | 98 | 99 | 100 | 98 |
| japonés | 100 | 100 | 25 | 95 | 98 | 100 | 100 | 1 | 87 | 99 | 100 | 100 | 5 | 100 | 100 | 100 | 100 | 68 | 100 | 96 |
| Kazáceo | 92 | 90 | - | 85 | - | 80 | 78 | - | 66 | - | 96 | 93 | - | 90 | - | 99 | 99 | - | 100 | - |
| coreano | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| latín | 87 | 73 | - | 70 | - | 72 | 49 | - | 43 | - | 93 | 76 | - | 71 | - | 97 | 93 | - | 96 | - |
| letón | 93 | 87 | 90 | 86 | 78 | 85 | 75 | 78 | 72 | 56 | 97 | 90 | 93 | 88 | 82 | 99 | 97 | 98 | 98 | 97 |
| lituano | 95 | 87 | 89 | 79 | 72 | 86 | 76 | 74 | 56 | 40 | 98 | 89 | 92 | 83 | 77 | 100 | 98 | 99 | 99 | 98 |
| macedónio | 84 | 72 | 83 | 68 | 46 | 66 | 52 | 66 | 37 | 10 | 86 | 70 | 83 | 68 | 32 | 99 | 95 | 100 | 98 | 97 |
| malayo | 31 | 31 | 23 | 19 | 4 | 26 | 22 | 19 | 10 | 0 | 38 | 36 | 22 | 20 | 0 | 30 | 36 | 28 | 27 | 11 |
| maorí | 92 | 83 | - | 92 | - | 84 | 64 | - | 85 | - | 92 | 88 | - | 90 | - | 99 | 98 | - | 100 | - |
| Marathi | 85 | 41 | 90 | 81 | 71 | 74 | 20 | 81 | 62 | 43 | 85 | 30 | 92 | 83 | 74 | 96 | 72 | 98 | 98 | 96 |
| mongol | 97 | 96 | - | 84 | - | 93 | 89 | - | 66 | - | 99 | 98 | - | 88 | - | 99 | 99 | - | 99 | - |
| Nynorsk | 66 | 52 | - | 55 | - | 41 | 25 | - | 24 | - | 66 | 49 | - | 47 | - | 90 | 81 | - | 92 | - |
| persa | 90 | 80 | 81 | 75 | 62 | 78 | 62 | 65 | 53 | 29 | 94 | 80 | 79 | 74 | 58 | 100 | 98 | 99 | 99 | 99 |
| Polaco | 95 | 90 | 90 | 83 | 81 | 85 | 77 | 76 | 61 | 57 | 98 | 93 | 93 | 89 | 86 | 100 | 99 | 100 | 100 | 100 |
| portugués | 81 | 69 | 63 | 58 | 40 | 59 | 42 | 34 | 22 | 7 | 85 | 70 | 58 | 54 | 19 | 98 | 95 | 98 | 98 | 94 |
| punjabi | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| rumano | 87 | 72 | 78 | 67 | 55 | 69 | 49 | 57 | 34 | 24 | 92 | 74 | 80 | 68 | 50 | 99 | 94 | 97 | 99 | 91 |
| ruso | 90 | 78 | 80 | 50 | 53 | 76 | 59 | 62 | 20 | 22 | 95 | 84 | 85 | 43 | 50 | 98 | 92 | 94 | 86 | 87 |
| serbio | 88 | 78 | 73 | 73 | 46 | 74 | 62 | 57 | 46 | 18 | 90 | 80 | 70 | 74 | 39 | 99 | 91 | 90 | 98 | 80 |
| Shona | 91 | 81 | - | - | - | 78 | 56 | - | - | - | 96 | 86 | - | - | - | 100 | 100 | - | - | - |
| eslovaco | 84 | 75 | 76 | 70 | 47 | 64 | 49 | 53 | 39 | 12 | 90 | 78 | 76 | 73 | 38 | 99 | 97 | 98 | 99 | 92 |
| esloveno | 82 | 67 | 74 | 71 | 37 | 61 | 39 | 53 | 43 | 3 | 87 | 68 | 72 | 72 | 18 | 99 | 93 | 98 | 99 | 90 |
| somalí | 92 | 85 | 91 | 69 | 79 | 82 | 64 | 78 | 35 | 50 | 96 | 90 | 94 | 74 | 88 | 100 | 100 | 100 | 98 | 100 |
| Sotho | 85 | 72 | - | - | - | 67 | 43 | - | - | - | 90 | 75 | - | - | - | 99 | 97 | - | - | - |
| Español | 70 | 56 | 59 | 42 | 32 | 44 | 26 | 29 | 8 | 0 | 69 | 49 | 50 | 25 | 6 | 97 | 94 | 97 | 93 | 91 |
| swahili | 81 | 70 | 75 | 73 | 60 | 60 | 43 | 50 | 45 | 26 | 84 | 68 | 75 | 74 | 58 | 98 | 97 | 99 | 99 | 98 |
| sueco | 84 | 72 | 71 | 69 | 50 | 64 | 46 | 44 | 41 | 15 | 88 | 76 | 72 | 69 | 42 | 99 | 95 | 97 | 97 | 94 |
| Tagalo | 78 | 66 | 77 | 61 | 61 | 52 | 36 | 53 | 27 | 23 | 83 | 67 | 79 | 57 | 62 | 99 | 96 | 99 | 98 | 97 |
| Tamil | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| Telugu | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| tailandés | 99 | 99 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 98 | 98 | 100 | 99 | 100 |
| Tsonga | 84 | 72 | - | - | - | 66 | 46 | - | - | - | 89 | 73 | - | - | - | 98 | 97 | - | - | - |
| Tswana | 84 | 71 | - | - | - | 65 | 44 | - | - | - | 88 | 73 | - | - | - | 99 | 96 | - | - | - |
| turco | 94 | 87 | 81 | 72 | 70 | 84 | 71 | 62 | 48 | 43 | 98 | 91 | 83 | 71 | 70 | 100 | 99 | 99 | 98 | 96 |
| ucranio | 92 | 86 | 81 | 79 | 68 | 84 | 75 | 62 | 54 | 39 | 97 | 92 | 84 | 83 | 69 | 95 | 93 | 97 | 99 | 94 |
| Urdu | 91 | 80 | 83 | 68 | 72 | 80 | 65 | 68 | 45 | 49 | 94 | 78 | 84 | 62 | 71 | 98 | 96 | 96 | 98 | 96 |
| vietnamita | 91 | 87 | 85 | 84 | 87 | 79 | 76 | 63 | 66 | 65 | 94 | 87 | 92 | 86 | 95 | 99 | 98 | 100 | 100 | 100 |
| galés | 91 | 82 | 85 | 77 | 77 | 78 | 61 | 68 | 50 | 50 | 96 | 87 | 88 | 81 | 82 | 99 | 99 | 100 | 99 | 99 |
| Xhosa | 82 | 69 | - | - | - | 64 | 45 | - | - | - | 85 | 67 | - | - | - | 98 | 94 | - | - | - |
| Yoruba | 75 | 62 | - | - | - | 50 | 33 | - | - | - | 77 | 61 | - | - | - | 97 | 93 | - | - | - |
| zulú | 81 | 70 | - | 78 | - | 62 | 45 | - | 51 | - | 83 | 72 | - | 82 | - | 97 | 94 | - | 100 | - |
| Significar | 86 | 77 | 80 | 74 | 65 | 74 | 61 | 64 | 53 | 41 | 89 | 78 | 81 | 74 | 61 | 96 | 93 | 96 | 95 | 93 |
| Mediana | 89.23 | 79.63 | 81.3 | 75.55 | 63.85 | 74.3 | 56.7 | 63.39 | 48.7 | 30.75 | 93.7 | 80.6 | 84.25 | 75.55 | 65.95 | 99.0 | 96.9 | 99.15 | 99.0 | 97.4 |
| Desviación estándar | 13.12 | 17.26 | 16.2 | 18.56 | 23.87 | 18.43 | 24.81 | 23.9 | 27.37 | 33.87 | 13.13 | 18.96 | 18.74 | 21.32 | 31.32 | 11.02 | 11.86 | 10.77 | 12.59 | 13.54 |
Cada detector de lenguaje utiliza un modelo probabilístico N-Gram entrenado en la distribución de personajes en algún corpus de entrenamiento. La mayoría de las bibliotecas solo usan n-gramos de tamaño 3 (trigramas) que es satisfactorio para detectar el lenguaje de fragmentos de texto más largos que consisten en múltiples oraciones. Sin embargo, para frases cortas o palabras únicas, los trigramas no son suficientes. Cuanto más corto sea el texto de entrada, menos n-gramos están disponibles. Las probabilidades estimadas a partir de tales n-gramos no son confiables. Esta es la razón por la cual Lingua utiliza N-Grams de tamaños 1 hasta 5, lo que resulta en una predicción mucho más precisa del lenguaje correcto.
Una segunda diferencia importante es que Lingua no solo usa un modelo estadístico de este tipo, sino también un motor basado en reglas. Este motor primero determina el alfabeto del texto de entrada y busca caracteres que sean únicos en uno o más idiomas. Si exactamente un idioma se puede elegir de manera confiable de esta manera, el modelo estadístico ya no es necesario. En cualquier caso, el motor basado en reglas filtra los idiomas que no satisfacen las condiciones del texto de entrada. Solo entonces, en un segundo paso, se tiene en cuenta el modelo probabilístico N-Gram. Esto tiene sentido porque cargar menos modelos de idioma significa menos consumo de memoria y un mejor rendimiento de tiempo de ejecución.
En general, siempre es una buena idea restringir el conjunto de idiomas a considerar en el proceso de clasificación utilizando los métodos API respectivos. Si sabe de antemano que ciertos idiomas nunca ocurren en un texto de entrada, no permita que participen en el proceso de clasificación. El mecanismo de filtrado del motor basado en reglas es bastante bueno, sin embargo, el filtrado basado en su propio conocimiento del texto de entrada siempre es preferible.
Si desea reproducir los resultados de precisión anteriores, puede generar los informes de prueba usted mismo para los cuatro clasificadores y todos los idiomas haciendo:
./gradlew accuracyReport
También puede restringir los clasificadores e idiomas para generar informes para aprobar argumentos a la tarea de graduación. La siguiente tarea genera informes para Lingua y los idiomas inglés y alemán solamente:
./gradlew accuracyReport -Pdetectors=Lingua -Planguages=English,German
Por defecto, solo se usa un solo núcleo de CPU para la generación de informes. Si tiene una CPU de múltiples núcleos en su máquina, puede desembolsar tantos procesos como tiene núcleos de CPU. Esto acelera la generación de informes significativamente. Sin embargo, tenga en cuenta que bifurcar más de un proceso puede consumir mucha RAM. Lo haces así:
./gradlew accuracyReport -PcpuCores=2
Para cada detector y lenguaje, se escribe un archivo de informe de prueba en /accuracy-reports , que se encuentran junto al directorio src . Como ejemplo, aquí está la salida actual del informe de lengua alemana:
##### GERMAN #####
Legend: 'low accuracy mode | high accuracy mode'
>>> Accuracy on average: 79.80% | 89.23%
>> Detection of 1000 single words (average length: 9 chars)
Accuracy: 56.70% | 73.90%
Erroneously classified as DUTCH: 2.80% | 2.30%, DANISH: 2.20% | 2.10%, ENGLISH: 1.90% | 2.00%, LATIN: 1.90% | 1.90%, BOKMAL: 2.40% | 1.60%, BASQUE: 1.60% | 1.20%, ITALIAN: 1.00% | 1.20%, FRENCH: 1.60% | 1.20%, ESPERANTO: 1.10% | 1.10%, SWEDISH: 3.20% | 1.00%, AFRIKAANS: 1.30% | 0.80%, TSONGA: 1.50% | 0.70%, NYNORSK: 1.40% | 0.60%, PORTUGUESE: 0.50% | 0.60%, YORUBA: 0.40% | 0.60%, SOTHO: 0.70% | 0.50%, FINNISH: 0.80% | 0.50%, WELSH: 1.30% | 0.50%, SPANISH: 1.20% | 0.40%, SWAHILI: 0.60% | 0.40%, TSWANA: 2.20% | 0.40%, POLISH: 0.70% | 0.40%, ESTONIAN: 0.90% | 0.40%, IRISH: 0.50% | 0.40%, TAGALOG: 0.10% | 0.30%, ICELANDIC: 0.30% | 0.30%, BOSNIAN: 0.10% | 0.30%, LITHUANIAN: 0.80% | 0.20%, MAORI: 0.50% | 0.20%, INDONESIAN: 0.40% | 0.20%, ALBANIAN: 0.60% | 0.20%, CATALAN: 0.70% | 0.20%, ZULU: 0.30% | 0.20%, ROMANIAN: 1.20% | 0.20%, CROATIAN: 0.10% | 0.20%, XHOSA: 0.40% | 0.20%, TURKISH: 0.70% | 0.10%, MALAY: 0.50% | 0.10%, LATVIAN: 0.40% | 0.10%, SLOVENE: 0.00% | 0.10%, SLOVAK: 0.30% | 0.10%, SOMALI: 0.00% | 0.10%, HUNGARIAN: 0.40% | 0.00%, SHONA: 0.80% | 0.00%, VIETNAMESE: 0.40% | 0.00%, CZECH: 0.30% | 0.00%, GANDA: 0.20% | 0.00%, AZERBAIJANI: 0.10% | 0.00%
>> Detection of 1000 word pairs (average length: 18 chars)
Accuracy: 83.50% | 94.10%
Erroneously classified as DUTCH: 1.50% | 0.90%, LATIN: 1.00% | 0.80%, ENGLISH: 1.40% | 0.70%, SWEDISH: 1.40% | 0.60%, DANISH: 1.20% | 0.50%, FRENCH: 0.60% | 0.40%, BOKMAL: 1.40% | 0.30%, TAGALOG: 0.10% | 0.20%, IRISH: 0.20% | 0.20%, TURKISH: 0.10% | 0.10%, NYNORSK: 0.90% | 0.10%, TSONGA: 0.40% | 0.10%, ZULU: 0.10% | 0.10%, ESPERANTO: 0.30% | 0.10%, AFRIKAANS: 0.60% | 0.10%, ITALIAN: 0.10% | 0.10%, ESTONIAN: 0.30% | 0.10%, FINNISH: 0.40% | 0.10%, SOMALI: 0.00% | 0.10%, SWAHILI: 0.20% | 0.10%, MAORI: 0.00% | 0.10%, WELSH: 0.10% | 0.10%, LITHUANIAN: 0.40% | 0.00%, INDONESIAN: 0.10% | 0.00%, CATALAN: 0.30% | 0.00%, LATVIAN: 0.20% | 0.00%, XHOSA: 0.30% | 0.00%, SPANISH: 0.50% | 0.00%, MALAY: 0.10% | 0.00%, SLOVAK: 0.10% | 0.00%, BASQUE: 0.40% | 0.00%, YORUBA: 0.20% | 0.00%, TSWANA: 0.30% | 0.00%, SHONA: 0.10% | 0.00%, PORTUGUESE: 0.10% | 0.00%, SOTHO: 0.30% | 0.00%, CZECH: 0.10% | 0.00%, ALBANIAN: 0.40% | 0.00%, AZERBAIJANI: 0.10% | 0.00%, ICELANDIC: 0.10% | 0.00%, SLOVENE: 0.10% | 0.00%
>> Detection of 1000 sentences (average length: 111 chars)
Accuracy: 99.20% | 99.70%
Erroneously classified as DUTCH: 0.00% | 0.20%, LATIN: 0.20% | 0.10%, NYNORSK: 0.10% | 0.00%, SPANISH: 0.10% | 0.00%, DANISH: 0.10% | 0.00%, SOTHO: 0.20% | 0.00%, ZULU: 0.10% | 0.00%
Lingua está alojada en paquetes de Github y Maven Central.
// Groovy syntax
implementation 'com.github.pemistahl:lingua:1.2.2'
// Kotlin syntax
implementation("com.github.pemistahl:lingua:1.2.2")
<dependency>
<groupId>com.github.pemistahl</groupId>
<artifactId>lingua</artifactId>
<version>1.2.2</version>
</dependency>
Lingua usa Gradle para construir y requiere Java> = 1.8 para eso.
git clone https://github.com/pemistahl/lingua.git
cd lingua
./gradlew build
Se pueden crear varios archivos de JAR a partir del proyecto.
./gradlew jar ensambla lingua-1.2.2.jar que contiene solo las fuentes compiladas../gradlew sourcesJar ensambla lingua-1.2.2-sources.jar que contiene el código fuente simple../gradlew jarWithDependencies ensambla lingua-1.2.2-with-dependencies.jar que contiene las fuentes compiladas y todas las dependencias externas necesarias en tiempo de ejecución. Este archivo JAR se puede incluir en proyectos sin sistemas de gestión de dependencias. También se puede usar para ejecutar lengua en modo independiente (ver más abajo). Lingua se puede usar programáticamente en su propio código o en modo independiente.
La API es bastante sencilla y se puede usar tanto en el código Kotlin como en Java.
/* Kotlin */
import com.github.pemistahl.lingua.api.*
import com.github.pemistahl.lingua.api.Language.*
val detector : LanguageDetector = LanguageDetectorBuilder .fromLanguages( ENGLISH , FRENCH , GERMAN , SPANISH ).build()
val detectedLanguage : Language = detector.detectLanguageOf(text = " languages are awesome " ) La API pública de Lingua nunca devuelve null en algún lugar, por lo que es seguro usarse también del código Java.
/* Java */
import com . github . pemistahl . lingua . api .*;
import static com . github . pemistahl . lingua . api . Language .*;
final LanguageDetector detector = LanguageDetectorBuilder . fromLanguages ( ENGLISH , FRENCH , GERMAN , SPANISH ). build ();
final Language detectedLanguage = detector . detectLanguageOf ( "languages are awesome" );Por defecto, Lingua devuelve el idioma más probable para un texto de entrada dado. Sin embargo, hay ciertas palabras que se escriben igual en más de un idioma. La palabra prólogo , por ejemplo, es una palabra válida de inglés y francés. Lingua generaría inglés o francés, lo que podría estar equivocado en el contexto dado. Para casos como ese, es posible especificar una distancia relativa mínima que las probabilidades logaritmizadas y resumidas para cada lenguaje posible tienen que satisfacer. Se puede decir de la siguiente manera:
val detector = LanguageDetectorBuilder
.fromAllLanguages()
.withMinimumRelativeDistance( 0.25 ) // minimum: 0.00 maximum: 0.99 default: 0.00
.build() Tenga en cuenta que la distancia entre las probabilidades del idioma depende de la longitud del texto de entrada. Cuanto más largo sea el texto de entrada, mayor será la distancia entre los idiomas. Entonces, si desea clasificar frases de texto muy cortas, no establezca la distancia relativa mínima demasiado alta. De lo contrario, obtendrá la mayoría de los resultados devueltos como Language.UNKNOWN .
Saber sobre el lenguaje más probable es bueno, pero ¿qué tan confiable es la probabilidad calculada? ¿Y qué menos probables son los otros idiomas examinados en comparación con el más probable? Estas preguntas también se pueden responder:
val detector = LanguageDetectorBuilder .fromLanguages( GERMAN , ENGLISH , FRENCH , SPANISH ).build()
val confidenceValues = detector.computeLanguageConfidenceValues(text = " Coding is fun. " )
// {
// ENGLISH=1.0,
// GERMAN=0.8665738136456169,
// FRENCH=0.8249537317466078,
// SPANISH=0.7792362923625288
// }En el ejemplo anterior, se devuelve un mapa de todos los idiomas posibles, ordenado por su valor de confianza en el orden descendente. Los valores que calcula el detector son parte de una métrica de confianza relativa , no de una absoluta. Cada valor es un número entre 0.0 y 1.0. El lenguaje más probable siempre se devuelve con el valor 1.0. Todos los demás idiomas obtienen valores asignados que son inferiores a 1.0, lo que denota lo menos probables de que esos idiomas sean en comparación con el idioma más probable.
El mapa devuelto por este método no necesariamente contiene todos los idiomas de los que se construyó la instancia de llamadas de LanguageDetector . Si el motor basado en reglas decide que un lenguaje específico es realmente imposible, entonces no será parte del mapa devuelto. Del mismo modo, si no se pueden encontrar probabilidades de NGRAM dentro de los idiomas del detector para el texto de entrada dado, el mapa devuelto estará vacío. Se supone que el valor de confianza para cada idioma que no es parte del mapa devuelto es 0.0.
De forma predeterminada, Lingua utiliza la carga perezosa para cargar solo aquellos modelos de lenguaje a pedido que se consideran relevantes por el motor de filtro basado en reglas. Para los servicios web, por ejemplo, es bastante beneficioso precargar todos los modelos de lenguaje en la memoria para evitar una latencia inesperada mientras espera la respuesta del servicio. Si desea habilitar el modo de carga ansiosa, puede hacerlo así:
LanguageDetectorBuilder .fromAllLanguages().withPreloadedLanguageModels().build() Múltiples instancias de LanguageDetector comparten los mismos modelos de idioma en la memoria a los que se accede asincrónicamente por las instancias.
La alta precisión de la detección de Lingua tiene el costo de ser notablemente más lento que otros detectores de idiomas. Los modelos de idiomas grandes también consumen cantidades significativas de memoria. Es posible que estos requisitos no sean factibles para los sistemas que se cuentan con recursos bajos. Si desea clasificar principalmente textos largos o necesita guardar recursos, puede habilitar un modo de baja precisión que cargue solo un pequeño subconjunto de los modelos de idioma en la memoria:
LanguageDetectorBuilder .fromAllLanguages().withLowAccuracyMode().build()La desventaja de este enfoque es que la precisión de detección para textos cortos que consisten en menos de 120 caracteres disminuirá significativamente. Sin embargo, la precisión de detección para textos que tienen más de 120 caracteres no se verán afectados.
Una alternativa para una huella de memoria más pequeña y un rendimiento más rápido es reducir el conjunto de idiomas al construir el detector de idiomas. En la mayoría de los casos, no es aconsejable construir el detector a partir de todos los idiomas compatibles. Cuando tiene conocimiento sobre los textos que desea clasificar, casi siempre puede descartar ciertos idiomas como imposibles o poco probables.
Puede haber tareas de clasificación en las que sepa de antemano que sus datos de idioma definitivamente no se escriben en latín, por ejemplo (qué sorpresa :-). La precisión de la detección puede mejorar en tales casos si excluye ciertos idiomas del proceso de decisión o simplemente incluye explícitamente idiomas relevantes:
// include all languages available in the library
// WARNING: in the worst case this produces high memory
// consumption of approximately 3.5GB
// and slow runtime performance
// (in high accuracy mode)
LanguageDetectorBuilder .fromAllLanguages()
// include only languages that are not yet extinct (= currently excludes Latin)
LanguageDetectorBuilder .fromAllSpokenLanguages()
// include only languages written with Cyrillic script
LanguageDetectorBuilder .fromAllLanguagesWithCyrillicScript()
// exclude only the Spanish language from the decision algorithm
LanguageDetectorBuilder .fromAllLanguagesWithout( Language . SPANISH )
// only decide between English and German
LanguageDetectorBuilder .fromLanguages( Language . ENGLISH , Language . GERMAN )
// select languages by ISO 639-1 code
LanguageDetectorBuilder .fromIsoCodes639_1( IsoCode639_1 . EN , IsoCode639_3 . DE )
// select languages by ISO 639-3 code
LanguageDetectorBuilder .fromIsoCodes639_3( IsoCode639_3 . ENG , IsoCode639_3 . DEU )Internamente, Lingua usa de manera eficiente todos los núcleos de su CPU para acelerar la carga de los modelos de idiomas y la detección de idiomas. Para este propósito, se utiliza un bifurcado interno. Si la biblioteca se usa dentro de un servidor de aplicaciones, la memoria consumida no se liberará automáticamente cuando la aplicación sea desanimada.
Si desea liberar todos los recursos de Lingua , tendrá que hacerlo manualmente llamando detector.unloadLanguageModels() durante el descendente. Esto borrará todos los modelos de lenguaje cargados de la memoria, pero el grupo de subprocesos seguirá funcionando.
Si desea probar Lingua antes de decidir si usarlo o no, puede ejecutarlo en un REPL e inmediatamente ver sus resultados de detección.
./gradlew runLinguaOnConsole --console=plainjava -jar lingua-1.2.2-with-dependencies.jarEntonces solo juega:
This is Lingua.
Select the language models to load.
1: enter language iso codes manually
2: all supported languages
Type a number and press <Enter>.
Type :quit to exit.
> 1
List some language iso 639-1 codes separated by spaces and press <Enter>.
Type :quit to exit.
> en fr de es
Loading language models...
Done. 4 language models loaded lazily.
Type some text and press <Enter> to detect its language.
Type :quit to exit.
> languages
ENGLISH
> Sprachen
GERMAN
> langues
FRENCH
> :quit
Bye! Ciao! Tschüss! Salut!
En caso de que desee contribuir con algo a Lingua , se le recomienda que lo haga. ¿Tienes ideas para mejorar la API? ¿Hay algunos idiomas específicos que desee haber apoyado temprano? ¿O has encontrado algún error hasta ahora? No dude en abrir un problema o enviar una solicitud de extracción. Es muy apreciado.
Para las solicitudes de extracción, asegúrese de que todas las pruebas unitarias pasen y que el código esté formateado de acuerdo con la guía de estilo Kotlin oficial. Puede verificar esto ejecutando el Kotlin Linter Ktlint usando ./gradlew ktlintCheck . La mayoría de los problemas que identifica el enlace se pueden solucionar ejecutándose ./gradlew ktlintFormat . Todos los demás problemas, especialmente líneas que tienen más de 120 caracteres, no se pueden solucionar automáticamente. En este caso, formatea las líneas respectivas a mano. Notará que la compilación fallará si el formato no es correcto.
Todo tipo de solicitudes de extracción son bienvenidas. Las más favoritas son las nuevas adiciones de idiomas. Si desea contribuir con nuevos idiomas a Lingua , aquí viene un manual detallado que explica cómo lograr eso.
Muchas gracias de antemano por todas las contribuciones, por pequeñas que sean.
Para ejecutar los pasos a continuación, necesitará Java 8 o más. A pesar de que la biblioteca en sí se ejecuta en Java> = 6, las clases FilesWriter hacen uso de la API Java.nio que se introdujo con Java 8.
IsoCode639_1 e IsoCode639_3 y agregue los códigos ISO del idioma. Entre otros sitios, Wikipedia proporciona una lista completa.Language enum y agregue una nueva entrada para su idioma. Si el lenguaje está escrito con un script que aún no es compatible con Alphabet de Lingua , entonces agregue una nueva entrada allí también.Language enum. Sin embargo, si los caracteres ocurren en más de un idioma pero no en todos los idiomas, agrégalos al CHARS_TO_LANGUAGES_MAPPING constante en clase Constant en su lugar.LanguageModelFilesWriter para crear los archivos del modelo de idioma. No es necesario que el archivo de datos de capacitación utilizado para la estimación de probabilidad de NGRAM tenga un formato específico que no sea ser un archivo txt válido./src/main/resources/language-models y coloque los archivos de modelo de idioma generados allí. No cambie el nombre de los archivos del modelo de idioma. El nombre del subdirectorio debe ser el código ISO 639-1 del idioma, completamente más bajo.TestDataFilesWriter para crear los archivos de datos de prueba utilizados para la generación de informes de precisión. El archivo de entrada desde el cual crear los datos de prueba debe tener cada oración en una línea separada./src/accuracyReport/resources/language-testdata . No cambie el nombre de los archivos de datos de prueba./src/accuracyReport/kotlin/com/github/pemistahl/lingua/report/config . Mire los archivos de los otros idiomas en este directorio para ver cómo debe ser la clase. Debería ser bastante autoexplicativo./src/accuracyReport/kotlin/com/github/pemistahl/lingua/report/lingua . Mire los archivos de los otros idiomas en este directorio para ver cómo debe ser la clase. Debería ser bastante autoexplicativo. Si una de las otras bibliotecas de detectores de idiomas ya admite su idioma, también puede agregar clases de prueba para ellas. Cada biblioteca tiene su propio directorio para este propósito. Si su idioma no es compatible con las otras bibliotecas de detectores de idiomas, excluya en AbstractLanguageDetectionAccuracyReport .linguaSupportedLanguages en /gradle.properties ../gradlew accuracyReport y agregue los informes de precisión actualizados a su solicitud de extracción../gradlew drawAccuracyPlots y agregue los gráficos actualizados a su solicitud de extracción../gradlew writeAccuracyTable y agregue la tabla de precisión actualizada a su solicitud de extracción.Eche un vistazo a los problemas planificados.