Мне нужно найти достаточно эффективный способ распознавания слогов в слове. Например,
Невидимый -> in-vi-sib-le
Вот несколько правил слоговой записи, которые можно использовать:
V CV VC CVC CCV CCCV CVCC
* где V - гласная, а C - согласная. Например,
Произношение (5 Pro-nun-ci-a -tion; CV-CVC-CV-V-CVC)
Я пробовал несколько методов, среди которых было использование регулярного выражения (которое помогает только в том случае, если вы хотите подсчитывать слоги) или жестко закодированного определения правила (метод грубой силы, который оказался очень неэффективным) и, наконец, использование конечного автомата (который не приведу ни к чему полезному).
Цель моего приложения - создать словарь всех слогов на данном языке. Этот словарь позже будет использоваться для приложений проверки орфографии (с использованием байесовских классификаторов) и синтеза речи.
Я был бы признателен, если бы можно было дать мне советы по альтернативному способу решения этой проблемы, помимо моих предыдущих подходов.
Я работаю на Java, но любой совет по C / C ++, C #, Python, Perl ... мне подойдет.
источник
Ответы:
Прочтите о подходе TeX к этой проблеме для расстановки переносов. Особенно см. Диссертацию Фрэнка Ляна Word Hy-phen-a -tion by Com-put-er . Его алгоритм очень точен, а также включает небольшой словарь исключений для случаев, когда алгоритм не работает.
источник
Я наткнулся на эту страницу, ища то же самое, и нашел здесь несколько реализаций статьи Лян: https://github.com/mnater/hyphenator или преемник: https://github.com/mnater/Hyphenopoly
Это если только вы не из тех, кто любит читать тезисы на 60 страниц вместо того, чтобы адаптировать свободно доступный код для решения неуникальной проблемы. :)
источник
Вот решение с использованием NLTK :
источник
Я пытаюсь решить эту проблему для программы, которая будет вычислять оценку чтения по методу flesch-kincaid и flesch для блока текста. В моем алгоритме используется то, что я нашел на этом веб-сайте: http://www.howmanysyllables.com/howtocountsyllables.html, и он становится достаточно близким. У него все еще есть проблемы со сложными словами, такими как невидимое и расстановка переносов, но я обнаружил, что он подходит для моих целей.
Его преимущество в том, что его легко реализовать. Я обнаружил, что «es» могут быть как слоговыми, так и нет. Это авантюра, но я решил убрать es в моем алгоритме.
private int CountSyllables(string word) { char[] vowels = { 'a', 'e', 'i', 'o', 'u', 'y' }; string currentWord = word; int numVowels = 0; bool lastWasVowel = false; foreach (char wc in currentWord) { bool foundVowel = false; foreach (char v in vowels) { //don't count diphthongs if (v == wc && lastWasVowel) { foundVowel = true; lastWasVowel = true; break; } else if (v == wc && !lastWasVowel) { numVowels++; foundVowel = true; lastWasVowel = true; break; } } //if full cycle and no vowel found, set lastWasVowel to false; if (!foundVowel) lastWasVowel = false; } //remove es, it's _usually? silent if (currentWord.Length > 2 && currentWord.Substring(currentWord.Length - 2) == "es") numVowels--; // remove silent e else if (currentWord.Length > 1 && currentWord.Substring(currentWord.Length - 1) == "e") numVowels--; return numVowels; }
источник
Это особенно сложная проблема, которая полностью не решается алгоритмом расстановки переносов LaTeX. Хороший обзор некоторых доступных методов и связанных с этим проблем можно найти в статье Evaluating Automatic Syllabification Algorithms for English (Marchand, Adsett, and Damper 2007).
источник
Зачем рассчитывать? Эта информация есть в каждом онлайн-словаре. http://dictionary.reference.com/browse/invisible in · vis · i · ble
источник
Спасибо Джо Басирико за то, что поделился вашей быстрой и грязной реализацией на C #. Я использовал большие библиотеки, и они работают, но обычно немного медленные, и для быстрых проектов ваш метод работает нормально.
Вот ваш код на Java вместе с тестовыми примерами:
Результат оказался ожидаемым (для Флеша-Кинкейда он работает достаточно хорошо):
источник
Удар @Tihamer и @ joe-basirico. Очень полезная функция, не идеальная , но подходящая для большинства небольших и средних проектов. Джо, я переписал реализацию вашего кода на Python:
def countSyllables(word): vowels = "aeiouy" numVowels = 0 lastWasVowel = False for wc in word: foundVowel = False for v in vowels: if v == wc: if not lastWasVowel: numVowels+=1 #don't count diphthongs foundVowel = lastWasVowel = True break if not foundVowel: #If full cycle and no vowel found, set lastWasVowel to false lastWasVowel = False if len(word) > 2 and word[-2:] == "es": #Remove es - it's "usually" silent (?) numVowels-=1 elif len(word) > 1 and word[-1:] == "e": #remove silent e numVowels-=1 return numVowels
Надеюсь, кто-то сочтет это полезным!
источник
Perl имеет модуль Lingua :: Phonology :: Syllable . Вы можете попробовать это или попробовать изучить его алгоритм. Я видел там и несколько других старых модулей.
Я не понимаю, почему регулярное выражение дает вам только количество слогов. Вы должны иметь возможность получить сами слоги, используя скобки для захвата. Если предположить, что вы можете построить работающее регулярное выражение, то есть.
источник
Сегодня я нашел эту Java-реализацию алгоритма расстановки переносов Фрэнка Ляна с шаблоном для английского или немецкого языков, который работает довольно хорошо и доступен на Maven Central.
Cave: важно удалить последние строки
.tex
файлов шаблонов, потому что в противном случае эти файлы не могут быть загружены с текущей версией в Maven Central.Чтобы загрузить и использовать
hyphenator
, вы можете использовать следующий фрагмент кода Java.texTable
- это имя.tex
файлов, содержащих нужные шаблоны. Эти файлы доступны на сайте проекта на github.После этого
Hyphenator
все готово к использованию. Основная идея для определения слогов - разделить термин по имеющимся дефисам.Вам нужно разделить на
"\u00AD
", так как API не возвращает нормальный"-"
.Этот подход превосходит ответ Джо Басирико, поскольку он поддерживает множество разных языков и более точно определяет немецкие расстановки переносов.
источник
Некоторое время назад я столкнулся с этой же проблемой.
В итоге я использовал Словарь произношения CMU для быстрого и точного поиска большинства слов. Для слов, которых нет в словаре, я вернулся к модели машинного обучения, которая ~ 98% точна при прогнозировании количества слогов.
Я обернул все это в простой в использовании модуль Python здесь: https://github.com/repp/big-phoney
Установить:
pip install big-phoney
Считайте слоги:
Если вы не используете Python и хотите попробовать подход, основанный на модели машинного обучения , я довольно подробно описал , как модель подсчета слогов работает в Kaggle .
источник
Спасибо @ joe-basirico и @tihamer. Я портировал код @ tihamer на Lua 5.1, 5.2 и luajit 2 ( скорее всего, он будет работать и на других версиях lua ):
countsyllables.lua
И несколько забавных тестов, чтобы подтвердить, что он работает ( в той степени, в которой он должен ):
countsyllables.tests.lua
источник
Я не мог найти адекватного способа подсчета слогов, поэтому сам разработал метод.
Вы можете просмотреть мой метод здесь: https://stackoverflow.com/a/32784041/2734752
Я использую комбинацию словаря и алгоритма для подсчета слогов.
Вы можете просмотреть мою библиотеку здесь: https://github.com/troywatson/Lawrence-Style-Checker
Я только что протестировал свой алгоритм и получил 99,4% результатов!
Lawrence lawrence = new Lawrence(); System.out.println(lawrence.getSyllable("hyphenation")); System.out.println(lawrence.getSyllable("computer"));
Выход:
источник
После большого количества тестов и опробования пакетов расстановки переносов я написал свой собственный, основанный на ряде примеров. Я также попробовал
pyhyphen
иpyphen
пакеты , что интерфейсы с переносами словарями, но они производят неверное число слогов во многих случаях.nltk
Пакет был просто слишком медленно для этого случая использования.Моя реализация на Python является частью написанного мной класса, а процедура подсчета слогов вставлена ниже. Он немного переоценивает количество слогов, поскольку я до сих пор не нашел хорошего способа учесть тихие окончания слов.
Функция возвращает соотношение слогов на слово, используемое для оценки читабельности Флеша-Кинкейда. Число не обязательно должно быть точным, достаточно близким для оценки.
На моем процессоре i7 7-го поколения эта функция занимала 1,1–1,2 миллисекунды для образца текста из 759 слов.
def _countSyllablesEN(self, theText): cleanText = "" for ch in theText: if ch in "abcdefghijklmnopqrstuvwxyz'’": cleanText += ch else: cleanText += " " asVow = "aeiouy'’" dExep = ("ei","ie","ua","ia","eo") theWords = cleanText.lower().split() allSylls = 0 for inWord in theWords: nChar = len(inWord) nSyll = 0 wasVow = False wasY = False if nChar == 0: continue if inWord[0] in asVow: nSyll += 1 wasVow = True wasY = inWord[0] == "y" for c in range(1,nChar): isVow = False if inWord[c] in asVow: nSyll += 1 isVow = True if isVow and wasVow: nSyll -= 1 if isVow and wasY: nSyll -= 1 if inWord[c:c+2] in dExep: nSyll += 1 wasVow = isVow wasY = inWord[c] == "y" if inWord.endswith(("e")): nSyll -= 1 if inWord.endswith(("le","ea","io")): nSyll += 1 if nSyll < 1: nSyll = 1 # print("%-15s: %d" % (inWord,nSyll)) allSylls += nSyll return allSylls/len(theWords)
источник
Я однажды использовал jsoup для этого. Вот пример синтаксического анализатора слогов:
источник