如何确定随机字符串是否听起来像英语?

时间:2008-09-18 12:20:21

标签: string linguistics nlp

我有一个基于输入单词列表生成字符串的算法。如何仅将听起来像英语单词的字符串分开?即。在保留 LORD 的同时丢弃 RDLO

编辑:为了澄清,它们不需要是字典中的实际单词。他们只需要听起来像英语。例如, KEAL 将被接受。

13 个答案:

答案 0 :(得分:28)

你可以建立一个巨大英文文本的马尔可夫链。

然后你可以将单词输入马尔可夫链并检查该单词是英语的概率有多高。

见这里:http://en.wikipedia.org/wiki/Markov_chain

在页面底部,您可以看到markov文本生成器。你想要的恰恰相反。

简而言之:马尔可夫链为每个角色存储下一个角色将遵循的概率。如果你有足够的内存,你可以将这个想法扩展到两个或三个字符。

答案 1 :(得分:18)

贝叶斯过滤器的简单方法(来自http://sebsauvage.net/python/snyppets/#bayesian的Python示例)

from reverend.thomas import Bayes
guesser = Bayes()
guesser.train('french','La souris est rentrée dans son trou.')
guesser.train('english','my tailor is rich.')
guesser.train('french','Je ne sais pas si je viendrai demain.')
guesser.train('english','I do not plan to update my website soon.')

>>> print guesser.guess('Jumping out of cliffs it not a good idea.')
[('english', 0.99990000000000001), ('french', 9.9999999999988987e-005)]

>>> print guesser.guess('Demain il fera très probablement chaud.')
[('french', 0.99990000000000001), ('english', 9.9999999999988987e-005)]

答案 2 :(得分:4)

使用马尔可夫链生成英语发音词非常容易。然而,倒退更是一个挑战。结果的可接受误差是多少?你总是可以得到一个普通字母对,三元组等的列表,并根据它进行评分。

答案 3 :(得分:4)

你可以通过将候选字符串标记为bigrams - 成对的相邻字母来检测这一点,并根据英语二元频率表检查每个二元组。

  • 简单:如果频率表上的任何二元组足够低(或完全不存在),则拒绝该字符串是不可信的。 (String包含一个“QZ”bigram?拒绝!)
  • 不太简单:根据每个二元组的频率除以该长度的有效英语字符串的平均频率的乘积计算整个字符串的总体合理性。这将允许你(a)在其他高频双字母组合中接受带有奇数低频二元组的字符串,以及(b)拒绝具有几个单独的低但不完全低于阈值的双字母组的字符串。

其中任何一个都需要对阈值进行一些调整,第二种技术比第一种更有效。

使用trigrams做同样的事情可能会更强大,但它也可能会导致一组更严格的“有效”字符串。是否胜利取决于您的申请。

基于现有研究语料库的Bigram和trigram表可以免费或购买(我没有找到任何免费的,但到目前为止只有一个粗略的谷歌),但你可以从你自己计算一个二元组或三元组表。任何大小合适的英文文本。只需将每个单词作为一个标记进行操作并计算每个双字母组合 - 您可以将其作为一个哈希值来处理,其中给定的二元组作为键,一个递增的整数计数器作为值。

英语形态学和英语语音学(着名的!)不是等距的,所以这种技术很可能会生成“看起来”英语的字符串,但会出现麻烦的原因。这是三卦而不是双胞胎的另一个论点 - 如果n-gram跨越整个声音,那么通过分析使用顺序使用几个字母产生给定音素的声音所产生的怪异将会减少。 (例如,想想“犁”或“海啸”。)

答案 4 :(得分:3)

您应该研究“可发音”的密码生成器,因为他们正在尝试完成相同的任务。

Perl解决方案是Crypt::PassGen,您可以使用字典训练(因此,如果需要,您可以将其训练为各种语言)。它遍历字典并收集有关1,2和3个字母序列的统计信息,然后根据相对频率构建新的“单词”。

答案 5 :(得分:2)

我很想在英语单词字典上运行soundex算法并缓存结果,然后对你的候选字符串进行索引并匹配缓存。

根据性能要求,您可以为soundex代码计算距离算法,并接受特定容差范围内的字符串。

Soundex非常容易实现 - 有关算法的说明,请参阅Wikipedia

您要执行的操作的示例实现是:

def soundex(name, len=4):
    digits = '01230120022455012623010202'
    sndx = ''
    fc = ''

    for c in name.upper():
        if c.isalpha():
            if not fc: fc = c
            d = digits[ord(c)-ord('A')]
            if not sndx or (d != sndx[-1]):
                sndx += d

    sndx = fc + sndx[1:]
    sndx = sndx.replace('0','')
    return (sndx + (len * '0'))[:len]

real_words = load_english_dictionary()
soundex_cache = [ soundex(word) for word in real_words ]

if soundex(candidate) in soundex_cache:
    print "keep"
else:
    print "discard"

显然,您需要提供read_english_dictionary的实现。

编辑:您的“KEAL”示例没问题,因为它与“KEEL”具有相同的soundex代码(K400)。如果您想了解故障率,可能需要记录被拒绝的单词并手动验证它们。

答案 6 :(得分:2)

MetaphoneDouble Metaphone与SOUNDEX相似,但除了SOUNDEX之外,它们可能更适合您的目标。它们的设计是基于他们的语音“声音”来“散布”单词,并且擅长为英语做这些(但不是那么多其他语言和专有名称)。

要记住这三种算法的一件事是它们对你单词的第一个字母非常敏感。例如,如果您要确定 KEAL 是否听起来像英语,那么您将找不到与 REAL 的匹配项,因为首字母不同。

答案 7 :(得分:1)

他们必须是真正的英语单词,还是只是看起来像英文单词的字符串?

如果他们只需要看起来像可能的英文单词,你可以对一些真实的英文文本进行一些统计分析,并找出经常出现的字母组合。一旦你完成了这个,你就可以抛弃那些太不可能的字符串,尽管其中一些可能是真正的单词。

或者您可以使用字典并拒绝不在其中的字词(对复数和其他变体有一些限制)。

答案 8 :(得分:0)

您可以将它们与字典(在互联网上免费提供)进行比较,但就CPU使用率而言,这可能会很昂贵。除此之外,我不知道有任何其他程序化方法。

答案 9 :(得分:0)

这听起来像是一项相关的任务!在我的头顶,辅音音素需要在它之前或之后的元音。虽然确定一个音素是多么困难!您可能需要手动写出它们的列表。例如,“TR”可以,但不是“TD”等。

答案 10 :(得分:0)

我可能会使用SOUNDEX算法针对英语单词数据库评估每个单词。如果您在SQL服务器上执行此操作,则应该很容易设置包含大多数英语单词列表的数据库(使用可免费获得的字典),并且MSSQL服务器将SOUNDEX实现为可用的搜索算法。

显然,如果你愿意,你可以用任何语言自己实现 - 但这可能是一项非常重要的任务。

通过这种方式,您可以评估每个单词听起来像现有英语单词的数量(如果有的话),并且您可以设置一些限制,以确定您希望接受结果的程度。您可能想要考虑如何组合多个单词的结果,并且您可能会根据测试调整接受限制。

答案 11 :(得分:0)

我建议看看phi测试和巧合指数。 http://www.threaded.com/cryptography2.htm

答案 12 :(得分:-1)

我建议一些简单的规则和标准对,三元组会很好。

例如,除了一些双元音和标准辅音对(例如,th和ei,oo,tr)之外,英语发音单词倾向于遵循元音 - 辅音 - 元音的模式。有了这样的系统,你应该删除几乎所有听起来都不像英语的单词。你会仔细查看你可能会发现许多听起来像英语的单词,但是你可以开始添加规则,允许更广泛的单词并手动“训练”你的算法。

你不会删除所有的漏报(例如,我认为你不能设法在没有明确编码的情况下包含'rythm',因为rythm是一个单词)但它会提供一种过滤方法

我还假设你想要的字符串可以是英语单词(发音时听起来合理)而不是字符串,这些字母肯定是具有英语含义的单词。