準備

必要なパッケージを読み込む。

pacman::p_load(tidyverse,
               rsample,
               gmodels,
               OneR,
               RWeka)

次に、ggplot2のテーマとフォントの設定を行う。自分好みの設定がある場合は自由に変えてよい。

if (.Platform$OS.type == "windows") { 
  if (require(fontregisterer)) {
    my_font <- "Yu Gothic"
  } else {
    my_font <- "Japan1"
  }
} else if (capabilities("aqua")) {
  my_font <- "HiraginoSans-W3"
} else {
  my_font <- "IPAexGothic"
}

theme_set(theme_gray(base_size = 9,
                     base_family = my_font))


データの準備

2021年10月31日に実施された衆議院議員総選挙のデータを使って実習を行う。このページ にある小選挙区のデータをダウンロードする。

download.file(
  url = "https://yukiyanai.github.io/jp/resources/data/hr2021_districts.csv",
  dest = "data/hr2021_districts.csv"
)

データを読み込む。

HR2021 <- read_csv("data/hr2021_districts.csv")

実習用に整形する。

myd <- HR2021 %>% 
  select(win_smd, age, party, status, previous, duplicate) %>% 
  mutate(win_smd = factor(win_smd,
                          levels = 0:1,
                          labels = c("Lose", "Win")),
         party = factor(party),
         status = factor(status),
         duplicate = factor(duplicate,
                            levels = 0:1,
                            labels = c("No", "Yes"))) %>% 
  rename(dual = duplicate) %>% 
  mutate_if(is.double, scale)

データを訓練データと検証データに分割する。

set.seed(2021-11-03)
myd_split <- initial_split(myd)
myd_train <- training(myd_split)
myd_test <- testing(myd_split)



ルールベースの分類

ZeroR

ルールを一切決めず、全員を「落選 (Lose)」に分類する。

N <- nrow(myd_test)
yhat_0R <-rep("Lose", N)

混同行列を作る。

CrossTable(x = myd_test$win_smd, 
           y = yhat_0R,
           dnn = c("実際の結果", "分類結果"),
           prop.r = FALSE,
           prop.c = FALSE,
           prop.t = TRUE,
           prop.chisq = FALSE)
## 
##  
##    Cell Contents
## |-------------------------|
## |                       N |
## |         N / Table Total |
## |-------------------------|
## 
##  
## Total Observations in Table:  215 
## 
##  
##                  | yhat_0R 
## myd_test$win_smd |      Lose | Row Total | 
## -----------------|-----------|-----------|
##             Lose |       124 |       124 | 
##                  |     0.577 |           | 
## -----------------|-----------|-----------|
##              Win |        91 |        91 | 
##                  |     0.423 |           | 
## -----------------|-----------|-----------|
##     Column Total |       215 |       215 | 
## -----------------|-----------|-----------|
## 
## 

正解率は57.7%である。

OneR

1Rアルゴリズムで分類してみよう。OneRパッケージのOneR() を使う。 RWekaパッケージにも同じ名前の関数があるので、パッケージ名と一緒に指定する。

m1r <- OneR::OneR(win_smd ~ ., 
                  data = myd_train)

分類結果を確認する。

m1r
## 
## Call:
## OneR.formula(formula = win_smd ~ ., data = myd_train)
## 
## Rules:
## If party = N党 then win_smd = Lose
## If party = れい then win_smd = Lose
## If party = 公明 then win_smd = Win
## If party = 共産 then win_smd = Lose
## If party = 国民 then win_smd = Lose
## If party = 無所 then win_smd = Lose
## If party = 社民 then win_smd = Lose
## If party = 立憲 then win_smd = Lose
## If party = 維新 then win_smd = Lose
## If party = 自民 then win_smd = Win
## If party = 諸派 then win_smd = Lose
## 
## Accuracy:
## 502 of 642 instances classified correctly (78.19%)

所属政党 (party) によって分類されていることがわかる。 「party = 自民」と「party = 公明」が当選(Win)、それ以外が落選(Lose)に分類されている。

このルールに従って、検証データの分類を行おう。

yhat_1R <- ifelse(myd_test$party %in% c("自民", "公明"), "Win", "Lose")

混同行列を作る。

CrossTable(x = myd_test$win_smd, 
           y = yhat_1R,
           dnn = c("実際の結果", "分類結果"),
           prop.r = FALSE,
           prop.c = FALSE,
           prop.t = TRUE,
           prop.chisq = FALSE)
## 
##  
##    Cell Contents
## |-------------------------|
## |                       N |
## |         N / Table Total |
## |-------------------------|
## 
##  
## Total Observations in Table:  215 
## 
##  
##              | 分類結果 
##   実際の結果 |      Lose |       Win | Row Total | 
## -------------|-----------|-----------|-----------|
##         Lose |       106 |        18 |       124 | 
##              |     0.493 |     0.084 |           | 
## -------------|-----------|-----------|-----------|
##          Win |        25 |        66 |        91 | 
##              |     0.116 |     0.307 |           | 
## -------------|-----------|-----------|-----------|
## Column Total |       131 |        84 |       215 | 
## -------------|-----------|-----------|-----------|
## 
## 

正解率は、80.0% である。ZeroR よりも正解率が22ポイント上昇した。

RIPPER

続いて、RIPPERアルゴリズムによる分類ルール学習を実行しよう。 RWekaパッケージのJRip() を使う。

m_ripper <- JRip(win_smd ~ .,
                 data = myd_train)

分類結果を確認する。

m_ripper
## JRIP rules:
## ===========
## 
## (status = 前) and (previous >= 0.975881) => win_smd=Win (102.0/28.0)
## (status = 前) and (previous >= 0.288109) and (age <= 0.226462) => win_smd=Win (77.0/24.0)
## (party = 自民) and (age <= -0.405126) => win_smd=Win (26.0/10.0)
## (party = 自民) and (previous <= -0.399662) => win_smd=Win (17.0/7.0)
##  => win_smd=Lose (420.0/45.0)
## 
## Number of Rules : 5

5つのルールを学習したことがわかる。最初のルールでは当選(Win)を分類しているが、102の観測点は実際に当選、28の観測点は実際には落選である。

この学習結果を利用して、検証データを分類しよう。

yhat_rip <- predict(m_ripper, newdata = myd_test)

混同行列を作る。

CrossTable(x = myd_test$win_smd, 
           y = yhat_rip,
           dnn = c("実際の結果", "分類結果"),
           prop.r = FALSE,
           prop.c = FALSE,
           prop.t = TRUE,
           prop.chisq = FALSE)
## 
##  
##    Cell Contents
## |-------------------------|
## |                       N |
## |         N / Table Total |
## |-------------------------|
## 
##  
## Total Observations in Table:  215 
## 
##  
##              | 分類結果 
##   実際の結果 |      Lose |       Win | Row Total | 
## -------------|-----------|-----------|-----------|
##         Lose |       105 |        19 |       124 | 
##              |     0.488 |     0.088 |           | 
## -------------|-----------|-----------|-----------|
##          Win |        21 |        70 |        91 | 
##              |     0.098 |     0.326 |           | 
## -------------|-----------|-----------|-----------|
## Column Total |       126 |        89 |       215 | 
## -------------|-----------|-----------|-----------|
## 
## 

正解率は81.4%である。分類性能はOneRと大差なさそうだ。


実習課題

  • 正解率以外の評価指標で比べると、OneRとRIPPERにどのような違いがあるだろうか。


授業の内容に戻る