R
*Decision tree
위와 같은 데이터가 있을때 의사결정나무를 사용한다면 아래와 같은 모양으로 나타낼수 있다.
각 피처들을 노드로 사용하여 분류에 분류를 거듭한다. 가장 처음에 나온 노드인 날씨테스트는 어떤 기준으로 선정 된것인가? 엔트로피를 사용하여 노드의 순서를 정할수 있다.
각 노드 별 무질서를 구할때 엔트ㅗ피를 사용하는데, 무질서는 양성,음성이 뒤섞여 있는 있을때 높은 수치를 보인다.
날씨는 맑을때 배드민턴을 친다는 사람이 4명이면 무질서는 0(난잡하지 않다), 반면 친다는 사람 2명, 아닌 사람 2명씩 있으면 막 뒤섞여 있으므로 무질서하다. 특히 이처럼 5:5 비율일 경우에는 무질서가 가장 높게 측정 된다. 한쪽으로 치우칠수록 분류가 잘되는 방향이기 때문이다.
값이 1/2 일때 가장 높은 무질서 값 1을 기록한다. 엔트로피 활용은 아래 그림처럼 사용된다.
날씨 테스트의 전체 무질서 값은 얼마인지 계산하여 각 노드에 들어올 순서를 정해 줄수 있다.
이로써 각 노드의 무질서값을 알수있다. 첫번재 노드는 날씨테스트를 시작으로 바람 -> 온도 -> 습도 순으로 분류가 진행될것이다.
의사결정나무의 단점은 과적합이다. 다시 말하면 일반화 하기엔 문제가 있다는 것이다. 왜?? 위와 같은 트리는 노드들의 순서가 정해져 있다. 이렇게 되면 일반화하기엔 무리가 있다. 이를 보완 위해서 랜덤포레스트를 사용한다.
install.packages('tree')
library(tree)
library(caret)
rawdata <- read.csv(file='wine.csv', header=TRUE)
rawdata$Class <- as.factor(rawdata$Class)
str(rawdata) #데이터 형태를 볼수 있다.
analdata <- rawdata
set.seed(2021)
datatotal <- sort(sample(nrow(analdata),nrow(analdata)*.7))
train <- rawdata[datatoal,]
test <- rawdata[-datatoal,]
str(train)
str(test)
#모델
library(tree)
#기본트리
treeRaw <- tree(Class~., data=train)
plot(treeRaw)
text(treeRaw) #Cv,가지치기 하지 않은 가장 기본적인 트리
#기본트리-> 가지치기위해서 적절한 사이즈(depth) 찾기
#prune.misclass: 오분류 기준
cv_tree <- cv.tree(treeRaw, FUN=prune.misclass)
plot(cv_tree)
#사이즈를 바꿔가며 오분류율을 본다. 최적의 사이즈:3
#사이즈가 높다 -> 트리가 많다 -> 피처들을 많이 사용해야한다 -> 복잡도가 올라간다
#너무 단순해도, 너무 복잡해도 안된다.
#사이즈 4로 가지치기(pruning)
prune_tree <- prune.misclass(treeRaw, best=4)
plot(prune_tree)
text(prune_tree,pretty = 0)
#예측하기
pred <- predict(prune_tree, test, type='class')
confusionMatrix(pred,test$Class)
#의사결정은 과적합 가능성이 높다
*랜덤포레스트
쉽게 생각하면 위와 같은 트리구조를 여러개 만든다. 피처들의 순서가 고정된 것이 아니라 여러가지의 경우의 수를 만들어 가면서 트리를 많이 만들어서 일반화에 가깝게 만든다.
주어진 데이터의 행을 추출하는데 중복이 가능하다. 2단계는 피처를 임의의 d개 만큼 뽑아서 의사결정나무처럼 트리구조를 만들어서 분류한다. 여러 트리를 만든 후에는 다수결 원칙?에 따라 최종 결과가 정해진다.
library(caret)
rawdata <- read.csv(file='wine.csv', header=TRUE)
rawdata$Class <- as.factor(rawdata$Class)
str(rawdata) #데이터 형태를 볼수 있다.
analdata <- rawdata
set.seed(2021)
datatotal <- sort(sample(nrow(analdata),nrow(analdata)*.7))
train <- rawdata[datatoal,]
test <- rawdata[-datatoal,]
str(train)
str(test)
#모델
ctrl <- trainControl(method='repeatedcv',repeats=5)
rfFit <- train(Class~.,
data=train,
method='rf',
trControl=ctrl,
preProcess=c('center','scale'),
metric='Accuracy')
rfFit
plot(rfFit)
#mtry: 랜덤 피처 갯수가 2일때 가장 좋다
#예측
pred_test <- predict(rfFit,newdata=test)
confusionMatrix(pred_test,test$Class)
#변수 중요도
importance_rf <- varImp(rfFit, scale=FALSE)
plot(importance_rf)
태양열 프로젝트
첫번째 시도. 랜덤 포레스트 log 상태에서 스케일링에 따른 변화
-> 변화 없음
두번째 시도. log 아닌 상태에서 스케일링에 따른 변화
->Normalizer
세번째 시도. 변수의 차분 변화에 따른 성능 측정
->변수2개이상 동시 사용시 성능 저하 발생
네번째 시도. extracted_features 활용
-> 모든 변수 사용시 성능 저하 발생하여 VIF 및 RFECV 실행
extracted_features 함수를 통해 얻은 변수들중 의미있어 보이는 120여개 피처들로 예측한 그래프입니다.
성능값이 23점을 기록했습니다;;
120여개의 피처들을 vif를 통해 추리고, 추린 값을 refecv를 통해 또 추려봤습니다. 120개의 피처을 refecv를 돌리면 에러가 발생해서 vif통해 1차적으로 걸렀습니다. 그래서 vif을 통해 얻은 피처 VS vif+refecv을 통해 얻은 피처들을 각각 랜덤포레스트에 돌렸고 결과는 아래와 같습니다. 기존 변수 활용시 성능은 7.801이였습니다.
* VIF : 7.98 (성능다운)
* refecv: 7.98(성능다운)
다섯번째 시도. 랜덤포레스트 그리드 서치
-> 랜덤포레스트 그리드 서치를 실행했습니다.
{'criterion': 'mse',
'max_depth': None,
'max_features': 'auto',
'min_samples_leaf': 2,
'min_samples_split': 8,
'n_estimators': 300}
앞서 구한 결과를 토대로 적용한 결과
* 7.96 (성능다운)
여섯번째 시도. 계절성 분해 적용
-> target값을 분해한 후 validation data인 2021년 01월달 추세&계절값은 2020년도 01월 값을 사용했습니다.
랜덤포레스트: 13.98 (추세+계절)
랜덤포레스트: 7.78(계절), 약 0.02 개선
개선된 값을 통해 SARIMAX에 적용 중입니다. 결과는 내일 포스팅 하겠습니다.
'Data Diary' 카테고리의 다른 글
2021-06-24(태양열예측27) (0) | 2021.06.24 |
---|---|
2021-06-23(태양열예측26) (0) | 2021.06.23 |
2021-06-21(R 데이터 분석_5(나이브베이즈)& 태양열예측24) (0) | 2021.06.21 |
2021-06-17(R 데이터 분석_4(knn,logitstic)) (0) | 2021.06.19 |
2021-06-16(R 데이터 분석_3(머신러닝_개요)& 태양열 예측23) (0) | 2021.06.16 |