不同大小的numpy数组元素的条件

时间:2018-09-06 17:51:11

标签: python numpy vector conditional vectorization

我在伪Python代码中遇到以下情况,为了优化起见,需要为此找到一种矢量化解决方案,因为我要处理成千上万的语音分析条目,并且嵌套循环是不可行的。我想知道如何对不同大小的数组进行条件检查的矢量化……例如,我知道np.greater,但这是元素明智的操作,对于不同大小的数组会失败。

words = [
    {'id': 0, 'word': 'Stu', 'sampleStart': 882, 'sampleEnd': 40571},
    {'id': 0, 'word': ' ', 'sampleStart': 40570, 'sampleEnd': 44540},
    {'id': 0, 'word': 'eyes', 'sampleStart': 44541, 'sampleEnd': 66590},
]

phonemes = [
    {'id': 0, 'phoneme': ' ', 'sampleStart': 0, 'sampleEnd': 881},
    {'id': 1, 'phoneme': 's', 'sampleStart': 882, 'sampleEnd': 7937},
    {'id': 2, 'phoneme': 't', 'sampleStart': 7938, 'sampleEnd': 11906},
    {'id': 3, 'phoneme': 'u', 'sampleStart': 11907, 'sampleEnd': 15433},
    {'id': 3, 'phoneme': ' ', 'sampleStart': 15434, 'sampleEnd': 47627},
    {'id': 3, 'phoneme': 'eye', 'sampleStart': 47628, 'sampleEnd': 57770},
    {'id': 3, 'phoneme': 's', 'sampleStart': 57771, 'sampleEnd': 66590},
]

associatedData = []
for w in words:
    startWord = w['sampleStart']
    endWord = w['sampleEnd']
    word = w['word']
    w_id = w['id']
    for p in phonemes:
        startPhoneme = p['sampleStart']
        endPhoneme = p['sampleEnd']
        phoneme = p['phoneme']
        p_id = p['id']
        if startPhoneme >= startWord and endPhoneme <= endWord:
            # I need to relate this data as it comes from 2 different sources
            # Some computations occur here that are too ling to reproduce here, this multiplication is just to give an example
            mult = startPhoneme * startWord
            associatedData.append({'w_id' : w_id, 'p_id': p_id, 'word' : word, 'phoneme' : phoneme, 'someOp': startWord})

# Gather associated data for later use:
print(associatedData)

什么是解决此问题的好方法?我对矢量操作还比较陌生,并且已经为此花了好几个小时苦苦挣扎,但收效甚微。

1 个答案:

答案 0 :(得分:0)

查看每个单词的所有可能音素将不会缩放。完成的工作量高于需要的工作量。使用任意数量的wordsphonemes,使用此方法将始终会有len(words) * len(phonemes)个操作。向量化可以加快速度,但是最好降低复杂度本身。

每个单词都尽量只看几个音素候选者。一种解决方案是使指针指向当前的音素。对于每个新单词,都在匹配的音素范围内(在本地,仅在当前音素指针附近)进行迭代。

伪代码解决方案:

# skip if already sorted
words = sorted(words, key=lambda x:x["sampleStart"])
phonemes = sorted(phonemes, key=lambda x:x["sampleStart"])

phoneme_idx = 0
for w in words:

    # go back until the earliest relevant phoneme
    while endtime(phonemes[phoneme_idx]) < starttime(w):
         phoneme_idx -= 1

    # evaluate all phonemes in range
    while endtime(phonemes[phoneme_idx]) <= starttime(w):
         # match and compute
         evavalute(phonemes[phoneme_idx], w)
         phoneme_idx += 1