Language recognition FrenchРазпознаването на езика на даден текст е доста обширна тема и тук няма да се спирам подробно на алгоритмите свързани с нея, а по-скоро на някои методи, които могат да се използват наготово за семантичен анализ на текст с цел извличане на езика му. Тъй като правя един проект, малка част от който е извличането на информация за езика на определен текст, ми се наложи да направя кратък research по темата. Методите, които опитах и изводите, до които стигнах, са описани тук.

Първи опит: Microsoft Extended Linguistic Services

Преди да опитам да правя каквито и да е web заявки към API-та и да губя трафик (а знаете че всеки MB се плаща, особено в cloud-а), реших да се поразровя и да проверя добрия стар .NET и добрите стари Windows API-та какво предлагат.

Оказа се че в .NET няма вградени класове за семантичен анализ на текст, но за сметка на това има Windows API наречено Extended Linguistic Services (ELS), което се опитва да предложи възможните езици, на които даден текст може да бъде. От Windows 7 нататък ELS се инсталира автоматично заедно с операционната система, което дава добри надежди да го има вградено и в Windows 8 Server.

Разбира се това нещо си имаше и .NET wrapper, който между другото включваше в себе си и доста полезни неща свързани с Windows Shell-а, DirectX, Windows 7 Taskbar и т.н. За семантичния анализ, свързан с разпознаването на текст, реално от целия „Windows API Code Pack“ ви трябва само „Microsoft.WindowsAPICodePack.ExtendedLinguisticServices.dll“.

Използването му е малко странно и изглежда така:

MappingService serv = new MappingService(
    MappingAvailableServices.LanguageDetection);
var res = serv.RecognizeText(@"
    Your cruel device
    your blood, like ice
    One look, could kill
    My pain, your thrill

    Your mouth, so hot
    Your web, I'm caught
    Your skin, so wet
    Black lace, on sweat", null);
var langs = res.FormatData(new StringArrayFormatter());
foreach (var lang in langs[0])
{
    Console.Write("{0} ", lang);
}
Console.WriteLine();

Големият му недостатък обаче е, че дава доста предложения за възможните езици. Например за горния текст е очевидно, че езикът е английски, обаче ELS-а ми даде 11 предложения (сред които и сръбски): en, af, de, sk, sl, ca, et, fi, hr, sr-Latn, tn. Един от куплетите на „Аз съм българче“ („Аз съм българче. Обичам наште планини зелени, българин да се наричам - първа радост е за мене.“) ELS ми предложи следните езици: bg, mk, ru, sr-Cyrl, be, uk, kk.

Едно леко лирическо отклонение. Една от другите полезни функции на Extended Linguistic Services е обръщане на текст от кирилица в латиница. Разбира се и то не работи коректно. Защо? Аз имам теория, че Microsoft имат 2 типа продукти: такива които са изпипани и работят почти перфектно (SQL Server, Visual Studio, .NET Framework, etc.) и такива които са направени през пръсти и са пълни с бъгове. ELS е от втория тип. Ето как можете да обърнете текст от кирилица на латиница с .NET Windows API Code Pack:

MappingService serv = new MappingService(
    MappingAvailableServices.TransliterationCyrillicToLatin);
var res = serv.RecognizeText(@"
    Аз съм българче. Обичам
    наште планини зелени,
    българин да се наричам -
    първа радост е за мене.", null);
var langs = res.FormatData(new StringFormatter());
Console.WriteLine(langs[0]);

Резултатът от работата на горния код е „Az s?m b?lgarce. Obicam naste planini zeleni, b?lgarin da se naricam - p?rva radost e za mene.“. Въпросителният знак явно трябва да замества липсващите в руския език букви. Само Microsoft си знаят какво са написали. :D

Втори опит: AlchemyAPI

AlchemyAPI е web service, който предлага всякакви семантични анализи: разпознаване на език, извличане на имена, извличане на тагове (ключови думи), категоризиране на текст, определяне на позитивен/негативен текст, извличане на мета тагове и микро формати и доста други.

Справя се перфектно с разпознаване на езика на текст (поддържа 97 езика), но за съжаление повечето му други функции не работят с български (например категоризирането и sentiment анализа). Разполага с API wrapper за .NET и използването му е доста лесно (при компилация използвайте build.bat и си настройте пътищата до csc.exe или стартирайте .bat файла през Visual Studio Command Prompt). Ето кратък пример за използването му (за да работи правилно трябва да заместите _YOUR_API_KEY_ с API ключа, който ще получите при регистрация):

string text = @"Аз съм българче.";
AlchemyAPI.AlchemyAPI alchemyObj = new AlchemyAPI.AlchemyAPI();
alchemyObj.SetAPIKey("_YOUR_API_KEY_");
var xmlData = alchemyObj.TextGetLanguage(text);
Console.WriteLine(xmlData);

За горните 3 думи без колебание AlchemyAPI  разпозна български език. Основният недостатък на AlchemyAPI е, че е платено и при това никъде не пише цените. За цена трябва да се пише на sales отдела им. Има и безплатна версия, поддържаща 1000 извиквания на функции на ден след като се регистрирате, но за големи проекти това е крайно недостатъчно.

Трети опит: Google Translate API

Добрият стар Google Translate работи перфектно като уеб tool и може би изкарва едни от най-точните резултати, но за използването на API-тата му, Google искат доста солидно заплащане. На всеки 1 милион символа (около 1 MB) искат по 20 долара, както за превод, така и за разпознаване на езика. Наистина скъпо удоволствие ще е за всеки да използва Google Translate API-то за разпознаване на текста.

Четвърти опит: NTextCat

NTextCat е библиотека с отворен код, която служи за класификация на текст. Основната й цел е разпознаване на езика на даден текст. Поддържа различни езикови модели (езиковият модел извлечен от Wikipedia поддържа над 280 езика). Хвърлих един поглед на библиотеката и като че ли ми се стори че прави анализа на базата на статистическа информация за срещането на буквите в даден език. Преди няколко месеца писах един блог пост със статистическа информация от Wikipedia и на който му е интересно, може да прочете.

Използването на NTextCat се оказа доста по-лесно отколкото очаквах. Включвате си библиотеките му и един „using IvanAkcheurov.NTextCat.Lib.Legacy;“ и можете да започнете анализа на текста. Ето кратко демо на анализ на любимото ни стихче:

LanguageIdentifier id = new LanguageIdentifier(
    @"N:\...\NTextCat 0.1.6\LanguageModels\Wikipedia-MostCommon-Utf8");
    LanguageIdentifier.LanguageIdentifierSettings sett =
    new LanguageIdentifier.LanguageIdentifierSettings();
var res = id.ClassifyText(@"Аз съм българче. Обичам наште планини зелени,
    българин да се наричам - първа радост е за мене.", sett);
foreach (var item in res)
{
    Console.Write("{0}; ", item);
}

Резултатът е „(bg, 94883); (mk, 97529);“. Явно NTextCat смята, че „Аз съм българче“ може да бъде и на македонски :D Според авторите на проекта, е необходимо поне 50 думи, за да може с точност да се определи езикът на даден текст с тази библиотека.

Направих си още няколко експеримента с NTextCat. Първо пробвах с дълъг текст на български (800 букви) и езиковия модел „Wikipedia-MostCommon-Utf8“ и резултатът е приблизително същият: българският бие с малко македонския. Когато обаче пуснах анализ на македонски текст, NTextCat реши без колебание, че езикът е македонски. С другите езикови модели генерирани от Wikipedia резултатът е почти същия, но времето за анализ е доста по-голямо. Когато опитах с default-ния езиков модел на библиотеката дори не разпозна езика. Това е защото той не поддържа utf8 енкодинг.

Като цяло може да се вярва на NTextCat (с езиков модел „Wikipedia-MostCommon-Utf8“). Дава доста добри резултати, нищо че понякога за българския текст се колебае между български и македонски. Голямо предимство обаче е че понякога може да ви отгатне енкодинга (освен езика) на дадена последователност от байтове. Като цяло го препоръчвам като офлайн вариант за разпознаване на език.

Заключение

Със сигурност има и други начини за разпознаване на езика на даден текст, но тези бяха четирите, които аз прегледах. Като цяло никой от тях не успя да разпознае шльокавицата („Az sam bulgarche obicham...“). В крайна сметка се спрях на NTextCat. Причините са ясни: работи вярно и сравнително бързо, open source е, стабилно е, лесно за ползване и не изисква допълнителни ресурси (като интернет трафик например). И тъй като не намерих проблем или причина да не използвам NTextCat, ще си го ползвам със здраве ;) Дано статията да ви е била полезна и ако знаете по-добър вариант за разпознаване на езика на текст ще се радвам да ми пишете. :)