Его задача проста: он говорит вам, в каком языке записываются некоторые текстовые данные. Это очень полезно в качестве шага предварительной обработки для лингвистических данных в приложениях обработки естественного языка, таких как классификация текста и проверка орфографии. Например, другие варианты использования могут включать маршрутизацию электронных писем в нужное географически расположенное отдел обслуживания клиентов на основе языков электронной почты.
Обнаружение языка часто выполняется как часть крупных структур машинного обучения или приложений для обработки естественного языка. В тех случаях, когда вам не нужна полноценная функциональность этих систем или вы не хотите изучать веревки их, небольшая гибкая библиотека пригодится.
До настоящего времени тремя другими комплексными библиотеками с открытым исходным кодом, работающими над JVM для этой задачи, являются Apache Tika, Apache OpenLP и оптимизированный языковой детектор. К сожалению, особенно у последнего есть три основных недостатка:
Лингю стремится устранить эти проблемы. Это почти не нуждается в каких -либо конфигурации и дает довольно точные результаты как по длинному, так и в коротком тексту, даже на отдельных словах и фразах. Он опирается как на основанных на правилах, так и на статистических методах, но не использует никаких словарей слов. Он также не нуждается в соединении с каким -либо внешним API или службой. Как только библиотека будет загружена, ее можно использовать полностью в автономном режиме.
По сравнению с другими библиотеками обнаружения языка, Lugua сосредоточено на качественном количестве , то есть к тому, чтобы сначала обнаружение для небольшого набора языков, прежде чем добавлять новые. В настоящее время поддерживаются следующие 75 языков:
Lingua может сообщать о статистике точности для некоторых комплексных тестовых данных, доступных для каждого поддерживаемого языка. Тестовые данные для каждого языка разделены на три части:
Как языковые модели, так и данные тестирования были созданы из отдельных документов корпорации Wortschatz, предлагаемых Университетом Лейпцига, Германия. Данные, заполненные различными новостными веб -сайтами, использовались для обучения, каждый корпус включает в себя миллион предложений. Для тестирования использовались корпуса, изготовленные из произвольно выбранных сайтов, каждый из которых содержит десять тысяч предложений. Из каждого тестового корпуса было извлечено случайное несортированное подмножество из 1000 отдельных слов, 1000 слов и 1000 предложений соответственно.
Учитывая сгенерированные данные тестирования, я сравнил результаты обнаружения Lingua , Apache Tika , Apache OpenLP и оптимизированного языкового детектора с использованием параметризованных тестов JUNIT, выполняемых по данным поддерживаемых 75 языков Lugua . Языки, которые не поддерживаются другими библиотеками, просто игнорируются для тех, кто в процессе обнаружения.
Каждый из следующих разделов содержит два сюжета. График бара показывает подробные результаты точности для каждого поддерживаемого языка. График коробки иллюстрирует распределения значений точности для каждого классификатора. Сами коробки представляют области, в которых находятся средние 50 % данных внутри. В цветных ящиках горизонтальные линии отмечают медиана распределений.
В таблице ниже показана подробная статистика для каждого языка и классификатора, включая среднее, медианное и стандартное отклонение.
| Язык | Средний | Отдельные слова | Пары слов | Предложения | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Лингва (режим высокой точности) | Лингва (режим низкой точности) | Тика | Opennlp | Оптимазе | Лингва (режим высокой точности) | Лингва (режим низкой точности) | Тика | Opennlp | Оптимазе | Лингва (режим высокой точности) | Лингва (режим низкой точности) | Тика | Opennlp | Оптимазе | Лингва (режим высокой точности) | Лингва (режим низкой точности) | Тика | Opennlp | Оптимазе | |
| африкаанс | 79 | 64 | 71 | 72 | 39 | 58 | 38 | 44 | 41 | 3 | 81 | 62 | 70 | 75 | 22 | 97 | 93 | 98 | 99 | 93 |
| албанский | 88 | 80 | 79 | 71 | 70 | 69 | 54 | 54 | 40 | 38 | 95 | 86 | 84 | 73 | 73 | 100 | 99 | 99 | 100 | 98 |
| арабский | 98 | 94 | 97 | 84 | 89 | 96 | 88 | 94 | 65 | 72 | 99 | 96 | 99 | 88 | 94 | 100 | 99 | 100 | 99 | 100 |
| Армянский | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - |
| Азербайджани | 90 | 82 | - | 82 | - | 77 | 71 | - | 60 | - | 92 | 78 | - | 86 | - | 99 | 96 | - | 99 | - |
| Баск | 84 | 74 | 83 | 77 | 66 | 71 | 56 | 64 | 56 | 33 | 87 | 76 | 86 | 82 | 70 | 93 | 91 | 98 | 92 | 95 |
| Белорус | 97 | 92 | 96 | 91 | 87 | 92 | 80 | 92 | 78 | 69 | 99 | 95 | 98 | 95 | 92 | 100 | 100 | 100 | 100 | 99 |
| Бенгальский | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| Бокмал | 58 | 49 | - | 66 | - | 39 | 27 | - | 42 | - | 59 | 47 | - | 69 | - | 75 | 74 | - | 87 | - |
| Боснийский | 35 | 29 | - | 26 | - | 29 | 23 | - | 12 | - | 35 | 29 | - | 22 | - | 40 | 36 | - | 44 | - |
| болгарский | 87 | 78 | 73 | 83 | 48 | 70 | 56 | 52 | 62 | 18 | 91 | 81 | 69 | 87 | 36 | 99 | 96 | 96 | 100 | 91 |
| Каталонский | 70 | 58 | 58 | 42 | 31 | 51 | 33 | 32 | 11 | 2 | 74 | 60 | 57 | 32 | 16 | 86 | 81 | 84 | 81 | 77 |
| китайский | 100 | 100 | 69 | 78 | 31 | 100 | 100 | 20 | 40 | 0 | 100 | 100 | 86 | 94 | 2 | 100 | 100 | 100 | 100 | 91 |
| хорватский | 72 | 60 | 74 | 50 | 41 | 53 | 36 | 54 | 23 | 8 | 74 | 57 | 72 | 44 | 24 | 90 | 85 | 97 | 81 | 91 |
| чешский | 80 | 71 | 72 | 67 | 49 | 66 | 54 | 54 | 42 | 21 | 84 | 72 | 75 | 70 | 46 | 91 | 87 | 88 | 90 | 81 |
| Датский | 81 | 70 | 83 | 60 | 55 | 61 | 45 | 63 | 34 | 19 | 84 | 70 | 86 | 52 | 51 | 98 | 95 | 99 | 94 | 96 |
| Голландский | 77 | 64 | 60 | 61 | 39 | 55 | 36 | 31 | 31 | 6 | 81 | 61 | 52 | 57 | 19 | 96 | 94 | 98 | 97 | 91 |
| Английский | 81 | 62 | 64 | 52 | 41 | 55 | 29 | 30 | 10 | 2 | 89 | 62 | 62 | 46 | 23 | 99 | 96 | 99 | 99 | 97 |
| эсперанто | 84 | 66 | - | 76 | - | 67 | 44 | - | 50 | - | 85 | 61 | - | 78 | - | 98 | 92 | - | 100 | - |
| эстонский | 92 | 83 | 84 | 59 | 61 | 80 | 62 | 66 | 29 | 23 | 96 | 88 | 88 | 60 | 63 | 100 | 99 | 100 | 88 | 98 |
| Финский | 96 | 91 | 94 | 86 | 79 | 90 | 77 | 86 | 68 | 51 | 98 | 95 | 96 | 91 | 86 | 100 | 100 | 100 | 100 | 100 |
| Французский | 89 | 77 | 78 | 59 | 54 | 74 | 52 | 55 | 25 | 18 | 94 | 83 | 80 | 55 | 48 | 99 | 97 | 99 | 98 | 97 |
| Ганда | 91 | 84 | - | - | - | 79 | 65 | - | - | - | 95 | 87 | - | - | - | 100 | 100 | - | - | - |
| Грузинец | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - | 100 | 100 | - | 100 | - |
| немецкий | 89 | 80 | 74 | 67 | 55 | 74 | 57 | 50 | 38 | 21 | 94 | 84 | 71 | 66 | 46 | 100 | 99 | 100 | 98 | 99 |
| Греческий | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| Гуджарати | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| иврит | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| хинди | 73 | 33 | 80 | 58 | 51 | 61 | 11 | 65 | 28 | 16 | 64 | 20 | 75 | 49 | 38 | 93 | 67 | 99 | 99 | 98 |
| венгерский | 95 | 90 | 88 | 78 | 77 | 87 | 77 | 75 | 53 | 51 | 98 | 94 | 91 | 82 | 82 | 100 | 100 | 100 | 100 | 99 |
| исландский | 93 | 88 | 90 | 76 | 78 | 83 | 72 | 76 | 53 | 53 | 97 | 92 | 94 | 76 | 82 | 100 | 99 | 100 | 99 | 99 |
| индонезийский | 60 | 48 | 60 | 29 | 18 | 39 | 25 | 37 | 10 | 0 | 61 | 46 | 62 | 25 | 1 | 81 | 72 | 82 | 52 | 54 |
| Ирландский | 91 | 85 | 90 | 78 | 80 | 82 | 70 | 80 | 56 | 58 | 94 | 90 | 92 | 82 | 85 | 96 | 95 | 99 | 97 | 98 |
| Итальянский | 87 | 71 | 80 | 64 | 51 | 69 | 42 | 58 | 31 | 12 | 92 | 74 | 84 | 61 | 43 | 100 | 98 | 99 | 100 | 98 |
| Японский | 100 | 100 | 25 | 95 | 98 | 100 | 100 | 1 | 87 | 99 | 100 | 100 | 5 | 100 | 100 | 100 | 100 | 68 | 100 | 96 |
| Казах | 92 | 90 | - | 85 | - | 80 | 78 | - | 66 | - | 96 | 93 | - | 90 | - | 99 | 99 | - | 100 | - |
| корейский | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| латинский | 87 | 73 | - | 70 | - | 72 | 49 | - | 43 | - | 93 | 76 | - | 71 | - | 97 | 93 | - | 96 | - |
| Латвиан | 93 | 87 | 90 | 86 | 78 | 85 | 75 | 78 | 72 | 56 | 97 | 90 | 93 | 88 | 82 | 99 | 97 | 98 | 98 | 97 |
| литовский | 95 | 87 | 89 | 79 | 72 | 86 | 76 | 74 | 56 | 40 | 98 | 89 | 92 | 83 | 77 | 100 | 98 | 99 | 99 | 98 |
| македонский | 84 | 72 | 83 | 68 | 46 | 66 | 52 | 66 | 37 | 10 | 86 | 70 | 83 | 68 | 32 | 99 | 95 | 100 | 98 | 97 |
| малайский | 31 | 31 | 23 | 19 | 4 | 26 | 22 | 19 | 10 | 0 | 38 | 36 | 22 | 20 | 0 | 30 | 36 | 28 | 27 | 11 |
| маори | 92 | 83 | - | 92 | - | 84 | 64 | - | 85 | - | 92 | 88 | - | 90 | - | 99 | 98 | - | 100 | - |
| Маратхи | 85 | 41 | 90 | 81 | 71 | 74 | 20 | 81 | 62 | 43 | 85 | 30 | 92 | 83 | 74 | 96 | 72 | 98 | 98 | 96 |
| Монгольский | 97 | 96 | - | 84 | - | 93 | 89 | - | 66 | - | 99 | 98 | - | 88 | - | 99 | 99 | - | 99 | - |
| Нинорск | 66 | 52 | - | 55 | - | 41 | 25 | - | 24 | - | 66 | 49 | - | 47 | - | 90 | 81 | - | 92 | - |
| Персидский | 90 | 80 | 81 | 75 | 62 | 78 | 62 | 65 | 53 | 29 | 94 | 80 | 79 | 74 | 58 | 100 | 98 | 99 | 99 | 99 |
| Лак | 95 | 90 | 90 | 83 | 81 | 85 | 77 | 76 | 61 | 57 | 98 | 93 | 93 | 89 | 86 | 100 | 99 | 100 | 100 | 100 |
| португальский | 81 | 69 | 63 | 58 | 40 | 59 | 42 | 34 | 22 | 7 | 85 | 70 | 58 | 54 | 19 | 98 | 95 | 98 | 98 | 94 |
| Пенджаби | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| румынский | 87 | 72 | 78 | 67 | 55 | 69 | 49 | 57 | 34 | 24 | 92 | 74 | 80 | 68 | 50 | 99 | 94 | 97 | 99 | 91 |
| Русский | 90 | 78 | 80 | 50 | 53 | 76 | 59 | 62 | 20 | 22 | 95 | 84 | 85 | 43 | 50 | 98 | 92 | 94 | 86 | 87 |
| сербский | 88 | 78 | 73 | 73 | 46 | 74 | 62 | 57 | 46 | 18 | 90 | 80 | 70 | 74 | 39 | 99 | 91 | 90 | 98 | 80 |
| Шона | 91 | 81 | - | - | - | 78 | 56 | - | - | - | 96 | 86 | - | - | - | 100 | 100 | - | - | - |
| словацкий | 84 | 75 | 76 | 70 | 47 | 64 | 49 | 53 | 39 | 12 | 90 | 78 | 76 | 73 | 38 | 99 | 97 | 98 | 99 | 92 |
| Словен | 82 | 67 | 74 | 71 | 37 | 61 | 39 | 53 | 43 | 3 | 87 | 68 | 72 | 72 | 18 | 99 | 93 | 98 | 99 | 90 |
| Сомалийский | 92 | 85 | 91 | 69 | 79 | 82 | 64 | 78 | 35 | 50 | 96 | 90 | 94 | 74 | 88 | 100 | 100 | 100 | 98 | 100 |
| Сото | 85 | 72 | - | - | - | 67 | 43 | - | - | - | 90 | 75 | - | - | - | 99 | 97 | - | - | - |
| испанский | 70 | 56 | 59 | 42 | 32 | 44 | 26 | 29 | 8 | 0 | 69 | 49 | 50 | 25 | 6 | 97 | 94 | 97 | 93 | 91 |
| суахили | 81 | 70 | 75 | 73 | 60 | 60 | 43 | 50 | 45 | 26 | 84 | 68 | 75 | 74 | 58 | 98 | 97 | 99 | 99 | 98 |
| Шведский | 84 | 72 | 71 | 69 | 50 | 64 | 46 | 44 | 41 | 15 | 88 | 76 | 72 | 69 | 42 | 99 | 95 | 97 | 97 | 94 |
| Тагаль | 78 | 66 | 77 | 61 | 61 | 52 | 36 | 53 | 27 | 23 | 83 | 67 | 79 | 57 | 62 | 99 | 96 | 99 | 98 | 97 |
| Тамильский | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| телугу | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 |
| Тайский | 99 | 99 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 98 | 98 | 100 | 99 | 100 |
| Цонга | 84 | 72 | - | - | - | 66 | 46 | - | - | - | 89 | 73 | - | - | - | 98 | 97 | - | - | - |
| Чвана | 84 | 71 | - | - | - | 65 | 44 | - | - | - | 88 | 73 | - | - | - | 99 | 96 | - | - | - |
| турецкий | 94 | 87 | 81 | 72 | 70 | 84 | 71 | 62 | 48 | 43 | 98 | 91 | 83 | 71 | 70 | 100 | 99 | 99 | 98 | 96 |
| Украинский | 92 | 86 | 81 | 79 | 68 | 84 | 75 | 62 | 54 | 39 | 97 | 92 | 84 | 83 | 69 | 95 | 93 | 97 | 99 | 94 |
| Урду | 91 | 80 | 83 | 68 | 72 | 80 | 65 | 68 | 45 | 49 | 94 | 78 | 84 | 62 | 71 | 98 | 96 | 96 | 98 | 96 |
| вьетнамский | 91 | 87 | 85 | 84 | 87 | 79 | 76 | 63 | 66 | 65 | 94 | 87 | 92 | 86 | 95 | 99 | 98 | 100 | 100 | 100 |
| валлийский | 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 | - | - | - |
| Йоруба | 75 | 62 | - | - | - | 50 | 33 | - | - | - | 77 | 61 | - | - | - | 97 | 93 | - | - | - |
| Зулу | 81 | 70 | - | 78 | - | 62 | 45 | - | 51 | - | 83 | 72 | - | 82 | - | 97 | 94 | - | 100 | - |
| Иметь в виду | 86 | 77 | 80 | 74 | 65 | 74 | 61 | 64 | 53 | 41 | 89 | 78 | 81 | 74 | 61 | 96 | 93 | 96 | 95 | 93 |
| Медиана | 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 |
| Стандартное отклонение | 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 |
Каждый языковой детектор использует вероятностную модель N-Gram, обученную распределению персонажей в некотором учебном корпусе. Большинство библиотек используют только N-граммы размера 3 (триграммы), что является удовлетворительным для обнаружения языка более длинных фрагментов текста, состоящих из нескольких предложений. Однако для коротких фраз или отдельных слов триграмм недостаточно. Чем короче текст ввода, тем меньше n-граммов доступны. Вероятности, оцененные из таких немногих N-граммов, не являются надежными. Вот почему Lingua использует N-граммы размеров 1 до 5, что приводит к гораздо более точному прогнозированию правильного языка.
Второе важное отличие состоит в том, что Lingua использует не только такую статистическую модель, но и двигатель, основанный на правилах. Этот двигатель сначала определяет алфавит входного текста и ищет символы, которые являются уникальными на одном или нескольких языках. Если именно один язык может быть надежно выбран таким образом, статистическая модель больше не нужна. В любом случае, двигатель, основанный на правилах, отображает языки, которые не удовлетворяют условиям входного текста. Только тогда, на втором этапе вероятностная модель N-грамма принимается во внимание. Это имеет смысл, потому что загрузка меньше языковых моделей означает меньше потребления памяти и лучшую производительность времени выполнения.
В целом, всегда является хорошей идеей ограничить набор языков, которые будут учитываться в процессе классификации с использованием соответствующих методов API. Если вы заранее знаете, что определенные языки никогда не возникают во входном тексте, не позволяйте им принимать участие в процессе классификации. Механизм фильтрации двигателя, основанного на правилах, довольно хорош, однако фильтрация, основанная на ваших собственных знаниях о входном тексте, всегда предпочтительнее.
Если вы хотите воспроизвести результаты точности выше, вы можете создать отчеты о испытаниях для всех четырех классификаторов и всех языков, выполняя:
./gradlew accuracyReport
Вы также можете ограничить классификаторы и языки, чтобы создать отчеты, передавая аргументы в задачу Gradle. Следующая задача генерирует отчеты только для языков и языков английского и немецкого языка:
./gradlew accuracyReport -Pdetectors=Lingua -Planguages=English,German
По умолчанию только одно ядро ЦП используется для генерации отчетов. Если у вас есть многоядерный процессор в вашей машине, вы можете расколоть столько процессов, сколько у вас есть ядра процессора. Это значительно ускоряет генерацию отчетов. Тем не менее, имейте в виду, что разбрызгивание более одного процесса может потреблять много оперативной памяти. Вы делаете это так:
./gradlew accuracyReport -PcpuCores=2
Для каждого детектора и языка файл отчета о тестировании затем записывается в /accuracy-reports , который можно найти рядом с каталогом src . В качестве примера, вот текущий выходной отчет Lingua German:
##### 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 размещен на пакетах GitHub и 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 использует Gradle для построения и требует Java> = 1,8 для этого.
git clone https://github.com/pemistahl/lingua.git
cd lingua
./gradlew build
Несколько архивов банок могут быть созданы из проекта.
./gradlew jar собирает lingua-1.2.2.jar содержащий только скомпилированные источники../gradlew sourcesJar собирает lingua-1.2.2-sources.jar содержащий простой исходный код../gradlew jarWithDependencies собирает lingua-1.2.2-with-dependencies.jar содержащий скомпилированные источники и все внешние зависимости, необходимые во время выполнения. Этот файл JAR может быть включен в проекты без систем управления зависимостями. Его также можно использовать для запуска Lingua в автономном режиме (см. Ниже). Lingua может использоваться программно в вашем собственном коде или в автономном режиме.
API довольно прост и может использоваться в коде Kotlin и 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 " ) Общественный API Lingua никогда не возвращается куда -то null , поэтому можно безопасно использовать и из кода 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" );По умолчанию Lingua возвращает наиболее вероятный язык для данного входного текста. Тем не менее, есть определенные слова, которые написаны одинаково на более чем на одном языке. Слово пролог , например, является как действительным английским, так и французским словом. Lingua выведет английский или французский, что может быть неправильно в данном контексте. В таких случаях можно определить минимальное относительное расстояние, которое должно удовлетворить логарифмизированные и суммированные вероятности для каждого возможного языка. Это можно указать следующим образом:
val detector = LanguageDetectorBuilder
.fromAllLanguages()
.withMinimumRelativeDistance( 0.25 ) // minimum: 0.00 maximum: 0.99 default: 0.00
.build() Имейте в виду, что расстояние между языковыми вероятностями зависит от длины входного текста. Чем длиннее входной текст, тем больше расстояние между языками. Поэтому, если вы хотите классифицировать очень короткие текстовые фразы, не устанавливайте минимальное относительное расстояние слишком высоким. В противном случае вы получите большинство результатов, возвращаемых как Language.UNKNOWN .
Знать о наиболее вероятном языке - это хорошо, но насколько надежна вычисленная вероятность? И насколько менее вероятно, что другие изучаемые языки по сравнению с наиболее вероятным? На эти вопросы можно ответить:
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
// }В приведенном выше примере карта всех возможных языков возвращается, отсортируемая по значению доверия в порядке убывания. Значения, которые рассчитывает детектор, являются частью относительной достоверной метрики, а не абсолютной. Каждое значение составляет число от 0,0 до 1,0. Наиболее вероятный язык всегда возвращается со значением 1.0. Все остальные языки получают присвоенные значения, которые ниже 1,0, обозначая, насколько меньше вероятность этих языков по сравнению с наиболее вероятным языком.
Карта, возвращаемая этим методом, не обязательно содержит все языки, из которых был построен призванный экземпляр LanguageDetector . Если двигатель, основанный на правилах, решает, что конкретный язык действительно невозможно, то он не будет частью возвращенной карты. Аналогичным образом, если в языках детектора не может быть найдено никаких вероятностей NGRAM для данного входного текста, возвращаемая карта будет пустой. Предполагается, что значение доверия для каждого языка, не являющегося частью возвращенной карты, составляет 0,0.
По умолчанию Lingua использует ленивую загрузку для загрузки только тех языковых моделей по требованию, которые считаются актуальными на основе правил фильтрационного двигателя. Например, для веб -сервисов довольно полезно предварительно загружать все языковые модели в память, чтобы избежать неожиданной задержки при ожидании ответа на обслуживание. Если вы хотите включить режим нетерпеливой загрузки, вы можете сделать это так:
LanguageDetectorBuilder .fromAllLanguages().withPreloadedLanguageModels().build() Многочисленные экземпляры LanguageDetector имеют одни и те же языковые модели в памяти, которые доступны асинхронно в результате экземпляров.
Высокая точность обнаружения Lingua достигается за счет того, что он заметно медленнее, чем другие языковые детекторы. Большие языковые модели также потребляют значительные объемы памяти. Эти требования могут быть невозможны для систем, работающих на низких ресурсах. Если вы хотите классифицировать в основном длинные тексты или вам необходимо сохранить ресурсы, вы можете включить режим низкой точности , который загружает лишь небольшое подмножество языковых моделей в память:
LanguageDetectorBuilder .fromAllLanguages().withLowAccuracyMode().build()Недостатком этого подхода является то, что точность обнаружения для коротких текстов, состоящих из менее чем 120 символов, значительно упадет. Тем не менее, точность обнаружения для текстов, которые более 120 символов останется в основном незатронутыми.
Альтернативой для меньшего действия памяти и более высокой производительности является уменьшение набора языков при создании языкового детектора. В большинстве случаев не рекомендуется построить детектор из всех поддерживаемых языков. Когда у вас есть знания о текстах, которые вы хотите классифицировать, вы можете почти всегда исключить определенные языки как невозможные или вряд ли произойдут.
Могут быть задачи классификации, где вы заранее знаете, что ваши языковые данные определенно не написаны на латыни, например (какой сюрприз :-). Точность обнаружения может стать лучше в таких случаях, если вы исключите определенные языки из процесса принятия решения или явно включают соответствующие языки:
// 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 )Внутренне Lingua эффективно использует все ядра вашего процессора, чтобы ускорить загрузку языковых моделей и самого обнаружения языка. Для этой цели используется внутренний форкжунпул. Если библиотека используется на сервере приложений, потребляемая память не будет освобождена автоматически, когда приложение недостаточно.
Если вы хотите освободить все ресурсы Lingua , вам придется сделать это вручную, позвонив в detector.unloadLanguageModels() во время недостатки. Это очистит все загруженные языковые модели из памяти, но пул потоков будет работать.
Если вы хотите попробовать Lingua, прежде чем решить, использовать его или нет, вы можете запустить его в реплике и немедленно увидеть результаты его обнаружения.
./gradlew runLinguaOnConsole --console=plainjava -jar lingua-1.2.2-with-dependencies.jarТогда просто поиграй:
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!
В случае, если вы хотите внести что -то в Lingua , вам рекомендуется сделать это. У вас есть идеи для улучшения API? Есть ли какие -то конкретные языки, которые вы хотите поддерживать рано? Или вы нашли ошибки до сих пор? Не стесняйтесь открыть проблему или отправить запрос на привлечение. Это очень ценится.
Для запросов на привлечение, пожалуйста, убедитесь, что все модульные тесты проходят и что код отформатирован в соответствии с официальным руководством по стилю Kotlin. Вы можете проверить это, запустив Kotlin Linter Ktlint, используя ./gradlew ktlintCheck . Большинство проблем, которые определяет Linter, может быть исправлена с помощью ./gradlew ktlintFormat . Все другие проблемы, особенно строки, которые более 120 символов, не могут быть исправлены автоматически. В этом случае, пожалуйста, отформатируйте соответствующие линии вручную. Вы заметите, что сборка потерпит неудачу, если форматирование не верно.
Всевозможные запросы на тягу приветствуются. Самыми любимыми являются новые языковые дополнения. Если вы хотите внести новые языки в Lingua , вот подробное руководство, объясняющее, как это сделать.
Большое спасибо заранее за все взносы, какими бы маленькими они ни были.
Чтобы выполнить приведенные ниже шаги, вам понадобится Java 8 или выше. Несмотря на то, что сама библиотека работает на Java> = 6, классы FilesWriter используют API java.nio, который был представлен с Java 8.
IsoCode639_1 и IsoCode639_3 и добавьте коды языка ISO. Среди других сайтов Википедия предоставляет комплексный список.Language перечисления и добавьте новую запись для вашего языка. Если язык написан с помощью сценария, который еще не поддерживается Alphabet Lingua , также добавьте для него новую запись.Language перечислении. Однако, если символы встречаются на более чем на одном языке , но не на всех языках, тогда добавьте их в CHARS_TO_LANGUAGES_MAPPING Вместо этого в Constant классе.LanguageModelFilesWriter для создания языковых модельных файлов. Файл обучающих данных, используемый для оценки вероятности NGRAM, не требуется, чтобы иметь конкретный формат, отличный от того, чтобы быть действительным файлом TXT./src/main/resources/language-models и поместите там сгенерированные файлы модели языка. Не переименуйте языковые файлы модели. Название подкаталории должно быть код ISO 639-1 в языке, который полностью оснащен.TestDataFilesWriter для создания файлов тестовых данных, используемых для генерации отчетов о точности. Входной файл для создания тестовых данных должен иметь каждое предложение на отдельной строке./src/accuracyReport/resources/language-testdata . Не переименуйте файлы тестовых данных./src/accuracyReport/kotlin/com/github/pemistahl/lingua/report/config . Посмотрите на файлы других языков в этом каталоге, чтобы увидеть, как должен выглядеть класс. Это должно быть довольно эксплуатационным./src/accuracyReport/kotlin/com/github/pemistahl/lingua/report/lingua . Посмотрите на файлы других языков в этом каталоге, чтобы увидеть, как должен выглядеть класс. Это должно быть довольно эксплуатационным. Если одна из других библиотек детектора языка уже поддерживает ваш язык, вы также можете добавить тестовые классы для них. Каждая библиотека имеет свой собственный каталог для этой цели. Если ваш язык не поддерживается другими библиотеками детектора языка, исключите его в AbstractLanguageDetectionAccuracyReport .linguaSupportedLanguages в /gradle.properties ../gradlew accuracyReport и добавьте обновленные отчеты о точности в свой запрос на привлечение../gradlew drawAccuracyPlots и добавьте обновленные графики в ваш запрос на привлечение../gradlew writeAccuracyTable и добавьте обновленную таблицу точности в свой запрос на привлечение.Взгляните на запланированные проблемы.