【Machine Learning】Mahout基於協同過濾(CF)的使用者推薦
一、Mahout推薦演算法簡介
Mahout演算法框架自帶的推薦器有下面這些:
l GenericUserBasedRecommender:基於使用者的推薦器,使用者數量少時速度快;
l GenericItemBasedRecommender:基於商品推薦器,商品數量少時速度快,尤其當外部提供了商品相似度資料後效率更好;
l SlopeOneRecommender:基於slope-one演算法的推薦器,線上推薦或更新較快,需要事先大量預處理運算,物品數量少時較好;
l SVDRecommender:奇異值分解,推薦效果較好,但之前需要大量預處理運算;
l KnnRecommender:基於k近鄰演算法(KNN),適合於物品數量較小時;
l TreeClusteringRecommender:基於聚類的推薦器,線上推薦較快,之前需要大量預處理運算,使用者數量較少時效果好;
Mahout最常用的三個推薦器是上述的前三個,本文的例項僅“基於使用者的推薦器”做個實驗,其實大體原理都差不多。
二、基於協同過濾(CF)模型的使用者推薦
Mahout裡自帶的基本CF模型原理如下:
GenericUserBasedRecommender是基於使用者(user-based)的簡單推薦器實現類,推薦主要參照傳入的DataModel和UserNeighborhood,總體是三個步驟:
(1)從UserNeighborhood獲取當前使用者Ui
(2)從這K個使用者集合排除Ui的偏好商品,剩下的Item集合為{Item0, Item1, …Itemm};
(3)對Item集合裡每個Itemj計算Ui可能偏好程度值pref(Ui, Itemj),並把Item按此數值從高到低排序,前N個item推薦給使用者Ui。
偏好程度值pref計算公式:三、資料庫結構設計
建立資料庫mahoutDB,裡面建立表table1,具體表的結構如下所示,裡面包含4個特徵:userId,itemId, preference, date,分別代表使用者ID、商品ID、偏好分數、交易日期。
建好table1之後,表結構如下所示。
往table1裡匯入事先準備好的資料data.txt,
mysql>LOAD DATA LOCAL INFILE ‘data.txt’ INTO TABLE table1;
匯入完成過後資料如下所示。
使用者ID為1的記錄如下所示。
交易日期為20140825的記錄如下所示。
當中有一條記錄,比如使用者ID=2的選擇了商品202,偏好值為3.5。那麼之後應根據模型演算法,將相似使用者找出,並把相似使用者的偏好商品(排除userId=2他自己所選商品)推薦給使用者2。
四、原始碼
import java.util.List;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.JDBCDataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
import com.mysql.MysqlDataSource;
/**
* mahout基於協同過濾(CF)的推薦
*
*/
public class Mahout {
public static void main(String[] args) throws TasteException {
//(1)----連線資料庫部分
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setServerName("localhost");
dataSource.setUser("admin");
dataSource.setPassword("admin");
dataSource.setDatabaseName("mahoutDB");
//(2)----使用MySQLJDBCDataModel資料來源讀取MySQL裡的資料
JDBCDataModel dataModel = new MySQLJDBCDataModel(dataSource, "table1", "userId", "itemId", "preference", "date");
//(3)----資料模型部分
//把MySQLJDBCDataModel物件賦值給DataModel
DataModel model = dataModel;
//使用者相似度UserSimilarity:包含相似性度量和鄰居引數
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
//相鄰使用者UserNeighborhood
UserNeighborhood neighborhood = new NearestNUserNeighborhood(2, similarity, model);
//一旦確定相鄰使用者,一個普通的user-based推薦器被構建,構建一個GenericUserBasedRecommender推薦器需要資料來源DataModel,使用者相似性UserSimilarity,相鄰使用者相似度UserNeighborhood
Recommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
//向用戶1推薦2個商品
List<RecommandedItem> recommendations = recommender.recommend(1, 2);
for(RecommendedItem recommendation : recommendations){
//輸出推薦結果
System.out.println(recommendation);
}
}
}