Python 快速计算数据帧中所有情况之间的余弦相似性
我正在做一个NLP项目,我必须比较许多句子之间的相似性 例如,从该数据帧: 我尝试的第一件事是将数据帧与自身连接起来,以获得以下格式并逐行比较: 问题是,对于大中型/大型数据集,我的内存很快就用完了, e、 g.对于10k行连接,我将得到100MM行,我无法放入ram中 我目前的做法是使用以下方法在数据帧上迭代: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
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)