按照以下步驟可以得出結論並看出協同過濾原理。

  1. 數據源如下,命名`testCF.csv`,放在我的桌面,路徑:C:/Users/Administrator/Desktop/。

A11111 101 5
A11111 102 3
A11111 103 2.5
A22222 101 2
A22222 102 2.5
A22222 103 5
A22222 104 2
A33333 101 2.5
A33333 104 4
A33333 105 4.5
A33333 107 5
A44444 101 5
A44444 103 3
A44444 104 4.5
A44444 106 4
A55555 101 4
A55555 102 3
A55555 103 2
A55555 104 4
A55555 105 3.5
A55555 106 4

2. 代碼如下:

運行完畢後直接執行UserBasedRecommender("A11111") #參數為用戶id,即輸入用戶id即可以得到若干推薦。UserBasedRecommender中有4個變數,分別是`UserBasedRecommender(uid,data=..,n=2,N=3)`.

其中,uid為用戶id,data為數據集,n代表與目標用戶距離最近的n個用戶,N代表最終推薦的商品數。

#載入數據
org_data = read.csv(C:\Users\Administrator\Desktop\testCF.csv,header=FALSE)
#1)將源數據轉化為矩陣
FileDataModel = function(org_data){
names(org_data) = c("uid","iid","pref")
M = dcast(uid ~ iid,data=org_data)
rownames(M) = unique(org_data$uid)
M = as.matrix(M[-1])
colnames(M) = unique(sort(org_data$iid))
M
}
#M = FileDataModel(org_data)
# 101 102 103 104 105 106 107
# 1 5.0 3.0 2.5 NA NA NA NA
# 2 2.0 2.5 5.0 2.0 NA NA NA
# 3 2.5 NA NA 4.0 4.5 NA 5
# 4 5.0 NA 3.0 4.5 NA 4 NA
# 5 4.0 3.0 2.0 4.0 3.5 4 NA
#原文是把NA替換為0,但是考慮到後面計算相似性的方便,這裡把它保留了。
#2). 歐氏距離相似度演算法
EuclideanDistanceSimilarity = function(M){
simple = function(x,y){
num = intersect(which(M[x,]!=0),which(M[y,]!=0))
s = sum((M[x,] - M[y,])^2,na.rm = T)
s = length(num)/(1 + sqrt(s))
if(s > 1) s = 1
if(s < -1) s = -1
return(s)
}
outer(1:nrow(M),1:nrow(M),Vectorize(simple)) - diag(nrow(M))
}

# S
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0.0000000 0.6076560 0.2857143 1.0000000 1.0000000
# [2,] 0.6076560 0.0000000 0.6532633 0.5568464 0.7761999
# [3,] 0.2857143 0.6532633 0.0000000 0.5634581 1.0000000
# [4,] 1.0000000 0.5568464 0.5634581 0.0000000 1.0000000
# [5,] 1.0000000 0.7761999 1.0000000 1.0000000 0.0000000
# 3). 最近鄰演算法
NearestNUserNeighborhood = function(S,n){
sapply(1:n,function(i) {m = apply(S,2,which.max)
ij = cbind(m,seq_along(m))
S[ij] <<- 0
m})
}
# #取距離最近的兩位用戶
# NEIGHBORHOOD_NUM = 2
# N = NearestNUserNeighborhood(S,NEIGHBORHOOD_NUM)
# # N
# # [,1] [,2]
# # [1,] 4 5
# # [2,] 5 3
# # [3,] 5 2
# # [4,] 1 5
# # [5,] 1 3
# # 4). 推薦演算法
# #RECOMMENDER_NUM是推薦產品的個數
# RECOMMENDER_NUM = 3
# UserBasedRecommender = function(uid,n,M,S,N){
# part = colnames(M)[is.na(M[uid,])] #用戶A沒有的商品
# m = S[uid, N[uid,]]
# md = M[N[uid,],part]
# if(length(dim(md)) >= 1) {
# a = colnames(md)[colSums(md,na.rm=TRUE)!=0]
# score = colSums(md*m,na.rm = T)/apply(!is.na(md),2,function(x) sum(m[x]))
# res = score[order(score,decreasing=T)][1:n]
# res = res[intersect(names(res),a)]
# return(res)
# } else { res = NA}
# }
#org_data是源數據集,uid為用戶id排序,n為推薦多少個產品,N為取多少個距離最近的幾個用戶
UserBasedRecommender=function(uid,data=org_data,n=2,N=3){
library(reshape2)
M = FileDataModel(org_data)#轉化矩陣形式
S = EuclideanDistanceSimilarity(M) #計算用戶之間的距離相似度,這裡用歐式距離
N = NearestNUserNeighborhood(S,N) #取出距離最近的幾個用戶
uid_N=which(rownames(M)==uid)
part = colnames(M)[is.na(M[uid_N,])] #用戶A沒有的商品
m = S[uid_N, N[uid_N,]]
md = M[N[uid_N,],part]
if(length(dim(md)) >= 1) {
a = colnames(md)[colSums(md,na.rm=TRUE)!=0]
score = colSums(md*m,na.rm = T)/apply(!is.na(md),2,function(x) sum(m[x]))
res = score[order(score,decreasing=T)][1:n]
res = res[intersect(names(res),a)]
return(res)
} else { res = NA}
}

3. 取相似用戶最喜歡的商品TOPN

UserBasedRecommender(uid=A11111,data=org_data,n=2,N=3)
# uid為待推薦用戶ID
# n=2為推薦的商品數
# N=3為取最近N個用戶
#上述即取與A11111相鄰的3個用戶偏好的商品TOP2

4.最後做成結果參數可配置化界面

具體代碼實現可以跳轉至我的博客:mp.csdn.net/mdeditor/92

參考文章:

用戶推薦協同過濾演算法(UserCF)的R實現 - R語言論壇 - 經管之家(原人大經濟論壇)


推薦閱讀:
相关文章