R語言-推薦系統


一.概述

目的:使用推薦系統可以給用戶推薦更好的商品和服務,使得產品的利潤更高

算法:協同過濾

協同過濾是推薦系統最常見的算法之一,算法適用用戶過去的購買記錄和偏好進行推薦

基於商品的協同過濾(IBCF計算每個商品之間的相似度矩陣):

  1.任意兩個商品計算相似度

  2.每一個商品找出其k個最相似的商品

  3.每一個用戶找出那些商品與其之前購買的商品最接近的商品

基於用戶的協同過濾(UBCF計算用戶之間的相似度矩陣):

  1.計算每個用戶與用戶之間的相似度,通常使用皮爾森相關系數和余弦距離

  2.找出最相近的用戶(KNN)

  3.把新用戶最相似的用戶所購買的商品進行排名

  4.基於相似性矩陣選出n個推薦的商品

二.案例

案例1:基於電影數據集的推薦(IBCF)

  1.1導入包

library(reshape2)
library(ggplot2)
library(countrycode)
library(recommenderlab)

  1.2查看數據集

data("MovieLense")
dim(MovieLense)
str(MovieLense)
head(MovieLense@data)

 

  結論:該數據集是一個稀疏矩陣,每一行是觀眾對每部電影的打分,每一列是電影,一共有943觀眾,1664部電影

  1.3找到評分大於0的電影

vector_rating <- as.vector(MovieLense@data)
table_rating <- table(vector_rating)

#查看非0的評分
vector_rating <- vector_rating[vector_rating!=0]
vector_rating <- factor(vector_rating)
qplot(vector_rating) + ggtitle('Distribution of the ratings')

  結論:3,4分的電影比較多

  1.4找到被評分較多的電影和打分比較多的觀眾

#找到評分比較多的電影和打分比較多的用戶
rating_moives <- MovieLense[rowCounts(MovieLense) > 50,colCounts(MovieLense) > 100]
dim(rating_moives)

  結論:只有560部電影和322位觀眾符合條件

  1.5划分數據集

#80%位訓練集,20%位測試集
which_train <- sample(x=c(T,F),size = nrow(rating_moives),replace = T,prob = c(0.8,0.2)) recc_data_train <- rating_moives[which_train,] recc_data_test <- rating_moives[!which_train,]

  1.6建立推薦模型

#IBCF是基於商品的推薦
recc_model=Recommender(data = recc_data_train,method="IBCF")

  1.7查看模型

model_detail <- getModel(recc_model)
model_detail$description
str(model_detail)

dim(model_detail$sim)
n_items_top <- 20
image(model_detail$sim[1:n_items_top,1:n_items_top],main = "Heatmap of the first rows and columns")

  結論:從相似性矩陣中抽取20*20的數據進行熱圖展示,顏色越深的電影相關性越大

  1.8使用模型進行推薦

#定義推薦的個數
n_recommended <- 6 recc_predicted <- predict(object = recc_model,newdata=recc_data_test,n=n_recommended) recc_user_1 <- recc_predicted@items[[1]] moive_user_1 <- recc_predicted@itemLabels[recc_user_1] #查看第一個用戶的推薦結果 moive_user_1

使用基於用戶的電影推薦(UBCF)

   1.9建立基於用戶的模型

recommender_models <- recommenderRegistry$get_entries(dataType ="realRatingMatrix")

  1.10查看參數

recommender_models$UBCF_realRatingMatrix$parameters

  結論:使用cosine來計算每個用戶的相似性

  1.11建立相關性矩陣

recc_model_UBCF = Recommender(data = recc_data_train,method='UBCF',
                              param=list(normalize='Z-score',nn=5,method='Cosine'))
model_detail_UBCF <- getModel(recc_model_UBCF)
names(model_detail_UBCF)
model_detail_UBCF$dat

  結論:模型的參數

  1.12使用模型進行推薦

recc_predicted_UBCF <- predict(object = recc_model_UBCF,newdata=recc_data_test,n=n_recommended)

  1.13查看推薦的結果

recc_martix <- sapply(recc_predicted_UBCF@items, function(x){
  colnames(rating_moives[x])
})
dim(recc_martix)
recc_martix[,1:4]

  結論:根據用戶進行推薦的結果

對二進制的數據進行建模(一般應用於網頁的商品推薦)

## 基於商品的建模

recc_model=Recommender(recc_data_train,method="IBCF", param=list(method="Jaccard"))
model_details <- getModel(recc_model)
###定義推薦個數
n_recommended <- 6
recc_predicted <- predict(object = recc_model, newdata = recc_data_test, n = n_recommended)
recc_matrix <- sapply(recc_predicted@items, function(x){
  colnames(ratings_movies)[x]
})

recc_matrix[, 1:4]

###UBCF
##基於用戶的建模
recc_model=Recommender(recc_data_train,method="UBCF", param=list(method="Jaccard"))
model_details <- getModel(recc_model)

n_recommended <- 6
recc_predicted <- predict(object = recc_model, newdata = recc_data_test,n = n_recommended)
recc_matrix <- sapply(recc_predicted@items, function(x){
  colnames(ratings_movies)[x]
})
dim(recc_matrix)

recc_matrix[, 1:4]

 

               IBCF                                             UBCF

使用 k-fold對模型進行驗證

   1.14使用交叉驗證

eval_set <- evaluationScheme(data=rating_moives,method='cross-validation',k=4,given=15,goodRating=3)
# 不同類型的模型和隨機推薦進行比較
models_to_evaluate <- list(
  IBCF_cos = list(name='IBCF',param=list(method='cosine')),
  IBCF_cor = list(name='IBCF',param=list(method='pearson')),
  UBCF_cos = list(name='UBCF',param=list(method='cosine')),
  UBCF_cor = list(name='UBCF',param=list(method='pearson')),
  random = list(name='Random',param=NULL)
)

  1.15作圖比較

##定義推薦電影的個數
n_recommendations <- c(1, 5, seq(10, 100, 10))

##開始建模
list_results <- evaluate(x = eval_sets, method = models_to_evaluate, n
                         = n_recommendations)


### plot #通過做圖查看模型差異

plot(list_results, annotate = 1, legend = "topleft")

title("ROC curve")

  結論:使用基於用戶的皮爾森作為推薦的模型是最優的

  1.16對參數進行優化

# 參數優化
vector_k <- c(5, 10, 20, 30, 40)


models_to_evaluate <- lapply(vector_k, function(k){
  list(name = "IBCF", param = list(method = "cosine", k = k))
})


names(models_to_evaluate) <- paste0("IBCF_k_", vector_k)


n_recommendations <- c(1, 5, seq(10, 100, 10))
list_results <- evaluate(x = eval_set, method = models_to_evaluate, n
                         = n_recommendations)

par(mar=c(1.1 ,1.1, 1.1, 1.1))

plot(list_results, annotate = 1, legend = "topleft")
title("ROC curve")

  

  結論:基於商品的推薦模式下,每個用戶推薦30部是最優策略

案例2基於網頁的推薦(用戶沒有對網頁評分,是根據用戶點擊瀏覽網頁來獲取用戶的行為作為推薦的依據)

  2.1導入包

library(data.table)
library(reshape2)
library(ggplot2)
library(countrycode)
library(recommenderlab)

  2.2查看並清洗數據集

web_data <- read.csv('E:\\Udacity\\Data Analysis High\\R\\R_Study\\高級課程代碼\\數據集\\第二天\\5推薦系統\\anonymous-msweb.test.txt',header=FALSE)
head(web_data)
#選擇前兩列
table_users <- web_data[, 1:2]
##定義成data frame
table_users <- data.table(table_users)
#定義列名稱
setnames(table_users, 1:2, c("category", "value"))
table_users <- table_users[category %in% c("C", "V")]
head(table_users)

 

  結論:

    1.該數據集一共有20492個對象,每個對象有6列

    2.該數據集的前兩列C的value表示用戶ID,V的value表示用戶訪問的網頁ID

   2.3將數據表轉化成寬表

#每遇到一個新用戶則chunk user +1
table_users[, chunk_user := cumsum(category == "C")]
head(table_users)
tail(table_users)

### 把user 和item 分成兩列
table_long <- table_users[, list(user = value[1], item = value[-1]), by ="chunk_user"]
head(table_long)


### long to wide 長表變寬表
table_long[, value := 1]
table_wide <- reshape(data = table_long,
                      direction = "wide",
                      idvar = "user",
                      timevar = "item",
                      v.names = "value")
head(table_wide[, 1:8, with = FALSE])

 

 

     step1              step2                          step3

  2.4將寬表的列名進行修正(第一列是用戶id,之后的每一列是Item id,每一個值是代表用戶是否訪問過該頁面)

# 保存用戶的id
vector_users <- table_wide[,user]
# 從數據集刪除用戶ID和chunk_user
table_wide[, user := NULL]
table_wide[, chunk_user := NULL]


##對列名稱進行修正,只取前7個字符
setnames(x = table_wide,
         old = names(table_wide),
         new = substring(names(table_wide),7))

# 添加行名稱,並轉化成矩陣
matrix_wide <- as.matrix(table_wide)
rownames(matrix_wide) <- vector_users
head(matrix_wide[,1:6])

  2.5畫出相關性熱力圖

# 轉換成二進制矩陣
matrix_wide[is.na(matrix_wide)] <- 0
ratings_matrix <- as(matrix_wide, "binaryRatingMatrix")

image(ratings_matrix[1:50, 1:50], main = "Binary rating matrix")

  2.6獲取其他的信息

# 如果有一些網頁,在五千個人中訪問不超過5的,則刪掉
ratings_matrix <- ratings_matrix[, colCounts(ratings_matrix) >= 5]
# 如果有一些用戶,在網頁中點評數量少於5個則刪除
ratings_matrix <- ratings_matrix[rowCounts(ratings_matrix) >= 5, ]
# 獲取描述信息
table_in <- data.table(table_in)
table_items <- table_in[V1 == "A"]
head(table_items)
# 修改列名
table_items <- table_items[,c(2,4,5),with=F]
setnames(table_items,1:3,c('id','description','url'))
table_items <- table_items[order(id)]
# 新增一列category,默認是product,如果描述在country_code中則category改為region
table_items[,category := 'product']
name_countries <-c(countrycode_data$country.name)
                    
table_items[description %in% name_countries, category := "region"]

table_items[, list(n_items = .N), by = category]

 

        step1                          step2                                                               step3

   2.7划分數據集

which_train <- sample(x=c(T,F),
                      size = nrow(ratings_matrix),
                      replace = T,
                      prob = c(0.8,0.2)
                      )
recc_data_train <- ratings_matrix[which_train,]
recc_data_test <- ratings_matrix[!which_train,]

  2.8基於商品的推薦模型

web_model <- Recommender(data=recc_data_train,method='IBCF',parameter=list(method='Jaccard'))

 

  2.9計算相似性矩陣

## item 的相似性矩陣(評分矩陣)
dist_ratings <- as(web_model@model$sim, "matrix")

## item category的相似性矩陣(商品之間的相似性矩陣)
dist_category <- table_items[, 1 - dist(category == "product")]
dist_category <- as(dist_category, "matrix")

dim(dist_category)
dim(dist_ratings)
## 給dist_category矩陣添加行名和列名 rownames(dist_category)
<- table_items[, id] colnames(dist_category) <- table_items[, id] ## 給dist_category矩陣抽取dist_ratings的長度,兩個矩陣的大小要一致 vector_items <- rownames(dist_ratings) dist_category <- dist_category[vector_items, vector_items] dim(dist_category)

     

  step1          step2

  2.10使用模型進行預測

## category matrix 包含信息較少,所以只給0.25的權重
weight_catrgory <- 0.25
dist_tot <- dist_category * weight_catrgory + dist_ratings * (1-weight_catrgory)
## 轉換成相似性矩陣
web_model@model$sim <- as(dist_tot,'dgCMatrix')
## 設定推薦的個數
n_recommend <- 10
web_predict <- predict(object = web_model,newdata=recc_data_test,n=n_recommend)
head(web_predict@itemLabels,10)

  結論:該用戶最想看到的10個網站的ID

 

 總結:

  1.了解業務需求

  2.載入包

  3.清洗並轉換數據集

  4.拆分數據集

  5.建立IBCF模型,如果兩個網站被相同用戶訪問的越多,其相似度越大

  6.使用對網站的描述建立描述相似性矩陣,如果是相同的類型則為1,否則是0

  7.對兩個相似性矩陣進行加權平均

  8.使用模型進行預測

 數據集:https://github.com/Mounment/R-Project


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM