創(chuàng)建數(shù)據(jù)模型 —> 用戶相似度算法 —>用戶近鄰算法 —>推薦算法。
基于用戶的
協(xié)同過濾算法在Mahout庫中已經(jīng)模塊化了,通過4個模塊進行統(tǒng)一的方法調(diào)用。首先,創(chuàng)建
數(shù)據(jù)模型(DataModel),然后定義用戶的相似度算法(UserSimilarity),接下來定義用戶近鄰算法(UserNeighborhood ),最后調(diào)用推薦算法(Recommender)完成計算過程。而基于物品的
協(xié)同過濾算法(ItemCF)過程也是類似的,去掉第三步計算用戶的近鄰算法就行了。
軟件環(huán)境:Win7 64位 + Eclipse4.4 +jdk1.6
使用Java語言,借用Mahout庫里的API,實現(xiàn)基于用戶的
協(xié)同過濾算法,從而進行
商品推薦。
1.數(shù)據(jù)集
//testCF.csv
1,101,5.0
1,102,3.0
1,103,2.5
2,101,2.0
2,102,2.5
2,103,5.0
2,104,2.0
3,101,2.5
3,104,4.0
3,105,4.5
3,107,5.0
4,101,5.0
4,103,3.0
4,104,4.5
4,106,4.0
5,101,4.0
5,102,3.0
5,103,2.0
5,104,4.0
5,105,3.5
5,106,4.0
該testCF.csv數(shù)據(jù)集中,第一列為用戶號UserID,第二列為商品號ItemID,第三列為評分Preference Value.
2.借用Java里Mahout庫,實現(xiàn)
協(xié)同過濾算法。
//UserBased.java
package com.xie;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.file.*;
import org.apache.mahout.cf.taste.impl.neighborhood.*;
import org.apache.mahout.cf.taste.impl.recommender.*;
import org.apache.mahout.cf.taste.impl.similarity.*;
import org.apache.mahout.cf.taste.model.*;
import org.apache.mahout.cf.taste.recommender.*;
import org.apache.mahout.cf.taste.similarity.*;
import java.io.*;
import java.util.*;
public class UserBased {
final static int NEIGHBORHOOD_NUM = 2;
final static int RECOMMENDER_NUM = 3;
public static void main(String[] args) throws IOException, TasteException {
String file = "src/data/testCF.csv";
DataModel model = new FileDataModel(new File(file));
UserSimilarity user = new EuclideanDistanceSimilarity(model);
NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, user, model);
Recommender r = new GenericUserBasedRecommender(model, neighbor, user);
LongPrimitiveIterator iter = model.getUserIDs();
while (iter.hasNext()) {
long uid = iter.nextLong();
List<RecommendedItem> list = r.recommend(uid, RECOMMENDER_NUM);
System.out.printf("uid:%s", uid);
for (RecommendedItem ritem : list) {
System.out.printf("(%s,%f)", ritem.getItemID(), ritem.getValue());
}
System.out.println();
}
}
}
基于用戶的
協(xié)同過濾算法(Java實現(xiàn)或
R語言實現(xiàn)圖(1)
協(xié)同過濾,從而進行
商品推薦
結(jié)果說明:
對于uid=1的用戶,給他推薦計算得分最高的2個物品,104和106。
對于uid=2的用戶,給他推薦計算得分最高的1個物品,105。
對于uid=3的用戶,給他推薦計算得分最高的2個物品,103和102。
對于uid=4的用戶,給他推薦計算得分最高的1個物品,102。
對于uid=5的用戶,沒有推薦。
用Java實現(xiàn)
協(xié)同過濾的工程代碼:
方法二:用
R語言實現(xiàn)
協(xié)同過濾算法
軟件環(huán)境:win7 64位 + RStudio 0.99 + R3.2.3
//mahout1.R
# part1 -------------------------------------------------------------------
##加載arules包
library(arules)
##建立模型矩陣
FileDataModel <- function(file){
##讀取CSV文件到內(nèi)存
data <- read.csv(file,header = FALSE)
##增加列名
names(data) <- c("uid","iid","pref")
##計算用戶數(shù)
user <- unique(data$uid)
##計算產(chǎn)品數(shù)
item <- unique(sort(data$iid))
uidx <- match(data$uid, user)
iidx <- match(data$iid, item)
##定義存儲矩陣
M <- matrix(0, length(user),length(item))
i <- cbind(uidx, iidx, pref=data$pref)
##給矩陣賦值
for(n in 1:nrow(i)){
M[i[n,][1], i[n,][2]] <- i[n,][3]
}
dimnames(M)[[2]] <- item
##返回矩陣值
M
}
# part2 -------------------------------------------------------------------
##歐式距離相似度算法
EuclideanDistanceSimilarity <- function(M){
row <- nrow(M)
##相似度矩陣
s <- matrix(0,row,row)
for(z1 in 1:row){
for(z2 in 1:row){
if(z1 < z2){
##可計算的列
num <- intersect(which(M[z1,]!=0),which(M[z2,]!=0))
sum <- 0
for(z3 in num){
sum <- sum+(M[z1,][z3] - M[z2,][z3])^2
}
s[z2,z1] <- length(num)/(1+sqrt(sum))
##對算法的閾值進行限制
if(s[z2,z1] > 1) s[z2,z1] <- 1
if(s[z2,z1] < -1) s[z2,z1] <- -1
}
}
}
ts <- t(s) ##補全三角矩陣
w <- which(upper.tri(ts))
s[w] <- ts[w]
s ##返回用戶相似度矩陣
}
# part3 -------------------------------------------------------------------
##用戶近鄰算法
NearestNUserNeigborhood <- function(S,n){
row <- nrow(S)
neighbor <- matrix(0,row,n)
for(z1 in 1:row){
for(z2 in 1:n){
m <- which.max(S[,z1])
neighbor[z1,][z2] <- m
S[,z1][m]=0
}
}
neighbor
}
# part4 -------------------------------------------------------------------
##推薦算法
UserBasedRecommender <- function(uid,n,M,S,N){
row <- ncol(N)
col <- ncol(M)
r <- matrix(0,row,col)
N1 <- N[uid,]
for(z1 in 1:length(N1)){
num <- intersect(which(M[uid,]==0),which(M[N1[z1],]!=0))
for(z2 in num){
r[z1,z2] = M[N1[z1],z2]*S[uid,N1[z1]]
}
}
##輸出推薦矩陣
sum <- colSums(r)
s2 <- matrix(0,2,col)
for(z1 in 1:length(N1)){
num <- intersect(which(colSums(r)!=0),which(M[N1[z1],]!=0))
for(z2 in num){
s2[1,][z2] <- s2[1,][z2]+S[uid,N1[z1]]
s2[2,][z2] <- s2[2,][z2]+1
}
}
s2[,which(s2[2,]==1)]=10000
s2 <- s2[-2,]
r2 <- matrix(0,n,2)
rr <- sum/s2
item <- dimnames(M)[[2]]
for(z1 in 1:n){
w <- which.max(rr)
if(rr[w]>0.5){
r2[z1,1] <- item[which.max(rr)]
r2[z1,2] <- as.double(rr[w])
rr[w]=0
}
}
r2
}
# part5 -------------------------------------------------------------------
##調(diào)用算法
setwd("G:\myProject\RDoc\Unit2\rChap2")
myFile <- "testCF.csv"
NeighborHodd_num <- 2 ##取兩個最大近鄰
Recommender_num <- 3 ##保留最多3個推薦結(jié)果
myM <- FileDataModel(myFile)
myS <- EuclideanDistanceSimilarity(myM)
myN <- NearestNUserNeigborhood(myS,NeighborHodd_num)
##對用戶user= 1的推薦結(jié)果
R1 <- UserBasedRecommender(1, Recommender_num,myM,myS,myN); R1
##對用戶user= 2的推薦結(jié)果
R2 <- UserBasedRecommender(2, Recommender_num,myM,myS,myN); R2
##對用戶user= 3的推薦結(jié)果
R3 <- UserBasedRecommender(3, Recommender_num,myM,myS,myN); R3
##對用戶user= 4的推薦結(jié)果
R4 <- UserBasedRecommender(4, Recommender_num,myM,myS,myN); R4
##對用戶user= 5的推薦結(jié)果
R5 <- UserBasedRecommender(5, Recommender_num,myM,myS,myN); R5
效果如下:

基于用戶的
協(xié)同過濾算法(Java實現(xiàn)或
R語言實現(xiàn)圖(2)用
R語言實現(xiàn)
協(xié)同過濾算法