【问题标题】:Estimate Phonemic Similarity Between Two Words估计两个词之间的音素相似度
【发布时间】:2014-12-15 23:28:48
【问题描述】:

我正在使用卡内基梅隆大学发音词典在 Python 中检测韵律,并且想知道:如何估计两个单词之间的音素相似度?换句话说,是否有一种算法可以识别“手”和“计划”比“手”和“薯条”更接近押韵的事实?

一些上下文:起初,如果两个单词的主要重读音节和所有后续音节相同,我愿意说两个词押韵(c06d,如果你想在 Python 中复制):

def create_cmu_sound_dict():

    final_sound_dict = {}

    with open('resources/c06d/c06d') as cmu_dict:
        cmu_dict = cmu_dict.read().split("\n")
        for i in cmu_dict:
            i_s = i.split()
            if len(i_s) > 1:
                word = i_s[0]
                syllables = i_s[1:]

                final_sound = ""
                final_sound_switch = 0

                for j in syllables:
                    if "1" in j:
                        final_sound_switch = 1
                        final_sound += j
                    elif final_sound_switch == 1:
                        final_sound += j

            final_sound_dict[word.lower()] = final_sound

    return final_sound_dict

如果我然后运行

print cmu_final_sound_dict["hands"]
print cmu_final_sound_dict["plans"]

我可以看到手和计划听起来非常相似。我可以自己估计这种相似性,但我想我应该问:是否有复杂的算法可以将数学值与这种程度的声音(或听觉)相似性联系起来?也就是说,可以使用哪些算法或程序包来数学化两个单词之间的音素相似度?我知道这是一个很大的问题,但如果其他人可以就这个问题提供任何建议,我将不胜感激。

【问题讨论】:

  • 您是否在寻找类似 Soundex 算法 (en.wikipedia.org/wiki/Soundex) 的东西?
  • 我不能代表反对者发言,但给出接近投票的原因是您的问题看起来像是asking for recommendations。您可能想改写它以更清楚地问“我如何做 X?”而不是“我应该使用哪个工具来做 X?”
  • 我认为这些问题是同义词(做某事意味着/需要一种方法来做那件事),但如果有帮助,我会很乐意重新措辞...
  • @acfrancis Soundex 看起来很有趣,但它似乎更像是一种散列算法,而不是一种可以估计两个单词之间音素相似度的方法
  • 是的,我认为你是对的。不幸的是,我不知道任何其他语音算法。 Levenshtein 距离会告诉您两个单词在写作方面有多相似,但不是基于它们的发音。

标签: python algorithm nlp linguistics phoneme


【解决方案1】:

1) 通过 Web API 或本地 SAPI 获取所有单词的所有 TTS 音频,

2) 尽可能提取语音特征(1,2),或者至少获得语音数据的威力

3) 取决于您拥有的功能,这里有一些方法。

如果你能得到语音数据(Dim=1)的每个样本(帧)的幂,那么一种简单的方法无疑是计算两组特征的correlation。

如果您有其他类型的特征,很可能会有更多维度,您可以将其视为图像并查看2d convolution 或Dynamic time warping

4) 如果您对任务 1、2、3 的语音处理一无所知,请查看pyphonetics

#pip install pyphonetics
>>> from pyphonetics import RefinedSoundex
>>> rs = RefinedSoundex()
>>> rs.distance('Rupert', 'Robert')
0
>>> rs.distance('assign', 'assist', metric='hamming')
2

【讨论】:

    【解决方案2】:

    作弊。

    #!/usr/bin/env python
    
    from Levenshtein import *
    
    if __name__ == '__main__':
        s1 = ['HH AE1 N D Z', 'P L AE1 N Z']
        s2 = ['HH AE1 N D Z', 'F R AY1 Z']
        s1nospaces = map(lambda x: x.replace(' ', ''), s1)
        s2nospaces = map(lambda x: x.replace(' ', ''), s2)
        for seq in [s1, s2, s1nospaces, s2nospaces]:
            print seq, distance(*seq)
    

    输出:

    ['HH AE1 N D Z', 'P L AE1 N Z'] 5
    ['HH AE1 N D Z', 'F R AY1 Z'] 8
    ['HHAE1NDZ', 'PLAE1NZ'] 3
    ['HHAE1NDZ', 'FRAY1Z'] 5
    

    图书馆:https://pypi.python.org/pypi/python-Levenshtein/0.11.2

    但是,说真的,因为您只有文本作为输入并且几乎是基于文本的 CMU dict,所以您只能对文本输入进行某种操作;但在我看来,可用的音素数量有限,因此您可以选择最重要的音素并为它们分配“音素权重”。你指的CMU字典里只有74个:

     % cat cmudict.06.txt | grep -v '#' | cut -f 2- -d ' ' | tr ' ' '\n' | sort | uniq | wc -l
     75
    

    (75 减一为空行)

    如果您在第 2 步中进行了更高级的操作,您可能会得到更好的结果:为特定的音素组合分配权重。然后你可以修改一些 Levenshtein 类型的距离度量,例如在上面的库中,提出对文本输入进行合理执行的“音素距离”度量。

    第 3 步的工作量不大:利润。

    【讨论】:

    • 这完全忽略了使“nd”倾向于同化为“n”的音素特征,而例如“nk”没有(或倾向于“ngk”,或者确实经常被理解为“ngk”)。
    猜你喜欢
    • 2017-08-22
    • 2012-03-11
    • 2018-07-15
    • 2011-03-11
    • 2013-03-20
    • 2017-03-19
    • 2019-08-05
    相关资源
    最近更新 更多