빅데이터 분석기사, 빅분기 실기 중 가장 어려운 작업형 2유형 연습 코드이다.
이 문제는 전체적인 데이터 분석의 Flow 를 따라가는 것이 중요하다고 생각한다.
kdata 데이터자격검정 공식 홈페이지의 실기 체험하기에서는
-. 데이터 전처리 , Feature Engineering, 분류 알고리즘 사용, 초매개변수 최적화, 모형 앙상블 등이 수반되어야 함
-. 수험번호.csv 파일이 만들어지도록 코드 제출
-. ROC-AUC 평가지표에 따라 모델 성능 채점
-. 데이터 저장은 다음과 같이 데이터 테이블 형식임.
이 점들을 고려해서 작업형 제2유형 기출문제 풀이를 진행하였다.
이전과 마찬가지로 R 을 사용하였고, 모든 것을 완벽하게 하기 보다는 적당하게 알짜만 가져가서 부분점수를 노리는 공략이다.
데이터 전처리 (결측치 NA 처리, 표준화/정규화) - 모델 형성(glm, randomForest, svm) - 앙상블로 진행.
저작권 문제가 생길 수 있으므로 문제는 상세하게 기술하기 어려움. 러프하게 비슷한 유형으로 진행.
1. 전자상거래 배송 데이터 모형을 활용하여 제품이 시간에 맞게 배송되었는지에 대한 예측모델 만들기.
학습용 데이터(x_train)를 통해 예측 모형을 만든 후 평가용 데이터(x_test)에 적용하여 얻은 예측값을 csv 파일로 생성하시오.
# 데이터 불러오기
> ds <- read.csv("c:/data/exam2/Train.csv")
# 데이터 확인
> str(ds)
'data.frame': 10999 obs. of 12 variables:
$ ID : int 1 2 3 4 5 6 7 8 9 10 ...
$ Warehouse_block : chr "D" "F" "A" "B" ...
$ Mode_of_Shipment : chr "Flight" "Flight" "Flight" "Flight" ...
$ Customer_care_calls: int 4 4 2 3 2 3 3 4 3 3 ...
$ Customer_rating : int 2 5 2 3 2 1 4 1 4 2 ...
$ Cost_of_the_Product: int 177 216 183 176 184 162 250 233 150 164 ...
$ Prior_purchases : int 3 2 4 4 3 3 3 2 3 3 ...
$ Product_importance : chr "low" "low" "low" "medium" ...
$ Gender : chr "F" "M" "M" "M" ...
$ Discount_offered : int 44 59 48 10 46 12 3 48 11 29 ...
$ Weight_in_gms : int 1233 3088 3374 1177 2484 1417 2371 2804 1861 1187 ...
$ Reached.on.Time_Y.N: int 1 1 1 1 1 1 1 1 1 1 ...
> head(ds)
ID Warehouse_block Mode_of_Shipment Customer_care_calls Customer_rating Cost_of_the_Product Prior_purchases
1 1 D Flight 4 2 177 3
2 2 F Flight 4 5 216 2
3 3 A Flight 2 2 183 4
4 4 B Flight 3 3 176 4
5 5 C Flight 2 2 184 3
6 6 F Flight 3 1 162 3
Product_importance Gender Discount_offered Weight_in_gms Reached.on.Time_Y.N
1 low F 44 1233 1
2 low M 59 3088 1
3 low M 48 3374 1
4 medium M 10 1177 1
5 medium F 46 2484 1
6 medium F 12 1417 1
> summary(ds)
ID Warehouse_block Mode_of_Shipment Customer_care_calls Customer_rating Cost_of_the_Product
Min. : 1 Length:10999 Length:10999 Min. :2.000 Min. :1.000 Min. : 96.0
1st Qu.: 2750 Class :character Class :character 1st Qu.:3.000 1st Qu.:2.000 1st Qu.:169.0
Median : 5500 Mode :character Mode :character Median :4.000 Median :3.000 Median :214.0
Mean : 5500 Mean :4.054 Mean :2.991 Mean :210.2
3rd Qu.: 8250 3rd Qu.:5.000 3rd Qu.:4.000 3rd Qu.:251.0
Max. :10999 Max. :7.000 Max. :5.000 Max. :310.0
Prior_purchases Product_importance Gender Discount_offered Weight_in_gms Reached.on.Time_Y.N
Min. : 2.000 Length:10999 Length:10999 Min. : 1.00 Min. :1001 Min. :0.0000
1st Qu.: 3.000 Class :character Class :character 1st Qu.: 4.00 1st Qu.:1840 1st Qu.:0.0000
Median : 3.000 Mode :character Mode :character Median : 7.00 Median :4149 Median :1.0000
Mean : 3.568 Mean :13.37 Mean :3634 Mean :0.5967
3rd Qu.: 4.000 3rd Qu.:10.00 3rd Qu.:5050 3rd Qu.:1.0000
Max. :10.000 Max. :65.00 Max. :7846 Max. :1.0000
# 결측치 없음, 한번 더 확인
> sum(!complete.cases(ds))
[1] 0
> # 음수나 특이한 값이 확인되지 않음.
> # Reached.on.Time_Y.N 는 0,1 인 이산형 데이터인데 summary 에서는 숫자로 취급되어 있음. 뒤에서 as.factor 을 써서 범주형 Factor 로 바꾸어 주어야 함.
# seed 고정. 결과값이 case에 따라 바뀌지 않도록 case를 고정시킨다
# 훈련용, 테스트용 데이터셋으로 나누기
> library(caret)
> set.seed(2022)
> idx <- createDataPartition(ds$Reached.on.Time_Y.N, p=0.7)
> summary(idx)
Length Class Mode
Resample1 7700 -none- numeric
# Resample1 을 train, test 로 구분해서 넣기
> x_train <- ds[idx$Resample1, ]
> x_test <- ds[-idx$Resample1, ]
> str(x_train)
'data.frame': 7700 obs. of 12 variables:
$ ID : int 1 2 3 4 7 8 9 10 11 12 ...
$ Warehouse_block : chr "D" "F" "A" "B" ...
$ Mode_of_Shipment : chr "Flight" "Flight" "Flight" "Flight" ...
$ Customer_care_calls: int 4 4 2 3 3 4 3 3 3 4 ...
$ Customer_rating : int 2 5 2 3 4 1 4 2 4 5 ...
$ Cost_of_the_Product: int 177 216 183 176 250 233 150 164 189 232 ...
$ Prior_purchases : int 3 2 4 4 3 2 3 3 2 3 ...
$ Product_importance : chr "low" "low" "low" "medium" ...
$ Gender : chr "F" "M" "M" "M" ...
$ Discount_offered : int 44 59 48 10 3 48 11 29 12 32 ...
$ Weight_in_gms : int 1233 3088 3374 1177 2371 2804 1861 1187 2888 3253 ...
$ Reached.on.Time_Y.N: int 1 1 1 1 1 1 1 1 1 1 ...
> str(x_test)
'data.frame': 3299 obs. of 12 variables:
$ ID : int 5 6 15 17 18 24 29 30 31 35 ...
$ Warehouse_block : chr "C" "F" "A" "C" ...
$ Mode_of_Shipment : chr "Flight" "Flight" "Flight" "Flight" ...
$ Customer_care_calls: int 2 3 4 3 5 4 2 5 3 4 ...
$ Customer_rating : int 2 1 3 4 5 3 3 4 4 2 ...
$ Cost_of_the_Product: int 184 162 152 143 227 211 234 183 266 227 ...
$ Prior_purchases : int 3 3 3 2 3 3 4 2 2 4 ...
$ Product_importance : chr "medium" "medium" "low" "medium" ...
$ Gender : chr "F" "F" "M" "F" ...
$ Discount_offered : int 46 12 43 6 36 12 44 36 38 22 ...
$ Weight_in_gms : int 2484 1417 1009 1194 3952 3922 3134 3819 2741 2460 ...
$ Reached.on.Time_Y.N: int 1 1 1 1 1 1 1 1 1 1 ...
# Reached.on.Time 은 중간값이 없다. 1이냐 0 이냐 둘 밖에 없으므로 이렇게 나올 수가 없다.
> summary(x_train$Reached.on.Time_Y.N)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.0000 0.0000 1.0000 0.6004 1.0000 1.0000
# Factor 로 변경
> x_train$Reached.on.Time_Y.N <- as.factor(x_train$Reached.on.Time_Y.N)
> x_test$Reached.on.Time_Y.N <- as.factor(x_test$Reached.on.Time_Y.N)
> summary(x_test$Reached.on.Time_Y.N)
0 1
1359 1940
# 데이터 preprocess (scale 작업)
# scale이 없을 경우 변수 X1, X2 가 만약 범위가 다르다면 ex) X1(0~1), X2(1000~10000) X1은 아무리 중요한 변수라도 모델에 미치는 중요도가 낮게 나올 것이다. 이로 인해 데이터를 표준화 or 정규화 작업을 해 주어야 한다.
# 정규화 (데이터의 범위를 0~1로 변환, 최대-최소 정규화)
- preProcess(x, method = "range")
- 정규화 한 후 preProcess 객체를 predict 함수를 사용해 데이터셋에 적용해야 한다.
# 표준화 (평균이 0, 분산이 1 인 정규분포)
- scale(x)
- preProcess(x, method = c("center, "scale"))
# 데이터 정규화
> x_train_scale <- preProcess(x_train, method="range")
> x_test_scale <- preProcess(x_train, method="range")
# 정규화된 데이터를 predict 함수로 데이터셋으로 만들어주기
> scaled_x_train <- predict(x_train_scale, x_train)
> scaled_x_test <- predict(x_test_scale, x_test)
# 모델 분석
# 1. 로지스틱 회귀분석 (범주형이므로)
> md_glm <- glm(Reached.on.Time_Y.N~., data = scaled_x_train, family='binomial')
> pred_glm <- predict(md_glm, scaled_x_test, type = 'response')
# 일반회귀가 아닌 범주형 로지스틱 회귀일때만 family = binomial, type=response
> pred_glm_result <- ifelse(pred_glm >= 0.5, 1, 0)
> pred_glm_result <- as.factor(pred_glm_result)
# 결과도 범주형으로 정리, 0.5보다 높은 확률이면 1, 아니면 0 으로 변경
#결과 분석
> confusionMatrix(pred_glm_result, scaled_x_test$Reached.on.Time_Y.N)
Confusion Matrix and Statistics
Reference
Prediction 0 1
0 819 596
1 540 1344
Accuracy : 0.6557
95% CI : (0.6392, 0.6719)
No Information Rate : 0.5881
P-Value [Acc > NIR] : 9.467e-16
Kappa : 0.2936
Mcnemar's Test P-Value : 0.1027
Sensitivity : 0.6026
Specificity : 0.6928
Pos Pred Value : 0.5788
Neg Pred Value : 0.7134
Prevalence : 0.4119
Detection Rate : 0.2483
Detection Prevalence : 0.4289
Balanced Accuracy : 0.6477
'Positive' Class : 0
# SVM 분석
> library(e1071)
> md_svm <- svm(Reached.on.Time_Y.N~., scaled_x_train)
> pred_svm <- predict(md_svm, scaled_x_test, type='response')
> confusionMatrix(pred_svm, x_test$Reached.on.Time_Y.N)
Confusion Matrix and Statistics
Reference
Prediction 0 1
0 1298 936
1 61 1004
Accuracy : 0.6978
95% CI : (0.6818, 0.7134)
No Information Rate : 0.5881
P-Value [Acc > NIR] : < 2.2e-16
Kappa : 0.4311
Mcnemar's Test P-Value : < 2.2e-16
Sensitivity : 0.9551
Specificity : 0.5175
Pos Pred Value : 0.5810
Neg Pred Value : 0.9427
Prevalence : 0.4119
Detection Rate : 0.3935
Detection Prevalence : 0.6772
Balanced Accuracy : 0.7363
'Positive' Class : 0
# 랜덤 포레스트 모델
> library(randomForest)
> md_rf <- randomForest(Reached.on.Time_Y.N~., scaled_x_train, ntree=300)
> pred_rf <- predict(md_rf, scaled_x_test, type='response')
> confusionMatrix(pred_rf, x_test$Reached.on.Time_Y.N)
Confusion Matrix and Statistics
Reference
Prediction 0 1
0 1010 723
1 349 1217
Accuracy : 0.6751
95% CI : (0.6588, 0.691)
No Information Rate : 0.5881
P-Value [Acc > NIR] : < 2.2e-16
Kappa : 0.3558
Mcnemar's Test P-Value : < 2.2e-16
Sensitivity : 0.7432
Specificity : 0.6273
Pos Pred Value : 0.5828
Neg Pred Value : 0.7771
Prevalence : 0.4119
Detection Rate : 0.3062
Detection Prevalence : 0.5253
Balanced Accuracy : 0.6853
'Positive' Class : 0
# 로지스틱 회귀 AUC : 0.6557
# SVM 회귀 AUC : 0.6978
# 랜덤 포레스트 회귀 AUC : 0.6751
# 데이터 저장
> total = as.data.frame(cbind(x_test$ID, pred_svm))
> View(total)
> names(total) <- c("ID", 'Reached.on.time_Y.N')
> head(total)
ID Reached.on.time_Y.N
2 2 2
3 3 2
13 13 2
21 21 2
22 22 2
23 23 2
> write.csv(total, "Train_result_00001.csv", row.names = FALSE)
'자기계발 > 자격증' 카테고리의 다른 글
[빅데이터 분석기사] 실기 모의고사 1회 - 2/2 (0) | 2022.06.18 |
---|---|
[빅데이터 분석기사] 실기 모의고사 1회 - 1/2 (0) | 2022.06.17 |
[빅데이터 분석기사] 2회 기출문제 연습(R 코드) - 2/3 (0) | 2022.06.15 |
[빅데이터 분석기사] 2회 기출문제 연습(R 코드) - 1/3 (0) | 2022.06.14 |
[빅데이터 분석기사] 실기 작업형 1 R 코드 - TEST체험하기 (dataq 예시문제) (0) | 2022.06.14 |
댓글