介紹
最近做了一個關於旅遊方面的項目,使用了比較流行的推薦算法,特地在此跟大家分享一下算法的實現過程。
項目簡介
採用前後端分離架構。
RESTful API風格接口化、Json形式數據傳輸。
前端頁面進行了升級,引用了一些基本的組件,如dataTables.js、bootstrap.js、bootbox.js。
前端沒有采用主流框架如Vue、React等,使用基本的HTML+CSS+JQ也減輕了上手難度。
引入皮爾遜線性相似度推薦算法的Java實現,應用於項目的“景點推薦”欄目。
項目架構
採用前後端分離,Jquery + SpringBoot2.0
後端語言Java
ORM使用SpringDataJPA
數據庫使用MySql5.7+Mongodb3
緩存Redis
部署Nginx+Jar
算法解析
皮爾遜相關係數的相似度算法(Pearson)
該算法在本系統中實現了基於景點分數近似度的推薦功能,以下給出數據獲取方法代碼,具體算法實現請查看CFUtils.cosineSimilarity()方法。
public List<Spots> findRecommendList(String id) {
//系統中我將景點抽象成了產品,這樣便於擴展,如酒店、旅行團均可看作產品評分,統一記錄在系統的分數表中
//如果是查詢景點推薦列表,則根據入參景點id查詢景點
List<Score> productScoreList = scoreDao.findByProductId(id);
//因爲相似度比對需要兩份數據,首先得到自己查詢的景點的分數集合
double[] ownProductScoreList = new double[productScoreList.size()];
for (int i = 0; i < productScoreList.size(); i++) {
ownProductScoreList[i] = Double.parseDouble(productScoreList.get(i).getGrade());
}
//然後得到分數表中所有景點的分數集合
List<Score> productCountInScoreList = scoreDao.findAllGroupByProductId();
HashMap<String,double[]> ss = new HashMap<String,double[]>();
//循環所有景點
for (int i = 0; i < productCountInScoreList.size(); i++) {
//得到該產品的所有分數
List<Score> bb = scoreDao.findByProductId(productCountInScoreList.get(i).getProductId());
double[] otherProductScoreList = new double[bb.size()];
//循環該產品的所有分數
for (int j = 0; j < bb.size(); j++) {
otherProductScoreList[j] = Double.parseDouble(bb.get(j).getGrade());
}
//將產品作爲key,分數集合作爲value存入map
ss.put(productCountInScoreList.get(i).getProductId(),otherProductScoreList);
}
List<Spots> resSpotsList = new ArrayList<>();
//循環Map依次比對其線性相似度
ss.forEach((String k, double[] v)->{
//得到相似度值
double n = CFUtils.cosineSimilarity(ownProductScoreList,v);
log.info("id:{},線性相似度:{}",k,n);
//判斷相似度值是否符合自己設定的閾值
if(n > pearsonCorrelation) {
//符合相似閾值,放入推薦列表
resSpotsList.add(spotsDao.findById(k));
}
});
return resSpotsList;
}
項目實際運行效果
運行視頻
springboot吊炸天旅遊推薦系統 旅遊管理系統 旅遊網站