numpy 在Python中计算n-gram重叠矩阵的最快方法

zsohkypk  于 2023-05-07  发布在  Python
关注(0)|答案(1)|浏览(221)

我有一个很大的文档语料库,如果它们有明显的n-gram重叠(在我的例子中,我考虑的是bigrams),我想合并它们。考虑集合列表:

corpus = [{'example', 'bigram'}, {'another', 'example'}, {'some', 'outlier'}]

我有以下代码来计算相似度矩阵:

import numpy as np

sim_matrix = np.zeros((len(corpus), len(corpus)))
for i in range(len(corpus)):
    for j in range(i+1, len(corpus)):
        sim_matrix[i][j] = get_ngram_overlap(corpus[i], corpus[j])
        
np.fill_diagonal(sim_matrix, 1)

其中get_ngram_overlap函数定义如下:

def get_ngram_overlap(ngrams_s1, ngrams_s2):

    if min(len(ngrams_s1), len(ngrams_s2)) == 0:
        return 0

    common_ngrams = ngrams_s1 & ngrams_s2

    return len(common_ngrams)/min(len(ngrams_s1), len(ngrams_s2))

结果是一个MxM矩阵,其中M是我的语料库中的n-gram的数量

print(sim_matrix)
>> [[1.  0.5  0.]
   [0.  1.   0.]
   [0.  0.   1.]]

问题是,当M变大时,代码非常慢,并且这在计算上变得非常昂贵,因为必须比较所有唯一对。**是否有更有效的方法来计算?**类似于使用优化的距离矩阵计算和自定义的相似性度量,这将适用于字符串集。任何帮助是赞赏!

jmp7cifd

jmp7cifd1#

使用itertools.combinations(获得连续的二元组对)和数组的 * 三角 * 计算(np.triu_indices):

from itertools import combinations

def get_ngram_overlap(ngrams_s1, ngrams_s2):
    min_len = min(len(ngrams_s1), len(ngrams_s2))
    if min_len == 0:
        return 0
    return len(ngrams_s1 & ngrams_s2) / min_len

corpus = [{'example', 'bigram'}, {'another', 'example'}, {'some', 'outlier'}]
sim_matrix = np.zeros((len(corpus), len(corpus)))

# fill upper triangle with calculated overlaps 
sim_matrix[np.triu_indices(len(sim_matrix), 1)] = \
            list(get_ngram_overlap(*c) for c in combinations(corpus, 2))
np.fill_diagonal(sim_matrix, 1)
print(sim_matrix)
[[1.  0.5 0. ]
 [0.  1.  0. ]
 [0.  0.  1. ]]

相关问题