我正在使用卡内基梅隆大学的发音词典检测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"]
我可以看到手和计划声音非常相似。我可以自己估计这种相似性,但我想我应该问:是否有复杂的算法可以将数学值与这种声音(或听觉)相似度联系起来?也就是说,可以使用哪些算法或包来对两个单词之间的音素相似度进行数学计算?我意识到这是一个很大的问题,但我非常感谢其他人可以就这个问题提出的建议。
答案 0 :(得分: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词典,所以你只能对文本输入进行某种操作;但就我看来,只有有限数量的手机可供使用,所以你可以选择最重要的手机并分配"手机重量"给他们。你指出的CMU词典中只有74个:
% cat cmudict.06.txt | grep -v '#' | cut -f 2- -d ' ' | tr ' ' '\n' | sort | uniq | wc -l
75
(75减去一行为空行)
如果你在第2步中做了更高级的事情,你可能会得到更好的结果:为特定的phonem组合分配权重。然后你可以修改一些Levenshtein型距离度量,例如:在上面的图书馆中,想出合理的表现"音素距离"处理文本输入的指标。
第3步没有多少工作:获利。
答案 1 :(得分:2)
1)通过网络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