深度学习笔记——搭建一个基于图片识别的推荐系统

依据用户的喜好推荐对应的东西目前是机器学习领域重要的应用,现在基于已有的卷积神经网络模型就可以快速地创建一个推荐系统,它能根据过去用户选择的图片从图库里推荐类似的图片。

获取图库

为了方便对比结果这里从 kaggle 上找了一个 家具相关的数据集,它每个类别的图片都包含多张因此更容易检查推荐系统的效果。

从 kaggle 网页上下载数据集后可以发现它包含两部分的数据: train 和 validation ,因为使用现成的模型并不需要训练数据集,所以我们只需要关注 val 目录下的图片,为了方便提取所有类别图片的特征这里把 val 下的图片都聚合到一个目录下:

import os, shutil, glob

for dirPath in glob.glob('val/*'):
dirName = os.path.basename(dirPath)
for filePath in glob.glob(dirPath + '/*'):
fileName = os.path.basename(filePath)
shutil.move(filePath, 'val_join/' + dirName + '_' + fileName)

提取特征

目前深度学习领域已经有不少针对图像分类训练好的模型,比如 VGG16, VGG19, Inception V3, MobileNet 等等,它们大都是在 ImageNet 数据集上训练得到的,可以满足大部分的图片分类需求,尤其在小数据集情况下直接使用这些现成模型往往比从头训练的效果更好,这一方法在机器学习领域叫做transfer learning。这里我们使用 Inception V3 这个模型,因为它的输出特征数据相对较少,需要的系统资源少,能够在更广泛的硬件平台上运行。

from os import listdir
from keras.applications.inception_v3 import InceptionV3
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array


conv_base = InceptionV3(weights='imagenet', include_top=False, input_shape=(150, 150, 3))


def extract_image_features(directory):
images = []
for name in listdir(directory):
filename = directory + '/' + name
image = load_img(filename, target_size=(150, 150))

image = img_to_array(image)
image = image.reshape((1, 150, 150, 3))
image = image.astype('float32') / 255

feature = conv_base.predict(image)

images.append((name, image, feature.flatten()))
if len(images) == 1000:
break

return images


images = extract_image_features('val_join')

上面的代码将 val_join 目录下的所有图片导入,然后使用 InceptionV3 模型进行特征提取。需要注意三点:1、图片导入后针对模型的输入格式进行了预处理:缩放图片到150*150,扩展为 4D 张量,将值的范围缩小到1以内;2、仅使用了 InceptionV3 模型的卷积神经网络部分,没有包含模型的全连接层(include_topFalse);3、输出特征 feature 降到了一维,方便后面建立推荐列表。

建立推荐列表

有了图片的特征之后便可以使用现有的数学算法找到相邻特征的图片,这里使用最近邻算法建立推荐列表:

from sklearn.neighbors import NearestNeighbors

image_features = [i[2] for i in images]

nbrs = NearestNeighbors(n_neighbors=6, algorithm='ball_tree', metric="euclidean", n_jobs = -1).fit(image_features)
distances, indices = nbrs.kneighbors(image_features)

indices 便是推荐列表,它针对每张图片都找出了最相似的5张图片,可以通过下面的函数查看效果:

import matplotlib.pyplot as plt

image_names = [i[0] for i in images]
image_data = [i[1] for i in images]

def show_recommender(image_name):
index = image_names.index(image_name)
for i in indices[index][1:]:
plt.imshow(image_data[i][0])
plt.figure()
plt.show()

例如执行 show_recommender('sofa_00000226.jpg') 之后便会显示5张类似的沙发图片。

参考