推荐系统(3)——最经典的推荐算法(协同过滤算法原理部分)

本文深入探讨了协同过滤推荐算法,包括基于用户和物品的两种类型。算法假设用户喜好相似的人或物品会有共同的兴趣。相似度计算涉及欧氏距离、杰卡德相似度、余弦相似度和皮尔逊相关系数。针对实数值评分和布尔反馈数据,介绍了不同的相似度计算方法,并通过案例解释了如何计算用户和物品的相似度,以及如何生成推荐列表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 最经典的推荐算法:协同过滤推荐算法(Collaborative Filtering)

算法思想:物以类聚,人以群分

基本的协同过滤推荐算法基于以下假设:

  • “跟你喜好相似的人喜欢的东西你也很有可能喜欢” :基于用户的协同过滤推荐(User-based CF)

  • “跟你喜欢的东西相似的东西你也很有可能喜欢 ”:基于物品的协同过滤推荐(Item-based CF)

 

实现协同过滤推荐有以下几个步骤:

  1. 找出最相似的人或物品:TOP-N相似的人或物品

    通过计算两两的相似度来进行排序,即可找出TOP-N相似的人或物品

  2. 根据相似的人或物品产生推荐结果

    利用TOP-N结果生成初始推荐结果,然后过滤掉用户已经有过记录的物品或明确表示不感兴趣的物品

关于相似度计算这里先用一个简单的思想:如有两个同学X和Y,X同学爱好[足球、篮球、乒乓球],Y同学爱好[网球、足球、篮球、羽毛球],可见他们的共同爱好有2个,那么他们的相似度可以用:2/3 * 2/4 = 1/3 ≈ 0.33 来表示。

二 相似度计算(Similarity Calculation)

相似度的计算方法

  • 数据分类

    • 实数值(物品评分情况)

    • 布尔值(用户的行为 是否点击 是否收藏)

  • 欧氏距离, 是一个欧式空间下度量距离的方法. 两个物体, 都在同一个空间下表示为两个点, 假如叫做p,q, 分别都是n个坐标, 那么欧式距离就是衡量这两个点之间的距离. 欧氏距离不适用于布尔向量之间

欧氏距离的值是一个非负数, 最大值正无穷, 通常计算相似度的结果希望是[-1,1]或[0,1]之间,一般可以使用如下转化公式:

 

 

  • 杰卡德相似度&余弦相似度&皮尔逊相关系数

    • 余弦相似度

      • 度量的是两个向量之间的夹角, 用夹角的余弦值来度量相似的情况

      • 两个向量的夹角为0是,余弦值为1, 当夹角为90度是余弦值为0,为180度是余弦值为-1

      • 余弦相似度在度量文本相似度, 用户相似度 物品相似度的时候较为常用

      • 余弦相似度的特点, 与向量长度无关,余弦相似度计算要对向量长度归一化, 两个向量只要方向一致,无论程度强弱, 都可以视为'相似'

    • 皮尔逊相关系数Pearson

      • 实际上也是一种余弦相似度, 不过先对向量做了中心化, 向量a b 各自减去向量的均值后, 再计算余弦相似度

      • 皮尔逊相似度计算结果在-1,1之间 -1表示负相关, 1表示正相关

      • 度量两个变量是不是同增同减

      • 皮尔逊相关系数度量的是两个变量的变化趋势是否一致, 不适合计算布尔值向量之间的相关度

    • 杰卡德相似度 Jaccard

      • 两个集合的交集元素个数在并集中所占的比例, 非常适用于布尔向量表示

      • 分子是两个布尔向量做点积计算, 得到的就是交集元素的个数

      • 分母是两个布尔向量做或运算, 再求元素和

    • 余弦相似度适合用户评分数据(实数值), 杰卡德相似度适用于隐式反馈数据(0,1布尔值)(是否收藏,是否点击,是否加购物车)

  • 余弦相似度

 

  • 皮尔逊相关系数

 

  • 计算出用户1和其它用户之间的相似度

 

  • 按照相似度大小排序, K近邻 如K取4:

  • 取出近邻用户的购物清单

  

  • 去除用户1已经购买过的商品

  • 在剩余的物品中根据评分排序

 

  • 物品相似度计算

    • 余弦相似度对绝对值大小不敏感带来的问题

      • 用户A对两部电影评分分别是1分和2分, 用户B对同样这两部电影进行评分是4分,5分 用余弦相似度计算,两个用户的相似度达到0.98

      • 可以采用改进的余弦相似度, 先计算向量每个维度上的均值, 然后每个向量在各个维度上都减去均值后,在计算余弦相似度, 用调整的余弦相似度计算得到的相似度是-0.1

  • 物品相似度计算案例  

  • 找出物品1的相似商品

  • 选择最近似的物品

  • 基于用户与物品的协同过滤比较

 

<think>首先,用户的问题是:“我想理解协同过滤算法推荐系统中的实现,特别是使用Java语言的实现或示例请问协同过滤算法推荐系统Java实现示例解析”。我需要根据系统指令来回答。系统指令的关键点:-所有行内数学表达式使用$...$格式。-独立公式使用$$...$$格式并单独成段。-LaTeX语法正确。-使用中文回答。-生成相关问题。-回答中引用的段落末尾自然地添引用标识,例如[^1]。-回答结构清晰,帮助用户逐步解决问题,保证真实可靠。-参考站内引用:引用[1]、[2]、[3]、[4]是关于协同过滤算法的不同应用。用户的需求是理解协同过滤算法推荐系统中的Java实现,包括示例和解析。所以,我的回答应该聚焦于此。结构化回答:1.**介绍协同过滤算法**:简要解释什么是协同过滤算法,使用中文。2.**Java实现示例**:提供一个简单的Java代码示例来展示协同过滤的实现。3.**解析代码**:逐步解释代码的工作原理。4.**生成相关问题**:在回答末尾添相关问题。5.**引用处理**:自然地引用提供的参考内容。引用[1]、[2]、[3]、[4]是关于协同过滤在不同领域的应用,如图书推荐、美食推荐、影片推荐等。我应该将这些引用融入回答中,以支持内容。引用内容摘要:-引用[1]:基于协同过滤的图书推荐系统,提到用户协同过滤和物品协同过滤。-引用[2]:协同过滤在电商等的应用,强调性能优化和与其他算法结合。-引用[3]:美食推荐系统,强调理论和实际意义。-引用[4]:基于Hadoop的影片推荐系统,使用SpringBoot和MySQL。在回答中,我可以提到这些应用场景来丰富内容。关于Java实现:我需要提供一个简单的协同过滤示例。协同过滤的核心是计算用户或物品的相似度。一个常见的实现是用户基于协同过滤(User-basedCollaborativeFiltering),使用皮尔逊相关系数或余弦相似度。示例结构:-定义用户评分矩阵。-计算用户相似度。-基于相似度预测评分。代码使用Java,确保是真实可靠的示例。数学表达式:如果有公式,如相似度计算,使用LaTeX格式。-例如,皮尔逊相关系数:$$r_{u,v}=\frac{\sum_{i=1}^{n}(r_{u,i}-\bar{r_u})(r_{v,i}-\bar{r_v})}{\sqrt{\sum_{i=1}^{n}(r_{u,i}-\bar{r_u})^2}\sqrt{\sum_{i=1}^{n}(r_{v,i}-\bar{r_v})^2}}$$在代码解析中解释。回答结构:1.引言:解释协同过滤算法。2.Java实现示例:提供代码块。3.代码解析:逐步解释。4.实际应用:引用提供的引用,讨论在推荐系统中的应用。5.相关问题:生成几个相关问题。后,添相关问题。确保回答是中文。</think>### 协同过滤算法推荐系统中的Java实现与解析 协同过滤算法是一种广泛应用于推荐系统的技术,它通过分析用户的历史行为(如评分、点击等)来预测用户对未接触项目的喜好。核心思想是“物以类聚,人以群分”:相似用户可能喜欢相似物品(用户基于协同过滤),或相似物品可能被相似用户喜欢(物品基于协同过滤)。该算法在图书、美食、影片等推荐系统中表现优异[^1][^2]。下面,我将逐步解析协同过滤算法,并提供基于Java的简化实现示例,帮助您深入理解。 #### 1. **协同过滤算法基础** 协同过滤主要分为两种类型: - **用户基于协同过滤 (User-Based CF)**:计算用户之间的相似度,预测目标用户对某物品的评分。例如,如果用户A和用户B相似,且用户B喜欢物品X,则推荐X给用户A。 - **物品基于协同过滤 (Item-Based CF)**:计算物品之间的相似度,基于用户的历史偏好推荐相似物品。这在处理大规模数据时更高效[^2][^4]。 关键数学公式: - **相似度计算**:常用皮尔逊相关系数(Pearson Correlation)或余弦相似度(Cosine Similarity)。例如,用户$u$和用户$v$的皮尔逊相关系数定义为: $$ r_{u,v} = \frac{\sum_{i=1}^{n} (r_{u,i} - \bar{r_u}) (r_{v,i} - \bar{r_v})}{\sqrt{\sum_{i=1}^{n} (r_{u,i} - \bar{r_u})^2} \sqrt{\sum_{i=1}^{n} (r_{v,i} - \bar{r_v})^2}} $$ 其中,$r_{u,i}$ 是用户$u$对物品$i$的评分,$\bar{r_u}$ 是用户$u$的平均评分。 - **预测评分**:对于用户$u$和物品$i$,预测评分公式为: $$ \hat{r}_{u,i} = \bar{r_u} + \frac{\sum_{v \in N_u} sim(u,v) \cdot (r_{v,i} - \bar{r_v})}{\sum_{v \in N_u} |sim(u,v)|} $$ 其中,$N_u$ 是用户$u$的邻居用户(相似用户),$sim(u,v)$ 是相似度得分。 在实际应用中,协同过滤常结合其他技术(如基于内容的推荐)解决冷启动问题[^2][^3]。 #### 2. **Java实现示例** 下面是一个简化的用户基于协同过滤实现,使用余弦相似度。示例模拟一个影片推荐系统(参考引用[4]),假设用户对电影评分(1-5分)。代码使用纯Java,无外部库,便于理解。 ```java import java.util.*; public class CollaborativeFiltering { // 用户评分矩阵:用户ID -> (电影ID -> 评分) private Map<Integer, Map<Integer, Double>> userRatings; public CollaborativeFiltering() { userRatings = new HashMap<>(); // 初始化示例数据:3个用户,4部电影 Map<Integer, Double> user1 = new HashMap<>(); user1.put(1, 5.0); // 用户1对电影1评分5 user1.put(2, 3.0); user1.put(3, 4.0); userRatings.put(1, user1); Map<Integer, Double> user2 = new HashMap<>(); user2.put(1, 4.0); user2.put(2, 2.0); user2.put(4, 5.0); // 用户2对电影4评分5 userRatings.put(2, user2); Map<Integer, Double> user3 = new HashMap<>(); user3.put(2, 5.0); user3.put(3, 3.0); user3.put(4, 4.0); userRatings.put(3, user3); } // 计算余弦相似度 public double cosineSimilarity(int user1, int user2) { Map<Integer, Double> ratings1 = userRatings.get(user1); Map<Integer, Double> ratings2 = userRatings.get(user2); // 获取共同评分电影 Set<Integer> commonMovies = new HashSet<>(ratings1.keySet()); commonMovies.retainAll(ratings2.keySet()); if (commonMovies.isEmpty()) return 0.0; // 无共同物品时相似度为0 double dotProduct = 0.0; double norm1 = 0.0; double norm2 = 0.0; for (int movie : commonMovies) { double r1 = ratings1.get(movie); double r2 = ratings2.get(movie); dotProduct += r1 * r2; norm1 += Math.pow(r1, 2); norm2 += Math.pow(r2, 2); } if (norm1 == 0 || norm2 == 0) return 0.0; return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2)); // 余弦相似度公式 } // 预测用户对电影的评分 public double predictRating(int targetUser, int movie) { if (!userRatings.containsKey(targetUser)) return 0.0; // 用户不存在 double totalSimilarity = 0.0; double weightedSum = 0.0; for (int otherUser : userRatings.keySet()) { if (otherUser == targetUser) continue; // 跳过自己 Map<Integer, Double> otherRatings = userRatings.get(otherUser); if (!otherRatings.containsKey(movie)) continue; // 其他用户未评分该电影 double similarity = cosineSimilarity(targetUser, otherUser); double otherRating = otherRatings.get(movie); weightedSum += similarity * otherRating; totalSimilarity += Math.abs(similarity); } if (totalSimilarity == 0) return 0.0; // 无可预测数据 return weightedSum / totalSimilarity; // 权平均预测评分 } public static void main(String[] args) { CollaborativeFiltering cf = new CollaborativeFiltering(); int targetUser = 1; // 预测用户1对电影4的评分 int movie = 4; double predictedRating = cf.predictRating(targetUser, movie); System.out.println("预测用户" + targetUser + "对电影" + movie + "的评分: " + predictedRating); } } ``` #### 3. **代码解析** 上述Java代码实现了一个基本的用户基于协同过滤系统。逐步解析如下: - **数据结构**:使用`Map<Integer, Map<Integer, Double>>`存储用户评分矩阵,键为用户ID,值为电影ID到评分的映射。这模拟了真实推荐系统中的数据模型(如影片推荐系统[^4])。 - **相似度计算**:`cosineSimilarity`方法计算两个用户的余弦相似度。公式基于共同评分电影:$$ sim(u,v) = \frac{\sum_{i \in I_{uv}} r_{u,i} \cdot r_{v,i}}{\sqrt{\sum_{i \in I_{uv}} r_{u,i}^2} \cdot \sqrt{\sum_{i \in I_{uv}} r_{v,i}^2}} $$其中$I_{uv}$是用户$u$和$v$共同评分的电影集合。余弦相似度范围在$[-1,1]$,值越接近1表示用户越相似。 - **预测评分**:`predictRating`方法预测目标用户对指定电影的评分。它遍历其他用户,计算相似度并权平均其评分:$$ \hat{r}_{u,i} = \frac{\sum_{v \neq u} sim(u,v) \cdot r_{v,i}}{\sum_{v \neq u} |sim(u,v)|} $$这简化了公式,忽略了用户平均评分调整,以保持代码简洁。 - **示例运行**:在`main`方法中,预测用户1(评分电影1,2,3)对电影4的评分。输出可能约为3.5(取决于相似度计算),表明系统可推荐电影4给用户1。 **实际应用优化**:在真实系统中(如图书或美食推荐[^1][^3]),需考虑: - **性能优化**:使用Hadoop或Spark处理大规模数据(参考引用[4]),避免内存溢出。 - **冷启动问题**:结合基于内容的算法(如分析图书标题或电影类型)[^2]。 - **评估指标**:通过准确率、召回率等验证效果[^2]。 #### 4. **实际应用场景** 协同过滤算法推荐系统中广泛应用: - **图书推荐**:如引用[1]所述,系统通过用户协同过滤找到相似读者,推荐他们喜欢的书籍。 - **美食推荐**:如引用[3]提到,算法分析用户偏好,提供个性化餐饮建议。 - **影片推荐**:如引用[4]的Hadoop系统,高效处理百万级用户数据。 这些系统通常采用Java技术栈(如SpringBoot + MySQL),确保可扩展性和可靠性[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值