ㅇ모델 성능 평가 복습
머신러닝 모델의 성능을 평가하는 방법들
1. 정확도 : 실제 분류 범주를 정확하게 예측한 비율
2. 카파통계량 : 두 관찰자(예측, 실제)의 측정 범주값에 대한 일치도(0~1)
3. 민감도 : 실제로 '긍정'인 범주 중에서 '긍정'으로 올바르게 예측한 비율( tp / (tp + fn) )
4. 특이도 : 실제로 '부정'인 범주 중에서 '부정'으로 올바르게 예측한 비율( tn / (tn + fp) )
5. 정밀도 : '긍정'으로 예측한 것 중에서 실제로 '긍정'인 것의 비율( tp / (tp + fp) )
4. 재현율 : 민감도와 같음
5. F-척도 : 정밀도와 재현율을 하나의 값으로 결합한 성능척도( 2 *(정밀도 * 재현율) / (정밀도 + 재현율 ) )
6. ROC곡선 : y축을 민감도(TPR)로 하고 x축을 1-특이도(FPR)로 하여 그린 2차원 그래프로 거짓 긍정인 FPR을 낮추면서 참긍정인 TPR을 높일 수 있는 가장 좋은 모형을 찾기위한 시각화 도구
7. AUC score : ROC곡선 아래의 면적으로 이 면적이 크면 클수록 분류를 잘하는 모형
ㅇ모델 성능 개선하는 방법
1. k-holdout
2. caret을 이용한 모델 자동튜닝
3. 앙상블
4. 배깅
5. 부스팅
85 홀드아웃
ㅇ 홀드아웃 방법 - p.466
훈련 데이터셋(90%) -> 훈련 데이터셋의 일부를 테스트하기 위해 따로 떼어냄. 이 따로 떼어낸 데이터를 검정 데이터라고 함.
테스트 데이터셋(10%)
검정데이터셋을 사용하는 이유는 훈련 데이터 가지고 학습 할 때 최적의 하이퍼 파라미터를 찾아내기 위함임.
언더피팅과 오버피팅이 크지 않은 "적절한 하이퍼 파라미터"를 찾아내야함. 그때 검정데이터를 사용함.
훈련데이터의 일부를 검정 데이터로 분리할 때 "어떻게" 분리를 할 것인지 중요
> k - fold 교차 검정을 사용함
훈련데이터를 5등분해서 그 중에 하나를 검정데이터로 사용. 검정데이터가 시도할 때마다 변경되어서 서로 다른 등분을 사용함. 정확도가 높고 오버피팅이 안되는 최적의 하이퍼 파라미터를 찾아줌.
즉, 홀드아웃이란 훈련데이터셋과 테스트셋을 분리하는 것이고, 교차검증이란 훈련데이터의 일부를 검정 데이터로 사용하여 최적의 하이퍼 파라미터를 발견할 수 있도록 검정 데이터를 교차해 검정하는 방법
훈련 데이터와 테스트 데이터를 분리할 때 정답 컬럼의 데이터 비율이 훈련 데이터와 테스트 데이터에 잘 분배가 되어야함.
훈련 데이터와 테스트 데이터를 분리할 때 정답 컬럼의 데이터의 비율이 훈련 데이터와 테스트 데이터에 잘 분배되어야함.
예제1. runif 함수를 이용해서 훈련데이터와 테스트 데이터를 나눴을 때
#1. 데이터 로드
credit <- read.csv("c:\\data\\credit.csv")
nrow(credit) #1000
#2. 훈련 데이터/테스트 데이터 분리 - runif
set.seed(10)
random_ids <- order(runif(1000)) #난수 1000개 생성
random_ids
credit_train <- credit[random_ids[1:750], ] #학습데이터의 75%
credit_test <- credit[random_ids[751:1000], ] #학습데이터의 25%
nrow(credit_train) #750
nrow(credit_test) #250
#3. 잘 분배되었는지 확인
# 학습 데이터 셋의 label 비율
table(credit$default) #no 700, yes 300
# 훈련데이터의 label 비율
table(credit_train$default) #no 530, yes 220
prop.table(table(credit_train$default)) # no 0.7066667, yes 0.2933333
#테스트테이터의 label 비율
table(credit_test$default) #no 170, yes 80
prop.table(table(credit_test$default)) # no 0.68, yes 0.32
runif 함수를 이용해 위와 같이 훈련과 테스트 데이터를 분리하면 정답 데이터의 비율이 잘 분배되지 않음.
예제2. caret 패키지의 createDataPartition을 사용해서 분리
#1. 데이터 로드
credit <- read.csv("c:\\data\\credit.csv")
nrow(credit) #1000
#2. 훈련 데이터/테스트 데이터 분리 - caret
library(caret)
k <- createDataPartition(credit$default, p = 0.75, list = F)
credit_train <- credit[k, ]
credit_test <- credit[-k,]
nrow(credit_train) #750
nrow(credit_test) #250
#3. 잘 분배되었는지 확인
# 학습 데이터 셋의 label 비율
table(credit$default) #no 700, yes 300
# 훈련데이터의 label 비율
table(credit_train$default) #no 525, yes 225
prop.table(table(credit_train$default)) # no 0.7, yes 0.3
#테스트테이터의 label 비율
table(credit_test$default) #no 175, yes 75
prop.table(table(credit_test$default)) # no 0.7, yes 0.3
ㅇ파이썬 사이킷런으로 데이터 분리
#1. 데이터 불러오기
import pandas as pd
credit = pd.read_csv("c:\\data\\credit.csv")
credit.head()
credit.shape #(1000, 17)
#2. 명목형 데이터를 더미변수화 하기
credit2 = pd.get_dummies(credit, drop_first = True) # drop_first 첫번째 값 drop
credit2.info # 숫자로 다 바뀐거 확인
credit2.head()
#3. 훈련 데이터와 테스트 데이터 분리하기
x = credit2.iloc[:, 0:-1]
y = credit2['default_yes']
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x,y, test_size = 0.25, random_state = 1)
print(x_train.shape, x_test.shape) #(750, 35) (250, 35)
#4. 정답 데이터의 비율 확인하기
import numpy as np
np.bincount(y_train) / 750 #[0.69866667, 0.30133333]
np.bincount(y_test) / 250 #[0.704, 0.296]
> 원본데이터의 비율과 분리한 훈련데이터, 테스트데이터의 정답(label) 컬럼의 비율이 잘 맞아야 하는데 맞지 않음
정확하게 나누기 위해서는 train_test_split에서 stratify = y 옵션을 쓰면 정확하게 나눠줌.
#3. 훈련 데이터와 테스트 데이터 분리하기
x = credit2.iloc[:, 0:-1]
y = credit2['default_yes']
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x,y, test_size = 0.25, random_state = 1, stratify = y)
print(x_train.shape, x_test.shape) #(750, 35) (250, 35)
#4. 정답 데이터의 비율 확인하기
import numpy as np
np.bincount(y_train) / 750 #[0.7, 0.3]
np.bincount(y_test) / 250 #[0.7, 0.3]
86 k fold 교차검증
ㅇ교차검증 R로 실험하기 - p470
#1. 데이터 로드
credit <- read.csv("c:\\data\\credit.csv", stringsAsFactors = TRUE)
#2. 훈련데이터 전체에 대해서 10개의 교차검증을 위한 행번호 생성
folds <- createFolds(credit$default, k = 10)
str(folds)
#3. fold1을 검정데이터로 하고 나머지를 훈련데이터로 만듦
credit1_test <- credit[folds$Fold01, ]
credit1_train <- credit[-folds$Fold01, ]
nrow(credit1_test) #100
nrow(credit1_train) #900
#############################################
# 10개의 폴드를 교차검정해서 훈련데이터에 대한 kappa 지수 10개를 출력
install.packages("irr")
library(caret)
library(C50)
library(irr)
credit <- read.csv("c:\\data\\credit.csv", stringsAsFactors = TRUE)
folds <- createFolds(credit$default, k = 10) #10개의 교차검정을 할 행번호
cv_results <- lapply(folds, function(x){
credit_train <- credit[ -x,]
credit_test <- credit[x, ]
credit_model <- C5.0(default ~ ., data = credit_train)
credit_pred <- predict(credit_model, credit_test)
credit_actual <- credit_test$default
kappa <- kappa2(data.frame(credit_actual, credit_pred))$value
return(kappa)
})
str(cv_results) #10개의 카파통계량 값 출력
위의 10개의 카파통계량값의 평균값을 출력하시오.
mean(unlist(cv_results)) #0.3175273
문제429. 위 결과를 trials = 1에 대한 카파지수이고 이번에는 trials = 100에 대한 카파지수의 평균값을 출력해보겠습니다.
credit <- read.csv("c:\\data\\credit.csv", stringsAsFactors = TRUE)
folds <- createFolds(credit$default, k = 10) #10개의 교차검정을 할 행번호
cv_results <- lapply(folds, function(x){
credit_train <- credit[ -x,]
credit_test <- credit[x, ]
credit_model <- C5.0(default ~ ., data = credit_train, trials = 100)
credit_pred <- predict(credit_model, credit_test)
credit_actual <- credit_test$default
kappa <- kappa2(data.frame(credit_actual, credit_pred))$value
return(kappa)
})
str(cv_results) #10개의 카파통계량 값 출력
mean(unlist(cv_results)) #0.3676481
문제430. 위의 출력되는 결과가 카파지수가 아닌 정확도가 되게 코드를 수정하시오.
cv_results <- lapply(folds, function(x){
credit_train <- credit[ -x,]
credit_test <- credit[x, ]
credit_model <- C5.0(default ~ ., data = credit_train)
credit_pred <- predict(credit_model, credit_test)
credit_actual <- credit_test$default
x<- data.frame(credit_actual, credit_pred)
accuracy <- sum(x$credit_actual == x$credit_pred) / (length(credit_actual))
return(accuracy)
})
str(cv_results) #10개의 카파통계량 값 출력
mean(unlist(cv_results)) #0.735 정확도 평균
문제431. (점심시간 문제) 위의 결과는 trials = 1의 정확도 평균입니다. 이번에는 trials = 100으로 했을 때의 정확도가 어떻게 되는지 실험하시오.
library(caret)
library(C50)
library(irr)
credit <- read.csv("c:\\data\\credit.csv", stringsAsFactors = TRUE)
set.seed(1)
folds <- createFolds(credit$default, k = 10) #10개의 교차검정을 할 행번호
cv_results <- lapply(folds, function(x){
credit_train <- credit[ -x,]
credit_test <- credit[x, ]
credit_model <- C5.0(default ~ ., data = credit_train, trials = 100)
credit_pred <- predict(credit_model, credit_test[,-17])
credit_actual <- credit_test$default
a <- data.frame(credit_actual, credit_pred)
accuracy <- sum(a$credit_actual == a$credit_pred) / length(credit_actual)
return(accuracy)
})
str(cv_results) #10개의 값 출력
# trials = 100에 대한 정확도 평균
mean(unlist(cv_results)) #0.766
ㅇ파이썬으로 10 fold 교차검증하기
#1. 데이터 로드
from sklearn import datasets
iris = datasets.load_iris()
iris['data']
iris['target']
#2. 10 fold 교차검증 파라미터 설정
from sklearn.model_selection import GridSearchCV
parameters = {'max_depth' : [1,2,3,4,5],
'random_state':[1,5,10] }
#3. 모델 생성
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier()
#4. 모델 훈련
gmodel = GridSearchCV(model, parameters, cv = 10, verbose = 2, n_jobs = -1 ) # cv가 fold 수
gmodel.fit(iris.data, iris.target)
#5. 최적의 하이퍼 파라미터 찾기
print(gmodel.best_params_) # {'max_depth': 3, 'random_state': 1}
문제432. 독일은행 데이터(credit.csv)에 대한 의사결정트리 모델을 생성하기 위해 최적의 하이퍼 파라미터가 무엇인지 알아내시오.
#1. 데이터 로드
import pandas as pd
credit = pd.read_csv("c:\\data\\credit.csv")
credit_scaled = pd.get_dummies(credit, drop_first = True)
x = credit_scaled.iloc[:,:-1]
y = credit_scaled.iloc[:,-1]
#2. 10 fold 교차검증 파라미터 설정
from sklearn.model_selection import GridSearchCV
parameters = {'max_depth' : [1,2,3,4,5],
'random_state':[1,5,10] }
#3. 모델 생성
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier()
#4. 모델 훈련
gmodel = GridSearchCV(model, parameters, cv = 10, verbose = 2, n_jobs = -1 ) # cv가 fold 수
gmodel.fit(x,y)
#5. 최적의 하이퍼 파라미터 찾기
print(gmodel.best_params_) # {'max_depth': 3, 'random_state': 1}
+) 교차검증 참고 블로그
https://wooono.tistory.com/105
87 caret 을 이용한 자동튜닝
이전에는 머신러닝 모델의 성능을 높이기 위해 우리가 직접 모델의 성능을 높이는 하이퍼 파라미터를 알아내야했음. 그런데 caret 패키지를 이용하면 이 패키지가 알아서 최적의 하이퍼 파라미터를 찾아줌.
파이썬의 gridsearchCV로 실험했을 때 최적의 하이퍼 파라미터를 알려주듯이 R에도 이 기능이 caret패키지에 내장되어 있음.
+) caret이 다루는 모델 패키지 및 파라미터 조정 옵션 목록
https://topepo.github.io/caret/available-models.html
의사결정트리 모델로 테스트 진행해보겠음.
의사결정트리의 튜닝은 model, trials, winnow 3가지 하이퍼 파라미터의 조합으로 튜닝을 함.
총 27개의 조합으로 정확도를 각각 계산해서 정확도가 가장 높은 조합을 찾아냄.
library(caret)
library(C50)
library(irr)
credit <- read.csv("c:\\data\\credit.csv", stringsAsFactors = TRUE)
set.seed(300)
m <- train(default~., data = credit, method = "C5.0")
m #튜닝된 결과 확인
m이라는 모델이 가장 최적의 하이퍼 파라미터의 조합으로 셋팅된 모델. 최적의 하이퍼 파라미터 조합은 다음과 같음.
The final values used for the model were trials = 20, model = tree and winnow = FALSE.
result <- predict(m, credit[,-17])
sum(result == credit[,17]) / length(result) #0.998
table(credit$default, result)
문제433. 이번에는 유방암 데이터(wisc_bc_data.csv)의 악성종양과 양성종양을 분류하는 의사결정트리
library(caret)
library(C50)
library(irr)
wisc <- read.csv("c:\\data\\wisc_bc_data.csv", stringsAsFactors = TRUE)
wisc2 <- wisc[,-1]
set.seed(300)
m <- train(diagnosis~., data = wisc2, method = "C5.0")
m #튜닝된 결과 확인
The final values used for the model were trials = 20, model = rules and winnow = FALSE.
result <- predict(m, wisc2[,-1])
sum(result == wisc2[,1]) /length(result) #1
table(wisc2$diagnosis, result)
문제434. 위의 스크립트는 데이터를 통재로 다 써서 최적의 하이퍼 파라미터를 알아내고 정확도를 확인했습니다. 그런데 이번에는 데이터를 훈련 90%, 테스트 10%으로 나눠서 자동튜닝을 하고, 최적의 하이퍼 파라미터로 모델을 수행하시오.
#1. 데이터 로드
wisc <- read.csv("c:\\data\\wisc_bc_data.csv", stringsAsFactors = TRUE)
wisc2 <- wisc[,-1]
#2. 훈련:테스트 분리
set.seed(1)
k <- createDataPartition(wisc2$diagnosis, p = 0.9, list = F)
train_data <- wisc2[k, ]
test_data <- wisc2[-k,]
nrow(train_data) #513
nrow(test_data) #56
#3. 훈련데이터로 자동 튜닝
set.seed(300)
m <- train(diagnosis~ ., data = train_data, method = "C5.0")
m #trials = 20, model = rules and winnow = FALSE
#4. 최적의 하이퍼 파라미터로 세팅된 모델로 테스트 데이터를 예측
result <- predict(m, test_data[,-1])
sum(result == test_data[,1]) / length(test_data[,1]) #0.9642857
table(test_data$diagnosis, result)
이번에는 독버섯 데이터를 분류하는 모델을 자동튜닝하여 생성해보도록 하겠음. 책 483의 표를 참고해 method를 C5.0이 아니라 nb로 바꿔주면 됨.
#1. 데이터 로드
library(caret)
library(e1071)
library(irr)
#2. 훈련 데이터와 테스트 데이터 분리(9:1)
mush <- read.csv("c:\\data\\mushrooms.csv", stringsAsFactors = T)
head(mush)
#3. 훈련 데이터로 자동 튜닝 모델 생성
library(caret)
set.seed(300)
k <- createDataPartition(mush$type, p = 0.9, list = F)
train_data <- mush[k, -1]
test_data <- mush[-k, -1]
train_label <- mush[k, 1]
test_label <- mush[-k, 1]
set.seed(300)
m <- train(train_data, train_label, method = 'nb')
m # were fL = 0, usekernel = TRUE and adjust = 1
#4. 테스트 데이터 예측
result <- predict(m, test_data)
table(test_label, result)
Ripper 알고리즘을 적용해보겠음.
#3. 훈련 데이터로 자동 튜닝 모델 생성
library(caret)
set.seed(300)
k <- createDataPartition(mush$type, p = 0.9, list = F)
train_data <- mush[k, -1]
test_data <- mush[-k, -1]
train_label <- mush[k, 1]
test_label <- mush[-k, 1]
set.seed(300)
m <- train(train_data, train_label, method = 'JRip')
m # NumOpt = 3, NumFolds = 4 and MinWeights = 1
#4. 테스트 데이터 예측
result <- predict(m, test_data)
table(test_label, result)
책491페이지에 나온것처럼 자동 튜닝 기능의 성능을 더 올리기 위해서 자동튜닝 + 10 폴드 교차검증을 사용해 유방암 데이터 분류모델 만들기
#1. 데이터 로드
library(caret)
library(C50)
library(irr)
wisc <- read.csv("c:\\data\\wisc_bc_data.csv", stringsAsFactors = T)
wisc2 <- wisc[,-1]
#2. 데이터 분리
set.seed(1)
k <- createDataPartition(wisc2$diagnosis, p = 0.8, list = F)
train_data <- wisc2[k,]
test_data <- wisc2[-k,]
nrow(train_data) #456
nrow(test_data) #113
#3. 자동튜닝 모델 생성( 자동튜닝 모델 + 10 폴드 교차검증)
set.seed(1)
ctrl <- trainControl(method = "cv", number = 10, selectionFunction = "oneSE")
# 10폴트 교차검정
# oneSE는 최고의 성능의 1 표준오차 내의 가장 단순한 후보를 선택한다는 뜻
m <- train(diagnosis ~., data = train_data, trControl = ctrl, method = "C5.0")
m #trials = 10, model = rules and winnow= FALSE
#4. 모델예측
result <- predict(m, test_data[,-1])
#5. 모델평가
table(test_data$diagnosis, result)
sum(test_data$diagnosis == result) / length(test_data$diagnosis) #0.9557522
문제435. 위의 폴드 교차검정의 갯수를 10으로 햇을 때의 정확도는 0.9557522 였습니다. 그럼 이번에는 교차검정의 갯수를 20으로 하고 정확도를 확인해보세요.
#1. 데이터 로드
library(caret)
library(C50)
library(irr)
wisc <- read.csv("c:\\data\\wisc_bc_data.csv", stringsAsFactors = T)
wisc2 <- wisc[,-1]
#2. 데이터 분리
set.seed(1)
k <- createDataPartition(wisc2$diagnosis, p = 0.8, list = F)
train_data <- wisc2[k,]
test_data <- wisc2[-k,]
nrow(train_data) #456
nrow(test_data) #113
#3. 자동튜닝 모델 생성( 자동튜닝 모델 + 10 폴드 교차검증)
set.seed(1)
ctrl <- trainControl(method = "cv", number = 20, selectionFunction = "oneSE")
# 10폴드 교차검정
# oneSE는 최고의 성능의 1 표준오차 내의 가장 단순한 후보를 선택한다는 뜻
m <- train(diagnosis ~., data = train_data, trControl = ctrl, method = "C5.0")
m #trials = 10, model = rules and winnow= FALSE
#4. 모델예측
result <- predict(m, test_data[,-1])
#5. 모델평가
table(test_data$diagnosis, result)
sum(test_data$diagnosis == result) / length(test_data$diagnosis) #0.9646018
cv 값을 늘렸더니 정확도가 상승한 것을 확인할 수 있음.
문제436. 이번에는 Riper 알고리즘으로 구현하시오(교차검정 + 자동튜닝)
wisc <- read.csv("c:\\data\\wisc_bc_data.csv", stringsAsFactors = T)
wisc2 <- wisc[,-1]
#2. 데이터 분리
set.seed(1)
k <- createDataPartition(wisc2$diagnosis, p = 0.8, list = F)
train_data <- wisc2[k,]
test_data <- wisc2[-k,]
nrow(train_data) #456
nrow(test_data) #113
#3. 자동튜닝 모델 생성( 자동튜닝 모델 + 10 폴드 교차검증)
set.seed(1)
ctrl <- trainControl(method = "cv", number = 20, selectionFunction = "oneSE")
# 10폴트 교차검정
# oneSE는 최고의 성능의 1 표준오차 내의 가장 단순한 후보를 선택한다는 뜻
m <- train(diagnosis ~., data = train_data, trControl = ctrl, method = "JRip")
m #trials = 10, model = rules and winnow= FALSE
#4. 모델예측
result <- predict(m, test_data[,-1])
#5. 모델평가
table(test_data$diagnosis, result)
sum(test_data$diagnosis == result) / length(test_data$diagnosis) #0.9292035
caret의 자동튜닝 + 10 폴드 교차검정을 이용하면 우리가 앞에서 머신러닝 모델 만들 때 찾아야했던 최적의 하이퍼 파라미터를 찾는 작업을 안해도 됩니다. 기계가 알아서 찾게끔 할 수 있기 때문.
우리는 같은 데이터에 대해서 여러개의 모델을 만들고 정확도, 카파통계량, 민감도, 특이도, 정밀도, 재현율, f1-score, ROC곡선, AUC 값 등을 표로 정리해 분석 보고서를 만들면 됨.
문제437. (오늘의 마지막 문제) iris2.csv를 로드하여 아이리스 꽃의 품종을 분류하는 모델을 자동 튜닝 + 10 폴드 교차검증으로 생성하고 테스트 데이터의 정확도를 확인하시오.
#1. 데이터 로드
library(caret)
library(C50)
library(irr)
library(RWeka)
iris <- read.csv("c:\\data\\iris2.csv", stringsAsFactors = T)
head(iris) #label 5번째 컬럼
#2. 데이터 분리
set.seed(1)
k <- createDataPartition(iris$Species, p = 0.8, list = F)
train_data <- iris[k,]
test_data <- iris[-k,]
nrow(train_data) #120
nrow(test_data) #30
#3. 자동튜닝 모델 생성( 자동튜닝 모델 + 10 폴드 교차검증)
set.seed(1)
ctrl <- trainControl(method = "cv", number = 10, selectionFunction = "oneSE")
m <- train(Species ~., data = train_data, trControl = ctrl, method = "JRip")
m
#4. 모델예측
result <- predict(m, test_data[,-5])
#5. 모델평가
table(test_data$Species, result)
sum(test_data$Species == result) / length(test_data$Species) #0.9666667
'Study > class note' 카테고리의 다른 글
머신러닝 / 병렬작업, 사회적 연결망 (0) | 2022.03.07 |
---|---|
머신러닝 / 앙상블 (0) | 2022.03.07 |
머신러닝 / 민감도와 특이도, 정밀도와 재현율, F-1 score, ROC곡선 (0) | 2022.03.03 |
머신러닝 / 모델 성능 평가(카파통계량) (0) | 2022.03.02 |
머신러닝 / k-means 함수를 파이썬으로 직접 만들기 (0) | 2022.03.02 |