R 중급 R을 이용한 결측치 회귀분석 예측 후 전치 , KNN 전치

  네이버 지식인에서 아래와 같은 이메일이 왔다. 

R을 이용한 결측치 예측

제가 가지고 있는 데이터셋은 연속형 변수인  x1,x2,x3과 y로 이루어져 있는데, y 변수에 결측치들이 군데군데 존재합니다. 이 결측치를 제거하지 않는 방법을 찾아보니 회귀 모형으로 예측을 하는 것이 가능하다고 하는데, 회귀모형을 어떤 식으로 만들면 위에서 말한대로 결측치를 예측할 수 있는 걸까요? train set과 test set을 나눠서 회귀 예측 모형을 만들 수 있나요?

결측치 전치




하긴 했는데,  회귀모형 진단을 해보니,   R squared 값이 0.3866 이 나왔다.   회귀모형으로 예측은 가능 한데,  설명력이 떨어져 결측치를 전치 해도 별로 좋아 보이지는 않는다.



회귀방식에 따른 결측치 전치

  방법에 대한 질문이 있었기 때문에  첫번째 단계로 회귀모형으로 예측한 다음에 전치를 하겠다. 


library(rio)
library(dplyr)
library(DMwR2)
library(readxl)
library(httr)

# 파일을 불러오는 path를 url 변수로 정의      
url = "https://drive.google.com/u/0/uc?id=1c0jxY0MjTPzkr44o92pagO4hkfmIizAp&export=download"
GET(url, write_disk(tf <- tempfile(fileext = ".xlsx")))
reg_na <- read_excel(tf, 1L)  



# 데이터 프레임으로 "NA" 
df <-  reg_na %>% 
    mutate(y = ifelse(y == "NA",NA, y))

# na 값으로 바뀐것 확인 
apply(df, 2, function(x){ sum(is.na(x))})
##   X1   X2   X3   X4    y 
##    0    0    0    0 1263
# 첫번째 방식
# 일반 선형 회귀 모형 진단
fit <-  lm(y~ X1+X2+X3+X4, data=
              df %>% filter(!is.na(y)))
summary(fit)
## 
## Call:
## lm(formula = y ~ X1 + X2 + X3 + X4, data = df %>% filter(!is.na(y)))
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -74.250 -18.862  -3.653  15.340 174.275 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -15.73934    0.88658  -17.75   <2e-16 ***
## X1           11.96302    0.15758   75.92   <2e-16 ***
## X2            0.40609    0.02113   19.21   <2e-16 ***
## X3           -0.25483    0.01119  -22.77   <2e-16 ***
## X4           -0.22542    0.02125  -10.61   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 26.83 on 19995 degrees of freedom
## Multiple R-squared:  0.3866, Adjusted R-squared:  0.3864 
## F-statistic:  3150 on 4 and 19995 DF,  p-value: < 2.2e-16

위의 데이터는 선형성을 가지기가 어렵다.  나중에 Train Set과 test Set을 나누어 Machine learning 하여도,    좋은 예측 결과를 갖기 어렵다. 

결측치 예측은 아래와 같이 독립변수 4개를 선택 하여  x 변수를 만든 다음에   predict 함수를 이용하여   y_hat 변수로 예측 하여,  그값을 cbind로 붙이면 예측 값이 나온다. 

# 예측 모형 
x <- df %>% select(X1, X2, X3, X4)
y_hat <-  predict(fit, newdata = x)
df_result <- cbind(reg_na, y_hat)
head(df_result)
##   X1        X2       X3       X4                  y    y_hat
## 1  4  74.38888 54.67878 52.96255 4.0999999999999996 36.44852
## 2  3  95.48690 62.23835 59.03245               11.4 29.75846
## 3  6 100.86128 50.88198 78.38262                 32 66.36202
## 4  4  76.44456 51.24567 59.35667              92.83 36.71681
## 5  6  31.80306 31.08071 15.84518                 35 57.46150
## 6  6  95.47081 56.30415 71.88264                 74 64.25652
 이것을 앞서 na  결측치로 만든 데이터 값을 전치 하면 결측치 예측에 의해 전치가  끝난 것이다. 

# 데이터 전치   
df_result <- df_result %>%  
               mutate(y = ifelse(is.na(y),y_hat, y))
                
# na 값으로 바뀐것 확인 
apply(df_result, 2, function(x){ sum(is.na(x))})
##    X1    X2    X3    X4     y y_hat 
##     0     0     0     0     0     0
 y에 결측치가 존재 하지 않는다. 이미 예측 값에 위해 전치가 된것이다. 




KNN  전치 

 K-최근접 이웃(K-Nearest Neighbor, KNN)은 지도학습 알고리즘 중의 하나인데,   아래 녹색의 데이터가 정해지면,  최근접 데이터의 값을 찾은 다음에  클래스를 정하던가  아니면  최근점 이웃값을 거리를 구한 다음 평균을 구하는 것이다. 


knn  알고리즘


이번에 전치 하는 방법은 최근접 이웃값을 구한 다음에 가중평균을 구한 값이다.  주변 10개의 값을 파라메터로 정했다. 

df$y <- as.double(df$y)


# 두번째 방식 knn 전치 방법
knn_result <-  knnImputation(df, k = 10, meth = "weighAvg",
                distData = NULL )  
이것은 아주 깔끔 하게 결측치 값이 전치 된다.    

Train Set과 Test Set을 나누어 예측

  회귀 분석의 머신러닝에 의한 방법으로 할 수 있는  caret 패키지를 이용하여 할 수 있다.  우선 아래의 4개의 패키지를 로딩 후   각 변수 간의 상관관계 분석 후 상관관계가 높은 변수는 전부 소거 하고,  실제 분석에 들어 간다. 

# 머신러닝에 의한 방법

library(corrplot)  
library(caret)  
library(tidyr) 
library(e1071)

# knn_result 값을  df1 으로 한다.
 df1 <- knn_result

 
# 회귀모형이므로,  별도로 스케일링 절차 없이 데이터 셋을 나눈다. 
 
# 상관관계를 시각적으로 확인 하기 위해서 corrplot을 그리기 위해
# 종속변수  y 제거
  cor_df1 <- df1 %>%  select(-y)
  
# 상관관계 분석
  correlations <- cor(cor_df1)
  correlations
##            X1         X2         X3         X4
## X1  1.0000000 -0.1419228 -0.3530644 -0.2929688
## X2 -0.1419228  1.0000000  0.8159770  0.9402982
## X3 -0.3530644  0.8159770  1.0000000  0.8482415
## X4 -0.2929688  0.9402982  0.8482415  1.0000000
# 상관관계 구조를 확인 한다.
  corrplot(correlations, order ="hclust")

# 상관관계가 높은 것을 데이터를 걸러낸다. 
  highCorr <- findCorrelation(correlations, cutoff = .75)
  cor_df1 <- cor_df1[, -highCorr]

  head(cor_df1) 
##   X1        X2
## 1  4  74.38888
## 2  3  95.48690
## 3  6 100.86128
## 4  4  76.44456
## 5  6  31.80306
## 6  6  95.47081

데이터를 걸러내는 이유는 변수의 상관관계가 높으면 다중 공선선의 오류가 발생 하기 때문이다.   아래는   데이터 셋을 8:2로  5겹 교차 검증을 통해 리샘플의 성능 추정 값을 구할 것이다.  하지만,  머신러닝을 돌리더라도, RMSE  값과,  R-squared 값의 변화는 거의 없을 것이다. 

y = df1$y

  cor_df1 <- cbind(cor_df1, y )

# 데이터 셋을 나눈다
  set.seed(1001)
  inx <- createDataPartition(cor_df1$X2, p = 0.8, list = F)    
  train <- cor_df1[inx, ]
  test <- cor_df1[-inx, ]

# 데이터 갯수가 많으므로 k-fold 교차 검증 5회 실시
  ctrl <- trainControl(method = "cv", number = 5)

# train set 만들기
  train_set <- train %>%  select(-y)
  
  
# 모델을 돌린다. 
  set.seed(1001)
  lmFit <- train(x = train_set, y = train$y,
                 method = "lm", trControl =ctrl)

  lmFit  
## Linear Regression 
## 
## 17012 samples
##     2 predictor
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 13609, 13610, 13611, 13609, 13609 
## Resampling results:
## 
##   RMSE      Rsquared   MAE     
##   27.24755  0.3647485  21.17054
## 

 위의 질문 사항에 대한 답변을 정하였지만, 예측 점수는 매우 낮으므로,  위의 데이터가지고, 예측하는 것은 의사 결정에 문제가 생길 수도 있다.   

이번 건은 방법에 대한 것만 설명 되었다고 보면 된다.   




댓글 없음:

댓글 쓰기

css cheat sheet 클래스 선택자, margin(마진), display , center 조정 간단한 구성 요소

 앞에서는 html의 간단한 sheet를 소개 하였습니다.   html은  주로 골격을 나타나는 것이라, 디자인을 하는데는 css로 하여야 합니다.  아래 코드와 같이 css 관련 하여 매우 간단하게 코딩 하겠습니다.  body 부분의 css 코딩  ...