์์ํ๋ฉฐ..! :)
๋ฐ์ดํฐ ๋ถ์ ์์
์ ์๊ฐํ๋ฉฐ ๋ฐฐ์ฐ๊ฒ๋ ์ถ์ฒ์์คํ
!
์ ํ๋ธ๊ฐ ์์ฉํ ๋ ์์ฆ, '์ ํ๋ธ ์๊ณ ๋ฆฌ์ฆ ์ผ์ํ๋ค~'๋ผ๋ ๋ง์ ์
์ ๋ฌ๊ณ ์ด๋ฉด์ ์ค์ํ์ ์ถ์ฒ์์คํ
์ด ๋
น์๋ค์ด์๋ค .์ด๋ฐ ์ถ์ฒ์์คํ
์ ์ง์ ๊ตฌํํด๋ณผ ์ ์๋ค๋ ๊ฒ ์์ฒด๋ง์ผ๋ก๋ ๊ต์ฅํ ํฅ๋ฏธ๊ฐ ์๊ฒผ๊ณ , ๋ด ์กธ์
ํ๋ก์ ํธ ๋ํ ์ถ์ฒ์์คํ
์ผ๋ก ์ฃผ์ ๊ฐ ์ ํด์ง๊ฒ ๋์์ง... ์ด์จ๋ , ๋ฏธ๋์ ๋๋ ์ค๋ฌด์์ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์ผ๋ง๋ ๋๋จํ ์ถ์ฒ์์คํ
์ ๊ตฌํํ ์ ์์๊น!? ๋ฒ์จ ์ค๋ ๋น! ์ผ๋ฅธ ์ทจ์
ํ์....โ
-- ๋ณธ ์๋ฃ๋ ๋๊ตญ๋ํ๊ต ๋ฐ์ดํฐ์ด๋ผ๋ฆฌํฑ์ค ๊ฐ์ ์๋ฃ๋ฅผ ํ์ฉํ์ฌ ์งํํ ํ๋ก์ ํธ ์ ๋๋ค :)
1. ํ๋ก์ ํธ ์งํ ๋ฐฉํฅ
R ์ธ์ด๋ฅผ ํ์ฉํ์ฌ Collaborative Filtering ๊ธฐ๋ฒ์ ํ์ฉํ Recommendation System์ ๊ตฌํํ ๊ฒ์ด๋ค. Collaborative Filtering ๊ธฐ๋ฒ ์ค์์๋, Item-Based ์ User-Based ๋๊ฐ์ง์ ๋ฐฉ๋ฒ์ ์ด์ฉํด ๋ณผ๊ฒ์ด๋ค! ๋ ๊ธฐ๋ฒ์ ๋ํ ์ฐจ์ด์ ์์ธํ ์ค๋ช ์ ์กฐ๋ง๊ฐ ๋ ์ ๋ก๋ ํด์ผ๊ฒ ๋ค :) (๊ณต๋ถ ํ์ํด...!)
2. ํ๋ก์ ํธ ์ฃผ์
์ฌ์ฉ์๊ฐ ๋จ๊ธด ์ํ ํ์ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ์ฌ ์ถ์ฒ์์คํ ์ ๊ตฌํํ๋ค.
User-base, Item-based ๋๊ฐ์ง์ ๋ฐฉ์์ ์ฌ์ฉํด๋ณด๊ณ , Bestํ ๋ชจ๋ธ์ด ๋ฌด์์ธ์ง ์ดํด๋ณด๋๋ก ํ๋ค.
3. ํ์ฉ ๋ฐ์ดํฐ
- MovieLense์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋ค.
- 1682๊ฐ์ ์ํ์ 943๋ช ์ ์ ์ ๊ฐ ๋จ๊ธด 10๋ง๊ฐ์ ํ์ ๋ฆฌ๋ทฐ๋ฅผ ํ์ฉํ๋ค. (ํ์ ์ 1~5์ ์ฌ์ด)
- ๊ฐ ์ ์ ๋ ์ต์ 20๊ฐ์ ์ํ์ ๋ฆฌ๋ทฐ ํ์ ์ ๋จ๊ฒผ๋ค.
- ์ ์ ์ ๊ฐ๋จํ demo ์ ๋ณด๋ ๋ค์ด์๋ค. (age, gender, occupatin, zip)
3. ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
3.1 ํ๊ฒฝ ๊ตฌ์ฑ
์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ์งํํ๊ธฐ ์ํ library๋ฅผ ์ค์น ๋ฐ ๋ถ๋ฌ์์ค๋ค.
install.packages("SnowballC") #tf-idf๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํ ํจํค์ง
install.packages("class") #KNN ๋ถ์์ ์ํ ํจํค์ง
install.packages("dbscan") #KNN ๋ถ์์ ์ํ ํจํค์ง
install.packages("proxy") #์ฝ์ฌ์ธ ์ ์ฌ๋, ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํ ํจํค์ง
install.packages("recommenderlab") #์ถ์ฒ ์์คํ
์ ์ํ ํจํค์ง
install.packages("dplyr") #๋ฐ์ดํฐ ํ๋ ์์ ์ฒ๋ฆฌํ๋ ํจ์ ํจํค์ง
install.packages("tm") #tf-idf matrix๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํ ํจํค์ง
install.packages('caTools')
library(recommenderlab)
library(dplyr)
library(tm)
library(SnowballC)
library(class)
library(dbscan)
library(proxy)
library(caTools)
3.2 ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
# ๊ฒฝ๋ก ์ค์ ํ๊ณ ๋ฐ์ดํฐ ์ฝ๊ธฐ
setwd("C:\\Users\\ml-100k")
data <- read.table('u.data')
colnames(data) <- c('user_id','item_id','rating','timestamp')
data = data[,-which(names(data) %in% c('timestamp'))]
# ์ฝ์ด์จ ๋ฐ์ดํฐ ํ์ธํ๊ธฐ
summary(data)
str(data)
hist(data$rating, main="Histogram of Rating")
# Data sparsity
RatingNumber = nrow(data)
MovieNumber = length(unique(data$item_id))
UserNumber = length(unique(data$user_id))
3.3 ๋ฐ์ดํฐ๋ฅผ Matrix ํํ๋ก ๋ณํ
์ถ์ฒ์์คํ ์ ํ๋ ฌ ๊ธฐ๋ฐ์ผ๋ก ๋์๊ฐ๊ธฐ์, Matrix ๋ก ๋ณํํด์ ์ฌ์ฉํด์ฃผ์ด์ผ ํ๋ค.
# ๋งคํธ๋ฆญ์ค ํํ๋ก ๋ณํ
data.frame2matrix = function(data, rowtitle, coltitle, datatitle,
rowdecreasing = FALSE, coldecreasing = FALSE,
default_value = NA) {
## ์ด ์ด๋ฆ ์กด์ฌํ๋์ง ํ์ธ
if ( (!(rowtitle%in%names(data)))
|| (!(coltitle%in%names(data)))
|| (!(datatitle%in%names(data))) ) {
stop('data.frame2matrix: bad row-, col-, or datatitle.')
}
## ์ด ๊ฐ์
ndata = dim(data)[1]
## ํ ๋ฐ ์ด ์ด๋ฆ
rownames = sort(unique(data[[rowtitle]]), decreasing = rowdecreasing)
nrows = length(rownames)
colnames = sort(unique(data[[coltitle]]), decreasing = coldecreasing)
ncols = length(colnames)
## matrix ์ด๊ธฐํ
out_matrix = matrix(NA,
nrow = nrows, ncol = ncols,
dimnames=list(rownames, colnames))
## ๋ฐ์ดํฐ์ ํ ๋ฐ๋ณต
for (i1 in 1:ndata) {
## ํ์ฌ ๋ฐ์ดํฐ ํ์ ๋ํ ํ๋ ฌ-ํ ๋ฐ ํ๋ ฌ-์ด ์์ธ ๊ฐ์ ธ์ค๊ธฐ
iR = which(rownames==data[[rowtitle]][i1])
iC = which(colnames==data[[coltitle]][i1])
## matrix ํญ๋ชฉ (iR, iC)๊ฐ ๊ณต๋ฐฑ์ด ์๋๋ผ๋ฉด ์๋ฌ ๋ฐ์
if (!is.na(out_matrix[iR, iC])) stop('data.frame2matrix: double entry in data.frame')
out_matrix[iR, iC] = data[[datatitle]][i1]
}
## matrix ๊ฒฐ์ธก์น์ default ๊ฐ ์ฝ์
ํ๊ธฐ
out_matrix[is.na(out_matrix)] = default_value
# return matrix
return(out_matrix)
}
# colnames(data) <- c('user_id','item_id','rating','timestamp')
pre_data = data.frame2matrix(data, 'user_id', 'item_id', 'rating')
target_data <- as(as.matrix(pre_data), "realRatingMatrix")
3.4 ๋ฐ์ดํฐ Partitions
๋ฐ์ดํฐ๋ 30ํ ์ด์์ ๋ฆฌ๋ทฐ๊ฐ ์กด์ฌํ๋ ์ํ๋ง ์ฌ์ฉํ ๊ฒ์ด๋ค.
# ๋ฆฌ๋ทฐ๊ฐ 30๋ฒ ์ด์ ๋ฌ๋ฆฐ ์ํ๋ง ์ด์ฉ
useData <- data[data$user_id
%in% names(table(data$user_id))
[table(data$user_id)>30],]
๊ทธ๋ฆฌ๊ณ Train๊ณผ Test๋ฅผ 7:3 ๋น์จ๋ก ๋๋์ด ์ฃผ์๋ค.
# Train:Test = 7:3
spl <- sample.split(useData$rating,0.7)
train <- subset(useData,spl==TRUE)
test <- subset(useData,spl==FALSE)
ํ์ ์ด ๊ฐ์ฅ ๋์ ์ํ, ์กฐํ์๊ฐ ๋์ ์ํ๋ฅผ ์กฐํํด๋ณด์.
# ํ๊ท ํ์ Top 5
avg_top5 <- target_data %>% normalize %>% colMeans %>% sort(decreasing=TRUE) %>% head(5)
avg_top5
# ์กฐํ์ Top 5
freq_top5 <- target_data %>% normalize %>% colCounts %>% sort(decreasing=TRUE) %>% head(5)
freq_top5
# ํ์ & ์กฐํ์ Top 5
avg_freq_top5 <- target_data %>% normalize %>% binarize(minRating=1) %>% colCounts() %>% sort(decreasing=TRUE) %>% head(5)
avg_freq_top5
- ํ๊ท ํ์ ์ด ๊ฐ์ฅ ๋์ ์ํ Top 5
- 814๋ฒ ์ํ, 1536๋ฒ ์ํ, 1467๋ฒ์ํ, 1500๋ฒ ์ํ, 1599๋ฒ ์ํ ์์ผ๋ก ํ์ ์ด ๋๋ค.
- ํ์ ์ ํ๊ท ์ ๊ฐ๊ฐ 1.90, 1.70, 1.49, 1.47, 1.41 ์ด๋ค!
- ์กฐํ์๊ฐ ๋์ ์ํ Top5
- 50๋ฒ ์ํ, 258๋ฒ ์ํ, 100๋ฒ ์ํ, 181๋ฒ ์ํ, 294๋ฒ ์ํ ์์ผ๋ก ์กฐํ์๊ฐ ๋๋ค.
- ์กฐํ์๋ ๊ฐ๊ฐ 583, 509, 508 507, 485 ์์ผ๋ก ๋ณด์ฌ์ง๋ค.
- ํ์ ๊ณผ ํ๊ท ๋์์ ๊ณ ๋ คํ ์ ์๊ฐ ๋์ ์ํ Top5
- 50๋ฒ, 100๋ฒ, 127๋ฒ 174๋ฒ, 313๋ฒ ์์ผ๋ก ๋๋ค.
- ๊ฐ๊ฐ 280, 190, 182, 168, 159์ ์ด๋ค.
4. User-based Collaborative Filtering
4.1 ๋ฐ์ดํฐ์ train/test๋ฅผ ๋๋์ด์ค๋ค.
75 %์ train set ๊ณผ 25%์ test set์ผ๋ก ๋ถ๋ฅํด์ฃผ์๋ค.
# Train / Test data ๋๋๊ธฐ
set.seed(100)
index <- sample(1:nrow(target_data), size=nrow(target_data)*0.75)
# ๋ฐ์ดํฐ ๊ตฌ๋ถ(train/test๋ฐ์ดํฐ๋ก ๊ตฌ๋ถ)
train <- target_data[index, ]
test <- target_data[-index, ]
dim(train)
4.1 User-based Collaborative Filtering ๋ชจ๋ธ๋ง
# User-based Collaborative Filtering ๋ชจ๋ธ๋ง
recommender_models <- recommenderRegistry$get_entries(dataType="realRatingMatrix")
model_UBCF <- Recommender(data=train, method="UBCF")
model_UBCF
model_UBCF@model$data
4.2 ์์ธก ์ํ
# Test data ์์ธก (๊ฐ์ฅ ๋ง์ด ์ถ์ฒ๋ฐ์ ๊ฐ๋ฅ์ฑ์ด ๋์ ์ํ ์์ 10๊ฐ)
pred_UBCF <- predict(model_UBCF, newdata=test, n=10)
pred_UBCF
# Test data์ ์๋ ํด๋น ์ฌ์ฉ์๊ฐ ๋ช ๋ฒ์งธ ์ํ๋ฅผ ์ถ์ฒ๋ฐ์์ง ์์ธก
pred_list_UBCF <- sapply(pred_UBCF@items, function(x) { colnames(pre_data)[x] })
pred_list_UBCF[5] ## 5๋ฒ ์ฌ์ฉ์์๊ฒ ์ถ์ฒํ๋ ์ํ
# Test์ ์ํ ์ฌ์ฉ์๋ค์๊ฒ ๋ช๊ฐ์ ์ํ๊ฐ ์ถ์ฒ๋์๋๊ฐ?
table(unlist(lapply(pred_list_UBCF, length)))
4.3 ๋ชจ๋ธ ํ๊ฐ
#๋ชจ๋ธํ๊ฐ ( train = 0.8, k = 10 )
data_modify <- target_data[rowCounts(target_data)]
eval_sets_UBCF <- evaluationScheme(data = data_modify,
method = "cross-validation",
train = 0.8, k = 10, goodRating = 3, given = 3)
sapply(eval_sets_UBCF@runsTrain, length)
getData(eval_sets_UBCF, "train")
# Traning
recomm_eval <- Recommender(data = getData(eval_sets_UBCF, "train"),
method = "UBCF", parameter = NULL)
recomm_eval
# prediction
pred_eval <- predict(recomm_eval,
newdata = getData(eval_sets_UBCF, "known"),
n = 10, type = "ratings")
pred_eval
# Calculate accuracy(๊ฐ ์ฌ์ฉ์๋ณ ์ถ์ฒ์ด ์ ์ ํ๋์ง)
accuracy_eval_UBCF <- calcPredictionAccuracy(x = pred_eval,
data = getData(eval_sets_UBCF,
"unknown"),
byUser = TRUE)
head( accuracy_eval_UBCF, 10 )
# User-based Collaborative Filtering ์ ํ๋
colMeans(accuracy_eval_UBCF, na.rm = TRUE)
# ์ ๋ฐ๋/์ฌํ์จ์ ์ด์ฉํ ์ ํ๋
accuracy_eval2_UBCF <- evaluate(x=eval_sets_UBCF, method="UBCF" )
head( getConfusionMatrix(accuracy_eval2_UBCF), 10)
# ROC ์ปค๋ธ
plot(accuracy_eval2_UBCF, annotate=TRUE, main="ROC Curve")
5. Item-based Collaborative Filtering
5.1 Item-based Collaborative Filtering ๋ชจ๋ธ๋ง
list(k)๋ ์์ดํ ์ ์ ์ฌ๋ ๊ฐ์ ๊ณ์ฐํ๋๋ฐ ๊ณ ๋ คํ๋ ์ด์์ ์๋ฅผ ์๋ฏธํ๋ค. k=30์ผ๋ก ์ง์ !
# Item-based Collaborative Filtering
model_IBCF <- Recommender(data = train,
method = "IBCF",
parameter = list(k = 30))
model_IBCF
str( getModel(model_IBCF) )
5.2 ์์ธก
# Test data ๋ด์ฉ ์์ธก
pred_IBCF <- predict(model_IBCF, newdata=test, n=10)
pred_list_IBCF <- sapply(pred_IBCF@items, function(x) { colnames(target_data)[x] })
pred_list_IBCF[1]
table(unlist(lapply(pred_list_IBCF, length)))
5.3 ๋ชจ๋ธํ๊ฐ
๋ฆฌ๋ทฐ๊ฐ 30๊ฐ ์ด์์ธ ๋ฐ์ดํฐ๋ง ์ฌ์ฉํด์, Train ๊ณผ Test๋ฅผ 7:3์ผ๋ก ๋๋๊ณ ์์ 10๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์์ธกํ๋ค.
k๊ฐ์ 5๋ก ์ง์ ํ๋ค.
# ๋ชจ๋ธํ๊ฐ
data_modify <- target_data[rowCounts(target_data)]
eval_sets_IBCF <- evaluationScheme(data = data_modify,
method = "cross-validation",
train = 0.7,
k = 5,
goodRating = 3,
given = 15)
# ๋ฐ์ดํฐ ์ธํธ ์ถ์ถ
sapply(eval_sets_IBCF@runsTrain, length)
getData(eval_sets_IBCF, "train")
# Training
recomm_eval_IBCF <- Recommender(data = getData(eval_sets_IBCF, "train"),
method = "IBCF",
parameter = NULL)
recomm_eval_IBCF
# Prediction
pred_eval_IBCF <- predict(recomm_eval_IBCF,
newdata = getData(eval_sets_IBCF, "known"),
n = 10, type = "ratings")
pred_eval_IBCF
# ์ ํ๋ ๊ณ์ฐ
accuracy_eval_IBCF <- calcPredictionAccuracy(x = pred_eval_IBCF,
data = getData(eval_sets_IBCF,
"unknown"),
byUser = TRUE)
head(accuracy_eval_IBCF,10)
# ํ๊ท ์ ํ๋
meanitem<- colMeans(accuracy_eval_IBCF,na.rm = TRUE)
# Item-based Collaborative Filtering ์ ํ๋
meanitem
# ์ ๋ฐ๋/์ฌํ์จ ์ ํ๋
accuracy_eval_IBCF <- evaluate(x = eval_sets_IBCF,
method = "IBCF",
n = seq(10, 100, by = 10))
head( getConfusionMatrix(accuracy_eval_IBCF) )
#ROC ์ปค๋ธ
plot(accuracy_eval_IBCF, annotate = TRUE, main = "ROC Curve")
5.4 ๋งค๊ฐ๋ณ์ ํ๋
- ์์ดํ ๊ฐ ์ ์ฌ๋๋ฅผ ๊ณ์ฐํ๋๋ฐ ํ์ํ ์ต์ ์ ์ด์์ ์(K)๋ฅผ ์์๋ณด๊ธฐ ์ํด ๋งค๊ฐ๋ณ์ ํ๋์ ์งํํ์๋ค.
- ์ฝ์ฌ์ธ ๋๋ ํผ์ด์จ ์๊ด๊ณ์ ์ค ์ ์ฌ๋ ๊ณ์ฐ ๊ธฐ์ค์ ์ ํํ๋ค.
#๋งค๊ฐ๋ณ์ ํ๋
#1. ์์ดํ
๊ฐ ์ ์ฌ๋๋ฅผ ๊ณ์ฐํ๋๋ฐ ํ์ํ ์ต์ ์ ์ด์์ ์
#2. ์ฝ์ฌ์ธ ๋๋ ํผ์ด์จ ์๊ด๊ณ์ ์ค ์ ์ฌ๋ ๊ณ์ฐ ๊ธฐ์ค ์ ํ
vector_k <- c(5, 10, 20, 30, 40)
mod1 <- lapply(vector_k, function(k, l) { list(name = "IBCF",
parameter = list(method = "cosine",
k = k)) })
names(mod1) <- paste0("IBCF_cos_k_", vector_k)
names(mod1)
mod2 <- lapply(vector_k, function(k, l) { list(name = "IBCF",
parameter = list(method = "pearson",
k = k)) })
names(mod2) <- paste0("IBCF_pea_k_", vector_k)
names(mod2)
mod <- append(mod1, mod2)
list_results <- evaluate(x = eval_sets_IBCF,
method = mod,
n = c(1, 5, seq(10, 100, by = 10)))
#๋งค๊ฐ๋ณ์ ๋ณ ROC ์ปค๋ธ
plot(list_results, annotate = c(1, 2), legend = "topleft")
title("ROC Curve")
#๋งค๊ฐ๋ณ์ ๋ณ ์ฌํ/ํ์
plot(list_results, "prec/rec", annotate = 1, legend = "bottomright")
title("Precision-Recall")
getTopNLists signature(x = "realRatingMatrix"):
getTopNLists()
6. ์ต์ข ๋ชจ๋ธ ์ ์
RMSE ๋, ๊ด์ธก๊ฐ์์ ๋ํ๋๋ ์ค์ฐจ๋ฅผ ์ ๊ณฑํด์ ํ๊ท ํ๊ฐ์ ์ ๊ณฑ๊ทผ์ ์๋ฏธํ๋ค. RMSE์ ๋ํ ์์ธํ ์ค๋ช ์ ๋ค๋ฅธ ํฌ์คํ ์์ ๋ค๋ฃจ๋๋ก ํ๊ณ , RMSE๊ฐ์ด ๊ฐ์ฅ ์ต์ํ ๋๊ฒ๋ ๋ชจ๋ธ์ ๋ง๋๋ ๊ฒ์ด ์ค์ํ๋ค.
๋ฐ๋ผ์ ์ ๋๊ฐ์ ๋ชจ๋ธ (User-based, Item-based) ์ค์์ RMSE๊ฐ ๋ ๋ฎ์ Item-based ๋ชจ๋ธ์ ์ต์ข ๋ชจ๋ธ๋ก ์ ์ ํ๋ฉด ๋๊ฒ ๋ค.
๋ง์น๋ฉฐ,,!
์์ ์์ ๋ฐฐ์ด ๋ด์ฉ์ ํ์ฉํ์ฌ ๋ ๊ฐ์ง์ ๋ชจ๋ธ์ ๊ตฌํํด๋ณด๊ณ , RMSE๋ฅผ ํ์ฉํ์ฌ best ๋ชจ๋ธ์ ์ ์ ํด ๋ณด์๋ค. ๋ค์์๋ ๋ฆฌ๋ทฐ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํด์ ์ถ์ฒ์์คํ ์ ๊ตฌํํด๋ณด๊ณ ์ถ๋ค๊ณ ๋๊ผ๋ค.