※ 개인적으로 ADP 실기 문제들을 풀이하려고 합니다. 사용 언어는 'R 프로그래밍'입니다.
※ 코드 및 관련 의견 주심 감사하겠습니다.
문제 복기 참고한 사이트
ADP 17회 실기 문제 — DataManim
1-4번 벌점, 앙상블을 포함하여 모형에 적합한 기계학습 모델 3가지를 제시하라 (평가지표는 MSE, MAPE, R2 모두 확인할 것) 2-1번 마지막 일자를 기준으로 인구 대비 확진자 비율이 높은 상위 5개 국
www.datamanim.com
ADP) ADP 실기 기출문제 모음 (17, 18, 19, 20, 21, 22, 23, 24, 25, 26회)
ADP 실기 문제집을 사기보다, 필기 문제집에 있는 각종 데이터마이닝 예제들을 직접 코드로 짜보는 것이 좋다는 후기들을 읽고, 코드 예제를 작성할 주제 목록을 잔뜩 만들었다. (정리하는데 꽤
lovelydiary.tistory.com
1-1. 데이터 EDA 수행 (시각화 및 통계량 제시)
데이터 구조 확인
df <- read.csv('https://raw.githubusercontent.com/Datamanim/datarepo/main/adp/17/problem1.csv', stringsAsFactors = F)
str(df)
head(df)
tail(df)
library(psych)
describe(df)
먼저, 데이터를 불러온 후 데이터의 구조를 확인하였다.
데이터는 총 1,460개의 행과 13개의 변수로 이루어져 있으며, 모든 변수는 numeric(수치형) 타입이다.
describe() 함수를 이용하여 각 변수에 대한 기술통계값을 확인하였다.
모든 변수는 누락된 행 없이 1,460개의 행을 갖고 있다.
각 변수에 대한 왜도(skew)와 첨도(kurtosis)를 확인하니 대부분의 변수가 정규분포에서 치우 처져 있다.
※ 왜도와 첨도의 값이 0이 아닌 경우, 정규분포라고 할 수 없다.
특히, 왜도와 첨도가 매우 큰 값으로 정규분포로부터 많이 벗어나 보이는 LotArea의 분포를 히스토그램을 그려 확인하였다. 히스토그램을 확인하니 LotArea의 분포는 오른쪽으로 긴 꼬리를 가지는 분포로 나타났다. (매우 치우쳐 있음)
이런 경우, 데이터 스케일링을 통해 데이터들의 단위(범위)를 조정해 주는 것이 좋다.
hist(df$LotArea)
결측치 확인
# 결측치 확인
sum(is.na(df))
colSums(is.na(df))
library(VIM)
aggr(df, prop=FALSE, number=TRUE)
# 결측치 비율 확인
round(sum(is.na(df)) / nrow(df), 2)
데이터에 결측치가 존재하는지 확인하였다.
결측치는 총 259개 있었고, LotFrontage 변수에만 결측치가 존재하였다.
시각화를 통해 결측치의 존재여부를 다시 확인하였고, LotFrontage 변수에만 259개가 존재하였다.
※ 변수의 이름이 모두 나타나지 않음 (총 13개의 변수)
결측치는 기계학습을 하기 위해 삭제 혹은 대체할 필요가 있다. 결측치는 비율에 따라 처리 방법을 다르게 적용한다. 결측값은 삭제를 통해 n 값이 달라지기 때문에 집단의 특성이 달라질 수 있기에 missing rate(10% 미만)을 확인한 후 삭제해야 하며, 결측값을 대체할 경우 틀린 값으로 대체될 수 있다는 가능성이 항상 존재한다.
- 10% 미만 : 삭제하거나 다른 값으로 치환
- 10 - 50% 미만 : 모델을 만들어 처리(대표값, 통계분석 기법, 예측값 추정 등)
- 50% 이상 : 변수 삭제
해당 데이터에서의 결측치 비율은 0.18(18%)이다. 즉, 10 - 50% 구간에 해당하기 때문에 대푯값, 통계분석 기법, 예측값 추정 등의 방법을 이용하여 결측치를 처리할 수 있고, 여기서는 대푯값 중 평균값으로 대체하겠다.
df$LotFrontage <- ifelse(is.na(df$LotFrontage), round(mean(df$LotFrontage, na.rm=T), 2), df$LotFrontage)
sum(is.na(df))
1-2. 모델링 및 예측
library(kernlab)
idx <- createDataPartition(df$price, p = 0.7, list = F)
train <- df[idx, ]
test <- df[-idx, ]
set.seed(123)
lm_origin <- train(price ~ ., data=train, method= "lm")
lm_origin
lm_pred <- predict(lm_origin, test)
rmse_origin <- postResample(pred = lm_pred, obs = test$price)
## 예측 결과 시각화
plot(lm_pred)
lines(test$price, col='red')
먼저, 7:3의 비율로 train과 test 셋을 나누고, 종속변수(price)에 모든 독립변수를 입력하여 '다중선형회귀분석'을 수행하였다. 다중선형회귀분석을 통해 추정된 모델 결과는 R-squared: 0.7933(79.33%)의 설명력을 보이며, 주목할 평가지표인 RMSE: 0.184882로 나타났다.
※ 평균 제곱근의 오차를 의미하는 RMSE 지표는 값이 작을수록 좋은 결과를 나타낸다고 할 수 있다.
이를 predict() 함수를 이용하여 예측을 진행하고, 예측 결과에 대한 시각화를 한 후 RMSE를 구하였다.
예측 결과에 대한 RMSE는 0.2075316, R-squared는 0.7399(73.99%)로 기존 추정 값보다 낮게 나타났다.
1-3. 하이퍼파라미터 조절 후 비교
1-2. 에서 생성한 모델은 단순히 데이터를 분할하여 모든 독립변수에 대한 영향을 확인한 것이다.
이번에는 1) 데이터 스케일링 (preProcess), 2) 10-fold CV 등을 조절함으로서 성능을 비교해보려고 한다.
## Preprocessing
lm_pre <- train(price ~ ., data=train, method="lm", preProcess=c("center", "scale"))
lm_pre
lm_pre_pred <- predict(lm_pre, test)
rmse_pre <- postResample(pred = lm_pre_pred, obs = test$price)
## 10-fold CV
fitControl <- trainControl(method = "cv",
number = 10, verboseIter = FALSE)
lm_fold <- train(price ~ ., data=train, method="lm", preProcess=c("center", "scale"),
trControl = fitControl)
lm_fold
lm_fold_pred <- predict(lm_fold, test)
rmse_fold <- postResample(pred = lm_fold_pred, obs = test$price)
lm_result_1 <- rbind(lm_origin = lm_origin$results[2], lm_pre = lm_pre$results[2], lm_fold = lm_fold$results[2])
lm_result_2 <- rbind(lm_origin = rmse_origin[1], lm_pre = rmse_pre[1], lm_fold = rmse_fold[1])
cbind(lm_result_1, lm_result_2)
1) 데이터 스케일링(preProcessing)에 대한 결과
추정된 모델 결과는 R-squared: 0.8152(81.52%)의 설명력을 보이며, 주목할 평가지표인 RMSE: 0.1753491로 나타났다.
RMSE 기준, 기존 모델(lm_origin)보다 좋은 성능을 보인다.
2) 교차 검증(10-fold CV)에 대한 결과
추정된 모델 결과는 R-squared: 0.8098(80.98%)의 설명력을 보이며, 주목할 평가지표인 RMSE: 0.1745493로 나타났다.
RMSE 기준, 기존 모델(lm_origin)과 정규화 모델(lm_pre)보다 좋은 성능을 보인다.
최종적으로 기존 모델(lm_origin), 정규화 모델(lm_pred), 교차검증 모델(lm_fold)에 대한 다중선형회귀분석 결과를 요약하면 아래와 같다. 아래 왼쪽 RMSE는 각 모델의 추정했을 때를 나타내고, 오른쪽 RMSE는 예측했을 때를 나타낸다.
추정했을 때의 RMSE는 교차 검증 모델이 가장 우수한 성능을 보이고 있으며, 예측 결과로는 모든 모델이 동일하게 나타났다.
※ 예측 결과에 대한 RMSE가 동일한 이유에 대해 설명해주실 수 있는 분 있으시면 감사하겠습니다.
1-4. 모형에 적합한 기계학습 모델 3가지 구현(벌점, 앙상블 포함)
모형에 적합한 기계학습은 "Lasso", "SVM", "RandomForest" 알고리즘이다.
각 알고리즘을 이용하여 아래와 같이 회귀분석에 대한 평가지표(RMSE, MSE, MAPE, R2)를 확인하였다.
## 벌점, 앙상블 포함 모형에 적합한 기계학습 모델 3가지 구현
## LASSO Regression
lasso_mo <- train(price ~ ., data=train, method="lasso")
lasso_mo
lasso_pred <- predict(lasso_mo, test)
## SVM Regression
svm_mo <- train(price ~ ., data=train, method="svmRadial")
svm_mo
svm_pred <- predict(svm_mo, test)
## randomForest Regression
rf_mo <- train(price ~ ., data=train, method="rf")
rf_mo
rf_pred <- predict(rf_mo, test)
## 평가지표 함수 만들기
library(Metrics)
eval_metrics <- function(actual, pred){
metrics <- list(RMSE = rmse, MSE = mse, MAPE = mape, R2 = caret::R2)
round(sapply(metrics, function(x) x(actual, pred)), 4)
}
lasso_result <- eval_metrics(test$price, lasso_pred)
svm_result <- eval_metrics(test$price, svm_pred)
rf_result <- eval_metrics(test$price, rf_pred)
rbind(lasso_result, svm_result, rf_result)
회귀분석의 평가지표에서 RMSE, MSE, MAPE는 값이 낮을수록 좋은 것이고, R2는 높을수록 좋은 것이다.
위 지표를 토대로 가장 좋은 모형을 확인하였을 때 "SVM"이라는 것을 알 수 있다.
[참고 사이트]
'분석가 Step 0. 자격증 > ADP' 카테고리의 다른 글
[23회 실기] 기계학습 문제 풀이 1편 (0) | 2023.04.18 |
---|---|
[22회 실기] 기계학습 문제 풀이 (0) | 2023.04.13 |
[20회 실기] 기계학습 문제 풀이 2편 (0) | 2023.03.28 |
[20회 실기] 기계학습 문제 풀이 1편 (0) | 2023.03.27 |
[17회 실기] 기계학습 문제 풀이 2편 (0) | 2023.03.24 |