基于用戶的協同過濾推薦算法實現(Java電商平臺)

在電商平臺中,基于用戶的協同過濾推薦算法是一種常見的推薦系統方法。它通過分析用戶之間的相似性來推薦商品。以下是一個簡單的實現思路和示例代碼,使用Java語言。

實現思路

  1. 數據準備:收集用戶的評分數據,通常以用戶-商品評分矩陣的形式存儲。
  2. 計算相似度:使用余弦相似度或皮爾遜相關系數等方法計算用戶之間的相似度。
  3. 生成推薦:根據相似用戶的評分,預測目標用戶對未評分商品的評分,并進行推薦。

1. 算法核心思想

基于用戶的協同過濾通過以下步驟工作:

  1. 計算用戶之間的相似度

  2. 找到與目標用戶最相似的K個用戶

  3. 根據這些相似用戶的喜好預測目標用戶可能喜歡的商品

  4. 推薦預測評分最高的N個商品

?2.Java實現代碼

import java.util.*;public class UserBasedCF {// 用戶-商品評分矩陣private Map<Integer, Map<Integer, Double>> userItemRatingMatrix;// 用戶相似度矩陣private Map<Integer, Map<Integer, Double>> userSimilarityMatrix;// 商品-用戶倒排表private Map<Integer, Set<Integer>> itemUserInverseTable;public UserBasedCF() {userItemRatingMatrix = new HashMap<>();userSimilarityMatrix = new HashMap<>();itemUserInverseTable = new HashMap<>();}/*** 添加用戶評分數據* @param userId 用戶ID* @param itemId 商品ID* @param rating 評分*/public void addRating(int userId, int itemId, double rating) {// 添加到用戶-商品矩陣userItemRatingMatrix.putIfAbsent(userId, new HashMap<>());userItemRatingMatrix.get(userId).put(itemId, rating);// 添加到商品-用戶倒排表itemUserInverseTable.putIfAbsent(itemId, new HashSet<>());itemUserInverseTable.get(itemId).add(userId);}/*** 計算用戶之間的相似度(使用皮爾遜相關系數)*/public void calculateUserSimilarities() {// 獲取所有用戶列表Set<Integer> users = userItemRatingMatrix.keySet();for (int u1 : users) {userSimilarityMatrix.putIfAbsent(u1, new HashMap<>());Map<Integer, Double> u1Ratings = userItemRatingMatrix.get(u1);for (int u2 : users) {if (u1 == u2) continue;Map<Integer, Double> u2Ratings = userItemRatingMatrix.get(u2);// 計算兩個用戶的共同評分商品Set<Integer> commonItems = new HashSet<>(u1Ratings.keySet());commonItems.retainAll(u2Ratings.keySet());if (commonItems.size() < 2) {// 共同評分商品太少,相似度為0userSimilarityMatrix.get(u1).put(u2, 0.0);continue;}// 計算皮爾遜相關系數double sum1 = 0, sum2 = 0;double sum1Sq = 0, sum2Sq = 0;double pSum = 0;for (int item : commonItems) {double r1 = u1Ratings.get(item);double r2 = u2Ratings.get(item);sum1 += r1;sum2 += r2;sum1Sq += Math.pow(r1, 2);sum2Sq += Math.pow(r2, 2);pSum += r1 * r2;}int n = commonItems.size();double num = pSum - (sum1 * sum2 / n);double den = Math.sqrt((sum1Sq - Math.pow(sum1, 2) / n) * (sum2Sq - Math.pow(sum2, 2) / n));double sim = (den == 0) ? 0 : num / den;userSimilarityMatrix.get(u1).put(u2, sim);}}}/*** 為目標用戶推薦商品* @param userId 目標用戶ID* @param k 相似用戶數量* @param n 推薦商品數量* @return 推薦商品ID列表*/public List<Integer> recommendItems(int userId, int k, int n) {if (!userItemRatingMatrix.containsKey(userId)) {return Collections.emptyList();}// 獲取目標用戶已評分的商品Set<Integer> ratedItems = userItemRatingMatrix.get(userId).keySet();// 獲取相似用戶并按相似度排序List<Map.Entry<Integer, Double>> similarUsers = new ArrayList<>(userSimilarityMatrix.get(userId).entrySet());similarUsers.sort((a, b) -> b.getValue().compareTo(a.getValue()));// 取前k個相似用戶if (similarUsers.size() > k) {similarUsers = similarUsers.subList(0, k);}// 計算推薦商品的預測評分Map<Integer, Double> itemPredictions = new HashMap<>();for (Map.Entry<Integer, Double> entry : similarUsers) {int similarUser = entry.getKey();double similarity = entry.getValue();// 獲取相似用戶評過但目標用戶未評的商品Map<Integer, Double> similarUserRatings = userItemRatingMatrix.get(similarUser);for (Map.Entry<Integer, Double> ratingEntry : similarUserRatings.entrySet()) {int item = ratingEntry.getKey();if (!ratedItems.contains(item)) {double rating = ratingEntry.getValue();// 加權評分itemPredictions.merge(item, similarity * rating, Double::sum);}}}// 對預測評分進行歸一化處理for (Map.Entry<Integer, Double> entry : similarUsers) {int similarUser = entry.getKey();double similarity = entry.getValue();Map<Integer, Double> similarUserRatings = userItemRatingMatrix.get(similarUser);for (int item : itemPredictions.keySet()) {if (similarUserRatings.containsKey(item)) {itemPredictions.put(item, itemPredictions.get(item) / Math.abs(similarity));}}}// 按預測評分排序并返回前n個商品List<Map.Entry<Integer, Double>> sortedItems = new ArrayList<>(itemPredictions.entrySet());sortedItems.sort((a, b) -> b.getValue().compareTo(a.getValue()));List<Integer> recommendations = new ArrayList<>();for (int i = 0; i < Math.min(n, sortedItems.size()); i++) {recommendations.add(sortedItems.get(i).getKey());}return recommendations;}// 測試代碼public static void main(String[] args) {UserBasedCF recommender = new UserBasedCF();// 模擬用戶評分數據recommender.addRating(1, 101, 5.0);recommender.addRating(1, 102, 3.0);recommender.addRating(1, 103, 2.5);recommender.addRating(2, 101, 2.0);recommender.addRating(2, 102, 2.5);recommender.addRating(2, 103, 5.0);recommender.addRating(2, 104, 2.0);recommender.addRating(3, 101, 2.5);recommender.addRating(3, 104, 4.0);recommender.addRating(3, 105, 4.5);recommender.addRating(3, 107, 5.0);recommender.addRating(4, 101, 5.0);recommender.addRating(4, 103, 3.0);recommender.addRating(4, 104, 4.5);recommender.addRating(4, 106, 4.0);recommender.addRating(4, 107, 2.0);// 計算用戶相似度recommender.calculateUserSimilarities();// 為用戶1推薦2個商品List<Integer> recommendations = recommender.recommendItems(1, 2, 2);System.out.println("為用戶1推薦的商品: " + recommendations);}
}

?3. 代碼說明

  1. 數據結構:

    • userItemRatingMatrix: 存儲用戶對商品的評分

    • userSimilarityMatrix: 存儲用戶之間的相似度

    • itemUserInverseTable: 商品到用戶的倒排表,加速計算

  2. 核心方法:

    • addRating(): 添加用戶評分數據

    • calculateUserSimilarities(): 計算用戶相似度(使用皮爾遜相關系數)

    • recommendItems(): 為目標用戶生成推薦列表

  3. 推薦過程:

    • 找到與目標用戶最相似的K個用戶

    • 收集這些相似用戶評價過但目標用戶未評價的商品

    • 計算這些商品的預測評分(加權平均)

    • 返回評分最高的N個商品作為推薦

4. 實際應用中的優化建議

  1. 數據稀疏性問題:

    • 實現降維技術(如SVD)

    • 使用混合推薦方法(結合基于內容的推薦)

  2. 性能優化:

    • 使用稀疏矩陣存儲數據

    • 實現增量更新機制,避免全量計算

    • 使用MapReduce或Spark進行分布式計算

  3. 冷啟動問題:

    • 對于新用戶,可以使用熱門商品推薦

    • 對于新商品,可以使用基于內容的推薦

  4. 業務適配:

    • 考慮時間衰減因素(最近的評分權重更高)

    • 加入業務規則過濾(如庫存、價格區間等)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83607.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83607.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83607.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LeetCode - 904. 水果成籃

題目 904. 水果成籃 - 力扣&#xff08;LeetCode&#xff09; 思路 題目本質 你有一個整數數組&#xff0c;每個元素代表一種水果。你只能用兩個籃子&#xff0c;每個籃子只能裝一種水果。你要在數組中找一個最長的連續子數組&#xff0c;這個子數組里最多只包含兩種不同的…

發現 Kotlin MultiPlatform 的一點小變化

最近發現 Kotlin 官方已經開始首推 Idea 的社區版的 KMP 插件了. 以前有網頁創建 KMP 的項目的文檔也消失了. 雖然有 Android Studio 的選項. 但是卻不是在默認的位置上了. 足以說明官方是有意想讓大家直接使用 Idea 社區版或者專業版 所以我直接在社區版上安裝 KMP 插件. 嘗試…

【Photoshop】金屬字體制作

新建一個空白項目&#xff0c;選擇橫排文字工具&#xff0c;輸入想要的文件建立文字圖層 選擇橫排文字工具選擇出文字內容&#xff0c;在通知欄出點擊’拾色器‘&#xff0c;設置好需要的文字顏色 圖層面板右下角點擊‘添加圖層樣式’&#xff0c;選擇斜面和浮雕 樣式設置為內斜…

centos 7.9 升級ssh版本 7.4p1 升級到 8.2p1

centos 7.9 升級ssh版本 7.4p1 升級到 8.2p1 1、安裝包下載2、安裝telnet3、安裝openssl-OpenSSL_1_1_1f.tar.gz4、安裝openssh-8.2p1.tar.gz5、修改ssh服務的相關配置文件6、確定可以ssh連接服務器后&#xff0c;卸載telnet&#xff0c;因為telnet不安全 本文是離線環境下升級…

stm32---dma串口發送+fifo隊列框架

之前分享了一個關于gd32的fifo框架&#xff0c;這次就用stm32仿照寫一個&#xff0c;其實幾乎一樣&#xff0c;這次說的更詳細點&#xff0c;我全文都寫上了注釋&#xff0c;大家直接cv模仿我的調用方式即可 uasrt.c #include "stm32f10x.h" // D…

【生產就曲篇】讓應用可觀測:Actuator監控端點與日志最佳實踐

摘要 本文是《Spring Boot 實戰派》系列的終章&#xff0c;我們將探討如何讓應用真正達到**“生產就緒” (Production-Ready)** 的標準。文章的核心是可觀測性 (Observability)&#xff0c;即從外部了解一個系統內部運行狀態的能力。 我們將深度挖掘 Spring Boot Actuator 的…

操作系統知識(1)

操作系統的分類總結 1、批處理操作系統:單道批處理和多道批處理(主機與外設可并行) 2、分時操作系統:一個計算機系統與多個終端設備連接。將CPU的工作時間劃分為許多很短的時間片&#xff0c;輪流為各個終端的用戶服務。 3、實時操作系統:實時是指計算機對于外來信息能夠以足…

一.Sharding分庫分表-基因法+自定義多key分片實現多字段查詢

前言 當下遇到這樣一個場景&#xff0c;由于訂單數據量達到千萬級別&#xff0c;采用分庫分表進行優化&#xff0c;根據訂單的熱查條件&#xff1a;order_no訂單編號進行分表&#xff0c;但是這樣帶來一個問題&#xff0c;用戶查詢自己的訂單怎么查&#xff1f;由于分片鍵使用…

【leetcode】543. 二叉樹的直徑

二叉樹的直徑 題目題解解釋 題目 543. 二叉樹的直徑 給你一棵二叉樹的根節點&#xff0c;返回該樹的 直徑 。 二叉樹的 直徑 是指樹中任意兩個節點之間最長路徑的 長度 。這條路徑可能經過也可能不經過根節點 root 。 兩節點之間路徑的 長度 由它們之間邊數表示。 題解 …

AI基礎知識(07):基于 PyTorch 的手寫體識別案例手冊

目錄 實驗介紹 實驗對象 實驗時間 實驗流程 實驗介紹 隨著人工智能技術的飛速發展&#xff0c;圖像識別技術在眾多領域得到了廣泛應用。手寫體識別作為圖像 識別的一個重要分支&#xff0c;其在教育、金融、醫療等領域具有廣泛的應用前景。本實驗旨在利用深度 學習框架 PyTorc…

wordpress后臺更新后 前端沒變化的解決方法

使用siteground主機的wordpress網站&#xff0c;會出現更新了網站內容和修改了php模板文件、js文件、css文件、圖片文件后&#xff0c;網站沒有變化的情況。 不熟悉siteground主機的新手&#xff0c;遇到這個問題&#xff0c;就很抓狂&#xff0c;明明是哪都沒操作錯誤&#x…

信號(瞬時)頻率求解與仿真實踐(2)

引言 本文是信號(瞬時)頻率求解與仿真實踐專題的第二篇文章&#xff0c;在上一篇博文 [1]信號(瞬時)頻率求解與仿真實踐(1)-CSDN博客中&#xff0c;我構建了信號瞬時頻率求解的基本框架&#xff0c;并且比較詳細地討論了瞬時頻率法。這篇博文探討適用于信號瞬時頻率求解的另一種…

Linux運行發布jar文件攜帶哪些參數

在 CentOS 8 上運行發布的 JAR 文件時,可以根據不同需求攜帶以下參數: 1. 基本運行方式 bash 復制 下載 java -jar your-application.jar 2. 常用 JVM 參數 參數說明-Xms256m初始堆內存大小(如 256MB)-Xmx1024m最大堆內存大小(如 1GB)-XX:MaxMetaspaceSize=256m元空間…

在GIS 工作流中實現數據處理(4)

結果輸出與可視化 最后&#xff0c;我們將統計結果輸出為一個 Excel 文件&#xff0c;并在 ArcMap 中對城市中心區域的土地利用情況進行可視化展示。 import pandas as pd# 將統計表格轉換為 pandas DataFrame df pd.read_csv(statistics_table, sep"\t")# 輸出為…

【術語解釋】網絡安全((SAST, DAST, SCA, IAST),Hadoop, Spark, Hive 的關系

## OWASP Top 10等 OWASP Top 10&#xff1a;OWASP (Open Worldwide Application Security Project&#xff0c;開放全球應用程序安全項目) Top 10 是一份由全球安全專家定期更新的報告&#xff0c;列出了當前 Web 應用程序面臨的十大最關鍵安全風險。 它是一個廣受認可的意識文…

NY197NY205美光閃存固態NY218NY226

NY197NY205美光閃存固態NY218NY226 美光科技作為全球領先的半導體存儲解決方案供應商&#xff0c;其閃存固態硬盤&#xff08;SSD&#xff09;產品線一直備受業界關注。NY197、NY205、NY218和NY226是美光近期推出的幾款重要固態硬盤型號&#xff0c;它們在性能、容量和適用場景…

MinHook 對.NET底層的 SendMessage 攔截真實案例反思

一&#xff1a;背景 1. 講故事 上一篇我們說到了 minhook 的一個簡單使用&#xff0c;這一篇給大家分享一個 minhook 在 dump 分析中的實戰&#xff0c;先看下面的線程棧。 0:044> ~~[138c]s win32u!NtUserMessageCall0x14: 00007ffc5c891184 c3 ret 0:061&g…

qt配合海康工業相機取圖開發

1.最近開發海康工業相機&#xff0c;做取圖demo 2.在MVS運行目錄下找到Development文件夾&#xff0c;找到下圖兩個文件夾一個是頭文件一個是庫文件 3.引用到qt項目中 4.下面是頭文件跟源文件 頭文件 #ifndef MVSCAMERA_H #define MVSCAMERA_H#include <QObject> #incl…

JavaScript基礎學習與應用(后端了解部分)

JavaScript JavaScript原名liveScrip,由美國網景公司開發的一種用于對網頁操作的腳本語言 腳本語言:(不需要編譯 sql html css)由某種解釋器直接解釋運行的 JavaScript是一種解釋性的腳本語言 JavaScript是網頁的行為,可以為網頁提供各種行為(圖片操作) JavaScript一般一對…

Linux環境下安裝和使用RAPIDS平臺的cudf和cuml - pip 安裝方法

? cuDF 和 cuML 是 RAPIDS平臺 的兩個核心組件&#xff0c;它們共同構成了RAPIDS平臺的主要功能 1.linux環境下pip安裝 pip install cuml-cu1224.6.0 --extra-index-urlhttps://pypi.nvidia.com 安裝過程中可能會提示缺少包之類的&#xff0c;按提示進行包的缺失安裝 2.安裝…