传统ItemCF的局限性

热门物品偏差:热门物品容易频繁共现,导致相似度虚高,比如书店里《哈利波特》和《新华字典》被大量客户购买,但二者并无实际关联

稀疏性问题:用户-物品交互数据稀疏时,传统相似度(如余弦)虽然可以用,但是计算不稳定。

Swing 的改进思路

如果两个物品被同一批用户交互过,则它们可能相似

进一步考虑共现用户的重叠程度,避免热门物品的干扰。

相似度计算公式为

$$
\text{Sim}(i, j) = \sum_{u \in U_i \cap U_j} \sum_{v \in U_i \cap U_j} \frac{1}{\alpha + |I_u \cap I_v|}
$$

其中:

  • $U_i$:交互过物品 $i$ 的用户集合
  • $I_u$:用户 $u$ 交互过的物品集合
  • $\alpha$:平滑参数(通常取1,防止分母为 0)

这么计算的原因是如果两个用户u和v都交互了物品i和j,且它们共同交互的其他物品很少(即$|I_u \cap I_v|$小),则i和j的相似度更高

这样可以降低热门物品的权重,因为热门物品通常会被很多用户共同交互。

Swing的算法流程

步骤1:构建用户-物品共现图

  • 对于每个物品i,记录交互过它的用户集合$U_i$
  • 对于每对物品(i,j),找到共同交互的用户$U_i \cap U_j$

步骤2:计算物品相似度

  • 对于每对共现用户(u,v),计算他们共同交互物品数$|I_u \cap I_v|$
  • 使用Swing公式计算相似度

步骤3:归一化

对相似度矩阵进行归一化(如最大值归一化)。

为什么要归一化?

直接计算的相似度可能数值范围差异很大(例如某些物品对的相似度为 100,另一些为 0.1),导致推荐结果偏向少数高分物品。将相似度缩放到统一范围(如 [0, 1]),避免数值量纲影响推荐排序。

步骤4:生成推荐

找出候选物品:遍历用户历史物品$I_u$,找到每个物品Top-K个相似物品,合并去重后得到候选池C

例如:

  • $A$ 的相似物品:${B, D, E}$(相似度分别为 $0.8,\ 0.6,\ 0.5$)
  • $B$ 的相似物品:${A, C, F}$(相似度分别为 $0.8,\ 0.7,\ 0.4$)
步骤 说明
用户历史交互 $I_u = {A, B}$(用户已与 A、B 交互)
A 的相似物品 ${B, D, E} \rightarrow$ 剔除 ${A, B}$ 后保留 ${D, E}$
B 的相似物品 ${A, C, F} \rightarrow$ 剔除 ${A, B}$ 后保留 ${C, F}$
合并候选选池 $C = {C, D, E, F}$(已去重)

计算推荐分数:对候选池中的每个物品j∈C,计算其与用户历史物品的加权相似度

$$
\text{Score}(j) = \sum_{i \in I_u} \text{Sim}_{\text{norm}}(i, j)
$$

基于用户历史物品$I_u = {A, B}$,计算物品D的分数:

$$
\text{Score}(D) = \text{Sim}(A, D) + \text{Sim}(B, D) = 0.6 + 0 = 0.6
$$

排序并生成推荐:按$\text{Score}(j)$降序排列候选物品,取Top-N作为推荐结果

候选物品 分数
$C$ 0.7
$D$ 0.6
$E$ 0.5
$F$ 0.4

Top-3 推荐结果:$[C, D, E]$

时间复杂度分析

Swing 算法的时间复杂度是多少?如何优化其在大规模数据下的性能?

时间复杂度:$O(n^2m^2)$($n$ 为物品数,$m$ 为平均用户交互数),最坏情况下需遍历所有物品对和用户对。

优化方法

  • 剪枝:仅计算共现用户数超过阈值的物品对。
  • 分片:按物品类别分片并行计算。
  • 近似:使用局部敏感哈希(LSH)快速查找相似用户对。