독버섯 분류
OneR, Ripper 알고리즘
https://archive.ics.uci.edu/ml/datasets/mushroom
8,124개의 버섯 표본과 23개의 주름 있는 버섯의 속성으로 되어 있음
버섯 머리 모양, 색, 냄새, 주름의 크기, 색, 모양, 서식지 등 22개의 속성에 대한 데이터
type - 독성 분류 poisonous, edible
1. 데이터 준비
> mr = read.csv("C:/R/mushrooms.csv", stringsAsFactors = T)
> str(mr)
'data.frame': 8124 obs. of 23 variables:
$ type : Factor w/ 2 levels "edible","poisonous": 2 1 1 2 1 1 1 1 2 1 ...
$ cap_shape : Factor w/ 6 levels "bell","conical",..: 3 3 1 3 3 3 1 1 3 1 ...
$ cap_surface : Factor w/ 4 levels "fibrous","grooves",..: 4 4 4 3 4 3 4 3 3 4 ...
$ cap_color : Factor w/ 10 levels "brown","buff",..: 1 10 9 9 4 10 9 9 9 10 ...
$ bruises : Factor w/ 2 levels "no","yes": 2 2 2 2 1 2 2 2 2 2 ...
$ odor : Factor w/ 9 levels "almond","anise",..: 8 1 2 8 7 1 1 2 8 1 ...
$ gill_attachment : Factor w/ 2 levels "attached","free": 2 2 2 2 2 2 2 2 2 2 ...
$ gill_spacing : Factor w/ 2 levels "close","crowded": 1 1 1 1 2 1 1 1 1 1 ...
$ gill_size : Factor w/ 2 levels "broad","narrow": 2 1 1 2 1 1 1 1 2 1 ...
$ gill_color : Factor w/ 12 levels "black","brown",..: 1 1 2 2 1 2 5 2 8 5 ...
$ stalk_shape : Factor w/ 2 levels "enlarging","tapering": 1 1 1 1 2 1 1 1 1 1 ...
$ stalk_root : Factor w/ 5 levels "bulbous","club",..: 3 2 2 3 3 2 2 2 3 2 ...
$ stalk_surface_above_ring: Factor w/ 4 levels "fibrous","scaly",..: 4 4 4 4 4 4 4 4 4 4 ...
$ stalk_surface_below_ring: Factor w/ 4 levels "fibrous","scaly",..: 4 4 4 4 4 4 4 4 4 4 ...
$ stalk_color_above_ring : Factor w/ 9 levels "brown","buff",..: 8 8 8 8 8 8 8 8 8 8 ...
$ stalk_color_below_ring : Factor w/ 9 levels "brown","buff",..: 8 8 8 8 8 8 8 8 8 8 ...
$ veil_type : Factor w/ 1 level "partial": 1 1 1 1 1 1 1 1 1 1 ...
$ veil_color : Factor w/ 4 levels "brown","orange",..: 3 3 3 3 3 3 3 3 3 3 ...
$ ring_number : Factor w/ 3 levels "none","one","two": 2 2 2 2 2 2 2 2 2 2 ...
$ ring_type : Factor w/ 5 levels "evanescent","flaring",..: 5 5 5 5 1 5 5 5 5 5 ...
$ spore_print_color : Factor w/ 9 levels "black","brown",..: 1 2 2 1 2 1 1 2 1 1 ...
$ population : Factor w/ 6 levels "abundant","clustered",..: 4 3 3 4 1 3 3 4 5 4 ...
$ habitat : Factor w/ 7 levels "grasses","leaves",..: 5 1 3 5 1 1 3 3 1 3 ...
> table(mr$veil_type) # 1개이므로 제외
partial
8124
> mr$veil_type = NULL
- veil_type의 변수가 1개의 라벨을 가지고 있으므로 제외시켜주었다.
목적변수인 type을 확인해보니
> # 목적변수 확인
> table(mr$type)
edible poisonous
4208 3916
> 4208/(4208+3916)*100 # edible 51.8%
[1] 51.79714
> 3916/(4208+3916)*100 # poisonous 48.2%
[1] 48.20286
51.8%는 먹을 수 있는 버섯, 48.2%는 독성이 있는 버섯으로 이루어져 있다.
2. 훈련 데이터와 테스트 데이터 생성 (8:2)
> # 훈련 데이터와 테스트 데이터 생성
> set.seed(12345)
> mr_rand = mr[order(runif(8124)), ]
>
> 8124*0.8 #6500
[1] 6499.2
>
> # 8:2로 나누기
> mr_train = mr_rand[1:6500, ]
> mr_test = mr_rand[6501:8124, ]
>
> table(mr_train$type)
edible poisonous
3339 3161
> table(mr_test$type)
edible poisonous
869 755
8:2의 비율로 train data, test data를 나눠주었다.
table을 확인해보면 골고루 잘 나뉜 것을 확인할 수 있다.
3. 분류 규칙 모델
① OneR 규칙기반 알고리즘
먼저 모델을 만들고 훈련한 후 확인해보자
> library(OneR)
> mr_1R = OneR(type~., data=mr_train)
> summary(mr_1R)
Call:
OneR.formula(formula = type ~ ., data = mr_train)
Rules:
If odor = almond then type = edible
If odor = anise then type = edible
If odor = creosote then type = poisonous
If odor = fishy then type = poisonous
If odor = foul then type = poisonous
If odor = musty then type = poisonous
If odor = none then type = edible
If odor = pungent then type = poisonous
If odor = spicy then type = poisonous
Accuracy:
6403 of 6500 instances classified correctly (98.51%)
Contingency table:
odor
type almond anise creosote fishy foul musty none pungent spicy Sum
edible * 318 * 305 0 0 0 0 * 2716 0 0 3339
poisonous 0 0 * 160 * 462 * 1746 * 26 97 * 203 * 467 3161
Sum 318 305 160 462 1746 26 2813 203 467 6500
---
Maximum in each column: '*'
Pearson's Chi-squared test:
X-squared = 6125.1, df = 8, p-value < 2.2e-16
- odor이 almond, anise, none이면 edible / creosote, fishy, foul 등이면 poisonous이라는 규칙이 생겼다.
이 모델의 성능을 평가해보면
> # 모델 성능 평가
> mr_pred = predict(mr_1R, mr_test)
>
> library(gmodels)
>
> CrossTable(mr_test$type, mr_pred,
+ prop.chisq = F, prop.c = F,
+ dnn = c('edible', 'poisonous'))
Cell Contents
|-------------------------|
| N |
| N / Row Total |
| N / Table Total |
|-------------------------|
Total Observations in Table: 1624
| poisonous
edible | edible | poisonous | Row Total |
-------------|-----------|-----------|-----------|
edible | 869 | 0 | 869 |
| 1.000 | 0.000 | 0.535 |
| 0.535 | 0.000 | |
-------------|-----------|-----------|-----------|
poisonous | 23 | 732 | 755 |
| 0.030 | 0.970 | 0.465 |
| 0.014 | 0.451 | |
-------------|-----------|-----------|-----------|
Column Total | 892 | 732 | 1624 |
-------------|-----------|-----------|-----------|
>
> (869+732) / 1624 * 100 # 정확도 98.6%
[1] 98.58374
- 이 모델의 정확도는 98.6%로 높은 성능을 보인다.
② Ripper 알고리즘
이번에는 조금 더 향상된 모델을 만들기 위해 Ripper 알고리즘으로 분류해보려고 한다.
> library(RWeka)
> mr_JRip = JRip(type~., data=mr_train)
> mr_JRip
JRIP rules:
===========
(odor = foul) => type=poisonous (1746.0/0.0)
(gill_size = narrow) and (gill_color = buff) => type=poisonous (929.0/0.0)
(gill_size = narrow) and (odor = pungent) => type=poisonous (203.0/0.0)
(odor = creosote) => type=poisonous (160.0/0.0)
(spore_print_color = green) => type=poisonous (60.0/0.0)
(stalk_surface_above_ring = silky) and (gill_spacing = close) => type=poisonous (52.0/0.0)
(stalk_color_above_ring = yellow) => type=poisonous (8.0/0.0)
(habitat = leaves) and (cap_color = white) => type=poisonous (3.0/0.0)
=> type=edible (3339.0/0.0)
Number of Rules : 9
> summary(mr_JRip)
=== Summary ===
Correctly Classified Instances 6500 100 %
Incorrectly Classified Instances 0 0 %
Kappa statistic 1
Mean absolute error 0
Root mean squared error 0
Relative absolute error 0 %
Root relative squared error 0 %
Total Number of Instances 6500
=== Confusion Matrix ===
a b <-- classified as
3339 0 | a = edible
0 3161 | b = poisonous
- 총 9개의 규칙이 만들어진 것을 확인할 수 있다.
- odor=foul이면 poisonous와 같이 poisonous로 분류하는 8개의 규칙이 생겼다.
- 이 8개의 규칙에 해당하지 않으면 edible로 분류한다는 규칙이 9번째 규칙이다.
이 모델의 성능을 평가해보면
> # 모델 성능 평가
> mr_pred2 = predict(mr_JRip, mr_test)
>
> library(gmodels)
>
> CrossTable(mr_test$type, mr_pred2,
+ prop.chisq = F, prop.c = F,
+ dnn = c('edible', 'poisonous'))
Cell Contents
|-------------------------|
| N |
| N / Row Total |
| N / Table Total |
|-------------------------|
Total Observations in Table: 1624
| poisonous
edible | edible | poisonous | Row Total |
-------------|-----------|-----------|-----------|
edible | 869 | 0 | 869 |
| 1.000 | 0.000 | 0.535 |
| 0.535 | 0.000 | |
-------------|-----------|-----------|-----------|
poisonous | 0 | 755 | 755 |
| 0.000 | 1.000 | 0.465 |
| 0.000 | 0.465 | |
-------------|-----------|-----------|-----------|
Column Total | 869 | 755 | 1624 |
-------------|-----------|-----------|-----------|
>
> (869+755) / 1624 * 100 # 정확도 100%
[1] 100
- 정확도 100%로 완벽한 성능을 보인다.
4. 두 알고리즘의 장단점
① OneR 규칙기반 알고리즘
장점 | 단점 |
쉽게 이해할 수 있다. 최상의 규칙 한 개를 생성한다. 좀 더 복잡한 알고리즘에 대해 벤치마크로서 실행할 수 있다. |
하나의 속성을 사용한다. 단순하다. |
② Ripper 알고리즘
장점 | 단점 |
쉽게 이해할 수 있다. 결정 트리보다 단순한 모델을 만든다. 크고 노이즈한 데이터에 대해 효과적이다. |
수치 데이터에 적합하지 않다. 좀 더 복잡한 모델은 성능 향상이 되지 않을 수도 있다. 전문 지식이나 일반 상식에 반대인 듯한 규칙을 만든다. |
'R > ML & DL 공부' 카테고리의 다른 글
[R] 와인 등급 예측 - 회귀트리, 모델트리 (0) | 2022.04.22 |
---|---|
[R] 의료비 예측 - 선형 회귀 (0) | 2022.04.22 |
[R] 휴대폰 스팸 분류 - Naive bayes (0) | 2022.04.20 |
[R] 은행 대출 채무 여부 분류 - 의사결정트리 (0) | 2022.04.15 |
[R] Breast Cancer Wisconsin Diagnostic - K-NN (0) | 2022.04.15 |