Обнаружение слогов в слове - PullRequest
126 голосов
/ 01 января 2009

Мне нужно найти достаточно эффективный способ обнаружения слогов в слове. Например.,

Невидимый -> in-vi-sib-le

Существует несколько правил слоговой логики:

V резюме VC CVC ККТ CCCV CVCC

* где V - гласный, а C - согласный. Например,

Произношение (5 Pro-nun-ci-a-aion; CV-CVC-CV-V-CVC)

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

Цель моего приложения - создать словарь всех слогов на данном языке. Этот словарь позже будет использоваться для приложений проверки правописания (с использованием байесовских классификаторов) и синтеза текста в речь.

Я был бы признателен, если бы вы могли дать мне советы по альтернативному способу решения этой проблемы помимо моих предыдущих подходов.

Я работаю в Java, но любой совет в C / C ++, C #, Python, Perl ... будет работать для меня.

Ответы [ 15 ]

2 голосов
/ 25 сентября 2015

Я не мог найти адекватный способ подсчета слогов, поэтому я сам разработал метод.

Вы можете посмотреть мой метод здесь: 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"));

Выход:

4
3
2 голосов
/ 10 сентября 2015

Спасибо, @ Джо-Базирико и @ Тиамер. Я перенес код @ tihamer на Lua 5.1, 5.2 и luajit 2 (, скорее всего, будет работать и на других версиях lua ):

countsyllables.lua

function CountSyllables(word)
  local vowels = { 'a','e','i','o','u','y' }
  local numVowels = 0
  local lastWasVowel = false

  for i = 1, #word do
    local wc = string.sub(word,i,i)
    local foundVowel = false;
    for _,v in pairs(vowels) do
      if (v == string.lower(wc) and lastWasVowel) then
        foundVowel = true
        lastWasVowel = true
      elseif (v == string.lower(wc) and not lastWasVowel) then
        numVowels = numVowels + 1
        foundVowel = true
        lastWasVowel = true
      end
    end

    if not foundVowel then
      lastWasVowel = false
    end
  end

  if string.len(word) > 2 and
    string.sub(word,string.len(word) - 1) == "es" then
    numVowels = numVowels - 1
  elseif string.len(word) > 1 and
    string.sub(word,string.len(word)) == "e" then
    numVowels = numVowels - 1
  end

  return numVowels
end

И несколько забавных тестов, чтобы подтвердить, что это работает ( столько, сколько должно ):

countsyllables.tests.lua

require "countsyllables"

tests = {
  { word = "what", syll = 1 },
  { word = "super", syll = 2 },
  { word = "Maryland", syll = 3},
  { word = "American", syll = 4},
  { word = "disenfranchized", syll = 5},
  { word = "Sophia", syll = 2},
  { word = "End", syll = 1},
  { word = "I", syll = 1},
  { word = "release", syll = 2},
  { word = "same", syll = 1},
}

for _,test in pairs(tests) do
  local resultSyll = CountSyllables(test.word)
  assert(resultSyll == test.syll,
    "Word: "..test.word.."\n"..
    "Expected: "..test.syll.."\n"..
    "Result: "..resultSyll)
end

print("Tests passed.")
0 голосов
/ 23 сентября 2018

Проведя много испытаний и проверяя пакеты переносов, я написал свой собственный, основанный на ряде примеров. Я также попробовал пакеты pyhyphen и pyphen, которые взаимодействуют со словарями переносов, но во многих случаях они выдают неправильное количество слогов. Пакет nltk был слишком медленным для этого варианта использования.

Моя реализация на Python является частью класса, который я написал, и процедура подсчета слогов вставлена ​​ниже. Это немного переоценивает количество слогов, так как я до сих пор не нашел хорошего способа объяснить окончание молчаливых слов.

Функция возвращает соотношение слогов на слово, которое используется для оценки читабельности Флеша-Кинкейда. Число не обязательно должно быть точным, достаточно приблизительным для оценки.

На моем 7-м поколении процессора i7 эта функция занимала 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)
0 голосов
/ 02 июля 2018

Я столкнулся с точно такой же проблемой некоторое время назад.

В итоге я использовал Словарь произношения CMU для быстрого и точного поиска большинства слов. Для слов, которых нет в словаре, я прибегнул к модели машинного обучения, которая с точностью ~ 98% предсказывает количество слогов.

Я завернул все это в простой в использовании модуль Python здесь: https://github.com/repp/big-phoney

Установка: pip install big-phoney

Количество слогов:

from big_phoney import BigPhoney
phoney = BigPhoney()
phoney.count_syllables('triceratops')  # --> 4

Если вы не используете Python и хотите попробовать подход, основанный на модели ML, я подробно описал , как работает модель подсчета слогов в Kaggle .

0 голосов
/ 09 января 2018

Я использовал jsoup, чтобы сделать это один раз. Вот пример синтаксического анализатора слогов:

public String[] syllables(String text){
        String url = "https://www.merriam-webster.com/dictionary/" + text;
        String relHref;
        try{
            Document doc = Jsoup.connect(url).get();
            Element link = doc.getElementsByClass("word-syllables").first();
            if(link == null){return new String[]{text};}
            relHref = link.html(); 
        }catch(IOException e){
            relHref = text;
        }
        String[] syl = relHref.split("·");
        return syl;
    }
...