Gorse推荐系统指南:性能和准确率的权衡

699 阅读7分钟

Github: Gorse推荐系统指南:性能和准确率的权衡

在最理想的情况下,推荐系统应当将用户最可能喜欢的物品推荐给用户。然而,由于计算和存储资源总是有限的,推荐系统往往必须在推荐性能和准确率之间做权衡。本文将介绍如何通过配置对Gorse的计算资源使用量、存储资源使用量和推荐准确率之间进行权衡。

设置物品和反馈的有效时间

在默认的配置下,Gorse会读取数据表内的全部数据作为训练数据。在配置文件中,可以通过item_ttlpositive_feedback_ttl限制读取的物品和反馈数量。如果物品的时间戳距今超过item_ttl天,那么Gorse不再读取此物品数据。如果反馈的时间戳距今超过 positive_feedback_ttl 天,那么Gorse同样不再读取此反馈。使用TTL的优缺点如下:

  • **优点:**移除过时的物品和反馈可以减少Gorse需要处理的数据量。太过时的物品例如新闻是没有推荐价值的,同样太久远的用户历史记录并不能反应当前的用户兴趣,适当地移除过时的物品和反馈对推荐系统是有益的。
  • **缺点:**如果TTL设置果断,会导致推荐算法训练中获取的信息量不足。

TTL用于移除过时的物品和反馈,但是应该设置得足够长防止丢失信息。

# The time-to-live (days) of positive feedback, 0 means disabled. The default value is 0.
positive_feedback_ttl = 0

# The time-to-live (days) of items, 0 means disabled. The default value is 0.
item_ttl = 0

设置训练和推荐频率

在Gorse推荐系统之中一共有三个循环执行的任务,分别是:

  • 模型训练循环:主节点加载数据,使用最新数据训练推荐模型,以及更新最新物品、热门物品、相似物品、相似用户等内容,模型训练循环的间隔对应配置文件中的fit_period
  • 模型优化循环:主节点加载数据,使用随机搜索查找推荐模型的最佳参数。循环间隔通过search_period设置,模型优化循环间隔的值可以设置得比较长。除非数据集发生巨大变化,否则最佳模型参数都是比较稳定的。
  • 推荐生成循环:工作节点检查每个用户是否应当更新推荐结果,检查的时间间隔为check_recommend_period分钟,如果需要更新测按照推荐策略生成推荐。用户更新推荐的条件是:用户的最后活跃时间超过最后生成推荐时间,或者最后生成推荐时间距今超过refresh_recommend_period天。检查推荐结果的间隔check_recommend_period应该设置得比较短,建议在几分钟左右,从而能够应对用户的推荐结果消耗。

循环间隔时间太长会导致模型和推荐结果过时,循环间隔时间太短会导致数据库和缓存负载过高。总之,check_recommend_period 应当较小,search_period 应当较大,fit_period 需要根据数据库负载进行合理设置。

# The time period for model fitting (minutes). The default values is 60.
fit_period = 360

# The time period for model searching (minutes). The default values is 100.
search_period = 60

# The number of epochs for model searching. The default values is 100.
search_epoch = 100

# The number of trials for model searching. The default values is 10.
search_trials = 10

# The time period to check recommendation for users (minutes). The default values is 1.
check_recommend_period = 1

# The time period to refresh recommendation for inactive users (days). The default values is 5.
refresh_recommend_period = 1

check_recommend_period是尚未发布的v0.3.4新增配置项,目前可以在nightly版本中使用,

开启相似物品和用户向量索引

Gorse会为每个用户和物品查询相似物品,用于相似物品推荐和基于相似用户的推荐。假设有N个物品,那么查询一件物品的相似物品的计算量就是O(N),为全部物品生成相似物品的计算量就是O(N^2)。Gorse提供了基于聚类的向量索引加速相似物品和用户的查询。相似物品(用户)向量索引首先对物品(用户)按照相似度进行聚类,也就是将最相似的物品(用户)分到多个组内。在查询相似物品(用户)的时候,首先找到中心点和当前物品(用户)最相似的K个组,然后再在K个组内查询相似物品(用户),算法基于思想源自于 [1]。

相似物品(用户)向量索引可以通过enable_item_neighbor_indexenable_user_neighbor_index)进行开关,目前版本默认关闭,后续版本考虑默认打开。相似物品(用户)向量索引需要设置参数K,也就是查询的组数,K太小会导致向量索引无法到达可用的精度,K太大则会降低查询性能。构建过程会尝试不断增大K,如果查询准确率到达item_neighbor_index_recalluser_neighbor_index_recall),或者增长次数到达item_neighbor_index_fit_epochuser_neighbor_index_fit_epoch),那么构建过程停止增长K。

# Enable approximate item neighbor searching using vector index.
enable_item_neighbor_index = true

# Minimal recall for approximate item neighbor searching.
item_neighbor_index_recall = 0.8

# Maximal number of fit epochs for approximate item neighbor searching vector index.
item_neighbor_index_fit_epoch = 3

# Enable approximate user neighbor searching using vector index.
enable_user_neighbor_index = true

# Minimal recall for approximate user neighbor searching.
user_neighbor_index_recall = 0.8

# Maximal number of fit epochs for approximate user neighbor searching vector index.
user_neighbor_index_fit_epoch = 3

使用相似物品/用户向量索引的优缺点如下:

  • 优点:节省相似物品/用户查询时间。
  • 缺点:索引需要额外的内存,如果数据难以分组(例如随机生成数据),那么索引查询准确率会很低。

相似用户和相似物品的向量查询精度在控制台主面板系统信息中的“User Neighbor Index Recall”和“Item Neighbor Index Recall”可以看到,如果数值过低的话需要关闭相似物品/用户向量索引。

image.png

开启协同过滤向量索引

Gorse的协同过滤算法将用户和物品映射为一组向量,对于每个用户,找到和用户向量点乘最大的物品向量即为推荐物品。因此,最直观的推荐物品搜索方法就是扫描全部物品,在扫描过程中求向量点乘,选择点乘最大的前几样物品作为推荐结果。假设有N个用户和M个物品,那么为全体用户生成推荐结果的计算量就是O(MN)。然而,如果物品和用户数据都比较大,那么整体计算量是令人无法接受的。

一种更加高效的方法是使用向量索引HNSW [2]。首先,HNSW索引会为所有的物品向量创建一张导航图。然后,只需要在导航图中查询用户向量点乘最大的物品向量,而不需要遍历全部的物品。HNSW索引上查询得到的结果不是精确的,但是极少的精度损失换取巨大的性能提升是值得的。HNSW向量索引可以通过enable_collaborative_index进行开关,目前版本默认关闭,后续版本考虑默认打开。HNSW向量索引需要设置一个参数ef_construction,ef_construction太小会导致向量索引无法到达可用的精度,ef_construction太大则会降低查询性能。构建过程会尝试不断增大ef_construction,如果查询准确率到达collaborative_index_recall,或者增长次数到达collaborative_index_fit_epoch,那么构建过程停止增长ef_construction。

# Enable approximate collaborative filtering recommend using vector index.
enable_collaborative_index = false

# Minimal recall for approximate collaborative filtering recommend.
collaborative_index_recall = 0.9

# Maximal number of fit epochs for approximate collaborative filtering recommend vector index.
collaborative_index_fit_epoch = 3

使用向量索引进行协同过滤推荐的优缺点如下:

  • 优点:向量索引可以显著提高协同过滤推荐速度,并且准确率在大部分情况下都不错。
  • 缺点:创建HNSW索引需要额外的内存空间,在极少情况下会产生比较低的准确率。

协同过滤的向量查询准确率对应控制台主面板系统信息中的“Matching Index Recall”,如果数值比较低那么可以考虑关闭索引查询改用简单遍历。

image.png

参考文献

  1. Auvolat, Alex, et al. "Clustering is efficient for approximate maximum inner product search." arXiv preprint arXiv:1507.05910 (2015).
  2. Malkov, Yu A., and Dmitry A. Yashunin. "Efficient and robust approximate nearest neighbor search using hierarchical navigable small world graphs." IEEE transactions on pattern analysis and machine intelligence 42.4 (2018): 824-836.