use*_*705 130 nlp spell-checking hyphenation
我需要找到一种相当有效的方法来检测单词中的音节.例如,
隐形 - > 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 ......中的任何提示都适合我.
jas*_*son 115
为了连字,请阅读有关此问题的TeX方法.特别参见Frank Liang的论文论文, 由Com-put-er提供的Word Hy-phen-a-tion.他的算法非常准确,然后包含一个小例外字典,用于算法不起作用的情况.
小智 45
我偶然发现了这个页面,寻找同样的东西,并在这里找到了梁文的一些实现:https: //github.com/mnater/hyphenator
除非你喜欢阅读60页的论文,而不是为非独特的问题调整免费的可用代码.:)
hoj*_*oju 40
这是使用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()]]
Run Code Online (Sandbox Code Playgroud)
Joe*_*ico 18
我正在尝试解决这个问题,这个程序将计算一段文本的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;
}
Run Code Online (Sandbox Code Playgroud)
这是一个特别困难的问题,LaTeX连字算法无法完全解决这个问题.一些可用的方法和所涉及的挑战的一个很好的总结可以在文章评估英语自动音节化算法(Marchand,Adsett和Damper 2007)中找到.
今天我发现了Frank Liang 的连字符算法的Java实现,具有英语或德语的模式,它运行得很好,并且可以在 Maven Central 上找到。
Cave:删除.tex模式文件的最后几行非常重要,否则这些文件将无法使用 Maven Central 上的当前版本加载。
要加载和使用hyphenator,您可以使用以下 Java 代码片段。是包含所需模式的文件texTable的名称。.tex这些文件可以在项目 github 站点上找到。
private Hyphenator createHyphenator(String texTable) {
Hyphenator hyphenator = new Hyphenator();
hyphenator.setErrorHandler(new ErrorHandler() {
public void debug(String guard, String s) {
logger.debug("{},{}", guard, s);
}
public void info(String s) {
logger.info(s);
}
public void warning(String s) {
logger.warn("WARNING: " + s);
}
public void error(String s) {
logger.error("ERROR: " + s);
}
public void exception(String s, Exception e) {
logger.error("EXCEPTION: " + s, e);
}
public boolean isDebugged(String guard) {
return false;
}
});
BufferedReader table = null;
try {
table = new BufferedReader(new InputStreamReader(Thread.currentThread().getContextClassLoader()
.getResourceAsStream((texTable)), Charset.forName("UTF-8")));
hyphenator.loadTable(table);
} catch (Utf8TexParser.TexParserException e) {
logger.error("error loading hyphenation table: {}", e.getLocalizedMessage(), e);
throw new RuntimeException("Failed to load hyphenation table", e);
} finally {
if (table != null) {
try {
table.close();
} catch (IOException e) {
logger.error("Closing hyphenation table failed", e);
}
}
}
return hyphenator;
}
Run Code Online (Sandbox Code Playgroud)
然后就Hyphenator可以使用了。要检测音节,基本思想是在提供的连字符处拆分术语。
String hyphenedTerm = hyphenator.hyphenate(term);
String hyphens[] = hyphenedTerm.split("\u00AD");
int syllables = hyphens.length;
Run Code Online (Sandbox Code Playgroud)
您需要根据"\u00AD" 进行拆分,因为 API 不会返回正常的"-".
这种方法优于 Joe Basirico 的答案,因为它支持许多不同的语言并且更准确地检测德语连字符。
为什么要计算?每个在线词典都有此信息。http://dictionary.reference.com/browse/invisible in·vis·i·ble
感谢Joe Basirico,在C#中分享快速而肮脏的实现.我使用过大型库,它们可以工作,但它们通常有点慢,对于快速项目,你的方法运行正常.
以下是Java中的代码以及测试用例:
public static int countSyllables(String word)
{
char[] vowels = { 'a', 'e', 'i', 'o', 'u', 'y' };
char[] currentWord = word.toCharArray();
int numVowels = 0;
boolean lastWasVowel = false;
for (char wc : currentWord) {
boolean foundVowel = false;
for (char v : 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 (word.length() > 2 &&
word.substring(word.length() - 2) == "es")
numVowels--;
// remove silent e
else if (word.length() > 1 &&
word.substring(word.length() - 1) == "e")
numVowels--;
return numVowels;
}
public static void main(String[] args) {
String txt = "what";
System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
txt = "super";
System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
txt = "Maryland";
System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
txt = "American";
System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
txt = "disenfranchized";
System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
txt = "Sophia";
System.out.println("txt="+txt+" countSyllables="+countSyllables(txt));
}
Run Code Online (Sandbox Code Playgroud)
结果如预期的那样(它对Flesch-Kincaid来说足够好):
txt=what countSyllables=1
txt=super countSyllables=2
txt=Maryland countSyllables=3
txt=American countSyllables=3
txt=disenfranchized countSyllables=5
txt=Sophia countSyllables=2
Run Code Online (Sandbox Code Playgroud)
撞到@Tihamer和@ joe-basirico.非常有用的功能,不完美,但适用于大多数中小型项目.Joe,我用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
Run Code Online (Sandbox Code Playgroud)
希望有人觉得这很有用!
不久前我遇到了这个完全相同的问题。
我最终使用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
Run Code Online (Sandbox Code Playgroud)
如果您不使用 Python 并且想尝试基于 ML 模型的方法,我写了一篇关于音节计数模型如何在 Kaggle 上工作的非常详细的文章。