안녕하세요. 이번 파트는 정형 데이터마이닝 - 분류분석에 대해서 알아보고자 합니다.
분류분석을 바로 알아보기에 앞서, 정형 데이터마이닝에 어떤 것이 있는가 부터 차근히 알아가볼께요..
정형 데이터마이닝 학습?
분석기법으로 활용도가 가장 높고, 지속적으로 주목받고 있는 데이터 마이닝 기법.
모든 산업과 다양한 문제해결에 즉각적 적용이 가능한 내용들로 CRM 분야에서 많이 사용되었으며,
빅데이터 시대에 더욱 각광받고 있다.
비정형 데이터와 정형 데이터 결합까지 고려하면 활용도가 매우 높아 깊이 있게 파악해야할 내용이다.
데이터마이닝의 개념과 분류?
개념 : 데이터 마이닝(data mining)은 대규모로 저장된 데이터 안에서 체계적이고 자동적으로 통계적 규칙이나 패턴을 찾아내는 것 (위키피디아)
분류 :
1) Classification(분류 분석) :
이미 정의된 유한한 범주를 분류하는 분석으로, CRM에서 캠페인에 반응할 고객과 반응하지 않을 고객으로 분류하거나 부실기업 예측 등에 활용.
2) Prediction(예측 분석) :
분류 분석과 유사하나 연속적인 값을 예측하는 분석으로, 고객의 소득 수준 예측, 자녀의 키 예측 등에 활용한다.
3) Clustering(군집 분석) :
관찰 대상에 대해 수집된 정보로 유사한 특성을 가진 그룹으로 나누어 집단의 특성을 도출하는 기법으로 집단의 프로파일링, 집단 간 구분 기준 파악에 활용.
4) Association Analysis(연관성 분석) :
데이터 간의 관계를 원인과 결과의 관계로 연결하는 분석으로 마트의 특정 상품 간의 연관성 분석을 통한 상품 디스플레이 방안 도출 등에 활용한다.
# 이렇게 정형 데이터마이닝이란 무엇인가 알아보았고, 분류엔 어떤 것이 있는지 알아보았는데요! 이제 분류분석부터 차근히 하나씩 알아가보겠습니다.
분류 분석(Classification)
분류예측하고자 하는 타겟 값을 0 또는 1, A 또는 B, C로 설정하고 입력변수들을 이용하여
타겟을 분류예측하는 패턴을 파악하는 방법이다.
1. 정의
-관찰 대상을 이미 정의된 유한한 범주로 분류하는 분석으로 잘 정의된 변수와 충분한 training set을 확보하는 것이 분석의 성공에 key factor이다.
2. 활용 분야
(1) CRM 캠페인 반응할 고객 분류
(2) 금융기관 대출 고객의 대출한도액 분류, 카드사 고객의 우량, 불량 분류
(3) 다수희 범주형 변수의 병합을 통한 범주 축소, 연속형 변수의 이산화
(4) 주식의 상승 및 하락 예상 종목 분류, 부실기업 예측 등
3. 적용 시 유의사항
-이미 정의된 특정 목적을 가지고 유한한 범주로 관측 대상을 나누는 분석이므로 분류 분석을 활용하기 위해서는 잘 정의된 Data set을 확보하여 Training과
Validation을 위해 8:2 또는 7:3으로 나누어야 하고, 개발된 모델을 시범 적용할 Test Data도 확보하여야 한다. 예를 들어 1월~6월의 Data를 가지고 있다면,
1~4월의 데이터를 7:3으로 분리하여 모델을 train하고 validation한 후, 5~6월의 data를 이용하여 다시 한번 검증(test)하여야 한다.
즉, 동일 기간 내에 모델을 생성하고, validation하는 것은 물론 인접한 다른 기간에 적요아여 시간의 흐름 등에 따른 변동 요인에도 안정적으로 적용이 가능한지를
검증(test)해야 한다.
4. 모형과 R패키지
(1) 의사결정나무 (Decision Tree) : party, rpart, randomForest
정의 : 의사 결정 규칙이 나무 모형으로 이루어진 분류 방법
용어 : node(노드, 각 분기점), root node(뿌리 노드, 최상위 분기점), leaf(잎, 최하단의 각 개체가 속하는 그룹, 분류의 결과)
(2) 최근접 이웃(Nearest Neighborhood) : kknn
(3) 신경망 분석(Neural Network) : nnet
(4) 지지도벡터기계(Support Vector Machine) : e1071
(5) caret(Classification ANd Regression Tree) : caret
(6) 베이지안 정리 (Bayesian Theorem) : LearnBayes
5. party 패키지 분석 사례
# 파티 패키지를 사용해서 분류분석을 하기 위해 데이터를 불러옵니다.
install.packages("HDclassif")
install.packages("party")
library(HDclassif)
library(party)
data(wine)
# wine data에대해서 알아보고 가겠습니다.
These data are the results of a chemical analysis of wines grown in the same region in Italy but derived from three different cultivars. The analysis determined the quantities of 13 constituents found in each of the three types of wines.
#이탈리아의 동일한 지역에서 재배되지만 3가지의 다른 품종으로 만들어진 와인에 대해서 13가지 구성요소로 화학 분석을 한 데이터이군요.
# 변수 구성은 다음과 같습니다.
V1(Alcohol), V2(Malic acid), V3(Ash), V4(Alcalinity of ash), V5(Magnesium), V6(Total phenols), V7(Flavanoids),
V8(Nonflavanoid phenols), V9(Proanthocyanins), V10(Color intensity), V11(Hue), V12(OD280/OD315 of diluted wines)
V13(Proline)
# A data frame with 178 observations on the following 14 variables : (14개의 변수, 178개의 관측치)
head(wine)
class V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13
1 1 14.23 1.71 2.43 15.6 127 2.80 3.06 0.28 2.29 5.64 1.04 3.92 1065
2 1 13.20 1.78 2.14 11.2 100 2.65 2.76 0.26 1.28 4.38 1.05 3.40 1050
3 1 13.16 2.36 2.67 18.6 101 2.80 3.24 0.30 2.81 5.68 1.03 3.17 1185
4 1 14.37 1.95 2.50 16.8 113 3.85 3.49 0.24 2.18 7.80 0.86 3.45 1480
5 1 13.24 2.59 2.87 21.0 118 2.80 2.69 0.39 1.82 4.32 1.04 2.93 735
6 1 14.20 1.76 2.45 15.2 112 3.27 3.39 0.34 1.97 6.75 1.05 2.85 1450
str(wine)
'data.frame': 178 obs. of 14 variables:
$ class: int 1 1 1 1 1 1 1 1 1 1 ...
$ V1 : num 14.2 13.2 13.2 14.4 13.2 ...
$ V2 : num 1.71 1.78 2.36 1.95 2.59 1.76 1.87 2.15 1.64 1.35 ...
$ V3 : num 2.43 2.14 2.67 2.5 2.87 2.45 2.45 2.61 2.17 2.27 ...
$ V4 : num 15.6 11.2 18.6 16.8 21 15.2 14.6 17.6 14 16 ...
$ V5 : int 127 100 101 113 118 112 96 121 97 98 ...
$ V6 : num 2.8 2.65 2.8 3.85 2.8 3.27 2.5 2.6 2.8 2.98 ...
$ V7 : num 3.06 2.76 3.24 3.49 2.69 3.39 2.52 2.51 2.98 3.15 ...
$ V8 : num 0.28 0.26 0.3 0.24 0.39 0.34 0.3 0.31 0.29 0.22 ...
$ V9 : num 2.29 1.28 2.81 2.18 1.82 1.97 1.98 1.25 1.98 1.85 ...
$ V10 : num 5.64 4.38 5.68 7.8 4.32 6.75 5.25 5.05 5.2 7.22 ...
$ V11 : num 1.04 1.05 1.03 0.86 1.04 1.05 1.02 1.06 1.08 1.01 ...
$ V12 : num 3.92 3.4 3.17 3.45 2.93 2.85 3.58 3.58 2.85 3.55 ...
$ V13 : int 1065 1050 1185 1480 735 1450 1290 1295 1045 1045 ...
#목적 변수 범주화와 구성 확인 : integer형태로 되어 있는 class 변수를 범주형(factor)으로 변환하고 각 factor별 수를 확인합니다.
wine$class<-factor(wine$class)
table(wine$class)
1 2 3
59 71 48
#data 분리 : data를 7:3으로 나누어 train set과 validation set으로 분리
#set.seed()는 음.. 난수생성에 있어서 초기값을 지정해 준 것이라고 보면 됩니다.
set.seed(2020)
ind<-sample(2, nrow(wine), replace=TRUE, prob=c(0.7,0.3))
table(ind)
ind
1 2
128 50
# train셋에 ind가 1인 것을 , validation셋에 ind가 2인 것을 넣습니다.
tr_wine<-wine[ind==1,]
val_wine<-wine[ind==2,]
#그리고 확인!
str(tr_wine)
'data.frame': 128 obs. of 14 variables:
$ class: Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
$ V1 : num 14.2 13.2 13.2 14.4 13.2 ...
$ V2 : num 1.71 1.78 2.36 1.95 2.59 1.76 1.87 2.15 1.64 1.35 ...
$ V3 : num 2.43 2.14 2.67 2.5 2.87 2.45 2.45 2.61 2.17 2.27 ...
$ V4 : num 15.6 11.2 18.6 16.8 21 15.2 14.6 17.6 14 16 ...
$ V5 : int 127 100 101 113 118 112 96 121 97 98 ...
$ V6 : num 2.8 2.65 2.8 3.85 2.8 3.27 2.5 2.6 2.8 2.98 ...
$ V7 : num 3.06 2.76 3.24 3.49 2.69 3.39 2.52 2.51 2.98 3.15 ...
$ V8 : num 0.28 0.26 0.3 0.24 0.39 0.34 0.3 0.31 0.29 0.22 ...
$ V9 : num 2.29 1.28 2.81 2.18 1.82 1.97 1.98 1.25 1.98 1.85 ...
$ V10 : num 5.64 4.38 5.68 7.8 4.32 6.75 5.25 5.05 5.2 7.22 ...
$ V11 : num 1.04 1.05 1.03 0.86 1.04 1.05 1.02 1.06 1.08 1.01 ...
$ V12 : num 3.92 3.4 3.17 3.45 2.93 2.85 3.58 3.58 2.85 3.55 ...
$ V13 : int 1065 1050 1185 1480 735 1450 1290 1295 1045 1045 ...
#이제 분류 분석을 위해서 party패키지를 설치해야 합니다. 저는 시작부터 설치해놨으니~ 스킵 하구요!
mdl_party <- ctree(class ~. , data=tr_wine)
#자 위의 설명은 mdl_party에 class를 타겟으로 하고, 나머지 변수를 투입변수로 하여 모델을 개발하는 공식입니다.
#밑에 str(tr_wine)을 치면 엄청나게 길게 주르륵 나옵니다. (유의)ㅋㅋ
str(mdl_party)
Formal class 'BinaryTree' [package "party"] with 10 slots
..@ data :Formal class 'ModelEnvFormula' [package "modeltools"] with 5 slots
.. .. ..@ env :<environment: 0x0f08c5b0>
.. .. ..@ get :function (which, data = NULL, frame = parent.frame(), envir = MEF@env)
.. .. ..@ set :function (which = NULL, data = NULL, frame = parent.frame(), envir = MEF@env)
.. .. ..@ hooks : list()
.. .. ..@ formula:List of 2
.. .. .. ..$ response: language ~class
.. .. .. ..$ input : language ~V1 + V2 + V3 + V4 + V5 + V6 + V7 + V8 + V9 + V10 + V11 + V12 + V13
..@ responses :Formal class 'ResponseFrame' [package "party"] with 14 slots
.. .. ..@ test_trafo : num [1:128, 1:3] 1 1 1 1 1 1 1 1 1 1 ...
.. .. .. ..- attr(*, "dimnames")=List of 2
.. .. .. .. ..$ : chr [1:128] "1" "2" "3" "4" ...
.. .. .. .. ..$ : chr [1:3] "X1" "X2" "X3"
.. .. ..@ predict_trafo : num [1:128, 1:3] 1 1 1 1 1 1 1 1 1 1 ...
.. .. .. ..- attr(*, "dimnames")=List of 2
.. .. .. .. ..$ : chr [1:128] "1" "2" "3" "4" ...
.. .. .. .. ..$ : chr [1:3] "class.1" "class.2" "class.3"
.. .. ..@ variables :'data.frame': 128 obs. of 1 variable:
.. .. .. ..$ class: Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
.. .. .. ..- attr(*, "terms")=Classes 'terms', 'formula' language ~class
.. .. .. .. .. ..- attr(*, "variables")= language list(class)
.. .. .. .. .. ..- attr(*, "factors")= int [1, 1] 1
.. .. .. .. .. .. ..- attr(*, "dimnames")=List of 2
.. .. .. .. .. .. .. ..$ : chr "class"
.. .. .. .. .. .. .. ..$ : chr "class"
.. .. .. .. .. ..- attr(*, "term.labels")= chr "class"
.. .. .. .. .. ..- attr(*, "order")= int 1
.. .. .. .. .. ..- attr(*, "intercept")= int 1
.. .. .. .. .. ..- attr(*, "response")= int 0
.. .. .. .. .. ..- attr(*, ".Environment")=<environment: 0x0f0a5b20>
.. .. .. .. .. ..- attr(*, "predvars")= language list(class)
.. .. .. .. .. ..- attr(*, "dataClasses")= Named chr "factor"
.. .. .. .. .. .. ..- attr(*, "names")= chr "class"
.. .. ..@ transformations:List of 1
.. .. .. ..$ : num [1:128, 1:3] 1 1 1 1 1 1 1 1 1 1 ...
.. .. .. .. ..- attr(*, "dimnames")=List of 2
.. .. .. .. .. ..$ : chr [1:128] "1" "2" "3" "4" ...
.. .. .. .. .. ..$ : chr [1:3] "1" "2" "3"
.. .. ..@ is_nominal : Named logi TRUE
.. .. .. ..- attr(*, "names")= chr "class"
.. .. ..@ is_ordinal : Named logi FALSE
.. .. .. ..- attr(*, "names")= chr "class"
.. .. ..@ is_censored : Named logi FALSE
.. .. .. ..- attr(*, "names")= chr "class"
.. .. ..@ ordering :List of 1
.. .. .. ..$ class: NULL
.. .. ..@ levels :List of 1
.. .. .. ..$ class: chr [1:3] "1" "2" "3"
.. .. ..@ scores :List of 1
.. .. .. ..$ class: num 0
.. .. ..@ has_missings : Named logi FALSE
.. .. .. ..- attr(*, "names")= chr "class"
.. .. ..@ whichNA :List of 1
.. .. .. ..$ class: int(0)
.. .. ..@ nobs : int 128
.. .. ..@ ninputs : int 1
..@ cond_distr_response:function (newdata = NULL, mincriterion = 0, ...)
..@ predict_response :function (newdata = NULL, mincriterion = 0, type = c("response", "node",
"prob"), ...)
..@ prediction_weights :function (newdata = NULL, mincriterion = 0, ...)
..@ get_where :function (newdata = NULL, mincriterion = 0, ...)
..@ update :function (weights = NULL)
..@ tree :List of 10
.. ..$ nodeID : int 1
.. ..$ weights : num [1:128] 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ criterion :List of 3
.. .. ..$ statistic : Named num [1:13] 78.3 38.2 19.8 34.6 13.4 ...
.. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. ..$ criterion : Named num [1:13] 1 1 0.999 1 0.984 ...
.. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. ..$ maxcriterion: num 1
.. ..$ terminal : logi FALSE
.. ..$ psplit :List of 7
.. .. ..$ variableID : int 7
.. .. ..$ ordered : logi TRUE
.. .. ..$ splitpoint : num 1.39
.. .. ..$ splitstatistics: num [1:128] 5.12 7.47 3.77 2.35 7.7 ...
.. .. ..$ toleft : int 1
.. .. ..$ table : NULL
.. .. ..$ variableName : chr "V7"
.. .. ..- attr(*, "class")= chr "orderedSplit"
.. ..$ ssplits : list()
.. ..$ prediction: num [1:3] 0.312 0.406 0.281
.. ..$ left :List of 10
.. .. ..$ nodeID : int 2
.. .. ..$ weights : num [1:128] 0 0 0 0 0 0 0 0 0 0 ...
.. .. ..$ criterion :List of 3
.. .. .. ..$ statistic : Named num [1:13] 9.14 11.94 13.68 14.02 2.15 ...
.. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. ..$ criterion : Named num [1:13] 0.968 0.993 0.997 0.998 0.136 ...
.. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. ..$ maxcriterion: num 1
.. .. ..$ terminal : logi FALSE
.. .. ..$ psplit :List of 7
.. .. .. ..$ variableID : int 11
.. .. .. ..$ ordered : logi TRUE
.. .. .. ..$ splitpoint : num 0.89
.. .. .. ..$ splitstatistics: num [1:128] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. ..$ toleft : int 1
.. .. .. ..$ table : NULL
.. .. .. ..$ variableName : chr "V11"
.. .. .. ..- attr(*, "class")= chr "orderedSplit"
.. .. ..$ ssplits : list()
.. .. ..$ prediction: num [1:3] 0 0.167 0.833
.. .. ..$ left :List of 10
.. .. .. ..$ nodeID : int 3
.. .. .. ..$ weights : num [1:128] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. ..$ criterion :List of 3
.. .. .. .. ..$ statistic : Named num [1:13] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. ..$ criterion : Named num [1:13] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. ..$ maxcriterion: num 0
.. .. .. ..$ terminal : logi TRUE
.. .. .. ..$ psplit :List of 6
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. ..$ ssplits : list()
.. .. .. ..$ prediction: num [1:3] 0 0 1
.. .. .. ..$ left : NULL
.. .. .. ..$ right : NULL
.. .. .. ..$ NA : num 34
.. .. .. ..- attr(*, "class")= chr "TerminalNode"
.. .. ..$ right :List of 10
.. .. .. ..$ nodeID : int 4
.. .. .. ..$ weights : num [1:128] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. ..$ criterion :List of 3
.. .. .. .. ..$ statistic : Named num [1:13] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. ..$ criterion : Named num [1:13] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. ..$ maxcriterion: num 0
.. .. .. ..$ terminal : logi TRUE
.. .. .. ..$ psplit :List of 6
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. ..$ ssplits : list()
.. .. .. ..$ prediction: num [1:3] 0 0.875 0.125
.. .. .. ..$ left : NULL
.. .. .. ..$ right : NULL
.. .. .. ..$ NA : num 8
.. .. .. ..- attr(*, "class")= chr "TerminalNode"
.. .. ..$ NA : num 42
.. .. ..- attr(*, "class")= chr "SplittingNode"
.. ..$ right :List of 10
.. .. ..$ nodeID : int 5
.. .. ..$ weights : num [1:128] 1 1 1 1 1 1 1 1 1 1 ...
.. .. ..$ criterion :List of 3
.. .. .. ..$ statistic : Named num [1:13] 59.35 2.23 11.51 24.88 17.14 ...
.. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. ..$ criterion : Named num [1:13] 1 0.00563 0.95957 0.99995 0.99753 ...
.. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. ..$ maxcriterion: num 1
.. .. ..$ terminal : logi FALSE
.. .. ..$ psplit :List of 7
.. .. .. ..$ variableID : int 1
.. .. .. ..$ ordered : logi TRUE
.. .. .. ..$ splitpoint : num 13
.. .. .. ..$ splitstatistics: num [1:128] 0 7.33 7.53 0 7.13 ...
.. .. .. ..$ toleft : int 1
.. .. .. ..$ table : NULL
.. .. .. ..$ variableName : chr "V1"
.. .. .. ..- attr(*, "class")= chr "orderedSplit"
.. .. ..$ ssplits : list()
.. .. ..$ prediction: num [1:3] 0.4651 0.5233 0.0116
.. .. ..$ left :List of 10
.. .. .. ..$ nodeID : int 6
.. .. .. ..$ weights : num [1:128] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. ..$ criterion :List of 3
.. .. .. .. ..$ statistic : Named num [1:13] 3.128 3.666 1.424 0.319 0.193 ...
.. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. ..$ criterion : Named num [1:13] 3.53e-01 4.76e-01 3.19e-02 1.59e-05 7.91e-07 ...
.. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. ..$ maxcriterion: num 0.476
.. .. .. ..$ terminal : logi TRUE
.. .. .. ..$ psplit :List of 6
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. .. ..$ : NULL
.. .. .. ..$ ssplits : list()
.. .. .. ..$ prediction: num [1:3] 0.0233 0.9767 0
.. .. .. ..$ left : NULL
.. .. .. ..$ right : NULL
.. .. .. ..$ NA : num 43
.. .. .. ..- attr(*, "class")= chr "TerminalNode"
.. .. ..$ right :List of 10
.. .. .. ..$ nodeID : int 7
.. .. .. ..$ weights : num [1:128] 1 1 1 1 1 1 1 1 1 1 ...
.. .. .. ..$ criterion :List of 3
.. .. .. .. ..$ statistic : Named num [1:13] 2.12 2.21 4.49 10.86 9.62 ...
.. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. ..$ criterion : Named num [1:13] 0.00394 0.0054 0.23361 0.94452 0.89911 ...
.. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. ..$ maxcriterion: num 1
.. .. .. ..$ terminal : logi FALSE
.. .. .. ..$ psplit :List of 7
.. .. .. .. ..$ variableID : int 6
.. .. .. .. ..$ ordered : logi TRUE
.. .. .. .. ..$ splitpoint : num 2.45
.. .. .. .. ..$ splitstatistics: num [1:128] 0 0 0 0 0 ...
.. .. .. .. ..$ toleft : int 1
.. .. .. .. ..$ table : NULL
.. .. .. .. ..$ variableName : chr "V6"
.. .. .. .. ..- attr(*, "class")= chr "orderedSplit"
.. .. .. ..$ ssplits : list()
.. .. .. ..$ prediction: num [1:3] 0.907 0.0698 0.0233
.. .. .. ..$ left :List of 10
.. .. .. .. ..$ nodeID : int 8
.. .. .. .. ..$ weights : num [1:128] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. ..$ criterion :List of 3
.. .. .. .. .. ..$ statistic : Named num [1:13] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. .. ..$ criterion : Named num [1:13] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. .. ..$ maxcriterion: num 0
.. .. .. .. ..$ terminal : logi TRUE
.. .. .. .. ..$ psplit :List of 6
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. ..$ ssplits : list()
.. .. .. .. ..$ prediction: num [1:3] 0.5 0.375 0.125
.. .. .. .. ..$ left : NULL
.. .. .. .. ..$ right : NULL
.. .. .. .. ..$ NA : num 8
.. .. .. .. ..- attr(*, "class")= chr "TerminalNode"
.. .. .. ..$ right :List of 10
.. .. .. .. ..$ nodeID : int 9
.. .. .. .. ..$ weights : num [1:128] 1 1 1 1 1 1 1 1 1 1 ...
.. .. .. .. ..$ criterion :List of 3
.. .. .. .. .. ..$ statistic : Named num [1:13] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. .. ..$ criterion : Named num [1:13] 0 0 0 0 0 0 0 0 0 0 ...
.. .. .. .. .. .. ..- attr(*, "names")= chr [1:13] "V1" "V2" "V3" "V4" ...
.. .. .. .. .. ..$ maxcriterion: num 0
.. .. .. .. ..$ terminal : logi TRUE
.. .. .. .. ..$ psplit :List of 6
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. .. ..$ : NULL
.. .. .. .. ..$ ssplits : list()
.. .. .. .. ..$ prediction: num [1:3] 1 0 0
.. .. .. .. ..$ left : NULL
.. .. .. .. ..$ right : NULL
.. .. .. .. ..$ NA : num 35
.. .. .. .. ..- attr(*, "class")= chr "TerminalNode"
.. .. .. ..$ NA : num 43
.. .. .. ..- attr(*, "class")= chr "SplittingNode"
.. .. ..$ NA : num 86
.. .. ..- attr(*, "class")= chr "SplittingNode"
.. ..$ NA : num 128
.. ..- attr(*, "class")= chr "SplittingNode"
..@ where : int [1:128] 9 9 9 9 9 9 9 9 9 9 ...
..@ weights : num [1:128] 1 1 1 1 1 1 1 1 1 1 ...
#무려 저 두줄을 쳤을 뿐인데 글이 나무처럼 보일 정도에요.
#하지만 저걸 읽을 필요 없이, 시각화하면 보기 편하게 됩니다.
plot(mdl_party)
# 보시면, ROOT NODE가 V7(1)이 되고, NODE는 V7(1) , V11(2), V1(5), V6(7), Node 3,4,6,8,9이고,
잎은 Node3,4,6,8,9가 됩니다.
# Node8에 대한 설명은, train set에서 V7>1.39, V1>13.03, V6<=2.45인 8개 항목이 Node 8에 속해있고, 8개 중 class가 1인것이
# 8개 중 class가 1인것이 0.5*8 = 4개 , class가 2인 것이 0.375*8=3개, 3인 것이 0.125*8=1개이다. 즉, 이 잎에 속한 개체는 모두
# Class 1로 분류되며, 전체 잎들 중에 가장 분류가 제대로 안된 leaf라고 할 수 있습니다. 반면 다른 리프는 대체적으로 잘 분류되었죠.
# 위의 그림은 plot(mdl_party, terminal_panel = node_barplot) 이것과 같습니다.
plot(mdl_party, type="simple")
#이러한 형태로도 나타낼 수 있습니다. plot(mdl_party, terminal_panel = node_terminal)와 같습니다.
#이제 분류 결과를 predict를 이용해 확인 가능하며, 이를 실제 결과와 비교한 matrix를 저장하고,
#Accuracy(정확성), Precision(정밀도), Detect Rate(탐지율)를 구할 수 있습니다.
#Detect Rate는 찾고자 하는 target에 대해서는 Sensitivity(민감도)를, 그 외 target에 대해서는 Specificity(특이도)라는 용어를 사용해
#향후 모델 평가 시 이용하게 됩니다.
#res_tr에 집어넣고, 전체 합으로 나눠줍니다.
res_tr<-table(predict(mdl_party), tr_wine$class)
res_tr/sum(res_tr)
1 2 3
1 0.3046875 0.0234375 0.0078125
2 0.0078125 0.3828125 0.0078125
3 0.0000000 0.0000000 0.2656250
#diag()함수는 diagonal matrix를 construct하는 함수입니다.
#Accuracy 정확성 계산
sum(diag(res_tr))/sum(res_tr)
[1] 0.953125
#Precision 정밀도 계산
res_tr[1,1]/sum(res_tr[1, ])
[1] 0.9069767
res_tr[2,2]/sum(res_tr[2, ])
[1] 0.9607843
res_tr[3,3]/sum(res_tr[3, ])
[1] 1
#Detect rate
res_tr[1, 1]/sum(res_tr[, 1])
[1] 0.975
res_tr[2, 2]/sum(res_tr[, 2])
[1] 0.9423077
res_tr[3, 3]/sum(res_tr[, 3])
[1] 0.9444444
##이제 training셋이 아닌, validation set입니다.
### Performance - validation set
res_val<-table(predict(mdl_party, newdata=val_wine), val_wine$class)
res_val/sum(res_val)
1 2 3
1 0.36 0.06 0.00
2 0.02 0.30 0.02
3 0.00 0.02 0.22
#Accuracy 정확성 계산
sum(diag(res_val))/sum(res_val)
[1] 0.88
#Precision 정밀도 계산
res_val[1,1]/sum(res_val[1, ])
[1] 0.8571429
res_val[2,2]/sum(res_val[2, ])
[1] 0.8823529
res_val[3,3]/sum(res_val[3, ])
[1] 0.9166667
#Detect rate
res_val[1, 1]/sum(res_val[, 1])
[1] 0.9473684
res_val[2, 2]/sum(res_val[, 2])
[1] 0.7894737
res_val[3, 3]/sum(res_val[, 3])
[1] 0.9166667
### 모델 평가
1) Confusion Matrix
-party패키지를 이용한 wine data분석에서 사용한 res_tr과 res_val을 도출한 결과가 Confusion Matrix를 이용한 모델 평가로 table(A,B)에서 A가
row를 형성하여 예측 값이 row로 들어가며, B는 실제 값으로 column에 들어간다. Confusion Matrix를 통해 accruracy, precision, detect rate
(sensitivity, specificitiy) 등이 정확성 지표를 도출할 수 있다.
#위에서 우리가 해본 것이랑 동일하다고 보면 되겠죠..
2) ROC Curve
-찾고자 하는 분류의 target을 얼마나 안정적으로 찾아 주는가를 나타내는 평가 모형으로 주어진 1-Specificity에 대해 Sensitivity가 높은 형태의 ROC Curve를
그리는 것을 우수한 모델로 평가받고 있다. ROC Curve는 각 leaf에서 0,1 로 갈는 확률이 0.5뿐만이 아닌 0부터 1까지 옮겨 감에 따라 Sensitivity와
1-Specificity가 어느 점에 위치하는 지를 curve로서 곡선이 좌상에 가까울 수록 좋은 모델이다.
#ROC Curve에 대해서는 책에서 실행하는 내용이 없는데, 나중에 쭉 다 한 후에 다른 포스팅에서 조금 더 세밀하게 들어갈 때~ ROC Curve를 그려보도록 하겠습니다~
### 오늘은 정형데이터마이닝-분류분석에 대해서 알아보았는데요, 다음시간에는 예측분석에 대해 알아보겠습니당~~
'## 오래된 게시글 (미관리) ## > R' 카테고리의 다른 글
26. 정형 데이터마이닝 - 군집분석(Clustering) (0) | 2018.11.21 |
---|---|
25. 정형 데이터마이닝 - 예측 분석(Prediction) (0) | 2018.11.21 |
23. Missing Data, 이상치 (0) | 2018.11.21 |
22. 데이터 가공 (2) | 2018.11.21 |
21. 데이터마트 - 2 (2) | 2018.11.21 |