“day.csv”파일에 저장된 Bike sharing dataset은 워싱턴 D.C.에서 운영되는 Capital Bikeshare 시스템의 자전거 대여 기록을 기반으로 만들어진 것으로, 특정한 날에 대여된 자전거 수와 날씨, 계절, 요일, 온도 등의 기후 특성을 포함한다. 다음 변수들을 사용하자.
• temp : 온도
• atemp :
체감온도
• hum : 습도
•
windspeed : 풍속
• cnt : 자전거 대여량
(target 변수)
위 4개의 feature들을 사용하여
target 변수인 자전거 대여량 cnt를 예측해보고자 한다.
데이터셋의 크기가 충분하지 않은 상황을 가정하여 첫 80개의 데이터만
사용하자.
1. Stratified sampling을 통해 traing set과 test set을 70:30
비율로 분할하고, 두 set에서의 target 변수의 분포를 비교해보자.
# 차트 테마 설정
my_theme <- function() {
theme_bw() +
theme(
panel.border = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "grey90"),
axis.line = element_line(color = "grey40"),
plot.title = element_text(size = 16, face = "bold"),
axis.title.x = element_text(size = 14),
axis.title.y = element_text(size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11)
)
}## 'data.frame': 731 obs. of 16 variables:
## $ instant : int 1 2 3 4 5 6 7 8 9 10 ...
## $ dteday : chr "2011-01-01" "2011-01-02" "2011-01-03" "2011-01-04" ...
## $ season : int 1 1 1 1 1 1 1 1 1 1 ...
## $ yr : int 0 0 0 0 0 0 0 0 0 0 ...
## $ mnth : int 1 1 1 1 1 1 1 1 1 1 ...
## $ holiday : int 0 0 0 0 0 0 0 0 0 0 ...
## $ weekday : int 6 0 1 2 3 4 5 6 0 1 ...
## $ workingday: int 0 0 1 1 1 1 1 0 0 1 ...
## $ weathersit: int 2 2 1 1 1 1 2 2 1 1 ...
## $ temp : num 0.344 0.363 0.196 0.2 0.227 ...
## $ atemp : num 0.364 0.354 0.189 0.212 0.229 ...
## $ hum : num 0.806 0.696 0.437 0.59 0.437 ...
## $ windspeed : num 0.16 0.249 0.248 0.16 0.187 ...
## $ casual : int 331 131 120 108 82 88 148 68 54 41 ...
## $ registered: int 654 670 1229 1454 1518 1518 1362 891 768 1280 ...
## $ cnt : int 985 801 1349 1562 1600 1606 1510 959 822 1321 ...
#원하는 데이터만 추출
day <- subset(day, select = c("temp", "atemp", "hum", "windspeed", "cnt"))
day <- day[0:80, ]
#시드 설정
set.seed(30)
#training set, test set split
split <- initial_split(day, prop = 0.7, strata = "cnt")
day_train <- training(split)
day_test <- testing(split)
#chat gpt의 조언을 참고하여 작성한 pdf 추정 그래프
ggplot() + geom_density(data = day_train, aes(x = cnt, color = "Train"), linewidth = 1.0) + geom_density(data = day_test, aes(x = cnt, color = "Test"), linewidth = 1.0) + scale_color_manual(values = c("Train" = "cornflowerblue", "Test" = "indianred")) + labs(title = "Train/Test 자전거 대여량 분포 비교", x = "자전거 대여량 (건)", y = "밀도", color = "구분") + my_theme()#training set 히스토그램
ggplot(data = day_train, aes(x = cnt)) + geom_histogram(binwidth = 500, color = "white", fill = "cornflowerblue") + labs(title = "Training set 자전거 대여량 분포", x = "자전거 대여량 (건)", y = "빈도") + my_theme()#test set 히스토그램
ggplot(data = day_test, aes(x = cnt)) + geom_histogram(binwidth = 500, color = "white", fill = "cornflowerblue") + labs(title = "Test set 자전거 대여량 분포", x = "자전거 대여량 (건)", y = "빈도") + my_theme()
[분석]
분포 비교를 위해 추정한 pdf를
봤을 때 둘 다 평균이 1500보다 조금 크고 분산 또한 비슷해보인다.
히스토그램을 보아도 분포가 비슷한 것을 확인할 수 있다.
k-nn 을 적용한다. 이때 5-fold CV를 사용하여 parameter k의 값을
결정해 보고자한다. CV의 반복횟수를 1, 5, 10, 20, 30으로 점점 증가시켜
본다. 어떠한 경향을 관찰할 수 있는가? best k 값, k 값의 변화에 따른
RMSE의 변화 그래프 등을 비교해본다. 그리고 최종적으로 best k 값을
합리적으로 결정하자.
#파라미터 설정
z_normalized <- c("center", "scale")
tune_grid <- expand.grid(k = seq(1, 30, 2))
#시드 설정
set.seed(3)
# 그래프에 사용할 변수 초기화
best_rmse <- numeric()
rmse_var <- numeric()
#knn training
repeat_values <- c(1, 5, 10, 20, 30)
for (r in repeat_values){
cv <- trainControl(method = "repeatedcv", number = 5, repeats = r)
knn_fit <- train(data = day_train, cnt~., method = "knn", trControl = cv, preProcess = z_normalized, tuneGrid = tune_grid)
# 그래프에 사용할 데이터 저장
if (r == 30) {
results_30 <- knn_fit$results
}
best_rmse <- c(best_rmse, min(knn_fit$results$RMSE))
rmse_var <- c(rmse_var, var(knn_fit$results$RMSE))
#Grok 3 (xAI)의 조언을 참고하여 만든 knn 결과 출력 코드
cat("-----------------------------------------------------------")
cat("\n\n")
cat("Repeat =", r, "\n")
cat("\n")
print(knn_fit)
cat("\n")
#최적 k, RMSE, R² 정보와 RMSE 분산 출력
cat("Best k:", knn_fit$bestTune$k, "\n")
cat("Best RMSE:", min(knn_fit$results$RMSE), "\n")
cat("Best R²:", max(knn_fit$results$Rsquared), "\n")
cat("RMSE Variance:", var(knn_fit$results$RMSE), "\n")
cat("\n")
}## -----------------------------------------------------------
##
## Repeat = 1
##
## k-Nearest Neighbors
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 1 times)
## Summary of sample sizes: 45, 44, 46, 44, 45
## Resampling results across tuning parameters:
##
## k RMSE Rsquared MAE
## 1 542.1473 0.4607749 415.3200
## 3 477.2154 0.4432472 356.8463
## 5 432.5570 0.5174207 327.9839
## 7 452.1574 0.5013646 349.2817
## 9 454.7373 0.5495771 354.5651
## 11 467.4289 0.5343379 366.7260
## 13 471.9635 0.5676291 358.5722
## 15 501.5767 0.5289202 383.1549
## 17 509.3103 0.5196757 386.3395
## 19 512.8992 0.5215422 390.2296
## 21 522.0925 0.5210945 399.9583
## 23 528.1591 0.5172868 405.7356
## 25 532.0391 0.5077316 410.9180
## 27 530.2925 0.5656306 411.4416
## 29 533.3868 0.5312332 414.6679
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was k = 5.
##
## Best k: 5
## Best RMSE: 432.557
## Best R²: 0.5676291
## RMSE Variance: 1253.971
##
## -----------------------------------------------------------
##
## Repeat = 5
##
## k-Nearest Neighbors
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 5 times)
## Summary of sample sizes: 44, 46, 44, 44, 46, 45, ...
## Resampling results across tuning parameters:
##
## k RMSE Rsquared MAE
## 1 594.1690 0.3088194 454.0300
## 3 472.6064 0.3999082 347.6938
## 5 450.4288 0.4615918 330.2926
## 7 475.1937 0.4398355 351.5327
## 9 482.3454 0.4405176 360.8972
## 11 492.3781 0.4299993 364.3566
## 13 503.6911 0.4026882 371.8036
## 15 516.1619 0.3762458 379.0384
## 17 522.6768 0.3631982 384.1989
## 19 528.6639 0.3406704 390.7690
## 21 532.8430 0.3223903 396.9350
## 23 539.4914 0.3057720 404.9029
## 25 541.8396 0.3276899 409.2720
## 27 540.8133 0.3501670 409.5914
## 29 545.0338 0.3384563 415.8335
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was k = 5.
##
## Best k: 5
## Best RMSE: 450.4288
## Best R²: 0.4615918
## RMSE Variance: 1354.782
##
## -----------------------------------------------------------
##
## Repeat = 10
##
## k-Nearest Neighbors
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 10 times)
## Summary of sample sizes: 45, 46, 44, 45, 44, 44, ...
## Resampling results across tuning parameters:
##
## k RMSE Rsquared MAE
## 1 554.8752 0.3786322 418.5348
## 3 480.7458 0.4257227 347.0326
## 5 448.0875 0.4793537 328.1789
## 7 471.0180 0.4553334 349.2942
## 9 487.4522 0.4376446 363.1696
## 11 497.4059 0.4295509 368.3979
## 13 511.7893 0.4077206 375.6022
## 15 523.9234 0.3786258 384.7847
## 17 532.2308 0.3507578 391.4872
## 19 535.2460 0.3432278 395.9427
## 21 540.1971 0.3384345 401.4717
## 23 541.5860 0.3517381 405.7261
## 25 543.2841 0.3654637 408.3246
## 27 543.1617 0.3820985 409.7665
## 29 544.8055 0.4027047 412.8136
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was k = 5.
##
## Best k: 5
## Best RMSE: 448.0875
## Best R²: 0.4793537
## RMSE Variance: 1057.151
##
## -----------------------------------------------------------
##
## Repeat = 20
##
## k-Nearest Neighbors
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 20 times)
## Summary of sample sizes: 44, 44, 45, 45, 46, 44, ...
## Resampling results across tuning parameters:
##
## k RMSE Rsquared MAE
## 1 567.1984 0.3558712 428.5388
## 3 484.0561 0.3926161 349.2420
## 5 458.5790 0.4370997 336.6930
## 7 472.1966 0.4300670 349.4459
## 9 485.1863 0.4140830 360.7831
## 11 494.3243 0.4062423 366.3666
## 13 505.1709 0.3892876 371.6229
## 15 519.0803 0.3615265 381.9438
## 17 525.4638 0.3449306 387.6600
## 19 526.2783 0.3519644 390.1181
## 21 531.4387 0.3488378 397.6454
## 23 535.9969 0.3393210 403.6415
## 25 537.6919 0.3555490 406.3625
## 27 537.1734 0.3821870 407.0801
## 29 540.1384 0.3901953 412.4044
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was k = 5.
##
## Best k: 5
## Best RMSE: 458.579
## Best R²: 0.4370997
## RMSE Variance: 907.9915
##
## -----------------------------------------------------------
##
## Repeat = 30
##
## k-Nearest Neighbors
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 30 times)
## Summary of sample sizes: 45, 47, 44, 44, 44, 45, ...
## Resampling results across tuning parameters:
##
## k RMSE Rsquared MAE
## 1 569.7491 0.3488126 429.8809
## 3 487.1302 0.3946491 351.7042
## 5 457.2267 0.4467259 336.6009
## 7 474.0558 0.4347767 353.5050
## 9 480.9359 0.4435049 360.7183
## 11 490.3408 0.4365148 366.2588
## 13 503.5584 0.4151470 373.1329
## 15 518.0028 0.3815954 383.0802
## 17 524.8195 0.3678716 389.6244
## 19 527.4387 0.3630747 392.9919
## 21 531.5363 0.3559446 399.5278
## 23 537.7241 0.3434305 406.4933
## 25 539.4846 0.3540733 408.0660
## 27 537.8177 0.3865391 408.3913
## 29 540.4286 0.3952572 413.2050
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was k = 5.
##
## Best k: 5
## Best RMSE: 457.2267
## Best R²: 0.4467259
## RMSE Variance: 964.4975
#k에 따른 RMSE값(반복횟수 = 30) 그래프
rmse_plot <- ggplot(results_30, aes(x = k, y = RMSE)) + geom_line(color = "cornflowerblue", linewidth = 1.0) + geom_point(color = "cornflowerblue", size = 2) + labs(title = "k 값에 따른 예측 오차 (반복횟수 = 30)", x = "k (이웃 수)", y = "RMSE") + my_theme()
rmse_plot#그래프를 그리기 위한 dataframe 설정
knn_result <- data.frame(repeat_values, best_rmse, rmse_var)
#반복횟수에 따른 RMSE 그래프
ggplot(knn_result, aes(x = repeat_values, y = best_rmse)) + geom_line(color = "cornflowerblue", linewidth = 1.0) + geom_point(color = "cornflowerblue", size = 2) + labs(title = "반복횟수에 따른 최적 예측 오차", x = "반복횟수", y = "최적 RMSE") + my_theme()#반복횟수에 따른 RMSE의 분산 그래프
ggplot(knn_result, aes(x = repeat_values, y = rmse_var)) + geom_line(color = "cornflowerblue", linewidth = 1.0) + geom_point(color = "cornflowerblue", size = 2) + labs(title = "반복횟수에 따른 RMSE의 분산", x = "반복횟수", y = "RMSE 분산") + my_theme()
[분석]
Best k : 반복횟수에 따른 최적의 k 값은 5로 동일했다. 첫 번째 그래프(k값에 따른 RMSE)를 보면 k값이 5일 때 RMSE 값이 가장 낮고 그 뒤로는 어느 특정한 값으로 유지되는 것으로 보인다. 따라서 최적의 k값은 5로 설정했다.
반복횟수와 RMSE : 1회 측정에서의 RMSE 최소값은
30회 측정 후 평균낸 RMSE 최소값보다 작을 가능성이 높다. 이를 실제
데이터로 확인하기 위해 두 번째 그래프(반복횟수에 따른 RMSE)를 살펴본
결과, 반복횟수가 1일 때 Best RMSE가 약 430으로 가장 낮았고, 5·10회일
때는 평균 약 449, 20·30회일 때는 평균 약 458로 나타났다. 이를 통해
반복횟수가 증가할수록 Best RMSE 값도 함께 커지는 경향을 실제로 확인할 수
있었다.
반복횟수와 RMSE의 분산 : 반복횟수가
증가하면 RMSE의 분산은 감소한다. 이를 실제 데이터로 확인한 결과, 세 번째
그래프(반복횟수에 따른 RMSE 분산)에서도 반복횟수가 증가할수록 RMSE의
분산이 감소하는 경향이 확인되었다.
결론 : 최적의 k 값은 5이며, 반복횟수가
증가할수록 RMSE의 분산은 감소하지만, Best RMSE 값은 증가하는 경향을
보인다.
2번에서 k-nn 모델의 best k를 선택할 때 사용한 동일한 CV 세팅에
대해, 4개의 feature들을 모두 사용하는 linear regression 모델의 성능을
평가해보자. RMSE 기준으로 k-nn과 linear regression 중 어떤 모델이 더
우수한가?
#파라미터 설정
z_normalized <- c("center", "scale")
tune_grid <- expand.grid(k = 5)
#시드 설정
set.seed(3)
knn_rmse <- numeric()
lm_rmse <- numeric()
#lm, knn training
repeat_values <- c(1, 5, 10, 20, 30)
for (r in repeat_values){
cv <- trainControl(method = "repeatedcv", number = 5, repeats = r)
lm_fit <- train(data = day_train, cnt~., method = "lm", trControl = cv, preProcess = z_normalized)
knn_fit_2 <- train(data = day_train, cnt~., method = "knn", trControl = cv, preProcess = z_normalized, tuneGrid = tune_grid)
#그래프에 사용할 데이터 저장
knn_rmse <- c(knn_rmse, knn_fit_2$results$RMSE)
lm_rmse <- c(lm_rmse, lm_fit$results$RMSE)
#lm 결과 출력
cat("-----------------------------------------------------------")
cat("\n\n")
cat("Repeat =", r, "\n")
cat("\n")
print(lm_fit)
cat("\n")
cat("LM RMSE:", lm_fit$results$RMSE, "\n")
cat("KNN RMSE:", knn_fit_2$results$RMSE, "\n")
}## -----------------------------------------------------------
##
## Repeat = 1
##
## Linear Regression
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 1 times)
## Summary of sample sizes: 45, 44, 46, 44, 45
## Resampling results:
##
## RMSE Rsquared MAE
## 423.8775 0.6008824 311.1581
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
##
## LM RMSE: 423.8775
## KNN RMSE: 464.8717
## -----------------------------------------------------------
##
## Repeat = 5
##
## Linear Regression
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 5 times)
## Summary of sample sizes: 44, 44, 46, 44, 46, 45, ...
## Resampling results:
##
## RMSE Rsquared MAE
## 506.9767 0.463799 340.4554
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
##
## LM RMSE: 506.9767
## KNN RMSE: 456.3111
## -----------------------------------------------------------
##
## Repeat = 10
##
## Linear Regression
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 10 times)
## Summary of sample sizes: 44, 45, 44, 44, 47, 44, ...
## Resampling results:
##
## RMSE Rsquared MAE
## 492.8298 0.4762414 336.7935
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
##
## LM RMSE: 492.8298
## KNN RMSE: 455.9302
## -----------------------------------------------------------
##
## Repeat = 20
##
## Linear Regression
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 20 times)
## Summary of sample sizes: 44, 45, 45, 44, 46, 45, ...
## Resampling results:
##
## RMSE Rsquared MAE
## 495.0815 0.4817853 337.0811
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
##
## LM RMSE: 495.0815
## KNN RMSE: 465.8344
## -----------------------------------------------------------
##
## Repeat = 30
##
## Linear Regression
##
## 56 samples
## 4 predictor
##
## Pre-processing: centered (4), scaled (4)
## Resampling: Cross-Validated (5 fold, repeated 30 times)
## Summary of sample sizes: 46, 46, 44, 44, 44, 45, ...
## Resampling results:
##
## RMSE Rsquared MAE
## 501.1471 0.4538195 338.0503
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
##
## LM RMSE: 501.1471
## KNN RMSE: 459.7732
## LM Mean RMSE: 483.9825
## KNN Mean RMSE: 460.5441
lm_knn_result <- data.frame(repeat_values, knn_rmse, lm_rmse)
#ChatGPT의 조언을 참고하여 작성한 ggplot2 그래프 코드
ggplot(lm_knn_result, aes(x = repeat_values)) + geom_line(aes(y = knn_rmse, color = "KNN"), linewidth = 1) + geom_line(aes(y = lm_rmse, color = "LM"), linewidth = 1) + geom_point(aes(y = knn_rmse, color = "KNN"), size = 2) + geom_point(aes(y = lm_rmse, color = "LM"), size = 2) + labs(title = "KNN과 Linear Regression 예측 오차 비교", x = "반복횟수", y = "RMSE", color = "모델") + scale_color_manual(values = c("KNN" = "cornflowerblue", "LM" = "indianred")) + scale_x_continuous(breaks = unique(lm_knn_result$repeat_values)) + my_theme()[분석]
반복 횟수가 1일 때를 제외하면 KNN의
RMSE 값이 LM보다 낮게 나타난다. 반복 횟수가 1일 때는 변동성이 크므로,
전반적인 성능을 고려했을 때 KNN이 LM보다 우수하다고 판단할 수 있다.
3번의 두 모델을 test set에 적용해보고, CV에서 계산된 RMSE와
test set에 대한 RMSE 값을 비교해보자. 두 값이 충분히 유사한가, 아니면
차이가 큰가? 결과를 분석해보자.
#knn, lm 모델을 test set에 적용(반복횟수 30)
test_pred_knn <- predict(knn_fit_2, day_test)
test_pred_lm <- predict(lm_fit, day_test)
#KNN test set, CV RMSE 출력
cat("KNN CV RMSE:",knn_fit_2$results$RMSE, "\n")## KNN CV RMSE: 459.7732
## KNN test RMSE: 354.5487
cat("KNN RMSE값 차이의 비율:", (knn_fit_2$results$RMSE - RMSE(test_pred_knn, day_test$cnt)) / RMSE(test_pred_knn, day_test$cnt), "\n")## KNN RMSE값 차이의 비율: 0.2967843
## LM CV RMSE: 501.1471
## LM test RMSE 306.6684
cat("LM RMSE값 차이의 비율:", (lm_fit$results$RMSE - RMSE(test_pred_lm, day_test$cnt)) / RMSE(test_pred_lm, day_test$cnt))## LM RMSE값 차이의 비율: 0.6341658
[분석]
KNN과 LM 모델의 CV RMSE와 test RMSE를
비교한 결과, KNN은 RMSE 값 차이의 비율이 0.2968, LM은 0.6341로 나타났다.
두 모델 간 RMSE 차이의 비율에서 상당한 차이를 보였으며, 특히 LM의 경우
CV RMSE와 test RMSE 간의 차이가 더 컸다.
CV에서 계산된 RMSE와 test
RMSE는 유사한 것이 일반적이지만, 앞서 분석한 반복횟수 30회에서의 RMSE
분산값이 964였음을 고려하면 이러한 차이가 발생할 가능성은 충분히
있다.