Препроцессоры и метаязыки в программах исправления ошибок

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

А. Реформатский, будучи весьма прозорливым лингвистом, писал, что существуют ошибки как результат неумелого преподавания в школе грамматики. Алпатов, человек язвительный, заметил, цитирую: «можно сказать, русская грамматика взяла за основу представления петербургских немцев о русском языке». Учитывая дефекты школьного преподавания и особенности психологии составителей грамматик, ться и тся остаются изгоями в компьютерных программах проверки орфографии.

Видимо, своей мрачной славе эти случаи обязаны также тем, что в грамматиках жестко рекомендуют «проверять» правильность написания вопросами «что делать» и «что делает», исключая иные способы. Конечно, если поступать рекомендованным образом, никакая алгоритмизация и последующая корректировка невозможны. Остается только «анаграмматический подход» (когда на выходе программы мы получаем несколько вариантов «исправленного» слова). Видимо, отсюда попытка разделить С.А. Крыловым программы на пуристские и лаксистские.

«Зацикленность» программистов, работающих в команде с профессиональными лингвистами на разборе предложения очевидно связана с недостаточным пониманием лингвистами принципов программирования и «навязыванием» лингвистических представлений программистам. И здесь уважаемый С. А. Крылов демонстрирует подобное — см пост на известном форуме. Это лингвистический взгляд, но не взгляд программиста, для которого важными остаются вопросы иного плана: возможно ли алгоритмизировать грамматическое правило или алгоритмизация невозможна, следует использовать «словарный» подход для проверки слова.
Правка ошибочного написания возвратных глаголов удивительно легка в 40 % (и более) случаев, если отказаться от «что делает, что делать», а понимать возвратный глагол именно так, как следует, по значению: собственно возвратное; взаимно-возвратное; безобъектно-возвратное; общевозвратное & etc. В этом случае задача исправления слова сводится к а) «препроцессорной» обработке фразы, слова; б) создания простейшего метаязыка, позволяющего использовать некие описания для «правил», и этот метаязык будет похожим на классический потоковый редактор, то есть хорошо известный класс программ.

Итак, пусть «топливом» для «препроцессора» у нас будет массив из семи (или меньше) последних букв слов на тся и ться (для примера берем словарь Зализняка). Если взять большее число букв, то «точность» увеличится, это очевидно.
Полученные данные мы разместим в массиве по принципу «елочка корнями в небо» — это оптимизирует и ускорит поиск, а также избавит от возможных ошибок (см. код).

Если кто-то рискнет повторить мой эксперимент со словарем Зализняка, то результат вряд ли удивит: в подобном массиве будет всего 3548 окончаний (т.е. семь или менее последних букв в слове), когда однозначно пишется ться или тся. Число окончаний, где возможно чередование «ться» / «тся» столь же мало — всего 407. Удивительно, правда? Ведь теперь достаточно «прогнать» через массивы проверяемое слово и мы на корню избавимся от неправильных написаний слов типа «кажетЬся», «придетЬся» и т.д. и пресловутых «анаграмм». (Для второго массива, когда возможны варианты написания, потребуется воспользоваться «метаязыком».)

Так выглядит массив «возможен только один вариант» (конечно, это несколько строк из 3548):

// «Елочка в небо»
Для ться — до разделителя ошибочное написание, после — правильное.
ящатся:: ящаться
яхатся:: яхаться
ятатся:: ятаться
ястся:: ясться
ыстся:: ысться
ызтся:: ызться
ртся:: рться
отся:: оться
зтся:: зться

Для тся — до разделителя ошибочное написание, после — правильное:

ящаються:: ящаются
ящаеться:: ящается
ридеться:: ридется
зеються:: зеются
зееться:: зеется
звяться:: звятся
звяться:: рутся
оються:: оются
оеться:: оется
ються:: ются

//Массив для случаев, когда невозможно определить правильное написание (для тся, но очевидно, что для ться следует лишь вставить мягкий знак)

яшится
ячится
ячатся
ушатся
учится
слятся
рщится
оится
нятся
нутся
ятся
ытся
утся
стся
ится
ется
атся

Для примера — простой код, позволяющий искать совпадения в базах:

string correction_verbs(string str) {
// Здесь нельзя использовать map, так как map автоматически сортирует массив
vector < pair < string, string > >data;
vector < pair < string, string > >::iterator it;
// Классы и функции настолько очевидны, что описывать их бессмысленно.
file_operations file_io; // это просто класс для чтения из файлов в массив
string_utilities str_ut; // это класс, где существует утилита replace_all
string first_str, second_str, separator;
// Получаем пути к файлам с данными и загружаем массив
string verbs = global::file_paths.find("verbs_cfg")->second;
data = file_io.readf_vector_pair(verbs, separator); 

for (it = data.begin(); it != data.end(); ++it) {
// Выводим графему после разделителя (может быть любым) и до разделителя
first_str = it->first; // неправильное написание
second_str = it->second; // правильное
// Поиск совпадений в строке
// Если найдено совпадение, то заменяем ться на тся (или наоборот)
if (str.find(second_str) != string::npos) {
str = str_ut.replace_all(str, second_str, first_str);
// Прекращаем работу функции
break;
}
}
// Очищаем массив
data.clear();
return str;
}


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

Смотрим здесь: online.orfo.ru
Вводим фразу с ошибкой: «придеться исправить ошибку».
На выходе получаем, как и ожидалось, следующий пассаж: приодеться, придется, приметься, продеться, прибиться.
Выводы делайте сами.
(Пожалуй, достойный пример того, как лингвисты «прогнули» программистов, получив на выходе неполноценное и безграмотное решение.)

Посмотрим на работу вышеописанного препроцессора. В переменной str у нас будет слово «придеться». В массиве будут только возвратные глаголы «с однозначным написанием». На выходе мы получаем (программа ищет совпадения по последним буквам, начиная с вершины массива) слово, где ридеться однозначно заменяется на ридется (см базы данных, иных вариантов не существует). Если программа не найдет в массиве совпадений, то функция вернет слово без изменений. Разумеется, далее следует произвести проверку в базе «ться» / «тся», применяя некий набор описаний. Но о «метаязыках» в подобных лингвистических программах я напишу в следующем посте, чтобы сообщение не получилось громоздким.

P.S. Безусловно, «препроцессорная» обработка имеет свои недостатки, но программа «мыслит по-человечески», а на выходе все-таки более вменяемый результат.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 10

    0
    > программа «мыслит по-человечески», а на выходе все-таки более вменяемый результат
    Результат-то более вменяемый, но гораздо менее лояльный к более-менее авторским текстам. Ну, например: «А все ли иконки ворда освящатся после этого патча?».

    Кроме того, программа мыслит совсем не по-человечески. По-человечески — это точно не сопоставить слово с таблицей на три с половиной тысячи записей.

    Но в целом препроцессор штука прекрасная. Если не убивать сгнившие листья, а понижать им вес до _почти_ нуля.
      0
      Добрый вечер. Конечно, здесь в сообщении основная тема иная, никакой «человечности». Если говорить более точно, то я пишу о т. н. «классической» проблеме спеллчекеров — «неспособности» традиционных спеллчекеров автоматически исправлять ошибки с более менее высокой «валидностью».
      Например, все «классические» спеллчекеры, в которых используются «алгоритмы Левенштейна», «расстояние Хэмминга» и даже «метод Soundex» на выходе явно избыточны. Так, ошибочное слово сравнивается тем или иным образом с «возможно истинным», определяя «расстояние», необходимое для перестановки букв, чтобы превратить какое-либо слово в набор «возможных» слов: возьмем ошибочные слова «колубель» и «преключение», на выходе программы aspell (или подобной) мы получим букет «возможных правок». Полученные варианты «правки» слова «преключение» компьютерными программами типа aspell, myspell: переключение, преклонение, приключение, перезаключение, приключении, приключений, переключен, переключенные — и это не все варианты! 
      На «колубель» варианты следующие: колу-бель, колу бель, кобель, колебля, колеблешь, клубень, колыбель, колыбелью, колыбели, кабель, колыбелька, колыбельки, колыбельку & etc.
      Как из «колубели» получается кобель и «заколебал» остается глубокой тайной работы современных программистов (хотя очевидно, что мы видим работу алгоритма Левенштейна).
      В данном сообщении я пишу о возможных решениях этой проблемы, позволяющей с той или иной точностью решать задачи автоматической правки ошибочного написания слова. Что интересно — подобные вышеописанному алгоритмы с успехом будут править и слова с ошибочными двойными гласными, согласными и т.д.
      Я обязательно продолжу эту тему, как только будет свободное время. Конечно, перейду к стохастическим грамматикам и биграммам, триграммам & etc
        0
        Чистого Левенштайна никто (надеюсь) не применяет, применяют Дамерау-Левенштайна, который, вообще-то тоже совсем не для этого. Надо измерять расстояние не просто против словарных вхождений, а против целого набора параметрических характеристик (например, упомянутых вами триграфов). Тогда по совокупности результат будет гораздо более внятный.

        Интересно вот что: я в слове «колубель» не смог угадать «колыбель» мгновенно. По-моему, это означает, что человеческий подход должен тоже немного ломаться на этом слове (а машинный, кстати, вообще-то не должен.) Из «колубели» — «кобель» получается запросто, вы просто, наверное, никогда с нетрезвыми людьми не переписывались. А вот пристаку «за-» нужно отметать сразу: никто не забудет две буквы в начале слова.

          0
          Я недавно поставил вычислительный эксперимент, а именно — обработал логи поисковых запросов Word2Vec. Получились весьма любопытные результаты:

          Enter word or sentence (EXIT to break): колубель

          Word: колубель Position in vocabulary: -1
          Out of dictionary word!

          Enter word or sentence (EXIT to break): преключение

          Word: преключение Position in vocabulary: 124515

          Word Cosine distance
          — приключение 0.748698
          преключения 0.726111
          приключения 0.692828
          приключеия 0.670168
          прключение 0.666706
          приключеня 0.663286
          прключения 0.660438
          приключени 0.659609
          приклучения 0.650463
          приклучение 0.649844
          приклюения 0.637038
          приклчения 0.630362
          приключене 0.621822
          приключния 0.621201
          преклучение 0.617969
          приклечение 0.607291
          приключениия 0.606688
          прикючения 0.602498
          приклюния 0.600069
          приключние 0.598981
          прилючение 0.594954
          приклюцение 0.594346
          пиключения 0.593655
          риключения 0.591968
          приклбчение 0.590200
          приклюение 0.589287
          приключ 0.587898
          прикдючения 0.585709
          приклю 0.583770
          прикльчения 0.581953
          прикльючения 0.580703
          приключенья 0.578545
          пиключение 0.571432
          прилючения 0.569031
          приколючения 0.567267
          приклоючения 0.566944
          нриключения 0.560486
          прикльчение 0.559658
          приклчение 0.559222
          прикллючение 0.558327



          Это говорит о том, что слово «колубель» вообще ни разу не встретилось за несколько миллиардов уникальных запросов. Люди, ищущие колыбель, так не ошибаются. Они ошибаются так:

          Enter word or sentence (EXIT to break): колыбель

          Word: колыбель Position in vocabulary: 23910

          Word Cosine distance
          — калыбель 0.705157
          колыбели 0.507207
          колыбелька 0.483677
          люлбка 0.471562
          колыбельная 0.454978
          эманация 0.444692
          зыбка 0.440952
          колыбел 0.439369
          колыбелью 0.432894
          кроватка 0.429658
          качалка 0.428552
          sip2132se 0.425523
          электрокачель 0.425489
          колыбельку 0.422677
          качеля 0.419852
          качель 0.414338
          кокон 0.411337
          кочалка 0.408711
          колыбельные 0.407508
          sip1728se 0.400879
          сокровищница 0.395137
          sih1528se 0.394529
          люлька 0.394288
          дневнего 0.394247
          sih1730se 0.392788
          спасительница 0.392640
          sim924e 0.392407
          империя 0.379475
          h924rx 0.377885
          кочель 0.377152
          люлечка 0.376139
          шезлонг 0.374627
          древняй 0.374593
          sih1226e 0.374286
          качели 0.374042
          хейзен 0.373382
          sil924r 0.372253
          богиня 0.370900
          королевство 0.369769
          древо 0.369519

            0
            К слову сказать, несколько лет назад С. А. Крылов из РГГУ предложил использовать поисковые технологии для создания лингвистических систем. Конечно, «в общем» эта идея очень интересна и привлекательна, но с некоторыми оговорками. Так, мы все понимаем, что «поисковик» (если говорить о Google), работая с массивами текстов, будет очевидно отражать какую-то «социолингвистическую» картину — как ее понимал наш российско-советский академик Ларин. То есть, Google на выходе можно использовать как статистический массив (как в вашем эксперименте с Word2Vec), но с определенного рода ограничениями. Однако даже в этом случае поисковик «исправляет» неправильное написание некоторых слов.
            Это легко показать на следующих примерах: а)
            «заборомлуг» — Гугль абсолютно логично выдаст следующий вариант «за забором – луг», опустив, правда, вариант «за бором луг»; б) «колубель» остается «колубелью», так как в кэше Гугля это слово есть, но «преключение» однозначно превращается в «приключение»; е) мировозрение — мировоззрение; рубак — рубаки, а не «рыбак» и т.д.; «тероррист» остается «терорристом», но «галюцинации» превращаются в «галлюцинации» и т. д.
            Поэтому последние месяцы меня все более соблазняет мысль, что в программы проверки орфографии (и даже пунктуации) следует встраивать классы работы со статистическими массивами. В нашей программе мы реализовали поиск по биграммам и получили весьма любопытные результаты. По крайней мере «тесты» Штольке уже не показывают полную бессмыслицу.
        0
        Добро пожаловать на Хабр, коллега. интересно пишете
          0
          добрый день, Сергей. Ну, Диалог почти «погиб», так что решила здесь общаться
          0
          Вопрос к Автору. Не очень знаком с этой темой, но появилась идея. В подобных системах как то используют физическую раскладку клавиатуры? Например, буква А и П стоят рядом и, значит, вероятность того, что в обычном слове вместо правильной буквы А я случайно напишу П выше чем Ъ просто потому, что А и П рядом, а А и Ъ далеко на клавиатуре. Используется эта информация как то?
            0
            Доброй ночи. Это вопрос к Дмитрию Калашникову, см здесь orfogrammka.ru/

            Only users with full accounts can post comments. Log in, please.