推荐系统,或者说推荐系统,是一种用于过滤信息的算法。收集信息提供与特定用户最相关的建议。当有人需要在信息量巨大的平台上做出决定时,这会很有帮助。
协作过滤使用用户过去的决策(例如过去的观看次数或对某个产品的评分)以及其他用户的类似行为来构建模型,以预测用户可能喜欢什么。它使用用户评分矩阵,并且不需要其他用户信息,例如人口统计数据或除评分之外的其他信息。这是协同过滤的主要优势,因为它依赖最少的信息,并且可以在不了解项目内容的情况下推荐项目。
Last.fm 通过观察用户经常收听的乐队和个人曲目并将其与其他用户的收听行为进行比较来推荐歌曲。 Last.fm 将播放未出现在用户库中但经常被具有相似兴趣的其他用户播放的曲目。由于这种方法利用了用户的行为,因此它是协作过滤技术的一个示例。 Last.fm 需要大量有关用户的信息才能做出准确的推荐。这是协同过滤系统中常见的冷启动问题的一个示例。 (来源:维基百科,https://en.wikipedia.org/wiki/Recommender_system)
协同过滤假设过去同意的人将来也会同意。它识别具有与当前用户相似的历史记录的另一个用户,并使用该邻域生成预测。这些方法被认为是基于内存和基于模型的方法。
可能干扰协同过滤算法的一些问题是冷启动、可扩展性和稀疏性。 冷启动是指缺乏数据来做出准确的推荐。还需要大量的计算能力,这通常是计算推荐所必需的,这使得算法可扩展性较差。此外,互联网上有大量的产品和物品,这意味着评级相当稀疏。
我们将使用包含顶级品牌和化妆品评论的数据集。该数据集可以在 Kaggle 网站上找到:https://www.kaggle.com/datasets/jithinanievarghese/cosmetics-and-beauty-products-reviews-top-brands
rating_list = pd.read_csv('top_brands_cosmetics_product_reviews.csv', sep=',', usecols=['author', 'product_title', 'product_rating', 'review_date']) items = pd.read_csv('top_brands_cosmetics_product_reviews.csv', usecols=['product_title', 'product_url', 'brand_name'], encoding='latin-1') print(f'Number of ratings: {rating_list.author.nunique()} | Number of items: {items.product_title.nunique()}')
使用用户-项目矩阵来旋转训练。
X_train, X_test, y_train, y_test = train_test_split(rating_list, rating_list.product_rating, test_size=0.1, random_state=42) ratings = X_train.pivot_table(index=['author'], columns=['product_title'], values='product_rating').fillna(0) mean_ratings = ratings.mean(axis=1) print(f'Number of users: {ratings.shape[0]} | Number of items: {ratings.shape[1]}')
计算相似度。
def get_all_recommendations(user_id, model, use_means=True): distance, knn = model.kneighbors(ratings.fillna(0)) # nearest neighbors knn = pd.DataFrame(knn + 1, index=ratings.index) sim = pd.DataFrame(1 - distance, index=ratings.index) # invert the distance neighbors = knn.loc[user_id, 1:] similarities = sim.loc[user_id, 1:] similarities.index = ratings.loc[neighbors].index if use_means: return pd.Series(mean_ratings.loc[user_id] + ratings.loc[neighbors].subtract(mean_ratings.loc[neighbors], axis='index').mul(similarities, axis='index').sum(axis='index') / similarities.sum(), name='recommendation') else: return pd.Series(ratings.loc[neighbors].mul(similarities, axis='index').sum(axis='index') / similarities.sum(), name='recommendation')
计算给定用户、产品和模型的单个推荐
def get_recommendations (user_id, product_id, model, use_means=True): if product_id not in ratings.columns: return 2.5 recommendations = get_all_recommendations(user_id, model, use_means=use_means) return recommendations.loc[product_id]
计算均方根误差 (RMSE) 以评估并预测数据集中每个用户的所有产品的评分。然后,将预测评分与测试集中的实际评分对齐并计算 RMSE.7。
model = NearestNeighbors(n_neighbors=40, metric='cosine') model.fit(ratings.fillna(0)) def get_RMSE(X_test, model, use_means=True): group = X_test[['product_title', 'product_rating']].groupby(X_test.author) mse = [] i = 0 for key in group.groups: if key not in rating_list['author']: continue # Skip users not in the dataset predictions = get_all_recommendations(key, model=model, use_means=use_means) rated_products = group.get_group(key).set_index('product_title') df = rated_products.join(predictions).dropna().reset_index() mse.append(df) if i % 100 == 0: score = np.sqrt(mean_squared_error(df.product_rating, df.recommendation)) print(f'{i}/{X_test.author.nunique()} - RMSE: {score:.4f}') i += 1 mse = pd.concat(mse).reset_index(drop=True) score = np.sqrt(mean_squared_error(mse.product_rating, mse.recommendation)) print(f'{X_test.author.nunique()}/{X_test.author.nunique()} - RMSE: {score:.4f}') get_RMSE(X_test, model)
ratings_dict = { "item": [1, 2, 1, 2, 1, 2, 1, 2, 1], "user": ['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D', 'E'], "rating": [1, 2, 2, 4, 2.5, 4, 4.5, 5, 3], } df = pd.DataFrame(ratings_dict) reader = Reader(rating_scale=(1, 5)) data = Dataset.load_from_df(df[["user", "item", "rating"]], reader) movielens = Dataset.load_builtin('ml-100k') trainingSet = movielens.build_full_trainset() algo.fit(trainingSet)
def get_recommendation(id_user, id_movie, ratings): #cosine similarity of the ratings similarity_matrix = cosine_similarity(ratings.fillna(0), ratings.fillna(0)) similarity_matrix_df = pd.DataFrame(similarity_matrix, index=ratings.index, columns=ratings.index) cosine_scores = similarity_matrix_df[id_user] ratings_scores = ratings[id_movie] ratings_scores.dropna().dot(cosine_scores[~ratings_scores.isna()]) / cosine_scores[~ratings_scores.isna()].sum() return np.dot(ratings_scores.dropna(), cosine_scores[~ratings_scores.isna()]) / cosine_scores[ ~ratings_scores.isna()].sum() get_recommendation(196, 8, ratings) # get recommandations for user 196 for movie 8
基于内容的过滤方法利用项目的一系列离散的、预先标记的特征来推荐具有相似属性的其他项目。它使用项目功能来选择并返回与用户正在寻找的内容相关的项目。一些基于内容的推荐算法根据项目的描述而不是实际内容来匹配项目。
Pandora 使用歌曲或艺术家的属性来播种播放具有相似属性的音乐的队列。用户反馈用于完善电台的结果,当用户“不喜欢”某首特定歌曲时,不强调某些属性,而当用户“喜欢”一首歌曲时,则强调其他属性。这是基于内容的方法的一个示例。 Pandora 需要很少的信息来启动,它的范围更加有限(例如,它只能提出与原始种子类似的推荐)。 (来源:维基百科,https://en.wikipedia.org/wiki/Recommender_system)
该方法使用产品的描述和用户的个人资料,使其适合已知商品数据但不知道用户数据的情况。基于内容的推荐器将推荐视为特定于用户的分类问题,并根据项目的特征学习用户喜欢和不喜欢的分类器。关键字用于描述项目,并构建用户配置文件来列出用户的喜好和厌恶。将各种候选项目与用户先前评分的项目进行比较,并推荐最匹配的项目。一种广泛使用的算法是 TF-IDF 表示。有机器学习技术,如贝叶斯分类器、聚类分析、决策树和人工神经网络来估计用户喜欢该项目的概率。
但是,基于内容的过滤通常会建议与用户已经喜欢的内容非常相似的项目,从而限制了多样性并使发现新事物变得更加困难。这可能会产生“泡沫”,让用户只能看到某些类型的内容。它还取决于项目的标签或描述程度,如果信息不足或者用户是新用户并且尚未与太多内容进行交互,这可能会成为问题。
rating_list = pd.read_csv('top_brands_cosmetics_product_reviews.csv', sep=',', usecols=['author', 'product_title', 'product_rating', 'review_date']) items = pd.read_csv('top_brands_cosmetics_product_reviews.csv', usecols=['product_title', 'product_url', 'brand_name'], encoding='latin-1') print(f'Number of ratings: {rating_list.author.nunique()} | Number of items: {items.product_title.nunique()}')
将绘图摘要转换为向量表示,以便能够应用数值机器学习算法。
X_train, X_test, y_train, y_test = train_test_split(rating_list, rating_list.product_rating, test_size=0.1, random_state=42) ratings = X_train.pivot_table(index=['author'], columns=['product_title'], values='product_rating').fillna(0) mean_ratings = ratings.mean(axis=1) print(f'Number of users: {ratings.shape[0]} | Number of items: {ratings.shape[1]}')
每个情节摘要都会被转化为一个单词序列来指向一个高维语义空间(这里使用了 TF-IDF 模型)。这会统计某个单词在文档中出现的次数,从而决定该单词在文档中的重要性。
print(f'矩阵包含 {tfidf_model.shape[0]} 行和 {tfidf_model.shape[1]} 列')
BOW(词袋)模型计算单词在文档中出现的次数(稀疏,向量中的大多数条目都是 0)
TF-IDF(词频 - 逆文档频率) 模型计算单词在文档中出现的次数,但也考虑单词在所有文档中出现的频率。它降低了文档中频繁出现的单词的权重,使其信息量低于那些很少出现的单词。每个情节摘要都被编码为单个向量,其长度等于所有情节摘要的词汇表的大小,TD-IDF 将情节摘要转换为矩阵。它会忽略出现在超过 80% 评论中的单词以及出现在少于 2 条评论中的单词 → 噪音减少。
使用流行的化妆词汇检查 TF-IDF 模型。
def get_all_recommendations(user_id, model, use_means=True): distance, knn = model.kneighbors(ratings.fillna(0)) # nearest neighbors knn = pd.DataFrame(knn + 1, index=ratings.index) sim = pd.DataFrame(1 - distance, index=ratings.index) # invert the distance neighbors = knn.loc[user_id, 1:] similarities = sim.loc[user_id, 1:] similarities.index = ratings.loc[neighbors].index if use_means: return pd.Series(mean_ratings.loc[user_id] + ratings.loc[neighbors].subtract(mean_ratings.loc[neighbors], axis='index').mul(similarities, axis='index').sum(axis='index') / similarities.sum(), name='recommendation') else: return pd.Series(ratings.loc[neighbors].mul(similarities, axis='index').sum(axis='index') / similarities.sum(), name='recommendation')
根据不同产品的绘图摘要术语频率出现签名应用不同产品之间的余弦相似度。
def get_recommendations (user_id, product_id, model, use_means=True): if product_id not in ratings.columns: return 2.5 recommendations = get_all_recommendations(user_id, model, use_means=use_means) return recommendations.loc[product_id]
将该函数应用于数据集中的任何产品。
model = NearestNeighbors(n_neighbors=40, metric='cosine') model.fit(ratings.fillna(0)) def get_RMSE(X_test, model, use_means=True): group = X_test[['product_title', 'product_rating']].groupby(X_test.author) mse = [] i = 0 for key in group.groups: if key not in rating_list['author']: continue # Skip users not in the dataset predictions = get_all_recommendations(key, model=model, use_means=use_means) rated_products = group.get_group(key).set_index('product_title') df = rated_products.join(predictions).dropna().reset_index() mse.append(df) if i % 100 == 0: score = np.sqrt(mean_squared_error(df.product_rating, df.recommendation)) print(f'{i}/{X_test.author.nunique()} - RMSE: {score:.4f}') i += 1 mse = pd.concat(mse).reset_index(drop=True) score = np.sqrt(mean_squared_error(mse.product_rating, mse.recommendation)) print(f'{X_test.author.nunique()}/{X_test.author.nunique()} - RMSE: {score:.4f}') get_RMSE(X_test, model)
您还可以结合这两种算法来提供更精细的推荐。推荐系统帮助用户发现他们可能找不到的物品。推荐系统通常使用索引非传统数据的搜索引擎来实现。
总之,推荐系统通过提供个性化建议,在帮助用户发现相关内容和产品方面发挥着关键作用。他们通过减少寻找自己感兴趣的内容所需的时间和精力来增强体验。
** 在 GitHub 上查看完整代码:https://github.com/alexiacismaru/recommender-systems
以上是什么是推荐系统以及如何使用它们的详细内容。更多信息请关注PHP中文网其他相关文章!