1. 程式人生 > >Recommenderlab包實現電影評分預測(R語言)

Recommenderlab包實現電影評分預測(R語言)

來源:http://cos.name/cn/topic/150937

1 獲取電影資料

電影資料來源於http://grouplens.org/datasets/movielens/ 網站,本文分析的資料是MovieLens 100k,總共有100,000個評分,來自1000使用者對1700部電影。

2 資料準備和清理

設定好工程路徑後,可用讀入資料,注意資料的格式,第一列是user id,第二列是item id,第三列是rating,第四列是時間戳,時間戳這裡用不到,可去掉。
> ml100k <- read.table("u.data", header = F, stringsAsFactors = T)
> head(ml100k)
   V1  V2 V3        V4
1 196 242  3 881250949
2 186 302  3 891717742
3  22 377  1 878887116
> ml100k <- ml100k[, -4]
可以簡單看下rating的分佈情況
> prop.table(table(ml100k[, 3]))
         1          2          3          4          5
0.06106870 0.12977099 0.41984733 0.32061069 0.06870229
> summary(ml100k[, 3])
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's
  1.000   3.000   3.000   3.206   4.000   5.000     812
3 stars和4 stars數量最多,接近總數的75%,1 stars和5 stars的數量最少,和預期的一致。

資料格式和我們想要的行為user,列為item的ratingMatrix還有很大的差距,對此可以使用reshape包的cast進行轉換,注意轉換後的缺失值預設為NA。
> library(reshape)
> ml100k <- cast(ml100k, V1 ~ V2, value = "V3")
> ml.useritem=ml100k[,-1]
> ml.useritem[1:3, 1:6]
   1  2  3  4  5  6
1  5  3  4  3  3  5
2  4 NA NA NA NA NA
3 NA NA NA NA NA NA

到此,把資料整理成ratingMatrix,接下來利用recommenderlab處理資料。

3 commenderlab處理資料

在用commenderlab處理資料之前,需將資料轉換為realRatingMatrix型別,這是commenderlab包中專門針對1-5 star的一個新類,需要從matrix轉換得到。上文獲得的ml.useritem有兩個類屬性,其中cast_df是不能直接轉換為matrix的,因此需要去掉這個類屬性,只保留data.frame
> class(ml.useritem)
[1] "cast_df"    "data.frame"
> class(ml.useritem) <- "data.frame"    ##只保留data.frame的類屬性
> ml.useritem <- as.matrix(ml.useritem)
> ml.ratingMatrix <- as(ml.useritem, "realRatingMatrix")  ##轉換為realRatingMatrix
> ml.ratingMatrix
943 x 1682 rating matrix of class ‘realRatingMatrix’ with 100000 ratings.

ml.ratingMatrix是可以用recommenderlab進行處理的realRatingMatrix,943是user數,1682指的是item數, realRatingMatrix可以很方便的轉換為matrix和list
> as(ml.ratingMatrix , "matrix")[1:3, 1:10]
   1  2  3  4  5  6  7  8  9 10
1  5  3  4  3  3  5  4  1  5  3
2  4 NA NA NA NA NA NA NA NA  2
3 NA NA NA NA NA NA NA NA NA NA
> as(ml.ratingMatrix , "list")[[1]][1:10]
 1  2  3  4  5  6  7  8  9 10
 5  3  4  3  3  5  4  1  5  3

另外,recommenderlab包中有提供用於歸一化的函式normalize,預設是均值歸一化x – mean,建立推薦模型的函式,裡面有歸一化處理的,在此不必單獨進行歸一化。

4 recommender簡單介紹

在建模之前可以先看下針對realRatingMatrix,recommederlab有提供那些推薦技術,總共有6種,我們會用到其中的三種random(隨機推薦),popular(基於流行度推薦),ibcf(基於專案協同過濾)
> recommenderRegistry$get_entries(dataType = "realRatingMatrix")
$IBCF_realRatingMatrix
Recommender method: IBCF  ##基於專案協同過濾
Description: Recommender based on item-based collaborative filtering (real data).
Parameters:
   k method normalize normalize_sim_matrix alpha na_as_zero minRating
1 30 Cosine    center                FALSE   0.5      FALSE        NA
$PCA_realRatingMatrix    ##主成份分析
Recommender method: PCA
Description: Recommender based on PCA approximation (real data).
Parameters:
  categories method normalize normalize_sim_matrix alpha na_as_zero minRating
1         20 Cosine    center                FALSE   0.5      FALSE        NA
$POPULAR_realRatingMatrix  ##基於流行度推薦
Recommender method: POPULAR
Description: Recommender based on item popularity (real data).
Parameters: None
$RANDOM_realRatingMatrix   ##隨機推薦
Recommender method: RANDOM
Description: Produce random recommendations (real ratings).
Parameters: None
$SVD_realRatingMatrix   ##奇異值分解
Recommender method: SVD
Description: Recommender based on SVD approximation (real data).
Parameters:
  categories method normalize normalize_sim_matrix alpha treat_na minRating
1         50 Cosine    center                FALSE   0.5   median        NA
$UBCF_realRatingMatrix   ##基於使用者協同過濾
Recommender method: UBCF
Description: Recommender based on user-based collaborative filtering (real data).
Parameters:
  method nn sample normalize minRating
1 cosine 25  FALSE    center        NA

以IBCF為例簡單介紹引數的含義
K:取多少個最相似的item,預設為30
method :相似度演算法,預設採用餘弦相似演算法cosine
Normalize:採用何種歸一化演算法,預設均值歸一化x –mean
normalize_sim_matrix:是否對相似矩陣歸一化,預設為否
alpha:alpha引數值,預設為0.5
na_as_zero:是否將NA作為0,預設為否
minRating:最小評分,預設不設定
這些引數均可在建立模型時設定,本文全部採用預設引數。

5 建立推薦模型

recommender是recommenderlab包中用於建立模型的函式,用法也相當簡單,注意在呼叫recommender之前需給矩陣的所有列按照itemlabels進行列命名。
> colnames(ml.ratingMatrix) <- paste("M", 1:1682, sep = "")
> as(ml.ratingMatrix[1,1:10], "list")
$<code>1code>
 M1  M2  M3  M4  M5  M6  M7  M8  M9 M10
  5   3   4   3   3   5   4   1   5   3
##【Warning】在建立推薦模型之前一定要給item按照itemLabels進行命名,否則會有如下錯誤
##Error in validObject(.Object) :
##  invalid class “topNList” object: invalid object for slot "itemLabels" in class "topNList": got class "NULL", should be or extend class "character"
> ml.recommModel <- Recommender(ml.ratingMatrix[1:800], method = "IBCF")
> ml.recommModel
Recommender of type ‘POPULAR’ for ‘realRatingMatrix’
learned using 800 users.

模型建立以後,可以用來進行預測和推薦了,同樣使用predict函式,這裡分別給801-803三個使用者進行推薦,predict函式有一個type引數,可用來設定是top-n推薦還是評分預測,預設是top-n推薦。
##TopN推薦,n = 5 表示Top5推薦
> ml.predict1 <- predict(ml.recommModel, ml.ratingMatrix[801:803], n = 5)
> ml.predict1
Recommendations as ‘topNList’ with n = 5 for 3 users.
> as( ml.predict1, "list")  ##顯示三個使用者的Top3推薦列表
[[1]]
[1] "M50"  "M100" "M127" "M98"  "M174"
[[2]]
[1] "M50"  "M100" "M127" "M174" "M313"
[[3]]
[1] "M50"  "M100" "M127" "M98"  "M174"
##使用者對item的評分預測
> ml.predict2 <- predict(ml.recommModel, ml.ratingMatrix[801:803], type = "ratings")
> ml.predict2
> as(ml.predict2, "matrix")[1:3, 1:6]   ##檢視三個用於對M1-6的預測評分,注意:實際的預測評分還要在此基礎上加上使用者的平均評分
           M1         M2        M3          M4         M5        M6
801 0.2909692 -0.2749699 -0.350463 -0.02231146 -0.2300878 0.2049403
802 0.2909692 -0.2749699 -0.350463 -0.02231146 -0.2300878 0.2049403
803 0.2909692 -0.2749699 -0.350463 -0.02231146 -0.2300878 0.2049403

6 模型的評估

本文只考慮評分預測模型的評估,對於Top-N推薦模型請檢視後面的參考資料,對於評分預測模型的評估,最經典的引數是RMSE(均平方根誤差)
rmse <- function(actuals, predicts)
{
    sqrt(mean((actuals - predicts)^2, na.rm = T))
}
幸運的是,recommenderlab包有提供專門的評估方案,對應的函式是evaluationScheme,能夠設定採用n-fold交叉驗證還是簡單的training/train分開驗證,本文采用後一種方法,即將資料集簡單分為training和test,在training訓練模型,然後在test上評估。
> model.eval <- evaluationScheme(ml.ratingMatrix[1:943], method = "split",
+ train = 0.9, given = 15, goodRating = 5)
> model.eval
Evaluation scheme with 15 items given
Method: ‘split’ with 1 run(s).
Training set proportion: 0.900
Good ratings: >=5.000000
Data set: 943 x 1682 rating matrix of class ‘realRatingMatrix’ with 100000 ratings.
##分別用RANDOM、UBCF、IBCF建立預測模型
> model.random <- Recommender(getData(model.eval, "train"), method = "RANDOM")
> model.ubcf <- Recommender(getData(model.eval, "train"), method = "UBCF")
> model.ibcf <- Recommender(getData(model.eval, "train"), method = "IBCF")
##分別根據每個模型預測評分
> predict.random <- predict(model.random, getData(model.eval, "known"), type = "ratings")
> predict.ubcf <- predict(model.ubcf, getData(model.eval, "known"), type = "ratings")
> predict.ibcf <- predict(model.ibcf, getData(model.eval, "known"), type = "ratings")

這裡簡單介紹,資料集是如何劃分的,其實很簡單,對於使用者沒有評分過的items,是沒法進行模型評估的,因為預測值沒有參照物件。getData的引數given便是來設定用於預測的items數量。

接下來計算RMSE,對比三個模型的評估引數,calcPredictionError函式可以計算出MAE(絕對值均方誤差)、MSE和RMSE。


> error <- rbind(
+ calcPredictionError(predict.random, getData(model.eval, "unknown")),
+ calcPredictionError(predict.ubcf, getData(model.eval, "unknown")),
+ calcPredictionError(predict.ibcf, getData(model.eval, "unknown")))
> rownames(error) <- c("RANDOM", "UBCF", "IBCF")
> error
             MAE      MSE     RMSE
RANDOM 1.7267304 4.486820 2.118211
UBCF   0.8254453 1.062409 1.030732
IBCF   0.8444152 1.333968 1.154976

為了更好的說明RMSE與training/test ratio、given等引數的關係,我們可以進行多組的比較。

從上面的兩張圖可以得出如下結論:
1、training/test ratio對RMSE沒什麼影響,並不是training比重越大RMSE越小,因此在實際過程中可適當降低training的比例,減少建立模型所需時間;
2、given值對協同過濾的推薦系統影響很多,given越大(用於預測items數量)RMSE越小,當然這裡最大given值為20,在[1, 20]範圍內,顯然given = 20是最優的;
3、基於使用者的協同過濾表現好,隨機推薦最差,另外,items的數量超過2倍的使用者數,因此無論從降低RMSE還是提高模型效能來說,UBCF都是最好的選擇。有興趣的童鞋還可以嘗試分析近鄰數K、相似度演算法和RMSE的關係。
在《recommender system handbook》的4.2.5節,很詳細對比了IBCF和UBCF,再結合以上的資料,可以很好的理解為什麼在這個案例中UBCF要明顯優於IBCF。

7 參考資料

[1] recommender system handbook
[2] Item-Based Collaborative Filtering Recommendation Algorithms
[3] recommenderlab: A Framework for Developing and Testing Recommendation Algorithms