놀고 싶어요

[R Programming] 다중회귀분석: 독립변수가 범주형 데이터 본문

R

[R Programming] 다중회귀분석: 독립변수가 범주형 데이터

챌린지 2021. 5. 20. 15:25

 

 

회귀분석 Regression analysis

세상의 많은 일들이 회귀분석으로 설명될 수 있다. 그러나 대개는 설명력이 부족하고 예측력이 낮아 하나의 독립변수로는 설명할 수 없다. 또한 수치형 데이터가 아닌데 회귀관계가 존재하는 경우가 있다.

Yes or no로 대답할 수 있는게(범주형 데이터) 종속변수에는 영향이 지대한 경우가 있을 수 있다.

 

 

 

 

 

머신러닝 Machine learning

: 기계가 많은 데이터를 사용해서 결과를 설명할 수 있는 특징, 패턴, 수식 등을 찾아내도록 하는 것

다양한 기법이 존재하고 기법마다 다른 접근법을 사용하지만 대개의 경우 그 하부에는 통계적 기법이나 통계적 아이디어가 있고 그것을 구현하는 관점에서 알고리즘, 컴퓨터 수학 그리고 수학이 어우러져 있다.

 

통계 관점에서 다루던 회귀분석이 머신러닝에도 적용된다.

특히 변수가 많아지면 머신러닝의 고급 기법들이 여러 관점에서 필요하기도 하고 매우 도움이 된다.

 

통계와 머신러닝 간의 관점의 차이가 있다고 생각되는데 통계는 설명이 가장 중요한 부분이라면 머신러닝은 예측을 가장 중요하게 여긴다.

 

 

 

 

머신러닝 프로세스

특징으로는 우선 회귀분석 모델을 만드는 Train함수와 그 모델을 가지고 예측하는 Predict함수, 그리고 예측결과의 정확도를 계산하는 Evaluate함수 3단계로 이루어진다.

Train함수에서 사용한 데이터를 그대로 Predict함수에 사용하게 되면 이미 사용했던 것이기 때문에 대부분 결과가 높게 나온다. 이 경우는 예측 오차를 측정하는 것이 아니라 학습 오차를 측정한다.

Ex) 모의고사 시험 치른 후 같은 문제로 본고사 시험 치르기

-> 개선하는 방법으로는 Train함수 데이터와 Predict함수 데이터를 분리한다. 또는 Predict함수 데이터를 여러 세트를 넣고 테스트 하는 방법이 있다.

 

1. 데이터 분리하기

데이터를 학습용과 평가용으로 분리하는 방법

 

 caret패키지를 활용한 데이터 세트 분리 - createDataPartition() 함수 사용

install.packages("caret")
library(caret)

train_index <- createDataPartition(bike_weather$Time_out,p=0.7,list=F)
training <- bike_weather[train_index,]
testing <- bike_weather[-train_index,]

 

train_index <- createDataPartition(bike_weather$Time_out,p=0.7,list=F)

 

데이터 분리: createDataPartition()

함수의 첫 번째 인자는 데이터 세트 분리의 기준이 되는 컬럼이다.

이 컬럼의 구성항목에 따른 구성비율을 고려해서 Train과 Test Set으로 구분해주는 특징이 있어서 균형있는 데이터로 나누어주는게 가능하다.

두 번째 인자는 Train 세트로 속하게 되는 데이터의 비율이다. 많은 경우에 Train:Test = 7:3 or 8:2로 로 나눈다.

마지막 인자는 함수의 결과값 데이터 형식이다. 

createDataPartition() 함수의 결과값은 list로 만드는 것이 default이다.

이 값을 위의 코드처럼 dataframe의 인덱싱에 사용하면 에러가 나기 때문에 list를 F(FALSE)로 놓는다.

(List 대신에 matrix / array 로 결과값을 만들어 내고 그 값을 dataframe의 인덱스로 직접 사용한다.)

FALSE 라고 하는 풀네임 대신에 F로 줄여서 사용하는 것이 가능하다.

 

training <- bike_weather[train_index,]

0.7의 비율로 선택된 인덱스를 사용해서 bike_weather 데이터를 필터링하고 

 

testing <- bike_weather[-train_index,]

반대로 - 를 붙여 해당 인덱스를 제외한 세트로 필터링해서

 

train과 test set를 나누게 된다. (임의 추출)

 

좌) training set 우) testing set

 

 

 

2. Traing set로 회귀 분석 실행

독립변수: cum_precipitation, humidity, temp, wind 사용

 

독립변수 1개인 회귀분석과 독립변수 개수를 제외하고는 방법이 동일하다.

R-squared:  0.5372 

R제곱값이 많이 향상되어 있다. 

 

p-value: 3.868e-07

F 검정통계량 추정치도 작은 p-value를 갖고 있어서 회귀식에 대한 통계적 유의성도 확인할 수 있다.

 

그렇지만 4개 독립변수인 cum_precipitation, humidity, temp, wind 에 대한 t 검정 통계량 추정치의 p-value(Pr(>|t|) )들은 humidity를 제외하고는 통계적 유의성이 있다고 볼 수 없는 큰 값이 나왔다.

 

회귀식은 통계적으로 유의하고 설명력은 0.5372으로 많이 높아졌지만 회귀식에 도입된 독립변수 4 개 가운데 통계적인 유의성이 있는 유일한 값은 humidity 이다.

-> 어떤 변수와 함께 고려되는가에 따라 통계적 유의성이나 회수계수 크기 등이 완전히 다르게 나타날 수 있다.

어떤 의미에서는 이전 모델이 너무 단순했다면 지금 모델은 좀 더 설명력이 있고 좀 더 유의미한 모델로 발전시킬 수 있다는 가능성을 보여주고 있다. 물론 데이터가 더 많이 활용 될 수 있다면 내용은 또 달라질 수 있다.

 

 

 

 

3. Test 세트와 회귀분석으로 생성해 낸 모델을 사용하여 예측해보기

 

pred <- predict(fitted, testing)

 

Predict 함수에서는 앞에 실행한 회귀분석 결과 model을 첫 번째 인자로 넣고 두 번째 인자는 test set를 넣은 후에 실행하면 테스트 데이터 세트에서 가져온 x값을 사용하여 y값(예측값)이 계산된다.

 

 

이렇게 계산된 결과와 원래 테스트 데이터 세트에 있는 결과값 Count와 비교해보기

# 비교하기 위해 새로운 패키지 설치 MLmetrics
install.packages('MLmetrics')
library(MLmetrics)


# 예측결과의 정확도 지표를 계산할 수 있는 함수를 사용하기 위한 패키지
MSE(pred, testing$Count)
RMSE(pred, testing$Count)
MAE(pred, testing$Count)
MAPE(pred, testing$Count)

 

모든 정확도 관련 값들은 에러값을 의미하기 때문에 낮을수록 좋은 결과이다.

특별한 기준값이 있는 것은 아니고 대개 목표를 정하고 그 목표의 에러보다 낮은 값을 만들어내기 위해 노력하는 것이다

 

실무에서 많이 사용하는 지표는 MAPE으로 퍼센티지(%)로 표현을 하기 때문에 비교하고 이해하기 쉽다.

 

 

 

 

 

4. bike_weather 데이터에 새로운 컬럼 Rain_YN 추가 (범주형 데이터)

cum_precipitation > 0: Y

cum_precipitation < 0: N

bike_weather$Rain_YN = 'N'
bike_weather[bike_weather$cum_precipitation>0, 'Rain_YN'] <- 'Y'
str(bike_weather)

제일 마지막에 새로운 컬럼이 생성된다.

 

bike_weather

 

 

 

 

 

 

5. cum_precipitation를 제외하고 새로 만든 컬럼 Rain_YN을 넣어서 분석해본다.

그렇지만 회귀분석에서는 수치 데이터만 독립변수로 사용하기 때문에 Y/N와 같이 문자로 되어 있는 컬럼은 바로 사용이 불가능하다. 

이 문자열로 된 범주형 데이터를 lm함수에 독립변수를 사용하여 Train 시키기 위해서는 수치형 변수로 변환해야 한다.

이러한 변환은 One_hot_encoding이라고 부르기도 한다.

일종의 더미 변수를 만드는 방법이다. N=0, Y=1으로 데이터를 변경한다. Rain_YN 하나의 컬럼으로 되어 있던 것을 N과 Y 두 개 컬럼으로 분리해서 표시해본다. 이 또한 여러 방법으로 가능하지만 여기서는 caret패키지의 dummyVars 함수를 사용한다.

 

dummy <- dummyVars(" ~ .", data=bike_weather)
newdata <- data.frame(predict(dummy,newdata=bike_weather))
str(newdata)
str(bike_weather)

Rain_YN이라는 하나의 컬럼 데이터를 Rain_YNN, Rain_YNY 두 컬럼으로 변경한 후에

원래 값이 N으로 표시 되어 있을 때는 N컬럼에 1, Y컬럼에 0

원래 값이 Y으로 표시 되어 있을 때는 N컬럼에 0, Y컬럼에 1

(만약 ‘자동차 색’이 기존 컬럼인 경우 One_hot_encoder 변환 후에는 자동차 색의 가짓수만큼 새 컬럼이 생기며 각 컬럼에 0과 1로 표시하게 된다.)

newdata

 

 

 

 

 

 

6. Train, Predict, Evaluation 단계 순차적 수행

 

# Training - Test 데이터 세트 분리
train_index <- createDataPartition(newdata$Time_out,p=.7, list=F)
training <- newdata[train_index,]
testing <- newdata[-train_index,]

# 독립변수가 5개인 회귀분석 실행
fitted <- lm(Count~humidity+temp+wind+Rain_YNN+Rain_YNY, data=training)
summary(fitted)

# Predict 함수
pred <- predict(fitted, testing)

# Evaluation
MSE(pred, testing$Count)
RMSE(pred, testing$Count)
MAE(pred, testing$Count)
MAPE(pred, testing$Count)

 

fitted <- lm(Count~humidity+temp+wind+Rain_YNN+Rain_YNY, data=training)

Rain_YNN+Rain_YNY 두 개 다 선택할 필요는 없었다.

하나가 0이면 하나는 1이기 때문에 두 컬럼이 사실은 똑같은 의미를 전달하기 때문이다.

-> 한 컬럼만 사용해도 된다 (Drop Last)

 

범주형 변수를 사용하려면 더미 변수를 이용하여 수치형 더미 데이터로 변경해야 한다.

회귀분석 실행결과
Evaluation

 

다음 포스팅은 범주형 데이터가 종속변수인 경우에 대해 알아보도록 !

 

 

 

 

좀 더 공부하기 위해서는 다양한 실험을 통해 결과 비교가 필요하다. (독립변수 바꾸기)

X=bike_weather[[ ‘cum_precipitation’, ‘humidity’, ‘temp’, ‘wind’ ]] 

독립변수 바꾸는 방법으로 포함된 컬럼을 빼거나 넣거나 하면서 조정하면 가능하다.