Python 如何更有效地计算用户相似度矩阵?
我有一组10个用户,每个用户都有自己的文件夹/目录,其中包含25-30张他们共享的图片(比如在一些社交媒体中)。我想根据用户共享的图像计算他们之间的相似性 为此,我使用一个特征提取器将每个图像转换成一个224x224x3数组,然后循环遍历每个用户及其文件夹中的每个图像,以找到每对图像之间的余弦相似性,然后对每对用户的所有成对图像相似性取平均值,以找到用户相似性。(顺便说一下,如果这个逻辑有错误,请告诉我) 我的代码如下所示:Python 如何更有效地计算用户相似度矩阵?,python,performance,loops,optimization,time,Python,Performance,Loops,Optimization,Time,我有一组10个用户,每个用户都有自己的文件夹/目录,其中包含25-30张他们共享的图片(比如在一些社交媒体中)。我想根据用户共享的图像计算他们之间的相似性 为此,我使用一个特征提取器将每个图像转换成一个224x224x3数组,然后循环遍历每个用户及其文件夹中的每个图像,以找到每对图像之间的余弦相似性,然后对每对用户的所有成对图像相似性取平均值,以找到用户相似性。(顺便说一下,如果这个逻辑有错误,请告诉我) 我的代码如下所示: from tensorflow.keras.applications.
from tensorflow.keras.applications.imagenet_utils import preprocess_input
from tensorflow.keras.applications import vgg16
from tensorflow.keras.preprocessing.image import load_img,img_to_array
from tensorflow.keras.models import Model
import os
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
import pandas as pd
# load the model
vgg_model = vgg16.VGG16(weights='imagenet')
# remove the last layers in order to get features instead of predictions
feat_extractor = Model(inputs=vgg_model.input, outputs=vgg_model.get_layer("fc2").output)
def processed_image(image):
original = load_img(image, target_size=(224, 224))
numpy_image = img_to_array(original)
image_batch = np.expand_dims(numpy_image, axis=0)
processed_image = preprocess_input(image_batch.copy())
img_features = feat_extractor.predict(processed_image)
return img_features
def image_similarity(image1, image2):
image1 = processed_image(image1)
image2 = processed_image(image2)
sim = cosine_similarity(image1, image2)
return sim[0][0]
user_list = ['User '+str(i) for i in range(1,11)]
user_sim_df = pd.DataFrame(columns=user_list, index=user_list)
for user1 in user_list:
for user2 in user_list:
sum_img_sim = 0
user1_files = [imgs_path + x for x in os.listdir('All_Users/'+user1) if "jpg" in x]
user2_files = [imgs_path + x for x in os.listdir('All_Users/'+user2) if "jpg" in x]
for image1 in user1_files:
for image2 in user2_files:
sum_img_sim += image_similarity(image1, image2)
user_sim_df[user1][user2] = 2*sum_img_sim/(len(user1_files)+len(user2_files))
现在,由于计算用户相似性矩阵时涉及到4个for
循环,因此代码运行时间太长(键入此问题时已超过30分钟,代码已运行了10个用户,每个用户有25-30张图像)
那么,如何重写本文的最后一部分以加快代码的运行速度呢?嵌套for循环对于Python来说尤其糟糕,但是这里可以做一些工作来改进 首先,你在比较中做了两次工作<对于所有对
i,j
,code>user\u-sim\u-df[user\u i][user\u j]与user\u-sim\u-df[user\u j][user\u i]
具有相同的值。可以从使用已计算的值中获益,而不是在以后的迭代中再次计算它们。除此之外,计算对角线上的值(user\u sim\u df[user\u i][user\u i]
)是否是应用程序所必需的
这些简单的更改将把执行时间减少一半。够了吗?也许不是。进一步的改进措施:
img\u to\u array()
操作多次应用于每个图像(每次计算与另一个图像的相似性时)。这是一个瓶颈吗?在这种情况下,如果您首先在所有图像上运行循环,并创建一个新文件供numpy稍后读取(例如使用numpy.read()
),或者只保存从当前使用的Tensorflow输出的预处理文件,性能也会得到提高