Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 통계학
- 사례
- 게임 이탈 분석
- 봇탐지
- 기초통계학
- LTV
- 유저이탈
- self-similarity
- 이상탐지
- dacon
- 데이터 분석
- 자기유사도
- anomaly
- LTV예측
- 딥러닝
- AutoEncoder
- 데이터분석
- 자료의요약
- 대회
- google.cloud
- Detection
- AE
- 게임분석
- 게임
- Kaggle
- 게임 데이터분석
- PYTHON
- anomaly detection
- 오토인코더
- google.oauth2
Archives
- Today
- Total
사쿠의 데이터 블로그
Stacking 혹은 Meta모델링 적용하기 본문
1. stacking에 관하여
1.1 stacking이란?
Kaggle 상위권 랭커들이 사용하는 알고리즘으로 여러 모델들의 장점을 하나로 합해 새로운 모델을 만드는 방법이다.
1.2 왜?
다음과 같은 가정과 장단점이 존재한다.
1.2.1. 가정
1. 모든 모델은 `mistake`를 가지고 있다. --> 완벽한 모델은 존재하지 않는다.
아무리 Xgboost, lightGBM 등 앙상블 계열 알고리즘이 뛰어나도 알고리즘 구조상
놓치는 부분이 존재한다는 것을 인정한다.
2. 잘 맞추는 부분을 통합 한다면 더 잘 맞추게 될 것이다.
1.2.2. 장점
1. 각 알고리즘의 좋은 부분을 습득 가능
1.2.3. 단점
1. 연산량이 증가한다
원본링크 위 사진은 1.2.1 가정
1번의 예시가 잘 담겨있다.
완벽한 알고리즘은 존재하지 않으며 각각의 장점을 살려보자!
KNN: 중앙에서 높은 정확도 & SVM: 가장자리에서 높은 정확도
2. Stacking 설명
2.1 Base Model 혹은 Level 0 모델
Base Model에 해당되는 알고리즘이 딱히 정해져 있지는 않다.
다만, 위에서 본 다트 예제 처럼 특정한 부분의 정확도가 높다면 쓸만하다.
전체적인 정확도가 낮더라도!!!
Base Model을 구성할 때, 다음 2가지 단계를 거쳐야 한다.
1. 알고리즘을 선정 (KNN, SVM 등)
2. Hyper Parameter 튜닝
먼저 데이터를 불러온다.
데이터는 이곳에서 받을 수 있다
setwd("D:/MLPB-master/Problems/Classify Dart Throwers")
# data load
train <- fread("_Data/train.csv")
test <- fread("_Data/test.csv")
# 타겟 변수 factor로 변경
train$Competitor<- as.factor(train$Competitor)
test$Competitor<- as.factor(test$Competitor)
2.1.1 KNN
어떤 K가 (1<=k<=40) 뛰어난지 알 수 없어 Cross Validation을 통해 k를 선택한다.
#Base Model 1: kNN
set.seed(7)
knn.cv <- tune.knn(x = train_mat, y = factor(train$Competitor), k = seq(1, 40, by = 2),
tunecontrol = tune.control(sampling = "cross"), cross = 10)
knn <- knn(train_mat, test_mat, factor(train$Competitor), k = knn.cv$best.parameters[, 1])
2.1.2 SVM - poly
마찬가지로 SVM에 대해서도 진행한다.
# Base Model 2: SVM with Polynomial Kernel
set.seed(7)
poly.svm.cv <- tune.svm(x = train_mat, y = factor(train$Competitor), kernel = "polynomial",
degree = c(2, 3, 4), coef0 = c(0.1, 0.5, 1, 2),
cost = c(0.001, 0.01, 0.1, 1, 3, 5),
tunecontrol = tune.control(sampling = "cross"))
poly_svm <- predict(poly.svm.cv$best.model, test_mat)
2.1.3 Base Model 결과
Accuracy(kNN): 0.7027
Accuracy(SVM, Polynomial): 0.8649
Accuracy(SVM, Radial): 0.7568
Accuracy(Random Forest): 0.7838
(SVM-Radial과 Random Forest는 아래 코드 참조)
2.1.4 Base Model 시각화
2.2 Meta model 혹은 Level 1 모델
2.1 에서 Base 모델을 선정하고 hyper paraneter를 잘 튜닝 했다면 꽤 찮은 결과가 나왔을 것이다.
하지만, 각자 잘 맞추는 영역이 다르니, 이를 통합해 보자.
2.2.1 Meta Model 선정
선정에 기준은 없다. 이 부분은 참고한 인터뷰를 읽어 보아도 Art의 영역이라고 한다.
그래서 이번 Meta Model은 위에서 다뤘던 RF로 진행한다.
Accuracy(Stacked Model): 0.8649
ACC는 좀전 SVM-poly보다 좋아 지지 않았다.
이 친구가 워낙 잘 맞춘 이유도 한몫 한 것 같다.
2.2.2 Meta Model 시각화
SVM-poly의 모습과 Meta로 사용한 RF의 모습이 담긴 것 같다.
2.2.3 마무리
-
발전 방향
- Base Model 선정 자동화
- Base Model을 변수 선택처럼 Stack시 자동화
- 다양한 Meta model 선정
-
아쉬운 점
- 정확한 이유 없이 Stacking 하는 법만 알게 되었다.
3 실습
데이터는 이곳에서 받을 수 있다
# 자료 출처:
# http://blog.kaggle.com/2016/12/27/a-kagglers-guide-to-model-stacking-in-practice/
options(scipen=10)
library(data.table)
library(caret)
library(dplyr)
library(e1071)
library(class)
library(randomForest)
setwd("D:/MLPB-master/Problems/Classify Dart Throwers")
# data load
train <- fread("_Data/train.csv")
test <- fread("_Data/test.csv")
train$Competitor<- as.factor(train$Competitor)
test$Competitor<- as.factor(test$Competitor)
# train, test간 데이터는 일정한지 비교
par(mfrow=c(1,2))
plot(train$XCoord, train$YCoord, col=train$Competitor)
plot(test$XCoord, test$YCoord, col=test$Competitor)
par(mfrow=c(1,1))
# X를 Input으로 받는 알고리즘을 위해, model.matrix() 함수를 사용한다.
train_mat <- model.matrix(data = train, Competitor ~ XCoord+ YCoord)[, -1]
test_mat <- model.matrix(data = test, Competitor ~ XCoord+ YCoord)[, -1]
#### Construct Base Model ###
# 생성한 데이터를 이용해서 Level 0의 기본 모델들을 생성한다.
# 사용할 모델은 총 4개로 다음과 같다.
# k Nearest Neighbor
# Support Vector Machine with Polynomial Kernel
# Support Vector Machine with Radial Kernel
# Random Forest
# 각각의 모델들은 모두 10-fold Cross Validation을 이용해서 Parameter tuning을 한다.
#Base Model 1: kNN
set.seed(7)
knn.cv <- tune.knn(x = train_mat, y = factor(train$Competitor), k = seq(1, 40, by = 2),
tunecontrol = tune.control(sampling = "cross"), cross = 10)
knn <- knn(train_mat, test_mat, factor(train$Competitor), k = knn.cv$best.parameters[, 1])
# Base Model 2: SVM with Polynomial Kernel
set.seed(7)
poly.svm.cv <- tune.svm(x = train_mat, y = factor(train$Competitor), kernel = "polynomial",
degree = c(2, 3, 4), coef0 = c(0.1, 0.5, 1, 2),
cost = c(0.001, 0.01, 0.1, 1, 3, 5),
tunecontrol = tune.control(sampling = "cross"))
poly_svm <- predict(poly.svm.cv$best.model, test_mat)
# Base Model 3: SVM with Radial Kernel
set.seed(7)
radial.svm.cv <- tune.svm(x = train_mat, y = factor(train$Competitor), kernel = "radial",
gamma = c(0.1, 0.5, 1, 2, 3), coef0 = c(0.1, 0.5, 1, 2),
cost = c(0.001, 0.01, 0.1, 1, 3, 5),
tunecontrol = tune.control(sampling = "cross"))
radial_svm <- predict(radial.svm.cv$best.model, test_mat)
# Base Model 4: Random Forest
# 랜덤 포레스트의 경우 변수가 현재 2가지 밖에 없어서 전부 사용하기로 한다.
set.seed(7)
rf <- randomForest(train_mat, train$Competitor, mtry = 2)
random_Forest <- predict(rf, test_mat)
ACC<- function(Y, Y_hat){
tab<- table(Y,Y_hat)
acc = sum(diag(tab))/sum(tab)
acc = round(acc,4)
return(acc)
}
cat("Accuracy(kNN):", ACC(Y = test$Competitor, Y_hat = knn),
"\nAccuracy(SVM, Polynomial):", ACC(Y = test$Competitor, Y_hat = poly_svm),
"\nAccuracy(SVM, Radial):", ACC(Y = test$Competitor, Y_hat = radial_svm),
"\nAccuracy(Random Forest):", ACC(Y = test$Competitor, Y_hat = random_Forest)
)
### 시각화 ###
x<- subset(train%>%data.frame, select = c(XCoord,YCoord,Competitor))
cl <- x[,'Competitor']
data <- x[,1:2]
k <- length(unique(cl))
plot(train_mat, col = as.integer(cl), pch = as.integer(cl))
# make grid
r <- sapply(train[,c(2,3)], range)
resolution = 100
xs <- seq(r[1,1], r[2,1], length.out = resolution)
ys <- seq(r[1,2], r[2,2], length.out = resolution)
g <- cbind(rep(xs, each=resolution), rep(ys, time = resolution))
colnames(g) <- colnames(r)
g <- as.data.frame(g)
folded_g <- g %>% mutate(foldID = rep(1:5, each = nrow(g)/5)) %>% select(foldID, everything())
### 출처: http://michael.hahsler.net/SMU/EMIS7332/R/viz_classifier.html
plot(train_mat, col = as.integer(cl)+1L, pch = as.integer(cl)+1L, main='KNN(70%)')
p_knn <- knn(train_mat, g, factor(train$Competitor), k = knn.cv$best.parameters[, 1])
z_knn <- matrix(as.integer(p_knn), nrow = resolution, byrow = TRUE)
contour(xs, ys, z_knn, add = TRUE, drawlabels = FALSE, lwd = 2, levels = (1:(k-1))+.5)
plot(train_mat, col = as.integer(cl)+1L, pch = as.integer(cl)+1L, main='SVM_poly(86%)')
p_svm <- predict(poly.svm.cv$best.model, g)
z_svm <- matrix(as.integer(p_svm), nrow = resolution, byrow = TRUE)
contour(xs, ys, z_svm, add = TRUE, drawlabels = FALSE, lwd = 2, levels = (1:(k-1))+.5)
plot(train_mat, col = as.integer(cl)+1L, pch = as.integer(cl)+1L, main='SVM_radial(75%)')
p_svm <- predict(radial.svm.cv$best.model, g)
z_svm <- matrix(as.integer(p_svm), nrow = resolution, byrow = TRUE)
contour(xs, ys, z_svm, add = TRUE, drawlabels = FALSE, lwd = 2, levels = (1:(k-1))+.5)
plot(train_mat, col = as.integer(cl)+1L, pch = as.integer(cl)+1L, main='RF(86%)')
p_rf <- predict(rf, g)
z_rf <- matrix(as.integer(p_rf), nrow = resolution, byrow = TRUE)
contour(xs, ys, z_rf, add = TRUE, drawlabels = FALSE, lwd = 2, levels = (1:(k-1))+.5)
### Stacking ###
k_NN <- NULL
svm.poly <- NULL
svm.radial <- NULL
rf <- NULL
meta<- NULL
folded_train <- train %>% mutate(foldID = rep(1:5, each = nrow(train)/5)) %>% select(foldID, everything())
folded_mat <- model.matrix(data = folded_train, Competitor ~ .)[, -1]
for(targetFold in 1:5){
trainFold <- filter(folded_train, foldID != targetFold) %>% select(-foldID)%>% select(-ID)
trainCompetitor <- trainFold$Competitor
fold_train_mat <- folded_mat[folded_mat[,'foldID'] != targetFold, -c(1,2)]
fold_test_mat <- folded_mat[folded_mat[,'foldID'] == targetFold, -c(1,2)]
### kNN ###
temp <- knn(fold_train_mat, fold_test_mat, trainCompetitor, k = knn.cv$best.parameters[, 1])
folded_train[ folded_train$foldID == targetFold, 'kNN']<- temp
### SVM with Polynomial Kernel ###
poly <- svm(x = fold_train_mat, y = trainCompetitor, kernel = 'polynomial',
cost = poly.svm.cv$best.parameters[1, "cost"],
degree = poly.svm.cv$best.parameters[1, "degree"],
coef0 = poly.svm.cv$best.parameters[1, "coef0"])
temp <- predict(poly, fold_test_mat)
folded_train[ folded_train$foldID == targetFold, 'svm_poly']<- temp
### SVM with Radial Basis Kernel ###
radial <- svm(x = fold_train_mat, y = trainCompetitor, kernel = 'radial',
cost = radial.svm.cv$best.parameters[1, "cost"],
gamma = radial.svm.cv$best.parameters[1, "gamma"],
coef0 = radial.svm.cv$best.parameters[1, "coef0"])
temp <- predict(radial, fold_test_mat)
folded_train[ folded_train$foldID == targetFold, 'svm_radial']<- temp
### Random Forest ###
set.seed(7)
RF <- randomForest(x = fold_train_mat, y= trainCompetitor)
temp <- predict(RF, fold_test_mat)
folded_train[ folded_train$foldID == targetFold, 'rf']<- temp
### 시각화 ###
folded_g_test<- folded_g[folded_g$foldID == targetFold,c(2,3)]
folded_g[ folded_g$foldID == targetFold, 'kNN']<- knn(fold_train_mat, folded_g_test, trainCompetitor, k = knn.cv$best.parameters[, 1])
folded_g[ folded_g$foldID == targetFold, 'svm_poly']<- predict(poly, folded_g_test)
folded_g[ folded_g$foldID == targetFold, 'svm_radial']<- predict(radial, folded_g_test)
folded_g[ folded_g$foldID == targetFold, 'rf']<- predict(RF, folded_g_test)
}
# testFold <- filter(folded_train, foldID == targetFold) %>% select(-foldID)%>% select(-ID)
# testSurvived <- testFold$Competitor
meta_test <- data.frame(test_mat,
kNN = knn,
svm_poly = poly_svm,
svm_radial = radial_svm,
rf = random_Forest )
set.seed(7)
meta.rf<- randomForest(x = subset(folded_train, select = -c(ID,foldID,Competitor ))
, y = folded_train$Competitor)
meta.randomForest <- predict(meta.rf, meta_test)
cat("Accuracy(Stacked Model):", ACC(test$Competitor, meta.randomForest) )
plot(test_mat, col = as.integer(cl)+1L, pch = as.integer(cl)+1L
,main= paste('Stacking RF :', ACC(test$Competitor, meta.randomForest) ) )
p_meta_rf <- predict(meta.rf, subset(folded_g, select= -foldID))
z_meta_rf <- matrix(as.integer(p_meta_rf), nrow = resolution, byrow = TRUE)
contour(xs, ys, z_meta_rf, add = TRUE, drawlabels = FALSE, lwd = 2, levels = (1:(k-1))+.5)
'게임 데이터 분석' 카테고리의 다른 글
유저 이탈 기준 정하기 (0) | 2020.11.20 |
---|---|
LTV 예측하기 (2) | 2020.05.24 |
[R code] 유저 플레이 타임(Play time) 군집화 (6) | 2020.03.26 |
게임회사 지표 활용사례 (매출 - ARPPU) (0) | 2019.10.26 |
게임 지표 용어 정리 (0) | 2019.10.16 |