본문 바로가기

Study/class note

머신러닝 / 규칙기반 알고리즘(one R,Riper) 이론 및 R로 구현

50 규칙기반 알고리즘(oneR,Riper)이론 - p227

규칙기반 알고리즘(oneR알고리즘, Riper알고리즘)

의사결정트리 모델이 분류를 할 때 if조건에 의해서 데이터를 분류해나가는 것인데 규칙기반도 if조건에 의해서 데이터를 분류해 나가는 것과 유사.

 

ㅇ1R알고리즘(p227 ~ p229)

하나의 사실(조건)만 가지고 간단하게 데이터를 분류하는 알고리즘

하나의 사실만 가지고 분류를 하다보니 간단하지만 오류가 많음

ex. 심장질환이 있는 환자인지 아닌지를 분류를 하고자 한다면 가슴통증이라는 조건 하나만 보고 분류하는게 1R 알고리즘. 가슴통증 하나만 보고 심장질환이 있다고 분류하기에는 오류가 많아짐. 왜냐면 식도염, 폐질환도 가슴통증을 동반하기 때문.

 

ㅇRiper알고리즘

복수개의 사실(조건)을 가지고 분류하는 알고리즘

ex. 가슴통증이 있으면서 호흡곤란이 있으면 심장질환이다.

 

규칙기반 알고리즘의 장점? 이 알고리즘이 데이터를 보고 패턴을 발견함.

의사결정트리처럼 분류하는 조건을 기술한 패턴을 보여줌.

 

 

51 R로 oneR알고리즘과 Riper알고리즘으로 독버섯 데이터를 분류하기(p237)

#1. 데이터 로드

#2. 결측치 확인

#3. 훈련데이터와 테스트 데이터 분리

#4. 정규화 작업 수행

#5. 모델 생성 및 훈련

#6. 모델 예측

#7. 모델 평가

#8. 모델 개선

# R
#1. 데이터 로드
mush <- read.csv("c:\\data\\mushrooms.csv", stringsAsFactors = T)
head(mush)

독버섯 데이터는 UCI머신러닝 저장소에서 제공하는 데이터로 23종의 버섯과 8124개의 버섯샘플에 대한 정보가 담겨있음. 버섯샘플 23개의 특징은 갓모양, 갓색깔, 냄새, 주름크기, 주름색, 줄기모양, 서식지와 같은 특징이 있음.

#2. 결측치 확인
colSums(is.na(mush))  #결측치 없음

#3. 훈련데이터와 테스트 데이터 분리
library(caret)
set.seed(1)
train_num = createDataPartition(mush$type, p=0.8, list = F)

train_data = mush[train_num,]
test_data = mush[-train_num,]

nrow(train_data)  #6500
nrow(test_data)  #1624

#4. 정규화 작업 수행
# 모두 문자형이라서 정규화 작업 필요 없음

#5. 모델 생성 및 훈련
install.packages("OneR")  #패키지 설치
library(OneR)

model <- OneR(type ~ ., data = train_data)
model   # 알고리즘이 데이터에서 발견한 패턴 확인

버섯냄새 한가지만 가지고 다음과 같이 분류했다고 함.

 

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:
6410 of 6500 instances classified correctly (98.62%)

summary(model)

Contingency table:
           odor
type        almond anise creosote fishy   foul musty   none pungent spicy  Sum
  edible     * 326  * 325          0      0      0       0   * 2716        0       0 3367
  poisonous      0     0     * 155  * 455 * 1732  * 30       90   * 205  * 466 3133
  Sum          326   325       155    455   1732    30    2806     205    466 6500
---
Maximum in each column: '*'

Pearson's Chi-squared test:
X-squared = 6151.1, df = 8, p-value < 2.2e-16

> 카이제곱 검정을 보면  p-value가 0.5보다 작은 것임을 확인 할 수 있음

귀무가설 : 냄새로 독버섯과 정상버섯을 분류할 수 없다.

대립가설 : 냄새로 독버섯과 정상버섯이 분류가능하다.

p-value가 2.2e-16보다 작으므로 귀무가설이 기각된다. (대립가설 채택)

#6. 모델 예측
result <- predict(model, test_data[,-1])
result

#7. 모델 평가
sum(result == test_data[,1])/nrow(test_data) * 100  #98.15271

table(x=test_data[,1],y=result)  #이원교차표 $t와 같은 것

           y
x           edible poisonous
  edible       841         0
  poisonous     30       753 > FN값 30

> 정확도는 98%로 아주 높으나 FN이 30개여서 잘못 버섯을 먹으면 죽을수도 있음.

> 이를 보완하기 위해 Riper알고리즘으로 개선하겠음.

#8. 모델 개선
install.packages("RWeka")
library(RWeka)

model2 <- JRip(type ~., data = train_data)
model2

JRIP rules:
===========

(odor = foul) => type=poisonous (1732.0/0.0)
(gill_size = narrow) and (gill_color = buff) => type=poisonous (921.0/0.0)
(gill_size = narrow) and (odor = pungent) => type=poisonous (205.0/0.0)
(odor = creosote) => type=poisonous (155.0/0.0)
(spore_print_color = green) => type=poisonous (52.0/0.0)
(stalk_surface_below_ring = scaly) and (stalk_surface_above_ring = silky) => type=poisonous (58.0/0.0)
(habitat = leaves) and (cap_color = white) => type=poisonous (7.0/0.0)
(stalk_color_above_ring = yellow) => type=poisonous (3.0/0.0)
 => type=edible (3367.0/0.0)

Number of Rules : 9

 

> JRIP이 발견한 rule이 9가지가 있음. 

(odor = foul), (gill_size = narrow) and (gill_color = buff), (gill_size = narrow) and (odor = pungent),(odor = creosote),(spore_print_color = green),(stalk_surface_below_ring = scaly) and (stalk_surface_above_ring = silky),(habitat = leaves) and (cap_color = white),(stalk_color_above_ring = yellow)

 

summary(model2)

=== Confusion Matrix ===

    a    b   <-- classified as
 3367    0 |    a = edible
    0 3133 |    b = poisonous

> 훈련데이터는 100%의 정확도로 분류했음.

 

문제278. (오늘의 마지막 문제) Riper 알고리즘으로 만든 model2 의 버섯 테스트 데이터의 정확도를 확인하고 FN 값을 확인하시오.

result_rip <- predict(model2, test_data[,-1])
sum(result_rip == test_data[,1]) / nrow(test_data) * 100   #100%정확도

table(x=test_data[,1],y=result_rip)
반응형