在电子商务网站中,推荐系统是一种常见的工具,它能够根据用户对某个商品的兴趣,推荐相似的商品。本文将探讨如何构建一个简单的推荐系统,该系统能够根据给定的商品推荐外观相似的商品。将使用最新的预训练模型和迁移学习技术来实现这一目标。
图像由红、绿、蓝三种基本颜色组成,可以通过一个二维矩阵来表示。例如,一个3x3大小的图像,每个颜色通道都有一个3x3的矩阵,每个单元格包含像素值,这些像素值表示颜色的饱和度(或亮度)。对于红色,有一个每个单元格值在0到255之间的矩阵,每个值代表不同的红色色调。因此,对于一个3x3大小的图像,有:
Red color having a matrix of size = 3 x 3 = 9 pixels
Green color having a matrix of size = 3 x 3 = 9 pixels
Blue color having a matrix of size = 3 x 3 = 9 pixels
So the entire image will be represented by a matrix of width X height X Components = 3 x 3 x 3 = 27 pixels.
然而,在现实世界中,图像的大小通常不会这么小。例如,一个1080p的图像大小为1920x1080,因此整个1080p图像需要1920x1080x3=6,220,800个像素。以下是获取这些像素的代码示例:
# import the necessary packages
import cv2
import imutils
import numpy as np
from matplotlib import pyplot as plt
# img_path = ‘food101/images/image_pizza_1.jpeg’
img_path = 'pizza.png'
im = cv2.imread(img_path)
plt.axis('off')
plt.imshow(im[:,:,::-1])
plt.title('Original Image')
plt.show()
row,col,plane = im.shape
# ... (省略其他代码)
如上所述,对于一个1080p的图像,需要存储1920x1080x3=6,220,800个像素。这些像素是信息的视觉表示,如人物、物体等。由于正在尝试构建一个图像推荐系统,使用约600万像素来识别相似性将非常耗费计算资源。是否有更简单的方法来表示图像?答案是肯定的。
可以使用图像嵌入,而不是使用图像像素。图像嵌入可以被看作是图像的向量表示。它将图像特征和信息捕获到向量格式中。让通过一个预训练模型来了解如何派生图像嵌入。
ResNet50架构是一个例子,它接受一个图像并使用多个隐藏的神经网络层进行多次变换。通过这些变换,它预测图像属于哪个类别。模型通过卷积机制从图像中接收像素和邻域数据。这些卷积对图像数据执行多次变换,并创建一个最终向量。输出层使用这个最终向量将图像分类为1000个类别。
不使用最后一层,而是使用ResNet50架构的倒数第二层。它包含一个大小为2048的向量,这是图像的表示。这将是图像嵌入。因此,现在可以使用图像嵌入而不是像素来表示图像特征。
from tensorflow.keras.applications.resnet50 import ResNet50, preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image
import numpy as np
import pandas as pd
import cv2
from tqdm.auto import tqdm
import os
from matplotlib import pyplot as plt
def return_image_embedding(model, img_path):
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
curr_df = pd.DataFrame(preds[0]).T
return curr_df
model = ResNet50(include_top=False, weights='imagenet', pooling='avg')
img_path = 'food101/images/image_french_fries_692.jpeg'
return_image_embedding(model, img_path)
将使用余弦距离来确定相似性。余弦相似度衡量两个向量之间的距离。如果两个向量对齐,它们之间的夹角将为0,cos 0 = 1。因此,从数学上讲,这种距离度量将被用来找到最相似的图像。
逻辑是:对于给定的图像,使用嵌入之间的余弦相似度来识别最相似的图像。这个想法是使用KNN(K最近邻)模型衍生出来的。
from sklearn.metrics.pairwise import cosine_distances, pairwise_distances, cosine_similarity
cosine_similarity_df = pd.DataFrame(cosine_similarity(embedding_df.drop('image',axis=1)))
让看看模型的表现如何。在此之前,创建一个显示图像的函数。
def show_img(image_name, title=image_name):
img_path = 'food101/images/'+str(image_name)
im = cv2.imread(img_path)
im = cv2.resize(im, (960, 540))
plt.axis('off')
plt.imshow(im[:,:,::-1])
plt.title(title)
plt.show()
def fetch_most_similar_products(image_name, n_similar=7):
print("-----------------------------------------------------------------------")
print("Original Product:")
show_img(image_name, image_name)
curr_index = embedding_df[embedding_df['image']==image_name].index[0]
closest_image = pd.DataFrame(cosine_similarity_df.iloc[
curr_index].nlargest(n_similar+1)[1:])
print("-----------------------------------------------------------------------")
print("Recommended Product")
for index, imgs in closest_image.iterrows():
similar_image_name = embedding_df.iloc[index]['image']
similarity = np.round(imgs.iloc[0], 3)
show_img(similar_image_name, str(similar_image_name)+' Similarity : '+str(similarity))