Post

1년 뒤 당뇨 예측

1년 뒤 당뇨 예측

1. 개요

본 분석에서는 scikit-learn의 당뇨병 데이터셋을 활용하여 다양한 통계 기법과 머신러닝 기법을 적용하여 당뇨병 진행률을 예측하고, 변수 간의 상관관계를 분석하였습니다.

2. 데이터 로드 및 전처리

# reticulate 라이브러리 설치 및 로드
library(reticulate)
reticulate::py_install("scikit-learn")

# scikit-learn 데이터셋 로드
sklearn <- import("sklearn")
load_diabetes <- sklearn$datasets$load_diabetes

diabetes <- load_diabetes()

# 데이터프레임 변환
library(dplyr)
diabetes_data <- diabetes$data
diabetes_target <- diabetes$target
diabetes_df <- as.data.frame(diabetes_data)
colnames(diabetes_df) <- diabetes$feature_names
diabetes_df$target <- diabetes_target

# 결측치 확인 및 제거
diabetes_df <- na.omit(diabetes_df)

# 이상치 제거 함수 정의
remove_notnorm <- function(df) {
  for (col in names(df)) {
    if (is.numeric(df[[col]])) {  
      Q1 <- quantile(df[[col]], 0.25, na.rm = TRUE)
      Q3 <- quantile(df[[col]], 0.75, na.rm = TRUE)
      IQR <- Q3 - Q1
      lower <- Q1 - 1.5 * IQR
      upper <- Q3 + 1.5 * IQR
      df <- df[df[[col]] >= lower & df[[col]] <= upper, ]
    }
  }
  return(df)
}
diabetes_df <- remove_notnorm(diabetes_df)

3. 데이터 탐색

# 상관관계 분석
library(PerformanceAnalytics)
chart.Correlation(diabetes_df, histogram = TRUE, pch = 19)

4. 선형 회귀 분석

# 데이터 분할
set.seed(300)
idx <- sample(1:nrow(diabetes_df), 0.7 * nrow(diabetes_df))
train_data <- diabetes_df[idx, ]
test_data <- diabetes_df[-idx, ]

# 선형 회귀 모델 생성
formula <- target ~ age + sex + bmi + bp + s1 + s2 + s3 + s4 + s5 + s6
lm_model <- lm(formula = formula, data = train_data)
summary(lm_model)
AIC(lm_model)

# 잔차 분석
residuals <- lm_model$residuals
shapiro.test(residuals)
qqnorm(residuals)
qqline(residuals, col = "red")
5. 다중공선성 확인 및 변수 선택

# 다중공선성 확인
library(car)
vif_values <- vif(lm_model)
print(vif_values)

# 변수 선택 후 회귀 모델 생성
model_please <- lm(target ~ bmi + bp + s1 + s5, data = train_data)
summary(model_please)

# 다중공선성 확인
vif(model_please)

6. 의사결정나무 분석

library(rpart)
library(rpart.plot)
library(caret)

# 데이터 변환 및 트리 모델 학습
diabetes_df2 <- diabetes_df[c("bmi", "bp", "s1", "s5", "target")]
diabetes_df2$target_cat <- cut(diabetes_df2$target,
                               breaks = unique(quantile(diabetes_df2$target, probs = c(0, 0.33, 0.67, 1), na.rm = TRUE)),
                               labels = c("Low", "Medium", "High"),
                               include.lowest = TRUE)
diabetes_df2$target_cat <- as.factor(diabetes_df2$target_cat)

# 트리 모델 생성
my.control <- rpart.control(xval = 10, cp = 0.015, minsplit = 2)
tree_model_multi <- rpart(target_cat ~ bmi + bp + s1 + s5, data = diabetes_df2, method = "class", control = my.control)
rpart.plot(tree_model_multi, box.palette = "RdYlGn")

# 예측 및 정확도 평가
pred <- predict(tree_model_multi, diabetes_df2, type = "class")
conf_matrix <- confusionMatrix(pred, diabetes_df2$target_cat)
print(conf_matrix)

7. 랜덤 포레스트 분석

# 랜덤 포레스트 모델 학습
install.packages("randomForest")
library(randomForest)
rf_model <- randomForest(target_cat ~ bmi + bp + s1 + s5, data = diabetes_df2, ntree = 500, importance = TRUE)

# 예측 및 평가
pred_rf <- predict(rf_model, diabetes_df2)
cm_rf <- confusionMatrix(pred_rf, diabetes_df2$target_cat)
print(cm_rf)

8. 변수 중요도 시각화

library(ggplot2)
varImpPlot(rf_model)
ggplot(diabetes_df, aes(x = target_cat, y = s5, fill = target_cat)) +
  geom_boxplot() +
  labs(title = "s5 Distribution by Target Category", x = "Target Category", y = "s5") +
  theme_minimal()

9. 결과 분석 및 결론

s5 변수가 당뇨 진행률 예측에 가장 중요한 변수로 나타남

bmi, bp 또한 중요한 예측 변수로 확인됨

랜덤 포레스트 모델을 적용한 결과, 의사결정나무 모델보다 높은 정확도를 보임

정확도를 더욱 향상시키기 위해 추가적인 변수 조정 및 다른 머신러닝 기법 활용 가능

This post is licensed under CC BY 4.0 by the author.