출처: 시작하세요! 데이터 분석 with R : R로 배우는 기초 통계와 데이터 분석 기법
Github Code: Jun4871 Github

데이터 로드 및 라이브러리 활성화

사과품종 데이터를 불러오는데 에러가 발생했다. 윈도우에 설치된 Rstudio에서는 정상적으로 읽어들였던 것을 생각해보면 AWS 환경과 연관이 있을 것 같다. 이 때 fileEncoding = “CP949”, encoding = “UTF-8” 옵션을 사용하여 정상적으로 불러올 수 있다.

데이터 탐색

간단하게 데이터를 탐색해보자. 각 컬럼의 속성을 보면 펙터로 표현되어야 할 부분과 숫자형으로 표현되어야하는 부분이 잘 처리되어 있는 것 같다. boxplot() 함수를 사용하여 항목별로 사과 품종을 구분할 수 있을 만한 특징이 있는지 상자그림을 활용해 살펴보도록 하자.

## 'data.frame':    25 obs. of  6 variables:
##  $ X     : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ model : Factor w/ 5 levels "로얄후지","미시마",..: 3 5 3 2 3 4 1 3 4 1 ...
##  $ weight: int  286 256 251 396 282 342 407 238 295 392 ...
##  $ sugar : num  12.9 13.4 12.1 16.3 15 13.4 13.6 13.5 15.1 15.6 ...
##  $ acid  : num  0.31 0.69 0.32 0.39 0.29 0.31 0.4 0.31 0.29 0.38 ...
##  $ color : Factor w/ 2 levels "적색","홍색": 2 1 2 2 2 2 1 2 2 1 ...
##        X           model       weight          sugar            acid       
##  Min.   : 1   로얄후지:5   Min.   :152.0   Min.   :12.10   Min.   :0.2800  
##  1st Qu.: 7   미시마  :5   1st Qu.:251.0   1st Qu.:13.30   1st Qu.:0.3100  
##  Median :13   아오리  :5   Median :329.0   Median :13.60   Median :0.3800  
##  Mean   :13   홍로    :5   Mean   :317.3   Mean   :14.01   Mean   :0.4168  
##  3rd Qu.:19   홍옥    :5   3rd Qu.:391.0   3rd Qu.:14.40   3rd Qu.:0.4100  
##  Max.   :25                Max.   :409.0   Max.   :16.80   Max.   :0.7300  
##   color   
##  적색:10  
##  홍색:15  
##           
##           
##           
## 

시각화

1) “사과품종 vs 무게”

로얄후지와 마시마가 다른 종에 비해 무게가 많이 나가고, 상대적으로 홍옥은 무게가 적게 나가는 것으로 보인다. 전체적으로 무게를 기준으로 품종이 어느 정도 나누어지지만, 로얄후지와 미시마는 무게만으로 구분하기 쉽지 않아보인다.


2) “사과품종 vs 당도”

무게보다 품종 간의 구분이 명확하진 않지만 무게로는 구분이 쉽지 않았던 로얄후지와 미시마는 구분이 된다. 로얄후지보다는 미시마가 더 단맛이 큼을 확인할 수 있다.

3) “사과품종 vs 산도”

홍옥의 산도가 월등하다. 확실히 산도가 약 0.6 이상이면 홍옥이라고 봐도 무방할 것으로 보인다.

4) “사과품종 vs 색상”

적생은 총 10개로 그 중 로얄후지와 홍옥이 각각 5개이다. 홍색은 총 15개로서 ‘홍로’, ‘아오리’, ’미시마’가 각각 5개씩 있다. 샘플 데이터를 기준으로 한다면 사과가 적색일 경우로 얄후지나 홍옥 중 하나일 가능성이 크다.


종합해보면 사과 품종 별로 서로 다른 특징이 존재하는 것을 알 수 있다. 무게가 350 이상인 것 중 색깔이 적색이면 ‘로얄후지’, 홍색이면 ‘미시마’, 무게가 350 미만이고 산도가 0.6 이상인 것은 ‘홍옥’, 당도가 대략 13 이상이면 ‘홍로’, 아니면 ’아오리’로 추정할 수 있다. 하지만 고려해야할 항목이 많아질수록 위와 같이 모든 것을 확인하면서 분류 기준을 산출한다는 것은 불가능할 것이다. 더군다나 모델을 한 번 만들고 계속 쓰는게 아니라 모델을 최신으로 유지하기 위해 주기적으로 들어오는 훈련 데이터를 가지고 모델에 반영해야 한다면 더더욱 불가능한 일이 됩니다. 이제 분류분석을 통해 분류하고자 하는 항목과 그와 관련되 항목들을 바탕으로 손쉽게 ’분류 기준’을 도출하는 방법을 살펴보도록 하자.



분류분석 순서

분류분석에는 의사결정 나무, 나이브 베이즈 분류, 신경망, 서포트 벡터 머신 등이 있다. 여기서 의사결정 나무를 통해서 분류분석을 해볼 것이다. 의사결정 나무는 트리 그래프를 통해 이해와 설명이 용이하고, 대용량 데이터에서도 처리 속도가 빠르며, 비정상 데이터에 대한 민감도가 상대적으로 적어 많이 활용되는 모델이다.

1) 훈련 시키기

훈련 데이터와 테스트 데이터


분류 분석 모델을 만들기 위해 먼저 해야할 일은 모델을 훈련 시키는 것이다. 그러기 위해서는 학습에 필요한 “답이 있는(이미 분류된) 데이터”가 필요한데 이 데이터는 용도에 따라 두 가지로 나누어 활용된다. 보통 훈련 데이터와 테스트 데이터는 8:2, 7:3의 비율로 나누는데 훈련 데이터를 선정할 때는 “모든 분류 유형이 포함되고 각 데이터에 대표할 만한 특성이 있는 데이터”가 될 수 있게 주의해야 한다. 그 이유는 훈련 데이터를 어떻게 추출하느냐가 그 모델의 성능에 큰 영향을 주기 때문이다.


2) 가지치키

분류분석 모델을 도출할 때는 어느 정도 상세화할 것인지 기준을 정해야 한다. 의사결정 트리 모델에서는 의사결정 트리의 노드 개수를 조절하거나 이상적인 노드 수를 선택하기 위해 CP라는 변수를 사용한다. CP를 설정함으로써 노드 생성 시 복잡성이 CP 값 이상이 되면 더 이상 분류 작업을 진행하지 않게 해준다.


3) 모델 평가하기

도출된 분류 모델의 적절성은 모델의 정확도를 통해 평가될 수 있따. 즉, 예측한 데이터 중에서 실제 값과 일치한 결과의 비율로 산정한다. 하지만 정확도만으로 분류모델을 평가하기에는 부족하며 이를 보완하기 위해 분류모델의 목적에 따라 다양한 지표들을 활요하는데 많이 활용하는 것 중 하나가 “혼동행렬”이다.


4) 데이터 나누기

의사결정 트리 분석을 하기 전 먼저 모델을 만들 훈련 데이터와 평가에 사용할 테스트 데이터를 나눈다. 먼저 아이리스 데이터로 실습해보겠다. table 함수를 통해 꽃 종류 별로 50개씩 데이터가 균일하게 존재하는 것을 확인할 수 있다. 훈련 데이터는 각 분류 항목들이 골고루 들어가도록 데이터를 구성해야 한다. 이를 위해 꽃 종류별로 직접 훈련 데이터를 선별해 만들 수 있겠지만, caret 패키지의 함수를 활용하면 각 분류 항목별 데이터를 균일한 비율로 손쉽게 추출할 수 있다. createDataPartition 은 데이터 자체를 직접 나누지는 않는다. 다만 팩터 벡터를 입력받아 항목별로 설정한 추출 비율의 데이터를 추출한 후 벡터 내 위치 정보를 결괏값으로 반환한다. 이렇게 추출된 위치 정보를 얻고 나면 데이터프레임으로부터 위치 정보를 이용해 해당 위치의 데이터를 추출할 수 있게 된다.

## [1] 150
## 
##     setosa versicolor  virginica 
##         50         50         50
##  int [1:120, 1] 1 2 4 5 6 7 8 10 11 12 ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : NULL
##   ..$ : chr "Resample1"
## 'data.frame':    120 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.6 5 5.4 4.6 5 4.9 5.4 4.8 ...
##  $ Sepal.Width : num  3.5 3 3.1 3.6 3.9 3.4 3.4 3.1 3.7 3.4 ...
##  $ Petal.Length: num  1.4 1.4 1.5 1.4 1.7 1.4 1.5 1.5 1.5 1.6 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.1 0.2 0.2 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
## 
##     setosa versicolor  virginica 
##         40         40         40


createDataPartition 함수를 활용해 꽃 종류별로 균일하게 40개씩 총 120 건의 훈련 데이터를 추출했다. 전체 데이터 중 훈련 데이터 이외의 건들은 테스트 데이터로 설정한다.

## 'data.frame':    30 obs. of  5 variables:
##  $ Sepal.Length: num  4.7 4.4 5.7 5.4 5 5 5.5 5 4.4 5.1 ...
##  $ Sepal.Width : num  3.2 2.9 4.4 3.9 3 3.4 4.2 3.2 3 3.8 ...
##  $ Petal.Length: num  1.3 1.4 1.5 1.3 1.6 1.6 1.4 1.2 1.3 1.6 ...
##  $ Petal.Width : num  0.2 0.2 0.4 0.4 0.2 0.4 0.2 0.2 0.2 0.2 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
## 
##     setosa versicolor  virginica 
##         10         10         10
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.575   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.844   Mean   :3.039   Mean   :3.757   Mean   :1.195  
##  3rd Qu.:6.425   3rd Qu.:3.400   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.100   Max.   :6.700   Max.   :2.500  
##        Species  
##  setosa    :40  
##  versicolor:40  
##  virginica :40  
##                 
##                 
## 
##   Sepal.Length    Sepal.Width    Petal.Length   Petal.Width          Species  
##  Min.   :4.400   Min.   :2.40   Min.   :1.20   Min.   :0.200   setosa    :10  
##  1st Qu.:5.425   1st Qu.:2.90   1st Qu.:1.60   1st Qu.:0.400   versicolor:10  
##  Median :5.900   Median :3.00   Median :4.35   Median :1.400   virginica :10  
##  Mean   :5.840   Mean   :3.13   Mean   :3.76   Mean   :1.217                  
##  3rd Qu.:6.300   3rd Qu.:3.20   3rd Qu.:5.05   3rd Qu.:1.800                  
##  Max.   :7.700   Max.   :4.40   Max.   :6.90   Max.   :2.400
## n= 120 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
##  1) root 120 80 setosa (0.33333333 0.33333333 0.33333333)  
##    2) Petal.Length< 2.45 40  0 setosa (1.00000000 0.00000000 0.00000000) *
##    3) Petal.Length>=2.45 80 40 versicolor (0.00000000 0.50000000 0.50000000)  
##      6) Petal.Width< 1.75 44  4 versicolor (0.00000000 0.90909091 0.09090909)  
##       12) Petal.Length< 4.95 40  1 versicolor (0.00000000 0.97500000 0.02500000)  
##         24) Petal.Width< 1.65 39  0 versicolor (0.00000000 1.00000000 0.00000000) *
##         25) Petal.Width>=1.65 1  0 virginica (0.00000000 0.00000000 1.00000000) *
##       13) Petal.Length>=4.95 4  1 virginica (0.00000000 0.25000000 0.75000000)  
##         26) Sepal.Length>=6.5 1  0 versicolor (0.00000000 1.00000000 0.00000000) *
##         27) Sepal.Length< 6.5 3  0 virginica (0.00000000 0.00000000 1.00000000) *
##      7) Petal.Width>=1.75 36  0 virginica (0.00000000 0.00000000 1.00000000) *


5) 의사결정 트리로 결과 보기

위에서 본 결괏값은 직관적으로 보기가 어려운 부분이 있으므로 그래프화 시켜서 보도록 하자. 이러면 보다 쉽게 이해할 수 있다. 제일 상단의 노드를 Root Node, 분기가 되는 중간 노드를 Branch Node, 제일 끝단의 노드를 Leaf Node라고 한다. 의사결정 트리를 통해 직관적으로 분류모델을 이해할 수 있으나 분류기준이 많아질수록 그래프는 복잡해지고 이해하기 어렵다. 또한 훈련 데이터에 너무 과적합되는 문제가 발생할 수도 있다. 이 때문에 분류 성능을 많이 훼손하지 않으면서 모델을 두 단순화할 수 있는지 확인해 볼 필요가 있으며 이 때 사용하는 것이 CP 이다. CP란 의사결정 가지를 생성할 때 소요되는 복잡도를 의미하는데 “CP 값에 따른 나뭇가지 수”와 “분류 오류율”을 확인할 수 있다.

##       CP nsplit rel error xerror       xstd
## 1 0.5000      0     1.000  1.225 0.05298388
## 2 0.4500      1     0.500  0.800 0.06831301
## 3 0.0250      2     0.050  0.100 0.03415650
## 4 0.0125      3     0.025  0.100 0.03415650
## 5 0.0100      5     0.000  0.075 0.02984334


cptable을 통해 CP 값이 0.01일 때 나눠지는 의사결정 분류기준은 7가지며, 오류율을 0%임을 확인할 수 있다. 가지치기 전 분류 모델은 기본적으로 오류율이 제일 낮은 CP 값으로 선택한다. CP 값이 0.0125인 경우를 보면, 오류율이 3.75로 높아졌지만 의사결정 분류 기준은 2개로 줄어들었다. 오류율이 다소 오르더라도 모델을 단순화하는 것이 좀 더 범용적인 케이스에 적용 가능하고 더욱 직관적인 모델이 될 수 있다. 이제 CP 값 0.0125를 기준으로 가지치기 해보자. 가지치기에는 prune() 함수를 사용한다.

오류율은 다소 높아졌지만 더 단순하게 모델이 변경된 것을 확인할 수 있다. 또한 의사결정 트리를 통해 꽃 종류를 구분하는데 영향을 미치는 중요한 요소는 꽃잎의 길이와 폭이라는 것도 알 수 있따.


6) 예측하기

이제 도출된 분류 예측 모델을 기반으로 분류 예측을 해보자. 분류 예측에는 predict 함수를 사용한다.

## 'data.frame':    30 obs. of  5 variables:
##  $ Sepal.Length: num  4.7 4.4 5.7 5.4 5 5 5.5 5 4.4 5.1 ...
##  $ Sepal.Width : num  3.2 2.9 4.4 3.9 3 3.4 4.2 3.2 3 3.8 ...
##  $ Petal.Length: num  1.3 1.4 1.5 1.3 1.6 1.6 1.4 1.2 1.3 1.6 ...
##  $ Petal.Width : num  0.2 0.2 0.4 0.4 0.2 0.4 0.2 0.2 0.2 0.2 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
##          3          9         16         17         26         27         34 
##     setosa     setosa     setosa     setosa     setosa     setosa     setosa 
##         36         39         47         52         62         64         70 
##     setosa     setosa     setosa versicolor versicolor versicolor versicolor 
##         71         81         84         89         92         97        104 
##  virginica versicolor  virginica versicolor versicolor versicolor  virginica 
##        111        119        121        124        128        130        137 
##  virginica  virginica  virginica  virginica  virginica versicolor  virginica 
##        139        140 
##  virginica  virginica 
## Levels: setosa versicolor virginica


iris_test_data를 입력받아 꽃 종류를 예측했다. 하지만 분류 결과를 옆으로 나열만 하다 보니 한눈에 보기가 쉽지 않다. 이번에는 꽃 종류의 실제 값과 예측 값을 한눈에 볼 수 있도록 두 항목을 하나의 데이터프레임 형태로 구성해 보도록 하자.

실제 값과 예상 값을 나란히 보니 결괏값 확인이 조금 더 편리해졌음을 알 수 있다.


7) 평가하기

이제 분류한 예측 값을 평가해 보자. 먼저 table 함수를 통해 혼동행렬을 확인해보자.

##             expect
## actual       setosa versicolor virginica
##   setosa         10          0         0
##   versicolor      0          8         2
##   virginica       0          1         9
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         10          0         0
##   versicolor      0          8         1
##   virginica       0          2         9
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9             
##                  95% CI : (0.7347, 0.9789)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : 1.665e-10       
##                                           
##                   Kappa : 0.85            
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            0.8000           0.9000
## Specificity                 1.0000            0.9500           0.9000
## Pos Pred Value              1.0000            0.8889           0.8182
## Neg Pred Value              1.0000            0.9048           0.9474
## Precision                   1.0000            0.8889           0.8182
## Recall                      1.0000            0.8000           0.9000
## F1                          1.0000            0.8421           0.8571
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.2667           0.3000
## Detection Prevalence        0.3333            0.3000           0.3667
## Balanced Accuracy           1.0000            0.8750           0.9000

위 결과의 주요 지표를 보면 정확도가 약 96%, Kappa 계수 0.95로 예측 결과가 상당히 정확하다는 것을 알 수 있다. No Information Rate 라는 항목은 전체 데이터 중 가장 많은 항목이 차지하는 비율이다. 즉 정확도가 이것보다는 높아야 분류를 제대로 하고 있다 라고 볼 수 있다.


사과 품종 분류

앞서 iris 데이터로 실습을 해보았는데, 본래 취지에 맞게 사과 품종을 분류하는 모델을 생성해보자.

##        X           model       weight          sugar            acid       
##  Min.   : 1   로얄후지:5   Min.   :152.0   Min.   :12.10   Min.   :0.2800  
##  1st Qu.: 7   미시마  :5   1st Qu.:251.0   1st Qu.:13.30   1st Qu.:0.3100  
##  Median :13   아오리  :5   Median :329.0   Median :13.60   Median :0.3800  
##  Mean   :13   홍로    :5   Mean   :317.3   Mean   :14.01   Mean   :0.4168  
##  3rd Qu.:19   홍옥    :5   3rd Qu.:391.0   3rd Qu.:14.40   3rd Qu.:0.4100  
##  Max.   :25                Max.   :409.0   Max.   :16.80   Max.   :0.7300  
##   color   
##  적색:10  
##  홍색:15  
##           
##           
##           
## 
## [1] 25
## [1] 20


이제 훈련데이터를 기반으로 분류모델을 도출하자.


도출한 분류 모델을 혼동행렬을 통해 평가해보니, 정확도 100, Kappa 100 으로 높은 정확도를 보여주고 있다.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction 로얄후지 미시마 아오리 홍로 홍옥
##   로얄후지        1      0      0    0    0
##   미시마          0      1      0    0    0
##   아오리          0      0      0    0    0
##   홍로            0      0      1    1    0
##   홍옥            0      0      0    0    1
## 
## Overall Statistics
##                                           
##                Accuracy : 0.8             
##                  95% CI : (0.2836, 0.9949)
##     No Information Rate : 0.2             
##     P-Value [Acc > NIR] : 0.00672         
##                                           
##                   Kappa : 0.75            
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: 로얄후지 Class: 미시마 Class: 아오리 Class: 홍로
## Sensitivity                      1.0           1.0           0.0      1.0000
## Specificity                      1.0           1.0           1.0      0.7500
## Pos Pred Value                   1.0           1.0           NaN      0.5000
## Neg Pred Value                   1.0           1.0           0.8      1.0000
## Precision                        1.0           1.0            NA      0.5000
## Recall                           1.0           1.0           0.0      1.0000
## F1                               1.0           1.0            NA      0.6667
## Prevalence                       0.2           0.2           0.2      0.2000
## Detection Rate                   0.2           0.2           0.0      0.2000
## Detection Prevalence             0.2           0.2           0.0      0.4000
## Balanced Accuracy                1.0           1.0           0.5      0.8750
##                      Class: 홍옥
## Sensitivity                  1.0
## Specificity                  1.0
## Pos Pred Value               1.0
## Neg Pred Value               1.0
## Precision                    1.0
## Recall                       1.0
## F1                           1.0
## Prevalence                   0.2
## Detection Rate               0.2
## Detection Prevalence         0.2
## Balanced Accuracy            1.0


이제 과적합 문제를 보완하기 위해 가지치기를 해보자. 조금 더 간결한 모습으로 문류모델이 만들어졌음을 알 수 있다.

##        CP nsplit rel error xerror      xstd
## 1 0.25000      0    1.0000 1.2500 0.0000000
## 2 0.18750      3    0.2500 1.2500 0.0000000
## 3 0.03125      4    0.0625 0.4375 0.1333171
## 4 0.01000      6    0.0000 0.5000 0.1369306


가지치기를 한 후 성능에 큰 영향이 없는지 다시 확인해보자. 정확도 0.8, Kappa 0.75로 가지치기 전 모델과 동일한 것으로 보아 가지치기를 적용한 후에도 모델의 정확도가 크게 훼손되지 않았음을 알 수 있다. 이런식으로 무게, 당도, 산도, 색상을 가지고 사과의 품종을 분류하는 모델을 만들어 보았다.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction 로얄후지 미시마 아오리 홍로 홍옥
##   로얄후지        1      0      0    0    0
##   미시마          0      1      0    0    0
##   아오리          0      0      0    0    0
##   홍로            0      0      1    1    0
##   홍옥            0      0      0    0    1
## 
## Overall Statistics
##                                           
##                Accuracy : 0.8             
##                  95% CI : (0.2836, 0.9949)
##     No Information Rate : 0.2             
##     P-Value [Acc > NIR] : 0.00672         
##                                           
##                   Kappa : 0.75            
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: 로얄후지 Class: 미시마 Class: 아오리 Class: 홍로
## Sensitivity                      1.0           1.0           0.0      1.0000
## Specificity                      1.0           1.0           1.0      0.7500
## Pos Pred Value                   1.0           1.0           NaN      0.5000
## Neg Pred Value                   1.0           1.0           0.8      1.0000
## Precision                        1.0           1.0            NA      0.5000
## Recall                           1.0           1.0           0.0      1.0000
## F1                               1.0           1.0            NA      0.6667
## Prevalence                       0.2           0.2           0.2      0.2000
## Detection Rate                   0.2           0.2           0.0      0.2000
## Detection Prevalence             0.2           0.2           0.0      0.4000
## Balanced Accuracy                1.0           1.0           0.5      0.8750
##                      Class: 홍옥
## Sensitivity                  1.0
## Specificity                  1.0
## Pos Pred Value               1.0
## Neg Pred Value               1.0
## Precision                    1.0
## Recall                       1.0
## F1                           1.0
## Prevalence                   0.2
## Detection Rate               0.2
## Detection Prevalence         0.2
## Balanced Accuracy            1.0