[推荐系统]利用用户行为数据
通过用户行为分析的推荐算法是个性化推荐系统的重要组成部分 ,通常我们将其归类为协同过滤方法。协同过滤就是指用户通过共同协作与网站平台进行持续互动的过程 ,这一过程会逐步剔除那些不符合个人兴趣的项目,并最终帮助用户形成越来越贴合自身需求的个性化推荐列表。
用户行为数据简介
用户行为数据在其网站上的最基本形式即为日志记录。当一个网站运行时会产生海量原始日志记录(raw logs),这些数据被系统自动存储于文件存储架构中。在线业务通常会将不同类型的原始日志按照用户的活动轨迹整合生成 getSession logs(session logs),每个 getSession log记录了一次完整的用户体验流程及其相关服务。这些 getSession logs一般会被存储在一个分布式的数据仓库架构中。例如,在线分析平台如Google Dremel提供实时查询能力(online analytical processing, OLAP),而离线分析框架如Hadoop Hive则更适合用于批量处理场景。
用户行为模式在个性化推荐系统中主要分为显性反馈模式(explicit feedback)和隐性反馈模式(implicit feedback):
- 显性反馈行为: 即指那些用户的明确表示对物品喜好的具体表现形式 。不同网站收集显性反馈的行为主要途径有评分系统以及"喜欢"与"不喜欢"等互动机制 。
- 隐性反馈行为: 指的就是那些无法直接反映用户喜好但能间接体现其偏好信息的行为模式 。最典型的隐性反馈现象即为网页浏览记录 。例如 ,当一个产品出现在用户的首页导航中时 ,即使该产品并未被直接点击 ,也容易获得更多的曝光机会 ,从而被视为潜在感兴趣的产品 。相比之下 ,与显式偏好表达相比 ,隐式偏好信号虽然不够直观 ,但却能够积累大量数据供分析研究使用 。
显性反馈数据和隐性反馈数据的比较.
| 显性反馈数据 | 隐性反馈行为 | |
|---|---|---|
| 用户兴趣 | 明确 | 不明确 |
| 数量 | 较少 | 庞大 |
| 存储 | 数据库 | 分布式文件系统 |
| 实时读取 | 实时 | 有延迟 |
| 正负反馈 | 都有 | 只有正反馈 |
依据正向和反向等方向对信息进行分类,在明确的信息提示下容易识别用户的喜好或偏好;而在非明确提示的情况下,则难以判断用户的偏好方向
通常情况下,在各个领域中所涉及的数据集都包含了各自独特的行为特征。当前广泛认可的数据集主要包括以下几个:
- 无上下文信息的隐性反馈数据集:每条行为日志仅记录了用户ID与商品ID的信息。
- 无上下文信息的显性反馈数据集:每条记录包含了用户的商品评价信息及评分。
- 有上下文信息的隐性反馈数据集:每条记录提供了用户的互动行为时间点。
- 有上下文信息的显性反馈数据集:每条记录包含了用户的商品互动时间和相关评分信息。
用户行为分析
在设计推荐算法时,在利用用户的行为主据进行分析之前(相当于ML中的数据分析阶段),研究人员首先要对用户的行为主据进行分析,并以识别其中存在的普遍规律为基础(类似于机器学习中的数据分析),从而为算法的设计提供指导作用。
用户活跃度和物品流行度的分布
[物品的流行度指对物品产生过行为的用户总数]
大量互联网数据的研究表明,在这一领域中也被称为长尾分布的数据模式均遵循被称为Power Law的分布模式
f(x) = \alpha x^k
已有大量研究者发现指出,
用户的某些行为特征往往呈现出长尾特征。
这些指标如物品流行度与用户的活跃度均呈现相似的分布模式。
用户活跃度和物品流行度的关系
专指仅根据用户行为数据构建的知识型推荐系统通常被定义为协同过滤系统。这种系统主要包含三种基本类型:基于邻域的方法(neighborhood-based)、隐语义模型(latent factor model)以及基于图论的随机游走模型(random walk on graph)。其中最为著名且应用最为广泛的推荐算法体系是基于邻域的方法体系;而这一类体系又可分为以下两种基本类型:
- 基于用户的协同过滤算法: 为用户提供推荐 与他兴趣相投的其他用户的喜好相关的产品或服务;
- 基于物品的协同过滤算法: 为用户提供推荐 与他以往 liked items 相似的商品或服务。
基于邻域的算法
根据邻域划分的算法分为两大类:其一是基于用户的数据进行协同过滤的方法;其二是根据物品特征进行协同过滤的技术
基于用户的协同过滤算法
基于用户的协同过滤算法是推荐系统中最古老的算法。
1.基础算法
基于用户的协同过滤算法主要包括两个步骤:
- 识别出与目标用户兴趣相投的用户群体;
- 将被识别出在该群体中偏好的物品中尚未被目标用户接触过的项目推荐给目标用户。
步骤一的核心在于涉及两个用户的偏好相似程度。协同过滤算法主要基于行为数据特征间的相似性来分析兴趣间的关联性。给定用户u和用户v,请定义为:其中N(u)代表用户u曾对产品和服务给予正面评价的商品集合;同样地,N(v)则代表了用户v所收藏的服务相关内容商品集合。通过采用Jaccard公式进行详细计算的方法来评估两者之间的偏好重叠程度

余弦相似度计算:

2.基于相似度计算的改进
传统的相似度计算方法中存在明显的不足之处。当两个用户均对冷门项目采取相同的行为时,则能更好地体现他们的兴趣相关性。 Breese在其论文中提出了以下公式(见下文),该公式基于用户的活动来评估其兴趣相关性:

其中N(i)代表物品i的流行度。该公式受到了对用户u和v共同兴趣列表中热门物品相似性计算的影响
基于用户的协同过滤算法存在以下两个主要缺陷:首先,在网站规模不断扩大时(当网站上的用户数量不断增加),计算用户兴趣相似度矩阵变得越来越困难(变得越来越困难),并且其运算时间复杂度与空间复杂度呈现出与用户数量平方的关系(呈现与用户数量平方的关系);其次,在解释推荐结果方面(在解释推荐结果方面),基于用户的协同过滤算法存在明显不足(存在明显不足)。
基于物品的系统过滤算法
以物品为基础的协同过滤是一种在业界广泛采用的方法
1.基础算法
基于内容的协同过滤算法(简称ItemCF)向用户提供与他们之前喜欢的商品具有高度相关性的商品集合。ItemCF算法不依赖于内容属性来计算各商品间的相似程度;相反地,在分析用户的购买记录时更能反映两商品间的关联。 其基本观点是由于这一特性就能推断出这两项商品之间存在显著的相关性
基于物品的协同过滤算法主要分为两步:
- 评估不同物品之间的相似性程度;
- 基于物品间的相似程度及用户的浏览历史信息为用户提供推荐列表。
购买了该商品的用户也会反复购买其他商品,在基于这一定义的基础上,请根据这一定义阐述物品相似度的具体计算公式

在其中,分母|N(i)|代表了喜欢物品i的用户数量,而分子则是表示同事群体中同时喜欢物品i和j的数量.然而,这一公式存在一个主要的问题:当物品j非常受欢迎时,会有大量用户对其感兴趣.这样一来,所有任务相关的物品都会与这一热门商品产生较高的相似度.为了避免推荐出现偏向热门商品的情况,我们建议采用如下的改进公式.

这个公式赋予了物品j的权重以惩罚作用,并从而减弱了热门物品与其他物品相似的可能性。
根据上述定义可知,在协同过滤机制中,两个物品产生相似度的原因在于它们共同吸引了大量用户的兴趣。换句话说,在协同过滤过程中,默认情况下每个用户都可以基于个人的历史兴趣偏好为物品提供相应的评价或偏好信息。
在ItemCF算法中计算物品相似度时,在构建完用户的评分数据后会生成一个基于用户的邻近关系矩阵;随后,在处理每个用户的评分记录时,在其评分项的基础上进行相应的相似性计算以得到最终的推荐结果
def ItemSimilarity(train):#train是用户-物品倒排表
C = dict()#物品i,j共现矩阵,用字典表示;
N = dict()#物品i的流行度--喜欢物品i的用户数目
for user, items in train.items():
for i in items:
N[i] += 1
for j in items:
if i != j:
C[i][j] = C[i].get(j, 0) + 1
W = dict()#物品相似度矩阵 字典
for i, related_items in C.items():
for j, cij in related_items.items():
W[i][j] = cij / math.sqrt(N[i]*N[j])
return W
基于不同物品间的相似程度计算,在获得了各项商品的属性数据之后,ItemCF模型会采用以下数学模型来计算用户u对商品j的兴趣。

这里N(u)表示用户偏好的商品集合,在隐式反馈模型中,默认情况下若某条记录被点击或收藏,则认为其兴趣值为1;S(j,K)代表与商品j最为接近的前K个商品集合;w_{ji}衡量了商品j与i之间的相似程度;r_{ui}表示用户u对商品i的关注程度。(对于隐反馈数据集,在默认情况下若某条记录被点击或收藏,则认为其兴趣值为1.)这一公式的核心思想在于:通过计算与用户的兴趣相关联的商品(即属于N(u)的部分),能够预测并推荐那些可能获得较高评分或更高位置的商品。
def Recommendation(train, user_id, W, K):
rank = dict()
ru = train[user_id]#用户喜欢物品字典,物品:rui(用户u对物品i的兴趣,默认为1)
for i, rui in ru.items():
# 选择物品i的相似度矩阵,并由大到小排序;然后选择前K个物品
si = sorted(W[i].items(),key=lambda a:a[1],reverse=True)
for j, wij in si[:K]:
if j in ru:#排除已经喜欢的物品
continue
rank[j] += wij * rui
return rank
从功能角度来看,ItemCF算法的一个显著优点在于其能够实现精准化的个性化推荐机制。针对那些要求了解推荐依据的用户群体而言,在实际应用场景中常被采用的技术方案包括:
def Recommendation(train, user_id, W, K):
rank = dict()
reason = dict()
ru = train[user_id]
for i, rui in ru.items():
si = sorted(W[i].items(),key=lambda a:a[1], reverse=True)
for j, wij in si[:K]:
if j not in ru:
rank[j] += wij * rui
reason[j][i] = wij * rui
return rank, reason
对不同 K 值的测量可以看到:
- 准确率与召回率与 K 之间并非呈现线性关系;选择一个合适的 K 值对于实现最佳精度至关重要;
- k 和流行度并非呈完全正相关:随着 k 值的增大而逐渐提升,在达到一定数值后不再有显著变化;
- 增大 K 值会导致系统覆盖范围缩小。
2.用户活跃度对物品相似度的影响
在协同过滤机制中,两个物品之间的相似度主要源于它们被广泛地包含在多个用户的兴趣集合中。换言之,在计算物品间的相似性时,每个用户的兴趣集合都会为其相关性提供基础。然而需要注意的是,在这种计算过程中,默认假设所有用户对相似性的贡献是均等的。
John S. Breese 在论文中阐述了一个名为 IUF(Inverse User Frequency)的参数。他主张活跃用户的物品相似性贡献值应低于非活跃者,并建议通过增加 IUF 参数来修正物品相似性计算公式。

首先,在分析协同过滤推荐系统时会遇到一些关键指标:i号和j号商品的热度;u表示同时被顾客购买的商品对(商品i与商品j),而|N(u)|则用于衡量顾客u的行为活跃程度(用来表示顾客u的活跃程度)。前面所述公式仅对活跃顾客施加了一种柔和的影响。然而,在实际应用中发现:对于那些过于活跃的顾客而言,在计算相似性矩阵时为了避免其带来的稠密效应问题[用来表示避免过热效应]...因此,在实际运算过程中通常会将这些过于活跃的顾客予以排除在相似性计算的数据集之外。而ItemCF-IUF算法正是基于这种思路构建起来的一种改进型协同过滤方法。
def ItemSimilarity(train):
C = dict()#分子
N = dict()#物品i的流行度
for u, items in train.items():
for i in items:
N[i] += 1
for j in items:
if i != j:
C[i][j] += 1 / math.log(1 + len(items)*1.0)
W = dict()#相似度矩阵
for i, related_items in C.items():
for j, cij in related_items.items():
W[i][j] = cij / math.sqrt(N[i] * N[j])
return W
3.物品相似度的归一化
通过研究发现,在研究汇中发现将ItemCF的相似度矩阵按最大值归一化能够显著提升推荐精度。研究表明,在获得了物品相似度矩阵w之后可以通过以下公式计算得到归一化的相似度矩阵w’:

对每行数据实施归一化处理。其优势不仅体现在提升推荐精确度方面,同时也能够增强覆盖范围与多样化的水平。
UserCF和ItemCF的综合比较
UserCF的推荐方式着重关注与用户兴趣高度相关的小众群体内的最新趋势性商品选择,并且ItemCF则侧重于维护用户的长期兴趣偏好。简而言之,在这种算法设计上存在显著差异:前者(UserCF)更加倾向于社会化的传播方式,并反映出该物品在用户小群体中的流行程度;而后者(ItemCF)则更能体现用户的个人化偏好传承。
就技术层面而言,在推荐系统中采用UserCF方法时会基于用户的相似性矩阵构建模型,在实现个性化推荐功能的同时也会占用较大的存储空间;而采用ItemCF方法时则会基于物品的相似性矩阵构建模型,并相应地, 当物品数量多时, 维护基于物品的相似性矩阵也会带来较高的存储成本。
UserCF和ItemCF优缺点对比.
| UserCF | ItemCF | |
|---|---|---|
| 性能 | 适用于用户较少的场合,如果用户很多,计算用户相似度矩阵代价很大 | 适用于物品数明显小鱼用户数的场合,如果物品很多(网页),计算物品相似度矩阵代价很大 |
| 领域 | 时效性强,用户个性化兴趣不太明显的领域 | 长尾物品丰富,用户个性化需求强烈的领域 |
| 实时性 | 用户有新行为,不一定造成推荐结果的立即变化 | 用户有新行为,一定会导致推荐结果的实时变化 |
| 冷启动 | 在新用户对很少的物品产生行为的情况下,不能立即对他进行个性化推荐,因为用户性相似度表是每隔一段时间离线计算的 新物品上线后一段时间,一旦有用户对物品产生行为,就可以将新物品推荐给和对它产生行为的用户兴趣相似的其他用户 | 新用户只要对一个物品产生行为,就可以给他推荐和该物品相关的其他物品 但没有办法在不离线更新物品相似度表的情况下将新物品推荐给用户 |
| 推荐利用 | 很难提供令用户信服的推荐解释 | 利用用户的历史行为给用户做推荐解释,可以令用户比较信服 |
离线实验的表现将起到关键作用,在选择推荐算法时。 在实施过程中首先要确保产品的基本功能得到实现,并且还需要考虑实现成本。
隐语义模型
LFM(latent factor model)是一种隐语义方法,在信息检索和推荐系统中最初应用于文本挖掘领域,并逐步扩展到其他数据处理场景中。其主要用途是发现文本中的潜在语义关联,并通过数学建模的方式提取这些关联性信息。其中涉及的关键术语包括线性代数降维(LSI)、概率潜在语义索引(pLSI)、非参数贝叶斯主题模型(LDA)以及主题模型(topic model)。
- 基础算法
隐语义模型的基本概念是通过潜在因子将用户兴趣与商品联系起来。具体来说就是根据商品的特性进行分类,在这种模型中,默认会对用户的兴趣进行细分。换句话说,在这种模型中,默认会对用户的兴趣进行细分。接着,在这些类别中挑选出他可能感兴趣的物品。基于这一方法的大致思路是解决三个关键问题:
- 对物品进行分类的方式是什么?
- 如何评估不同类别的物品是否符合用户的兴趣及其强度?
- 在指定类别下,如何挑选该类别相关的商品并推荐给用户?同时,请说明这些商品在该类别中的重要性评分方法。
在对物品进行分类的问题中,隐含语义分析技术能够较为有效地运用。这种技术主要依赖于用户的行为主数据分析来进行分类,并与人工标签比较
- 基于用户行为数据分析的结果能够涵盖各种用户的观点;
- 通过设定类别数量来调节分类粒度,在类别数目增加时会提高粒度;
- 隐语义模型能够将一个物品分配到多个类别中,并非强制将其归入单一类别;这使得每个物品在各个类别中的重要性得以体现;
- 该系统包含多维属性信息,并且这些信息既可以独立存在(多维度)也可以相互关联(同维度);
- 系统能够根据用户的浏览和互动数据动态调整各个类别中的权重分布情况
这些都是专家标记不能或者很难做到的。
LFM通过如下公式计算用户u对物品i的兴趣:

在公式中,puk和qik分别代表模型的两个参数,在这里分别表示不同的关系强度。具体来说,在公式中定义为:puk衡量了用户u的兴趣与其所在隐类之间的关系强度;而qik则衡量了该隐类与物品i的相关性程度。这些参数的设计初衷是为了更好地捕捉用户的兴趣偏好与潜在类别之间的联系。
推荐系统的用户行为可分为显式反馈与隐式反馈两种类型。基于LFM模型,在显式反馈数据(即评分数据)上可有效解决评分预测问题,并展现出较高的预测精度。若采用隐式数据集,则该类数据集仅包含正样本实例(表示用户感兴趣的商品或内容),而不包含反向实例(表示用户不感兴趣的商品或内容)。
在隐性反馈数据集中采用LFM来应对TopN推荐中的首要核心问题,并从每个用户的视角生成相应的负面样本
对负样本采样时应该遵循以下原则:
- 为每位用户提供正负样本数量均衡的数据;
- 在为每位用户采样负样本时,请选择高关注度但无交互记录的物品。
普遍认为,在非常热门但用户却缺乏明确的行为表现时,则更能表明该用户对这一物品并不感兴趣。这是因为对于那些冷门的物品而言,在线平台上的用户体验可能会较差,并且可能导致用户体验下降的原因多种多样
需要优化的损失函数如下:

其中,在防止过拟合方面设置了两个正则化项;lambda值可以通过实验确定;使用梯度下降方法对损失函数进行优化求解得到了两个参数
在LFM中,重要的参数有4个:
- 隐变量的数量F;
- 学习率系数alpha;
- 正则化系数lambda;
- 负样本与正样本的比例ratio。
通过实验发现,radio对LFM的性能影响最大。
2.LFM和基于邻域的方法的比较
LFM是一种以机器学习为理论支撑的技巧,在理论体系上具有显著优势与不足。相较于基于邻域的方法而言,则各自存在一定的优缺点
- 理论基础 LFM基于其坚实的理论基础,在信息处理领域作为一种有效的学习机制存在。它通过优化预设的目标函数来构建最优模型,在对比分析中展现出显著的优势特点。
- 离线计算的空间复杂度 在离线计算过程中占据一定空间资源需求的是相关表的建立这一关键环节。
基于图的模型
用户的活动相对简单地可以用二分图的形式来描述,并且由此许多图论算法都可以被应用于推荐系统中
1.用户行为数据的二分图表示
在研究基于图的知识体系之前,在此之前首先要将用户的的行为数据以图形形式呈现出来。在这里我们探讨的知识体系中用户的的行为数据由一系列有序对构成,在这种情况下我们通常会使用一种二分图来直观地展示这些关系
其中每个有序对(u,i)代表用户u在其物品i上拥有过互动这一状态

2.基于图的推荐算法
基于二分图模型实现个性化推荐算法。将个性化推荐算法嵌入到二分图模型中,则该任务可转化为计算用户顶点vu与其未直接相连的物品节点在其图上的相关性;其相关性越高,则被赋予更高的权重。
多种多样的方法用于度量图中两个顶点之间的相关性;然而,在一般情况下,图中顶点的相关性主要受以下三个因素的影响。
- 在图中任意两点间的路径数量;
- 两节点间连接的边的数量;
- 两节点间的连接路线所涉及的所有中间节点。
相关性高的一堆顶点一般具有如下特征:
- 存在较多的连接途径将这两个顶点相互连通;
- 不管选择哪条连接这两个顶点的路径都不会太长;
- 这些连接不会穿过任何高处生子(high out-degree)的中间节点。
根据这三大关键要素为基础原则,在研究图内节点间相互关联性问题时衍生出了众多相关分析方法。其中一种典型的例子是基于随机游走策略实现的PageRank算法
为了实现对用户u的个性化推荐,在用户物品二分图中可以从节点vu出发开始进行随机游走。当访问到任何一个节点时,请根据概率alpha决定是否继续进行下一步的随机游走或结束当前路径并重新从vu节点开始遍历。如果选择继续移动,则可以在当前节点连接的所有相邻节点中等概率地选择下一个访问的目标节点。经过大量次这样的随机移动操作后,在整个系统中每个物品被访问到的可能性会逐渐趋于稳定状态,并最终收敛于一个确定的概率值。在实际应用中,默认情况下系统会计算出每个物品对应的访问频率作为其重要性评分,并将这些评分结果按照一定的排序规则生成最终的推荐列表
表示公式如:

alpha游走概率,1-alpha停留概率;
代码实现:
def PersonalRank(G, alpha, root, max_step):
rank = dict()#推荐结果
rank = {x : 0 for x in G.keys()}
rank[root] = 1
for k in range(max_step):
tmp = {x : 0 for x in G.keys()}
#取节点i和它的出边尾节点集合ri
for i, ri in G.items():
#取i->j边的尾节点j以及边E(i,j)的权重wij, 边的权重都为1,
for j, wij in ri.items():
if j not in tmp:
tmp[j] = 0
tmp[j] += alpha * rank[i] / (1.0 * len(ri))
if j == root:
tmp[j] += 1 - alpha
rank = tmp
return rank
然而PersonalRank算法虽然具有良好的理论基础,在实际应用中却面临显著的时间效率问题。具体而言,在向每个用户推荐内容时,该算法需要在整个用户的物品二分图中反复计算每个顶点的PersonalRank值,并等待直到所有顶点的PR值达到稳定状态才能完成计算工作。这样的计算流程所消耗的时间资源非常庞大,在实际应用中不仅无法实现即时推荐功能,在离线处理阶段同样面临着巨大的时间和资源消耗问题。
为了解决PersonalRank在每次迭代时都需要遍历整个图而导致计算效率较低的问题, 提出两种优化方案. 首先, 通过提前终止迭代, 在收敛前退出算法流程, 这样可以减少不必要的计算步骤, 从而降低运行时间. 然而, 这种优化可能会导致最终结果的小幅波动, 但通常这种影响程度较小; 另一种方法则是基于矩阵理论对算法进行重构, 寻找更高效的解决方案.
