본문 바로가기

데이터 분석 (Data Analysis)/R

[데이터분석기사 실기] 예시문제 풀이 - 최근접 이웃 알고리즘(Knn) - 작업 2유형

1. 기본 전처리 과정입니다.

################################################################################
rm(list=ls())

library(dplyr)
library(knitr)
library(ggplot2)

setwd(".../data")

x.train <- read.csv("X_train.csv")
y.train <- read.csv("Y_train.csv")

x.test <- read.csv("X_test.csv")


x.train %>% tail(5)
y.train %>% head(5)

x.test %>% head(5)


# 트레이닝 셋
x.train %>% dim()
y.train %>% dim()

# 테스트 셋
x.test %>% dim()

# 학습할 데이터셋 병합
train <- merge(x.train, y.train, by='cust_id')
train %>% head(5)

# 결측값 처리

train$환불금액[is.na(train$환불금액)== TRUE] = 0

x.test$환불금액[is.na(x.test$환불금액)== TRUE] = 0

# 범주형변수 factor 처리

train$gender <- as.factor(train$gender)

train$주구매상품 <- as.factor(train$주구매상품)
train$주구매지점 <- as.factor(train$주구매지점)

x.test$주구매상품 <- as.factor(x.test$주구매상품)
x.test$주구매지점 <- as.factor(x.test$주구매지점)

train <- train[,-1] # 불필요 변수 제거(`cust_id`)

# 데이터셋 나누기

set.seed(210613) # 랜덤샘플링을 위한 시드값 고정
n <- nrow(train)
idx <- 1:n
training_idx <- sample(idx, n * .75)

idx <- setdiff(idx, training_idx) # setdiff() : 차집합
validate_idx <- sample(idx, n * .25)

training <- train[training_idx,]
validation <- train[validate_idx,]

2. LDA로 접근, F1 Score 계산도 해보았습니다. 약 0.3647

################################################################################
# LDA
set.seed(210613)

library(MASS)

lda_fit <- lda(gender ~ ., data=training)
lda_fit

lda_pred <- predict(lda_fit, validation)
lda_pred$posterior[,2]

################################################################################
# F1 Score 로 평가

# 패키지를 이용하여 confusion matrix 그리기
library(caret)
library(e1071)
lda_cm <- confusionMatrix(lda_pred$class, validation$gender)
lda_cm$table

## 직접 그리기
table(validation$gender, lda_pred$class) # Confusion Matrix, table(행방향=실제, 열방향=예측)

# F1 Score 계산
TP <- 91
FP <- 58
TN <- 467
FN <- 259

lda_accuracy <- (TP+TN) / (TP+FP+TN+FN) # 정확도
lda_recall <- TP / (TP+FN) # 재현율
lda_precision <- TP / (TP+FP) # 정밀도

# f1 core는 Recall(재현율)과 Precision(정밀도)의 조화평균
lda_F1_Score <- 2 *(lda_recall*lda_precision) / (lda_recall+lda_precision)

# MLmetrics 패키지 이용해서 계산한거 검산해보기

library(MLmetrics) # 시험 x 검산용으로만 적용했습니다.
? F1_Score # (y_true, y_pred, positive = ?) positive는 "positive" 결과일때 레벨
F1_Score(validation$gender, lda_pred$class, positive = 1) # F1 Score : 0.3647295
################################################################################
# AUC 로 평가
library(pROC)

class(validation$gender)
class(lda_pred$posterior[,2])
roc(validation$gender, lda_pred$posterior[,2])
auc(roc(validation$gender, lda_pred$posterior[,2])) # AUC : 0.6536


################################################################################
# 결과값 제출
final_predict <- predict(lda_fit, x.test)
final <- data.frame(x.test$cust_id, final_predict$posterior[,2])
colnames(final) <- c("cust_id", "gender")
final %>% head(10)

write.csv(final, "예측값 정답 제출.csv", row.names=F)

3. Knn, 최적화된 k 값은 무엇일지?

library(caret)
knn_fit <- knn3(gender ~., data=training, k = 20) # k값 20으로 설정

knn_pred <- predict(knn_fit, validation, "prob")
knn_pred

knn_pred_class <- predict(knn_fit, validation, "class")
knn_pred_class

data.frame(knn_pred, knn_pred_class) # 임계치(threshold) 값 0.5로 설정 후 예측값들을 factor 형으로 변환

knn_cm <- confusionMatrix(knn_pred_class, validation$gender)

knn_cm$table # Confusion Matrix
################################################################################

# AUC 값?
class(validation$gender)
class(knn_pred[,2])

roc(validation$gender, knn_pred[,2])
auc(roc(validation$gender, knn_pred[,2])) # AUC : 0.6392

<결론>

LDA의 AUC가 Knn의 AUC에 비해 약 0.6536으로 더 우수하네요.

 

진흥원에서 제공하는 예시데이터가 다소 단순해서 LDA가 더 우수한가봅니다. 또한 KNN 모델에서  적절한 k값을 찾지못한점도 이유라고 생각합니다.

 

이것으로 데이터분석기사 실기 대비를 마치겠습니다. 감사합니다.