当前位置:   article > 正文

基于faiss的内容推荐实现_faiss元数据

faiss元数据
1.背景
根据物品或内容的元数据,发现物品或内容的相关性,然后基于用户以前的喜好记录推荐给用户相似的物品,如图所示:

上图给出了基于内容推荐的一个典型的例子,电影推荐系统,首先我们需要对电影的元数据有一个建模,这里只简单的描述了一下电影的类型;然后通过电影的元数据发现电影间的相似度,因为类型都是“爱情,浪漫”电影 A 和 C 被认为是相似的电影(当然,只根据类型是不够的,要得到更好的推荐,我们还可以考虑电影的导演,演员等等);最后实现推荐,对于用户 A,他喜欢看电影 A,那么系统就可以给他推荐类似的电影 C。

2.实现

上面在计算电影A和电影C的相似度时,通常可以用余弦相似度进行计算,但是当系统item百万级时,直接计算太耗时了,本文介绍fassi在基于内容推荐的使用(fassi我们经常在YouTubeDnn, DSSM等模型最后推荐topN的场景常见),本文基于moivelens的数据集实现,下面直接上代码:

2.1 电影数据处理

import re
import os
import numpy as np
from utils.movielen_read import loadfile

base_path = os.path.dirname(os.path.abspath(__file__)) + "/../../data/"

def judge_year(year):
    """判断年份"""

    if year >= 2000:
        year_label = 1
    elif year >= 1990 and year < 2000:
        year_label = 2
    elif year >= 1980 and year < 1990:
        year_label = 3
    elif year >= 1970 and year < 1980:
        year_label = 4
    else:
        year_label = 0
    return [year_label]

def judge_genres(genres):
    """类型区分"""
    genres_lables = ["Action", "Adventure", "Animation", "Children's", "Comedy", "Crime", "Documentary", "Drama",
                   "Fantasy", "Film-Noir", "Horror", "Musical", "Mystery", "Romance", "Sci-Fi", "Thriller", "War",
                   "Western"]
    genres_list = np.zeros(len(genres_lables), dtype=int)
    for genre in genres:
        if genre in genres_lables:
            ind = genres_lables.index(genre)
            genres_list[ind] = 1
    return list(genres_list)

def item_features():
    """商品特征矩阵"""
    item_feature = {}
    for line in loadfile(base_path + "ml-1m/movies.dat", encoding="ISO-8859-1"):
        arr = line.split("::")
        year = int(re.findall("\d{4}", arr[1])[0])
        year_label = judge_year(year)
        genres = arr[2].split("|")
        genres_list = judge_genres(genres)
        item_feature_list = year_label + genres_list
        item_feature.setdefault(arr[0], item_feature_list)

    return item_feature

2.2 模型构建

import numpy as np
import faiss
from utils.item_util import item_features

class FaissCB:
    def __init__(self):
        self.n_sim_movie = 10

    def fit(self, item_matrix):
        num, vec_dim = item_matrix.shape
        # 创建索引
        self.faiss_index = faiss.IndexFlatL2(vec_dim)  # 使用欧式距离作为度量
        # 添加数据
        self.faiss_index.add(item_matrix)

    def predict(self, item_matrix):
        res_distance, res_index = self.faiss_index.search(item_matrix, self.n_sim_movie)
        print(res_index)

if __name__ == '__main__':
    fcb = FaissCB()
    items = item_features()
    item_matrix = []
    item_index_mapping = {}  # {item_matrix_index: item_id}
    index = 0
    for item_id, feature in items.items():
        item_matrix.append(feature)
        item_index_mapping[index] = int(item_id)
        index += 1

    item_matrix = np.array(item_matrix, dtype='float32')
    fcb.fit(item_matrix)
    fcb.predict(item_matrix)

代码:https://github.com/littlemesie/recommend-learning/tree/master/src/cb

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号