在 python 中创建一个快速的自定义相似度矩阵
create a fast custom similarity matrix in python
我正在尝试在使用自定义相似度函数的同时构建相似度矩阵。
问题是代码运行很慢。
我有一个如下所示的数据框:
col1 col2 col3
'car' 'A' 'cat'
'car' 'C' 'dog'
'bike' 'A' 'cat'
...
并且我有一系列权重,这些权重将重要性归于某一列 [0.1, 0.5, 0.4]
我想计算自定义相似性矩阵中行之间的相似性,其中如果行对具有相同的值(给定使某些列比其他列更重要的权重),则它们是相似的
我当前的相似性将两个数组作为输入,并使用一些权重检查它们之间有多少元素相同(这是一个与 x 和 y 具有相同长度的数组)
def custom_similarity(x, y, weights):
similarity = np.dot((x == y).values*1,weights)
return(similarity)
给定一个数据框,其中每一行代表要比较的数组之一,我想使用该函数生成数据框的相似度矩阵。
目前我正在做这样的事情(填充一个空矩阵),它可以工作但是速度非常慢:
sim_matrix = np.zeros((len(df),len(df)))
for i in tqdm(range(len(df))):
obs_i = df.iloc[i,:]
for j in range(i, len(df)):
obs_j = df.iloc[j,:]
sim_matrix[i,j] = sim_matrix[j,i] = custom_similarity(obs_i, obs_j, weights)
如何提高效率并加快速度?
一种方法是使用 scipy.spatial
。这已经比你自己滚动的效率高了很多。特别是,您可以使用 pdist
和自定义度量函数执行以下操作:
import numpy as np
from scipy.spatial.distance import pdist, squareform
def sim_mat(df, weights):
mat = squareform(pdist(df.values, metric=lambda x, y: (x == y) @ weights))
np.fill_diagonal(mat, sum(weights))
return mat
将此方法与您在不断增加的数据集上使用的原始方法进行比较,我得到以下结果:
我正在尝试在使用自定义相似度函数的同时构建相似度矩阵。 问题是代码运行很慢。
我有一个如下所示的数据框:
col1 col2 col3
'car' 'A' 'cat'
'car' 'C' 'dog'
'bike' 'A' 'cat'
...
并且我有一系列权重,这些权重将重要性归于某一列 [0.1, 0.5, 0.4]
我想计算自定义相似性矩阵中行之间的相似性,其中如果行对具有相同的值(给定使某些列比其他列更重要的权重),则它们是相似的
我当前的相似性将两个数组作为输入,并使用一些权重检查它们之间有多少元素相同(这是一个与 x 和 y 具有相同长度的数组)
def custom_similarity(x, y, weights):
similarity = np.dot((x == y).values*1,weights)
return(similarity)
给定一个数据框,其中每一行代表要比较的数组之一,我想使用该函数生成数据框的相似度矩阵。
目前我正在做这样的事情(填充一个空矩阵),它可以工作但是速度非常慢:
sim_matrix = np.zeros((len(df),len(df)))
for i in tqdm(range(len(df))):
obs_i = df.iloc[i,:]
for j in range(i, len(df)):
obs_j = df.iloc[j,:]
sim_matrix[i,j] = sim_matrix[j,i] = custom_similarity(obs_i, obs_j, weights)
如何提高效率并加快速度?
一种方法是使用 scipy.spatial
。这已经比你自己滚动的效率高了很多。特别是,您可以使用 pdist
和自定义度量函数执行以下操作:
import numpy as np
from scipy.spatial.distance import pdist, squareform
def sim_mat(df, weights):
mat = squareform(pdist(df.values, metric=lambda x, y: (x == y) @ weights))
np.fill_diagonal(mat, sum(weights))
return mat
将此方法与您在不断增加的数据集上使用的原始方法进行比较,我得到以下结果: