Pull to refresh

PHP: Определение языка текста с помощью N-грамм. Часть 2

Reading time5 min
Views2.5K
Original author: Ian Barber
Вторая часть статьи Яна Барбера об определении языка текста с помощью PHP. Первую часть можно найти тут.

Разбить на две части пришлось из-за большого объема текста с форматированием («Some error… We know...).

К сожалению, на моем компьютере не было особо большого количества материалов для построения моделей, но для этого сгодились многоязычные словари OSX. Убрав с помощью strip_tags XML теги, я получил чистый текст.
<?php

$lang = new LangDetector();
$dir = "/Library/Dictionaries/Apple Dictionary.dictionary/Contents/Resources/";
$dutch = strip_tags(file_get_contents($dir . "Dutch.lproj/Body.data"));
$lang->adddocument($dutch, 'dutch');
$english = strip_tags(file_get_contents($dir . "English.lproj/Body.data"));
$lang->adddocument($english, 'english');
$finnish = strip_tags(file_get_contents($dir . "fi.lproj/Body.data"));
$lang->adddocument($finnish, 'finnish');
$spanish = strip_tags(file_get_contents($dir . "Spanish.lproj/Body.data"));
$lang->adddocument($spanish, 'spanish');
$italian = strip_tags(file_get_contents($dir . "Italian.lproj/Body.data"));
$lang->adddocument($italian, 'italian');
$french = strip_tags(file_get_contents($dir . "French.lproj/Body.data"));
$lang->adddocument($french, 'french');
$swedish = strip_tags(file_get_contents($dir . "sv.lproj/Body.data"));
$lang->adddocument($swedish, 'swedish');
?>

Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.

С построенным индексом мы теперь можем протестировать большое количество текстов на различных языках, чтобы убедиться в точности распознавания. Огромное спасибо Lorenzo, Soila (который говорит на огромном количестве различных языков) и Ivo за предоставленные примеры:

<?php

$italian = "
Nel mezzo del cammin di nostra vita
mi ritrovai per una selva oscura
ch&#233; la diritta via era smarrita.
";
echo $italian, "\n", "is ", $lang->detect($italian), "\n";

$finnish = "
Suomalainen on sellainen, joka vastaa kun ei kysyt&#228;,
kysyy kun ei vastata, ei vastaa kun kysyt&#228;&#228;n,
sellainen, joka eksyy tielt&#228;, huutaa rannalla
ja vastarannalla huutaa toinen samanlainen.
";
echo $finnish, "\n", "is ", $lang->detect($finnish), "\n";

$dutch = "
zoals het klokje thuis tikt, tikt het nergens
";
echo $dutch, "\n", "is ", $lang->detect($dutch), "\n";

$spanish = "
Por qu&#233; los inmensos aviones
No se pasean com sus hijos?
Cu&#225;l es el p&#225;jaro amarillo
Que llena el nido de limones?
Por qu&#233; no ense&#241;an a sacar
Miel del sol a los helic&#243;pteros?
";
echo $spanish, "\n", "is ", $lang->detect($spanish), "\n";

$swedish = "
Och knyttet tog av skorna och suckade och sa:
hur kan det k&#228;nnas sorgesamt fast allting &#228;r s&#229; bra?
Men vem ska tr&#246;sta knyttet med att s&#228;ga: lilla v&#228;n,
vad g&#246;r man med en sn&#228;cka om man ej f&#229;r visa den?
";
echo $swedish, "\n", "is ", $lang->detect($swedish), "\n";
?>
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.


Как легко можно увидеть (результат работы скрипта слегка обрезан, чтобы сократить изложение), каждый язык был корректно определен:

Nel mezzo del cammin...
is italian

Suomalainen on sellainen...
is finnish

zoals het klokje thuis tikt, tikt het nergens
is dutch

Por que los inmensos...
is spanish

Och knyttet tog av...
is swedish


Аналогичную операцию можно проделать с целымим вебсайтами, удалив HTML теги с помощью strip_tag. Целью послужили сайты трех локальных офисов Ibuildings:

<?php

$nl = strip_tags(file_get_contents('www.ibuildings.nl'));
echo "IB NL reads as: " . $lang->detect($nl), "\n";

$uk = strip_tags(file_get_contents('www.ibuildings.co.uk'));
echo "IB Uk reads as: " . $lang->detect($uk), "\n";

$it = strip_tags(file_get_contents('www.ibuildings.it'));
echo "IB IT reads as: " . $lang->detect($it), "\n";
?>
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.


Похоже, что на странице в домене NL все же больше английского текста, чем датского, поэтому он определелился как английский. Однако, с итальянским все прошло отлично:

IB NL reads as: english
IB UK reads as: english
IB IT reads as: italian


Другие методы


Несмотря на то, что метод триграмм очень удобен и прост, он совершенно не обязательно является лучшим для использования в каждой ситуации. Например, если вам требуется метод, который работает без предварительного обучения или с минимальными затратами памяти, можно просто собрать список коротких, часто встречающихся слов в каждом языке (вроде артиклей и предлогов) и искать в заданном тексте только их.

Точно также, поиск Unicode символов, уникальных для заданного языка, может дать вам достаточную точность его определения.

PEAR: Text_LanguageDetect

Когда мы с Лоренцо обсуждали эту проблему, он упомянул, что в библиотеку PEAR уже включен пакет для определения языка текста, хотя и в альфа-версии. Он тоже использует метод триграмм, но располагает несколько более богатыми возможностями. Как и ожидалось, он достаточно прост в использовании, поддерживает Unicode и поставляется уже с готовой базой триграмм для некоторых языков, так что почти не нуждается в обучении. Для полноты картины мы попытались определить с его помощью языки тех же фрагментов текста:

<?php

require_once 'Text/LanguageDetect.php';

function detect($text, $l) {
        $result = $l->detect($text, 1);
        if (PEAR::isError($result)) {
            return $result->getMessage();
        } else {
                return key($result);
        }
}

$l = new Text_LanguageDetect();

$italian = "
Nel mezzo del cammin di nostra vita
mi ritrovai per una selva oscura
ch&#233; la diritta via era smarrita.
";
echo $italian, "\n", "is ", detect($italian, $l), "\n";

// ...остаток удален для краткости, но результат аналогичен
?>
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.


Как и ожидалось, результат оказался аналогичным. Пакет можно легко установить из PEAR, используя команду

pear -d preferred_state=alpha install Text_LanguageDetect
Tags:
Hubs:
Total votes 12: ↑9 and ↓3+6
Comments5

Articles