Sa tâche est simple: il vous indique quelle langue certaines ont fourni des données textuelles. D'autres cas d'utilisation, par exemple, peuvent inclure des e-mails de routage vers le bon service client géographiquement situé géographiquement, sur la base des langues des e-mails.
La détection du langage se fait souvent dans le cadre de grands cadres d'apprentissage automatique ou d'applications de traitement du langage naturel. Dans les cas où vous n'avez pas besoin des fonctionnalités à part entière de ces systèmes ou ne voulez pas apprendre les cordes de ceux-ci, une petite bibliothèque flexible est utile.
Jusqu'à présent, trois autres bibliothèques open source complètes travaillant sur le JVM pour cette tâche sont Apache Tika, Apache OpenNLP et Optimaize Language Detector. Malheureusement, en particulier ce dernier a trois inconvénients majeurs:
Lingua vise à éliminer ces problèmes. Il n'a presque pas besoin de configuration et donne des résultats assez précis sur du texte long et court, même sur des mots et des phrases uniques. Il s'appuie à la fois sur des méthodes basées sur des règles et statistiques mais n'utilise aucun dictionnaire de mots. Il n'a pas besoin d'une connexion à aucune API ou service externe non plus. Une fois la bibliothèque téléchargée, elle peut être utilisée complètement hors ligne.
Par rapport aux autres bibliothèques de détection de langues, Lingua se concentre sur la qualité de la quantité , c'est-à-dire que la détection est correcte pour un petit ensemble de langues avant d'en ajouter de nouvelles. Actuellement, les 75 langues suivantes sont prises en charge:
Lingua est en mesure de signaler les statistiques de précision pour certaines données de test groupées disponibles pour chaque langue prise en charge. Les données de test pour chaque langue sont divisées en trois parties:
Les modèles linguistiques et les données de test ont été créés à partir de documents distincts des corpus Wortschatz offerts par l'Université de Leipzig, en Allemagne. Les données rampées à partir de divers sites de nouvelles ont été utilisées pour la formation, chaque corpus comprenant un million de phrases. Pour les tests, les corpus en sites Web choisis arbitrairement ont été utilisés, chacun comprenant dix mille phrases. À partir de chaque corpus de test, un sous-ensemble aléatoire non trié de 1000 mots simples, 1000 paires de mots et 1000 phrases a été extrait, respectivement.
Compte tenu des données de test générées, j'ai comparé les résultats de détection de Lingua , Apache Tika , Apache OpenNLP et Optimaize Language Detector à l'aide de tests JUnit paramétrés fonctionnant sur les données des 75 langues prises en charge de Lingua . Les langues qui ne sont pas prises en charge par les autres bibliothèques sont simplement ignorées pour celles du processus de détection.
Chacune des sections suivantes contient deux parcelles. Le tracé de la barre montre les résultats de précision détaillés pour chaque langue prise en charge. Le tracé de la boîte illustre les distributions des valeurs de précision pour chaque classificateur. Les boîtes elles-mêmes représentent les zones dans lesquelles les 50% du milieu se trouvent dans les données. Dans les boîtes colorées, les lignes horizontales marquent la médiane des distributions.
Le tableau ci-dessous montre des statistiques détaillées pour chaque langue et classificateur, y compris la moyenne, la médiane et l'écart type.
| Langue | Moyenne | Mots simples | Paires de mots | Phrases | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Lingua (Mode de haute précision) | Lingua (mode de faible précision) | Tika | Opennlp | Optimisation | Lingua (Mode de haute précision) | Lingua (mode de faible précision) | Tika | Opennlp | Optimisation | Lingua (Mode de haute précision) | Lingua (mode de faible précision) | Tika | Opennlp | Optimisation | Lingua (Mode de haute précision) | Lingua (mode de faible précision) | Tika | Opennlp | Optimisation | |
| afrikaans | 79 | 64 | 71 | 72 | 39 | 58 | 38 | 44 | 41 | 3 | 81 | 62 | 70 | 75 | 22 | 97 | 93 | 98 | 99 | 93 |
| albanais | 88 | 80 | 79 | 71 | 70 | 69 | 54 | 54 | 40 | 38 | 95 | 86 | 84 | 73 | 73 | 100 | 99 | 99 | 100 | 98 |
| arabe | 98 | 94 | 97 | 84 | 89 | 96 | 88 | 94 | 65 | 72 | 99 | 96 | 99 | 88 | 94 | 100 | 99 | 100 | 99 | 100 |
| arménien | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - |
| azerbaïdjanais | 90 | 82 | - | 82 | - | 77 | 71 | - | 60 | - | 92 | 78 | - | 86 | - | 99 | 96 | - | 99 | - |
| Basque | 84 | 74 | 83 | 77 | 66 | 71 | 56 | 64 | 56 | 33 | 87 | 76 | 86 | 82 | 70 | 93 | 91 | 98 | 92 | 95 |
| Biéloruste | 97 | 92 | 96 | 91 | 87 | 92 | 80 | 92 | 78 | 69 | 99 | 95 | 98 | 95 | 92 | 100 | 100 | 100 | 100 | 99 |
| bengali | 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 | - |
| Bosnie | 35 | 29 | - | 26 | - | 29 | 23 | - | 12 | - | 35 | 29 | - | 22 | - | 40 | 36 | - | 44 | - |
| bulgare | 87 | 78 | 73 | 83 | 48 | 70 | 56 | 52 | 62 | 18 | 91 | 81 | 69 | 87 | 36 | 99 | 96 | 96 | 100 | 91 |
| catalan | 70 | 58 | 58 | 42 | 31 | 51 | 33 | 32 | 11 | 2 | 74 | 60 | 57 | 32 | 16 | 86 | 81 | 84 | 81 | 77 |
| Chinois | 100 | 100 | 69 | 78 | 31 | 100 | 100 | 20 | 40 | 0 | 100 | 100 | 86 | 94 | 2 | 100 | 100 | 100 | 100 | 91 |
| croate | 72 | 60 | 74 | 50 | 41 | 53 | 36 | 54 | 23 | 8 | 74 | 57 | 72 | 44 | 24 | 90 | 85 | 97 | 81 | 91 |
| tchèque | 80 | 71 | 72 | 67 | 49 | 66 | 54 | 54 | 42 | 21 | 84 | 72 | 75 | 70 | 46 | 91 | 87 | 88 | 90 | 81 |
| danois | 81 | 70 | 83 | 60 | 55 | 61 | 45 | 63 | 34 | 19 | 84 | 70 | 86 | 52 | 51 | 98 | 95 | 99 | 94 | 96 |
| Néerlandais | 77 | 64 | 60 | 61 | 39 | 55 | 36 | 31 | 31 | 6 | 81 | 61 | 52 | 57 | 19 | 96 | 94 | 98 | 97 | 91 |
| Anglais | 81 | 62 | 64 | 52 | 41 | 55 | 29 | 30 | 10 | 2 | 89 | 62 | 62 | 46 | 23 | 99 | 96 | 99 | 99 | 97 |
| espéranto | 84 | 66 | - | 76 | - | 67 | 44 | - | 50 | - | 85 | 61 | - | 78 | - | 98 | 92 | - | 100 | - |
| estonien | 92 | 83 | 84 | 59 | 61 | 80 | 62 | 66 | 29 | 23 | 96 | 88 | 88 | 60 | 63 | 100 | 99 | 100 | 88 | 98 |
| finlandais | 96 | 91 | 94 | 86 | 79 | 90 | 77 | 86 | 68 | 51 | 98 | 95 | 96 | 91 | 86 | 100 | 100 | 100 | 100 | 100 |
| Français | 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 | - | - | - |
| géorgien | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - |
| Allemand | 89 | 80 | 74 | 67 | 55 | 74 | 57 | 50 | 38 | 21 | 94 | 84 | 71 | 66 | 46 | 100 | 99 | 100 | 98 | 99 |
| grec | 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 |
| hébreu | 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 |
| hongrois | 95 | 90 | 88 | 78 | 77 | 87 | 77 | 75 | 53 | 51 | 98 | 94 | 91 | 82 | 82 | 100 | 100 | 100 | 100 | 99 |
| islandais | 93 | 88 | 90 | 76 | 78 | 83 | 72 | 76 | 53 | 53 | 97 | 92 | 94 | 76 | 82 | 100 | 99 | 100 | 99 | 99 |
| indonésien | 60 | 48 | 60 | 29 | 18 | 39 | 25 | 37 | 10 | 0 | 61 | 46 | 62 | 25 | 1 | 81 | 72 | 82 | 52 | 54 |
| irlandais | 91 | 85 | 90 | 78 | 80 | 82 | 70 | 80 | 56 | 58 | 94 | 90 | 92 | 82 | 85 | 96 | 95 | 99 | 97 | 98 |
| italien | 87 | 71 | 80 | 64 | 51 | 69 | 42 | 58 | 31 | 12 | 92 | 74 | 84 | 61 | 43 | 100 | 98 | 99 | 100 | 98 |
| japonais | 100 | 100 | 25 | 95 | 98 | 100 | 100 | 1 | 87 | 99 | 100 | 100 | 5 | 100 | 100 | 100 | 100 | 68 | 100 | 96 |
| Kazakh | 92 | 90 | - | 85 | - | 80 | 78 | - | 66 | - | 96 | 93 | - | 90 | - | 99 | 99 | - | 100 | - |
| coréen | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| latin | 87 | 73 | - | 70 | - | 72 | 49 | - | 43 | - | 93 | 76 | - | 71 | - | 97 | 93 | - | 96 | - |
| letton | 93 | 87 | 90 | 86 | 78 | 85 | 75 | 78 | 72 | 56 | 97 | 90 | 93 | 88 | 82 | 99 | 97 | 98 | 98 | 97 |
| lituanien | 95 | 87 | 89 | 79 | 72 | 86 | 76 | 74 | 56 | 40 | 98 | 89 | 92 | 83 | 77 | 100 | 98 | 99 | 99 | 98 |
| Macédonien | 84 | 72 | 83 | 68 | 46 | 66 | 52 | 66 | 37 | 10 | 86 | 70 | 83 | 68 | 32 | 99 | 95 | 100 | 98 | 97 |
| malais | 31 | 31 | 23 | 19 | 4 | 26 | 22 | 19 | 10 | 0 | 38 | 36 | 22 | 20 | 0 | 30 | 36 | 28 | 27 | 11 |
| Maoris | 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 | - |
| persan | 90 | 80 | 81 | 75 | 62 | 78 | 62 | 65 | 53 | 29 | 94 | 80 | 79 | 74 | 58 | 100 | 98 | 99 | 99 | 99 |
| polonais | 95 | 90 | 90 | 83 | 81 | 85 | 77 | 76 | 61 | 57 | 98 | 93 | 93 | 89 | 86 | 100 | 99 | 100 | 100 | 100 |
| portugais | 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 |
| roumain | 87 | 72 | 78 | 67 | 55 | 69 | 49 | 57 | 34 | 24 | 92 | 74 | 80 | 68 | 50 | 99 | 94 | 97 | 99 | 91 |
| russe | 90 | 78 | 80 | 50 | 53 | 76 | 59 | 62 | 20 | 22 | 95 | 84 | 85 | 43 | 50 | 98 | 92 | 94 | 86 | 87 |
| serbe | 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 | - | - | - |
| slovaque | 84 | 75 | 76 | 70 | 47 | 64 | 49 | 53 | 39 | 12 | 90 | 78 | 76 | 73 | 38 | 99 | 97 | 98 | 99 | 92 |
| slovène | 82 | 67 | 74 | 71 | 37 | 61 | 39 | 53 | 43 | 3 | 87 | 68 | 72 | 72 | 18 | 99 | 93 | 98 | 99 | 90 |
| somali | 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 | - | - | - |
| Espagnol | 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 |
| suédois | 84 | 72 | 71 | 69 | 50 | 64 | 46 | 44 | 41 | 15 | 88 | 76 | 72 | 69 | 42 | 99 | 95 | 97 | 97 | 94 |
| Tagalog | 78 | 66 | 77 | 61 | 61 | 52 | 36 | 53 | 27 | 23 | 83 | 67 | 79 | 57 | 62 | 99 | 96 | 99 | 98 | 97 |
| Tamoul | 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 |
| thaïlandais | 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 | - | - | - |
| turc | 94 | 87 | 81 | 72 | 70 | 84 | 71 | 62 | 48 | 43 | 98 | 91 | 83 | 71 | 70 | 100 | 99 | 99 | 98 | 96 |
| ukrainien | 92 | 86 | 81 | 79 | 68 | 84 | 75 | 62 | 54 | 39 | 97 | 92 | 84 | 83 | 69 | 95 | 93 | 97 | 99 | 94 |
| Ourdou | 91 | 80 | 83 | 68 | 72 | 80 | 65 | 68 | 45 | 49 | 94 | 78 | 84 | 62 | 71 | 98 | 96 | 96 | 98 | 96 |
| vietnamien | 91 | 87 | 85 | 84 | 87 | 79 | 76 | 63 | 66 | 65 | 94 | 87 | 92 | 86 | 95 | 99 | 98 | 100 | 100 | 100 |
| gallois | 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 | - | - | - |
| zoulou | 81 | 70 | - | 78 | - | 62 | 45 | - | 51 | - | 83 | 72 | - | 82 | - | 97 | 94 | - | 100 | - |
| Signifier | 86 | 77 | 80 | 74 | 65 | 74 | 61 | 64 | 53 | 41 | 89 | 78 | 81 | 74 | 61 | 96 | 93 | 96 | 95 | 93 |
| Médian | 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 |
| Écart-type | 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 |
Chaque détecteur de langue utilise un modèle N-gram probabiliste formé sur la distribution des caractères dans certains corpus d'entraînement. La plupart des bibliothèques n'utilisent que des n-grammes de taille 3 (trigrammes), ce qui est satisfaisant pour détecter la langue des fragments de texte plus longs composés de plusieurs phrases. Pour les phrases courtes ou les mots uniques, cependant, les trigrammes ne suffisent pas. Plus le texte d'entrée est court, moins les grammes N sont disponibles. Les probabilités estimées à partir de ces quelques n-grammes ne sont pas fiables. C'est pourquoi Lingua utilise des n-grammes de tailles 1 jusqu'à 5, ce qui se traduit par une prédiction beaucoup plus précise de la langue correcte.
Une deuxième différence importante est que Lingua n'utilise pas seulement un tel modèle statistique, mais aussi un moteur basé sur des règles. Ce moteur détermine d'abord l'alphabet du texte d'entrée et recherche des caractères uniques dans une ou plusieurs langues. Si exactement une langue peut être choisie de manière fiable de cette façon, le modèle statistique n'est plus nécessaire. Dans tous les cas, le moteur basé sur des règles filtre les langues qui ne satisfont pas aux conditions du texte d'entrée. Ce n'est qu'à ce moment-là, dans une deuxième étape, le modèle probabiliste N-gram est pris en considération. Cela a du sens car le chargement des modèles de langue moins de la langue signifie moins de consommation de mémoire et de meilleures performances d'exécution.
En général, c'est toujours une bonne idée de restreindre l'ensemble des langues à considérer dans le processus de classification en utilisant les méthodes API respectives. Si vous savez au préalable que certaines langues ne se produisent jamais dans un texte d'entrée, ne laissez pas les personnes participer au processus de classifcation. Le mécanisme de filtrage du moteur basé sur des règles est assez bon, cependant, le filtrage basé sur votre propre connaissance du texte d'entrée est toujours préférable.
Si vous souhaitez reproduire les résultats de précision ci-dessus, vous pouvez générer les rapports de test vous-même pour les quatre classificateurs et toutes les langues en faisant:
./gradlew accuracyReport
Vous pouvez également restreindre les classificateurs et les langues pour générer des rapports pour passer des arguments à la tâche Gradle. La tâche suivante génère des rapports pour Lingua et les langues anglais et allemand uniquement:
./gradlew accuracyReport -Pdetectors=Lingua -Planguages=English,German
Par défaut, un seul noyau CPU est utilisé pour la génération de rapports. Si vous avez un processeur multi-core dans votre machine, vous pouvez débarquer autant de processus que vous avez des cœurs de CPU. Cela accélère considérablement la génération de rapports. Cependant, sachez que la transmission de plus d'un processus peut consommer beaucoup de RAM. Vous le faites comme ceci:
./gradlew accuracyReport -PcpuCores=2
Pour chaque détecteur et langue, un fichier de rapport de test est ensuite rédigé dans /accuracy-reports , à trouver à côté du répertoire src . À titre d'exemple, voici la sortie actuelle du rapport allemand de Lingua :
##### 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 hébergé sur les packages GitHub et 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 utilise Gradle pour construire et nécessite Java> = 1,8 pour cela.
git clone https://github.com/pemistahl/lingua.git
cd lingua
./gradlew build
Plusieurs archives JAR peuvent être créées à partir du projet.
./gradlew jar assemble lingua-1.2.2.jar contenant uniquement les sources compilées../gradlew sourcesJar assemble lingua-1.2.2-sources.jar contenant le code source simple../gradlew jarWithDependencies assemble lingua-1.2.2-with-dependencies.jar contenant les sources compilées et toutes les dépendances externes nécessaires au moment de l'exécution. Ce fichier JAR peut être inclus dans des projets sans systèmes de gestion des dépendances. Il peut également être utilisé pour exécuter Lingua en mode autonome (voir ci-dessous). Lingua peut être utilisé par programme dans votre propre code ou en mode autonome.
L'API est assez simple et peut être utilisée dans le code Kotlin et 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 " ) L'API publique de Lingua ne revient jamais null quelque part, il est donc sûr d'être également utilisé à partir du code 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" );Par défaut, Lingua renvoie la langue la plus probable pour un texte d'entrée donné. Cependant, certains mots sont orthographiés de la même manière dans plus d'une langue. Le mot prologue , par exemple, est à la fois un mot anglais et français valide. Lingua sortirait l'anglais ou le français, ce qui pourrait être faux dans le contexte donné. Pour des cas comme celui-ci, il est possible de spécifier une distance relative minimale que les probabilités logarithmiques et résumées pour chaque langue possible doivent satisfaire. Il peut être énoncé de la manière suivante:
val detector = LanguageDetectorBuilder
.fromAllLanguages()
.withMinimumRelativeDistance( 0.25 ) // minimum: 0.00 maximum: 0.99 default: 0.00
.build() Sachez que la distance entre les probabilités de langue dépend de la longueur du texte d'entrée. Plus le texte d'entrée est long, plus la distance entre les langues est grande. Donc, si vous souhaitez classer les phrases de texte très courtes, ne définissez pas la distance relative minimale trop élevée. Sinon, vous obtiendrez la plupart des résultats renvoyés en tant que Language.UNKNOWN .
Connaître le langage le plus probable est agréable, mais à quel point la probabilité calculée est-elle fiable? Et à quel point les autres langues examinées sont-elles moins probables par rapport à la plus probable? Ces questions peuvent également être répondues:
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
// }Dans l'exemple ci-dessus, une carte de toutes les langues possibles est renvoyée, triée par leur valeur de confiance dans l'ordre descendant. Les valeurs calculées par le détecteur font partie d'une métrique de confiance relative , et non d'une métrique absolue. Chaque valeur est un nombre entre 0,0 et 1,0. La langue la plus probable est toujours renvoyée avec la valeur 1.0. Toutes les autres langues obtiennent des valeurs attribuées qui sont inférieures à 1,0, indiquant à quel point ces langues sont moins probables par rapport à la langue la plus probable.
La carte renvoyée par cette méthode ne contient pas nécessairement toutes les langues dont l'instance d'appel de LanguageDetector a été construite. Si le moteur basé sur des règles décide qu'un langage spécifique est vraiment impossible, il ne fera pas partie de la carte retournée. De même, si aucune probabilité NGRAM ne peut être trouvée dans les langues du détecteur pour le texte d'entrée donné, la carte retournée sera vide. La valeur de confiance pour chaque langue ne faisant pas partie de la carte retournée est supposée être de 0,0.
Par défaut, Lingua utilise un chargement paresseux pour charger uniquement les modèles de langue à la demande qui sont considérés comme pertinents par le moteur de filtre basé sur des règles. Pour les services Web, par exemple, il est plutôt avantageux de précharger tous les modèles de langue en mémoire pour éviter une latence inattendue en attendant la réponse du service. Si vous souhaitez activer le mode de chargement impatient, vous pouvez le faire comme ceci:
LanguageDetectorBuilder .fromAllLanguages().withPreloadedLanguageModels().build() Plusieurs instances de LanguageDetector partagent les mêmes modèles de langue en mémoire qui sont accessibles de manière asynchrone par les instances.
La haute précision de détection de Lingua se fait au prix d'être sensiblement plus lent que les autres détecteurs de langue. Les grands modèles de langue consomment également des quantités importantes de mémoire. Ces exigences pourraient ne pas être réalisables pour les systèmes à faible teneur en ressources. Si vous souhaitez classer les textes principalement longs ou devez enregistrer des ressources, vous pouvez activer un mode de faible précision qui ne charge qu'un petit sous-ensemble des modèles de langue en mémoire:
LanguageDetectorBuilder .fromAllLanguages().withLowAccuracyMode().build()L'inconvénient de cette approche est que la précision de détection pour les textes courts composés de moins de 120 caractères baissera considérablement. Cependant, la précision de détection pour les textes de plus de 120 caractères restera principalement non affectées.
Une alternative pour une empreinte mémoire plus petite et des performances plus rapides consiste à réduire l'ensemble des langues lors de la construction du détecteur de langue. Dans la plupart des cas, il n'est pas conseillé de construire le détecteur à partir de toutes les langues prises en charge. Lorsque vous avez des connaissances sur les textes que vous souhaitez classer, vous pouvez presque toujours exclure certaines langues comme impossibles ou peu susceptibles de se produire.
Il peut y avoir des tâches de classification où vous savez au préalable que vos données linguistiques ne sont certainement pas écrites en latin, par exemple (quelle surprise :-). La précision de détection peut devenir meilleure dans de tels cas si vous excluez certaines langues du processus de décision ou incluez simplement explicitement les langues pertinentes:
// 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 )En interne, Lingua utilise efficacement tous les noyaux de votre CPU afin d'accélérer le chargement des modèles de langue et de la détection du langage lui-même. À cette fin, une fourche interne est utilisée. Si la bibliothèque est utilisée dans un serveur d'applications, la mémoire consommée ne sera pas libérée automatiquement lorsque l'application n'est pas exploitée.
Si vous souhaitez libérer toutes les ressources de Lingua , vous devrez le faire manuellement en appelant detector.unloadLanguageModels() pendant le Undeployment. Cela effacera tous les modèles de langage chargés de la mémoire, mais le pool de thread continuera à fonctionner.
Si vous souhaitez essayer Lingua avant de décider de l'utiliser ou non, vous pouvez l'exécuter dans un REP et voir immédiatement ses résultats de détection.
./gradlew runLinguaOnConsole --console=plainjava -jar lingua-1.2.2-with-dependencies.jarAlors jouez simplement:
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!
Dans le cas où vous souhaitez contribuer quelque chose à Lingua , vous êtes encouragé à le faire. Avez-vous des idées pour améliorer l'API? Y a-t-il des langues spécifiques que vous souhaitez avoir soutenues tôt? Ou avez-vous trouvé des bogues jusqu'à présent? N'hésitez pas à ouvrir un problème ou à envoyer une demande de traction. C'est très apprécié.
Pour les demandes de traction, assurez-vous que tous les tests unitaires passent et que le code est formaté en fonction du guide officiel de style Kotlin. Vous pouvez vérifier cela en exécutant le Kotlin Linter Ktlint en utilisant ./gradlew ktlintCheck . La plupart des problèmes que le Linter identifient peut être résolu en exécutant ./gradlew ktlintFormat . Tous les autres problèmes, en particulier les lignes de plus de 120 caractères, ne peuvent pas être réparés automatiquement. Dans ce cas, veuillez formater les lignes respectives à la main. Vous remarquerez que la construction échouera si le formatage n'est pas correct.
Toutes sortes de demandes de traction sont les bienvenues. Les plus préférés sont les nouveaux ajouts de langue. Si vous souhaitez contribuer de nouvelles langues à Lingua , voici un manuel détaillé expliquant comment y parvenir.
Merci beaucoup à l'avance pour toutes les contributions, aussi petites qu'elles soient.
Afin d'exécuter les étapes ci-dessous, vous aurez besoin de Java 8 ou plus. Même si la bibliothèque elle-même s'exécute sur Java> = 6, les classes FilesWriter utilisent l'API Java.nio qui a été introduite avec Java 8.
IsoCode639_1 et IsoCode639_3 et ajoutez les codes ISO de la langue. Entre autres sites, Wikipedia fournit une liste complète.Language d'énumération et ajoutez une nouvelle entrée pour votre langue. Si la langue est écrite avec un script qui n'est pas encore pris en charge par Alphabet de Lingua , ajoutez également une nouvelle entrée.Language . Cependant, si les caractères se produisent dans plusieurs langues mais pas dans toutes les langues, ajoutez-les à la constante CHARS_TO_LANGUAGES_MAPPING dans Constant de classe.LanguageModelFilesWriter pour créer les fichiers de modèle de langue. Le fichier de données de formation utilisé pour l'estimation de probabilité NGRAM n'est pas nécessaire d'avoir un format spécifique autre que d'être un fichier TXT valide./src/main/resources/language-models et y mettez les fichiers de modèle de langue générés. Ne renommez pas les fichiers du modèle de langue. Le nom du sous-répertoire doit être le code ISO 639-1 de la langue, complètement classé inférieur.TestDataFilesWriter pour créer les fichiers de données de test utilisés pour la génération de rapport de précision. Le fichier d'entrée à partir de laquelle créer les données de test doit avoir chaque phrase sur une ligne distincte./src/accuracyReport/resources/language-testdata . Ne renommez pas les fichiers de données de test./src/accuracyReport/kotlin/com/github/pemistahl/lingua/report/config . Regardez les fichiers des autres langues dans ce répertoire pour voir à quoi doit ressembler la classe. Cela devrait être assez explicite./src/accuracyReport/kotlin/com/github/pemistahl/lingua/report/lingua . Regardez les fichiers des autres langues dans ce répertoire pour voir à quoi doit ressembler la classe. Cela devrait être assez explicite. Si l'une des autres bibliothèques de détecteur de langue prend déjà en charge votre langue, vous pouvez également ajouter des classes de test pour celles-ci. Chaque bibliothèque a son propre répertoire à cet effet. Si votre langue n'est pas prise en charge par les autres bibliothèques de détecteur de langue, excluez-la dans AbstractLanguageDetectionAccuracyReport .linguaSupportedLanguages dans /gradle.properties ../gradlew accuracyReport et ajoutez les rapports de précision mis à jour à votre demande de traction../gradlew drawAccuracyPlots et ajoutez les tracés mis à jour à votre demande de traction../gradlew writeAccuracyTable et ajoutez la table de précision mise à jour à votre demande de traction.Jetez un œil aux problèmes prévus.