ch0nny_log

[빅데이터분석] R _ 56. 규칙기반 알고리즘(one r/riper 알고리즘) 본문

빅데이터 분석(with 아이티윌)/R

[빅데이터분석] R _ 56. 규칙기반 알고리즘(one r/riper 알고리즘)

chonny 2024. 7. 12. 17:14

■ 의사결정트리 

※ 랜덤 포레스트
 1. 의사결정트리  
  2. 규칙 기반 알고리즘 
 (if 조건에 의해서 데이터를 분류해 나가는 알고리즘)
1. oneR 알고리즘
(하나의 사실(조건) 만 가지고 간단하게 데이터를 분류하는 알고리즘)
 2. Riper 알고리즘  

 

규칙 기반 알고리즘 (if 조건에 의해서 데이터를 분류해 나가는 알고리즘)

   □  OneR 알고리즘

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

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

     -   예:  심장질환이 있는 환자인지 아닌지를 분류하고자 한다면 가슴통증이라는 조건 하나만 보고 분류하는 알고리즘

                가슴통증 하나만 보고 심장질환이 있다고 분류하기에는 오류가 많아집니다.

                왜냐하면 식도염, 폐질환도 가슴통증이기 때문입니다. 

 

   □  Riper 알고리즘  

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

     - 예: 가슴 통증이 있으면서 호흡곤란이 있으면 심장질환임 

실습1. one R 알고리즘으로 독버섯 데이터 분류하기
#1. 데이터 불러오기
mush <- read.csv("c:\\data\\mushrooms.csv", stringsAsFactors=TRUE)

#2. 데이터 관찰하기
# 결측치 확인
colSums(is.na(mush))

#3. 훈련 데이터와 테스트 데이터 분리하기
library(caret)
set.seed(1)
k <-  createDataPartition( mush$type, p=0.8, list=F)
train_data <-  mush[ k ,    ]  
test_data <- mush[ -k,    ]

dim(train_data)
dim(test_data)

#4. 모델 생성 및 훈련시키기
install.packages("OneR")
library(OneR)

model <- OneR( type ~  . ,  data=train_data) 
model  # 알고리즘이 데이터에서 발견한 패턴을 확인할 수 있습니다.​

summary(model)​

귀무가설: 냄새로 독버섯과 정상 버섯을 분류할 수 없다.
대립가설: 냄새로 독버섯과 정성버섯을 분류할 수 있다.
-> p-value 0.05보다 낮으므로 대립가설 채택

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

#6. 모델 평가하기 
sum(result== test_data[ , 1])/nrow(test_data) *100  # 정확도 98%
library(gmodels)
a<- CrossTable(result, test_data[ ,1])
a$t

 

#7. 모델 계산하기
install.packages("RWeka")
library(RWeka)

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

summary(model2)​

갓의 크기가 좁고, 냄새가 톡쏘는 경우, 이 버섯은 독성이 있습니다. 250개의 샘플중 오차는 0 입니다.
위의 모든 조건을 만족하지 않는 경우, 이 버섯은 식용입니다. 3367개의 샘플중에 오차는 0 입니다.

#8. 모델이 예측하기
result2 <-  predict(  model2,  test_data[  , -1] )
result2

#9. 모델 평가하기 
sum( result2 == test_data[  , 1]) / nrow(test_data) * 100​

 

 

규칙기반 알고리즘은 분류를 위한 질문을 만들기 위해서 컬럼들중에 어떤 컬럼을 선택하는것인가 ? 

 

 

가장 중요한 컬럼이 뭔지 아는것입니다.

One R 알고리즘은 "냄새" 가 가장 중요한 컬럼이라는것을 알아냈고 리퍼 알고리즘은 "냄새", "갓의 크기", "갓의 색깔" 등이 중요한 컬럼이라는 것을 알아냈고 중요도의 순서도 알고 있었습니다. 

어떻게 알고리즘이 이 중요도를 알아냈을까 ?

 

 

Decision Tree 알고리즘_v2.pdf
0.29MB

 

화장품 구매여부에 있어서 어떤 컬럼이 가장 중요한 콜럼인지 알아내려면 정보획득량이라는 수학식을 이해하면됨

 

정보 획득량 --> 의사 결정트리 --> OneR --> Riper --> 랜덤포레스트

 

실습2. skin.csv 에서 coupon_react 에 가장 중요한 컬럼이 무엇인가 ?
구매를 하는데 있어서 가장 중요한 컬럼이 성별, 나이 인지 어떤 컬럼이 중요한지 정보 획득량을 구하시오 !
skin <- read.csv("c:\\data\\skin.csv", stringsAsFactors=T)

install.packages("FSelector")
library(FSelector)

information.gain( cupon_react ~  . , skin,  unit='log2')​


결혼 유무가 정보획득량이 제일 높게 나타내고 있습니다.
실습 3. 지방간을 일으키는 원인중에 가장 큰 영향력을 보이는 요인은 무엇인지 fatliver2.csv 를 불러와서 정보 획득량을 구해서 알아내시오 !
setwd('c:\\data')
fatliver <- read.csv("c:\\data\\fatliver2.csv", stringsAsFactors=T,  fileEncoding ='euc-kr') 
fatliver

install.packages("FSelector")
library(FSelector)

information.gain( FATLIVER ~  . , fatliver,  unit='log2')​
★ 마지막 문제. 어제 만들었던 샤이니 인터페이스를 누구나 쉽게 사용할 수 있도록 실행 파일로 생성하시오. 
https://cafe.daum.net/oracleoracle/Soei/62
if (!require("shiny")) install.packages("shiny")
if (!require("naivebayes")) install.packages("naivebayes")
if (!require("e1071")) install.packages("e1071")
if (!require("caret")) install.packages("caret")
if (!require("ggplot2")) install.packages("ggplot2")

library(shiny)
library(naivebayes)
library(e1071)
library(caret)
library(ggplot2)

# 데이터 불러오기
movie <- read.csv("c:\\data\\movie2.csv", stringsAsFactors=TRUE, fileEncoding = "euc-kr")

# 결측치 확인
colSums(is.na(movie))

# 훈련 데이터와 테스트 데이터로 분리
set.seed(1)
k <- createDataPartition(movie$장르, p=0.8, list=F)
train_data <- movie[k, ]
test_data <- movie[-k, ]

# 나이브 베이즈 모델 생성
new_model <- naive_bayes(장르 ~ ., data=train_data)

# UI 정의
ui <- fluidPage(
  tags$head(
    tags$style(HTML("
      body {
        background-color: #F0F8FF; /* 완전 연한 하늘색 배경색 */
      }
      .btn-predict {
        background-color: #87CEEB; /* 하늘색 배경색 */
        border-color: #87CEEB; /* 하늘색 테두리 색 */
        color: white; /* 글자 색상 */
      }
      .title {
        font-size: 24px; /* 제목 글씨 크기 조정 */
        color: #0072B2; /* 남색 글자 색상 */
      }
    "))
  ),
  div(class = "title", "영화 장르 예측기"),  # 직접 HTML 태그를 사용하여 제목 정의
  sidebarLayout(
    sidebarPanel(
      radioButtons("age", "연령대", choices = unique(movie$나이), selected = NULL),
      radioButtons("gender", "성별", choices = unique(movie$성별), selected = NULL),
      radioButtons("job", "직업", choices = unique(movie$직업), selected = NULL),
      radioButtons("married", "결혼여부", choices = unique(movie$결혼여부), selected = NULL),
      radioButtons("relationship", "이성친구 여부", choices = unique(movie$이성친구), selected = NULL),
      actionButton("predict", "예측하기", class = "btn-predict")
    ),
    mainPanel(
      plotOutput("predictionPlot"),
      textOutput("predictionText")
    )
  )
)

# 서버 로직 정의
server <- function(input, output) {
  values <- reactiveValues(result_df = NULL)
  
  observeEvent(input$predict, {
    test_data <- data.frame(
      나이 = input$age,
      성별 = input$gender,
      직업 = input$job,
      결혼여부 = input$married,
      이성친구 = input$relationship
    )
    
    result <- predict(new_model, test_data, type = "prob")
    
    values$result_df <- as.data.frame(t(result))
    values$result_df$장르 <- rownames(values$result_df)
    colnames(values$result_df) <- c("확률", "장르")
  })
  
  output$predictionPlot <- renderPlot({
    req(values$result_df)
    ggplot(values$result_df, aes(x = 장르, y = 확률)) +
      geom_bar(stat = "identity", fill = "skyblue") +
      theme_minimal() +
      labs(title = "예측된 영화 장르 확률", x = "장르", y = "확률") +
      ylim(0, 1)
  })
  
  output$predictionText <- renderText({
    req(values$result_df)
    max_genre <- values$result_df$장르[which.max(values$result_df$확률)]
    paste("예측된 영화 장르 확률은", max_genre, "입니다.")
  })
}

# Shiny 앱 실행
shinyApp(ui = ui, server = server)​