ch0nny_log

[빅데이터분석] R _ 63. 회귀트리와 모델트리 본문

빅데이터 분석(with 아이티윌)/R

[빅데이터분석] R _ 63. 회귀트리와 모델트리

chonny 2024. 7. 18. 16:31
 회귀 트리란?

수치를 예측하는 의사결정트리 (tree)
 회귀트리 --->  회귀 모델 + 의사결정트리 모델을 결합한 모델

※ 관련 자료

 

회귀트리 수업 자료

■ 회귀트리 수업 자료  1. 의사결정트리와 회귀트리의 비교의사 결정트리회귀트리문제. 의사결정트리와 회귀트리의 차이점?  답:  2. 질문나무를 만드려면 필요한 두가지? 1. 어떤걸 물어볼

cafe.daum.net

 

Machine Learning - Regression Tree (3B) (2) (1) (1).pdf
0.62MB

 

-> 분할 할때/ 질문순서 정할때 모두 표준편차 축소를 이용함.

 

 

 

※ 표준편차 축소 계산:

두 가지 분할 기준에 대해 표준편차 축소를 계산해보겠습니다. 이를 통해 어떤 분할이 더 나은지 확인할 수 있습니다.

# 원본 데이터
평수 <- c(30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100)
집값 <- c(100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240)

# 평수 60으로 나누기
그룹_A_평수 <- c(30, 35, 40, 45, 50, 55, 60)
그룹_B_평수 <- c(65, 70, 75, 80, 85, 90, 95, 100)
그룹_A_집값 <- c(100, 110, 120, 130, 140, 150, 160)
그룹_B_집값 <- c(170, 180, 190, 200, 210, 220, 230, 240)

# 평수 80으로 나누기
그룹_C_평수 <- c(30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80)
그룹_D_평수 <- c(85, 90, 95, 100)
그룹_C_집값 <- c(100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200)
그룹_D_집값 <- c(210, 220, 230, 240)

# 전체 데이터 표준편차
전체_표준편차 <- sd(집값)

# 평수 60으로 나누었을 때의 SDR 계산
sdr_60 <- 전체_표준편차 - (length(그룹_A_집값) / length(집값) * sd(그룹_A_집값) + length(그룹_B_집값) / length(집값) * sd(그룹_B_집값))

# 평수 80으로 나누었을 때의 SDR 계산
sdr_80 <- 전체_표준편차 - (length(그룹_C_집값) / length(집값) * sd(그룹_C_집값) + length(그룹_D_집값) / length(집값) * sd(그룹_D_집값))

cat("전체 데이터의 표준편차:", 전체_표준편차, "\n")
cat("평수 60으로 나누었을 때의 표준편차 축소:", sdr_60, "\n")
cat("평수 80으로 나누었을 때의 표준편차 축소:", sdr_80, "\n")

 

 

          5. 왜 표준편차  축소가 중요하게 사용되나?

 

# 원본 데이터
초콜릿 <- c(1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7)

# 크기 5로 나누기
그룹_A <- c(1, 1, 1, 2, 2, 3, 4)
그룹_B <- c(5, 5, 6, 6, 7, 7, 7, 7)

# 크기 6으로 나누기
그룹_C <- c(1, 1, 1, 2, 2, 3, 4, 5, 5)
그룹_D <- c(6, 6, 7, 7, 7, 7)

# 표준편차 계산
sdr_5 <- sd(초콜릿) - (length(그룹_A) / length(초콜릿) * sd(그룹_A) + length(그룹_B) / length(초콜릿) * sd(그룹_B))
sdr_6 <- sd(초콜릿) - (length(그룹_C) / length(초콜릿) * sd(그룹_C) + length(그룹_D) / length(초콜릿) * sd(그룹_D))

cat("크기 5로 나누었을 때의 표준편차 축소:", sdr_5, "\n")
cat("크기 6으로 나누었을 때의 표준편차 축소:", sdr_6, "\n")

 

6. 질문나무를 만드려면 필요한 두가지?

 

1. 어떤걸 물어볼것인가? 질문 리스트 뽑기

2. 어떤 질문을 먼저 물어볼것인가 ? 우선 순위 정하기

 

어떤 질문을 먼저 물어볼것인가 ? 

 

수치를 예측하는 회귀 트리에서 지역을 먼저 물어봐야하나 로얄층 여부를 먼저 물어봐야하나?

 

실습. R을 이용해서 회귀트리 모델 생성하기 (p339)
와인의 품질(수치형 데이터)를 예측하는 회귀트리 모델을 생성하기

#1. 데이터를 불러옵니다.

wine <- read.csv("c:\\data\\whitewines.csv", header=T)
head(wine)
unique(wine$quality)

#2. 종속변수가 정규분포에 속하는 안정적인 데이터인지 확인하기
hist(wine$quality)

## 설명: 어느 한쪽으로 데이터가 치우치지 않은 안정적인 모양을 보이고 있습니다.

#3. 결측치가 있는지 확인합니다.
colSums( is.na(wine) )

#4. 훈련 데이터와 테스트 데이터를 분리합니다.
library(caret)
set.seed(1)
train_num <- createDataPartition( wine$quality, p=0.9, list=F)

train_data <- wine[ train_num,    ]
test_data <- wine[ - train_num,    ]

nrow( train_data )  #4409
nrow( test_data )   # 489

#5. 훈련 데이터로 모델을 생성합니다.
install.packages("rpart")
library(rpart)

model <-rpart(quality~., data=train_data)
model

#6. 생성된 모델을 시각화 합니다.
install.packages("rpart.plot")
library(rpart.plot)

rpart.plot( model,  digits=3)   # digit=3 은 소수점 3번째자리까지 허용하겠다.

#7. 훈련된 모델로 테스트 데이터를 예측합니다.
result <-  predict( model, test_data[  , -12] ) 
result

#8. 모델 성능 평가
cor(result, test_data[  ,12]) # 0.5150889

#9. 모델 성능을 높입니다. (회귀트리 --> 모델트리) 
install.packages("Cubist")
library(Cubist)

model2 <-  cubist( x=train_data[   , -12], y=train_data[   ,12] )
model2

#모델 예측
result2 <- predict( model2,  test_data[  , -12] )
result2

# 성능 확인

cor( result2,  test_data[  , 12] ) #0.59 로 올라감​


wine 의 quality 가 3~9 등급으로 구성되어있는데 잎노드 5.9로 예측한것으로 예를들면 alcohol <10.85 이고 volatile.acidity < 0.2525 이면서 volatile.acidity < 0.20756 이고 잔류설탕 <12.65 이면 와인의 품질이 5.9 로 예상됩니다.

회귀트리는 분할후의 종속변수의 평균값으로 예측했는데 모델트리는 분할후의 종속변수의 회귀식으로 예측을 합니다. 회귀트리보다 모델트리가 오차가 더 작습니다.

0.51 ---> 0.59 로 올라갔습니다.
실습. 와인 품질을 예측하는 모델을 랜덤포레스트 모델로 변경해서 수행하시오 !
#1. 데이터를 불러옵니다.
wine <- read.csv("c:\\data\\whitewines.csv", header=T)

#2. 종속변수가 정규분포에 속하는 안정적인 데이터인지 확인하기
hist(wine$quality)

#3. 결측치가 있는지 확인합니다.
colSums( is.na(wine) )

#4. 훈련 데이터와 테스트 데이터를 분리합니다.
library(caret)
set.seed(1)
train_num <- createDataPartition( wine$quality, p=0.9, list=F)

train_data <- wine[ train_num,    ]
test_data <- wine[ - train_num,    ]

nrow( train_data )  #4409
nrow( test_data )   # 489

#5. 랜덤포레스트 모델을 생성합니다.
library(randomForest)
set.seed(1)
model_rf <- randomForest( quality~ . , data=train_data, ntree= 500, mtry=3)​

설명: ntree가 트리의 갯수인데 일반적으로 100~500개로 설정합니다.
데이터와 문제의 복잡도에 따라 더 많은 트리를 사용할 수 있는데 트리의 갯수가 많아지면 계산의 비용이 많으 듭니다.

mtry =3은 나무의 노드에서 분할위해 고려할 변수의 수를 지정하는 파라미터입니다.
#6. 테스트 데이터를 예측합니다.
result_rf <-predict(model_rf,test_data[  ,-12])

#7. 모델을 평가합니다.
cor(result_rf,test_data[  ,12]) #0.7468368​


 

※ 수치예측하는 모델

다중회귀 모델 -> 회귀트리모델 -> 모델트리모델 ->랜덤포레스트

                                   0.51                    0.59                  0.74

 

실습. 회귀트리 모델을 생성하는데 데이터를 콘크리트 강도를 예측하는 모델을 생성하시오;
# 데이터를 불러옵니다.

concrete <- read.csv("c:\\data\\concrete.csv", header=T)
head(concrete)

unique(concrete$strength)

# 종속변수가 정규분포에 속하는 안정적인 데이터인지 확인하기
hist(concrete$strength)

## 설명: 어느 한쪽으로 데이터가 치우치지 않은 안정적인 모양을 보이고 있습니다.

# 결측치가 있는지 확인합니다.
colSums( is.na(concrete) )

# 훈련 데이터와 테스트 데이터를 분리합니다. 
library(caret)
set.seed(1)
train_num <- createDataPartition( concrete$strength, p=0.9, list=F)

train_data <- concrete[ train_num,    ]
test_data <- concrete[ - train_num,    ]

nrow( train_data )  #930
nrow( test_data )   #100

# 훈련 데이터로 모델을 생성합니다. (회귀트리 모델)
install.packages("rpart")
library(rpart)

model <-rpart(strength~., data=train_data)
model

#6. 생성된 모델을 시각화 합니다.
install.packages("rpart.plot")
library(rpart.plot)

rpart.plot( model,  digits=3)   # digit=3 은 소수점 3번째자리까지 허용하겠다.

# 훈련된 모델로 테스트 데이터를 예측합니다.
result <-  predict( model, test_data[  , -9] ) 
result

# 모델 성능 평가
cor(result, test_data[  ,9]) # 0.745415

# 모델 성능을 높입니다. (회귀트리모델 --> 모델트리모델) 
install.packages("Cubist")
library(Cubist)

model2 <-  cubist( x=train_data[   , -9], y=train_data[   ,9] )
model2

# 모델 예측
result2 <- predict( model2,  test_data[  , -9] )
result2

# 성능 확인

cor( result2,  test_data[  , 9] ) #0. 9338277 로 올라감


# 모델 성능을 높입니다. (모델트리모델 --> 랜덤포레스트모델 )
library(randomForest)
set.seed(1)
model_rf <- randomForest( strength~ . , data=train_data, ntree= 500, mtry=3)

# 테스트 데이터를 예측합니다.
result_rf <-predict(model_rf,test_data[  ,-9])

# 모델을 평가합니다.
cor(result_rf,test_data[  ,9]) #0.9684604​

- 회귀트리모델


- 모델트리모델

- 랜덤포레스트

                             

★ 마지막 문제. 콘크리트 데이터에 대한 모델별로 오차값 구하기. (오차는 작을 수록 좋음) 
 
# 모델별 오차값 확인
mae <- function( actual, predicted ) {  mean( abs( actual - predicted) ) }

# 회귀트리 모델 오차값 
mae (test_data[ ,9], result)

# 모델트리모델 오차값
mae (test_data[ ,9], result2)

# 랜덤포레스트델 오차값
mae (test_data[ ,9], result_rf)​
  회귀트리 모델 모델트리 모델 랜덤 포레스트 모델
상관계수 0.745415 0.9338277 0.9684604
오차 8.979734 4.518774 3.458593

-> 그동안 어떻게 모델을 생성했는지에 대한 과정을 보여주고 뒤로 갈수록 좋은 모델이 선택되었다는 것을 데이터 분석을 으뢰한 사람에게 알려줌. (선택은 고객이 하게 끔)

-> 상관계수는 1에 가까울 수록 좋고 오차는 0에 가까울 수록 좋음.