153 votes

Détection des syllabes dans un mot

Je dois trouver un moyen assez efficace de détecter les syllabes dans un mot. Par exemple,

Invisible -> in-vi-sib-le

Il existe certaines règles de syllabation qui pourraient être utilisées :

V CV VC CVC CCV CCCV CVCC

*où V est une voyelle et C une consonne. Par exemple,

Prononciation (5 Pro-nun-ci-a-tion ; CV-CVC-CV-V-CVC)

J'ai essayé plusieurs méthodes, parmi lesquelles l'utilisation de regex (qui n'est utile que si l'on veut compter les syllabes) ou la définition de règles codées en dur (une approche par force brute qui s'avère très inefficace) et enfin l'utilisation d'un automate à états finis (qui n'a rien donné d'utile).

Le but de mon application est de créer un dictionnaire de toutes les syllabes d'une langue donnée. Ce dictionnaire sera ensuite utilisé pour des applications de correction orthographique (à l'aide de classificateurs bayésiens) et de synthèse vocale.

J'apprécierais si quelqu'un pouvait me donner des conseils sur une autre façon de résoudre ce problème en dehors de mes approches précédentes.

Je travaille en Java, mais toute astuce en C/C++, C#, Python, Perl... me conviendrait.

0 votes

Voulez-vous vraiment les points de division réels ou juste le nombre de syllabes dans un mot ? Dans ce dernier cas, envisagez de rechercher les mots dans un dictionnaire de synthèse vocale et de compter les phonèmes qui codent les voyelles.

0 votes

La méthode la plus efficace (en termes de calcul et non de stockage) serait d'avoir un dictionnaire Python avec des mots comme clés et le nombre de syllabes comme valeurs. Cependant, vous auriez toujours besoin d'une solution de repli pour les mots qui ne figurent pas dans le dictionnaire. Faites-moi savoir si vous trouvez un tel dictionnaire !

133voto

Jason Points 125291

Lisez l'approche TeX de ce problème pour les besoins de la césure. Voir en particulier l'article de Frank Liang mémoire de thèse Hy-phen-a-tion des mots par Com-put-er . Son algorithme est très précis, et comprend ensuite un petit dictionnaire des exceptions pour les cas où l'algorithme ne fonctionne pas.

64 votes

J'aime bien que vous ayez cité une thèse sur le sujet, c'est un petit indice pour le posteur initial que la question n'est peut-être pas facile.

0 votes

Oui, je suis conscient qu'il ne s'agit pas d'une question simple, même si je n'y ai pas beaucoup travaillé. J'ai cependant sous-estimé le problème, je pensais travailler sur d'autres parties de mon application, et revenir plus tard à ce problème "simple". Je suis stupide :)

0 votes

J'ai lu le document de thèse et l'ai trouvé très utile. Le problème avec l'approche était que je n'avais pas de modèles pour la langue albanaise, bien que j'ai trouvé quelques outils qui pourraient générer ces modèles. Quoi qu'il en soit, pour mon cas, j'ai écrit une application basée sur des règles, qui a résolu le problème...

48voto

Sean Points 241

Je suis tombé sur cette page en cherchant la même chose, et j'ai trouvé quelques implémentations de l'article de Liang ici : https://github.com/mnater/hyphenator ou son successeur : https://github.com/mnater/Hyphenopoly

À moins que vous ne soyez du genre à aimer lire une thèse de 60 pages au lieu d'adapter un code librement disponible à un problème non unique :)

0 votes

Nous sommes d'accord - il est beaucoup plus pratique d'utiliser une implémentation existante.

43voto

hoju Points 7182

Voici une solution utilisant NLTK :

from nltk.corpus import cmudict
d = cmudict.dict()
def nsyl(word):
  return [len(list(y for y in x if y[-1].isdigit())) for x in d[word.lower()]]

0 votes

Hey merci petite erreur de bébé dans la fonction def nsyl(word) : return [len(list(y for y in x if y[-1].isdigit())) for x in d[word.lower()]]

6 votes

Que suggérez-vous comme solution de repli pour les mots qui ne figurent pas dans ce corpus ?

4 votes

@Pureferret cmudict est un dictionnaire de prononciation pour les mots de l'anglais nord-américain. il divise les mots en phonèmes, qui sont plus courts que les syllabes (par exemple, le mot "chat" est divisé en trois phonèmes : K - AE - T). mais les voyelles ont également un "marqueur de stress" : soit 0, 1, ou 2, en fonction de la prononciation du mot (donc AE dans "chat" devient AE1). le code dans la réponse compte les marqueurs de stress et donc le nombre de voyelles - ce qui donne effectivement le nombre de syllabes (remarquez comment dans les exemples de OP chaque syllabe a exactement une voyelle).

20voto

Joe Basirico Points 1128

J'essaie d'aborder ce problème pour un programme qui calculera le score de lecture flesch-kincaid et flesch d'un bloc de texte. Mon algorithme utilise ce que j'ai trouvé sur ce site : http://www.howmanysyllables.com/howtocountsyllables.html et il s'en approche raisonnablement. Il a encore des difficultés avec des mots compliqués comme invisible et césure, mais j'ai trouvé qu'il était dans la moyenne pour mes besoins.

Il a l'avantage d'être facile à mettre en œuvre. J'ai découvert que le "es" peut être syllabique ou non. C'est un pari, mais j'ai décidé de supprimer le "es" dans mon algorithme.

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;
    }

0 votes

Pour mon scénario simple de recherche de syllabes dans des noms propres, cela semble fonctionner assez bien au départ. Merci de l'avoir mis en place ici.

0 votes

Par exemple, "anyone" renvoie 1 syllabe au lieu de 3, "Minute" renvoie 3 au lieu de 2, et "Another" renvoie 2 au lieu de 3.

8voto

Kilo Points 311

Voici quelques liens connexes que j'ai trouvés en travaillant sur un problème similaire :

  • Un simple Programme Python que l'auteur estime être fiable à 85% environ (et Perl version).

  • Une discussion sur le Haiku, avec code .

  • Une discussion sur le forum Python listant quelques règles phonétiques .

  • PyHyphen (bibliothèque de césure d'OpenOffice et de FireFox enveloppée dans Python) qui comprend une méthode de "syllabes".

(Je ne les ai pas encore étudiés ou expérimentés en détail).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X