Python 快速计算数据帧中所有情况之间的余弦相似性

Python 快速计算数据帧中所有情况之间的余弦相似性,python,pandas,numpy,nlp,linear-algebra,Python,Pandas,Numpy,Nlp,Linear Algebra,我正在做一个NLP项目,我必须比较许多句子之间的相似性 例如,从该数据帧: 我尝试的第一件事是将数据帧与自身连接起来,以获得以下格式并逐行比较: 问题是,对于大中型/大型数据集,我的内存很快就用完了, e、 g.对于10k行连接,我将得到100MM行,我无法放入ram中 我目前的做法是使用以下方法在数据帧上迭代: final = pd.DataFrame() ### for each row for i in range(len(df_sample)): ### select

我正在做一个NLP项目,我必须比较许多句子之间的相似性 例如,从该数据帧:

我尝试的第一件事是将数据帧与自身连接起来,以获得以下格式并逐行比较:

问题是,对于大中型/大型数据集,我的内存很快就用完了, e、 g.对于10k行连接,我将得到100MM行,我无法放入ram中

我目前的做法是使用以下方法在数据帧上迭代:

final = pd.DataFrame()

### for each row 
for i in range(len(df_sample)):

    ### select the corresponding vector to compare with 
    v =  df_sample[df_sample.index.isin([i])]["use_vector"].values
    ### compare all cases agains the selected vector
    df_sample.apply(lambda x:  cosine_similarity_numba(x.use_vector,v[0])  ,axis=1)

    ### kept the cases with a similarity over a given th, in this case 0.6
    temp = df_sample[df_sample.apply(lambda x:  cosine_similarity_numba(x.use_vector,v[0])  ,axis=1) > 0.6]  
    ###  filter out the base case 
    temp = temp[~temp.index.isin([i])]
    temp["original_question"] = copy.copy(df_sample[df_sample.index.isin([i])]["questions"].values[0])
    ### append the result     
    final = pd.concat([final,temp])
但这条路也不快。
如何提高此过程的性能?

我昨天刚刚回答了一个与您类似的问题,即

产出:

Data: 
          use_vector
0  [-0.1, -0.2, 0.3]
1  [0.1, -0.2, -0.3]
2  [-0.1, 0.2, -0.3]

Similarities:
[[-2.         -0.42857143 -0.85714286]  # vector 0 & 1, 2
 [-2.         -2.          0.28571429]  # vector 1 & 2
 [-2.         -2.         -2.        ]]

您可能采用的一个技巧是从稀疏tfidf表示切换到Facebook的密集单词嵌入:

然后,您可以继续使用更节省空间、上下文感知和性能更好的(?)密集词嵌入计算余弦相似度:

df = pd.DataFrame({"questions":["This is a question",
                                "This is a similar questin",
                                "And this one is absolutely different"]})

df["vecs"] = df["questions"].apply(model.get_sentence_vector)

from scipy.spatial.distance import pdist, squareform
# only pairwise distance with itself
# vectorized, no doubling data
out = pdist(np.stack(df['vecs']), metric="cosine")
cosine_similarity = squareform(out)
print(cosine_similarity)

同样要注意的是,除了内存效率之外,由于使用了
scipy
中的余弦相似性,您还获得了关于速度提高的信息

另一个可能的技巧是将相似向量从默认的
float64
转换为
float32
float16

df["vecs"] = df["vecs"].apply(np.float16)
这将给你的速度和记忆增益

df = pd.DataFrame({"questions":["This is a question",
                                "This is a similar questin",
                                "And this one is absolutely different"]})

df["vecs"] = df["questions"].apply(model.get_sentence_vector)

from scipy.spatial.distance import pdist, squareform
# only pairwise distance with itself
# vectorized, no doubling data
out = pdist(np.stack(df['vecs']), metric="cosine")
cosine_similarity = squareform(out)
print(cosine_similarity)
[[0.         0.08294727 0.25305626]
 [0.08294727 0.         0.23575631]
 [0.25305626 0.23575631 0.        ]]
df["vecs"] = df["vecs"].apply(np.float16)