Lecture9: 線形判別分析, 決定木, ランダムフォレスト

参照コード&データ

石田・小林(2013)『Rで学ぶ日本語テキストマイニング』

小林(2017)『Rによるやさしいテキストマイニング:機械学習編』

線形判別分析

(石田・小林(2013)『Rで学ぶ日本語テキストマイニング』: p.146-152

作家データの読み込み

data1 <- read.delim("Lec09_data1.txt", row.names = 1, header = TRUE)

データの確認

head(data1)
colnames(data1)

データの概要

summary(data1)

MASSパッケージの読み込み

library (MASS) 

線形判別分析

lda.model <- lda(作者 ~ ., data = data1)
lda.model
## Call:
## lda(作者 ~ ., data = data1)
## 
## Prior probabilities of groups:
## 芥川龍之介     太宰治 
##        0.5        0.5 
## 
## Group means:
##                   か       が       く        し        ず       て
## 芥川龍之介 0.8936821 4.144038 0.277098 0.5041663 0.4065555 2.691739
## 太宰治     0.6525080 2.678417 1.000287 1.7003246 0.5639713 7.449845
##                   で       と       に       は        ば        へ
## 芥川龍之介 0.8360013 2.911046 3.604787 4.921635 1.0630131 0.6053547
## 太宰治     2.5381815 1.524926 2.519240 9.464232 0.6039739 0.1122260
##                  も       ら       り        れ
## 芥川龍之介 2.216960 4.284926 1.336640 0.1318495
## 太宰治     3.507773 3.046492 1.703575 0.5010864
## 
## Coefficients of linear discriminants:
##           LD1
## か  4.2377384
## が -3.9090605
## く  3.5219509
## し  1.0069004
## ず  4.9585492
## て -0.2500134
## で  2.9350605
## と  1.2377630
## に -2.2879268
## は  1.5029414
## ば -1.9974492
## へ 12.0567489
## も  2.0506138
## ら -3.4331053
## り -7.7088565
## れ -0.5375046

分類

lda.pred <- predict(lda.model, data1)
lda.pred$class
##  [1] 芥川龍之介 芥川龍之介 芥川龍之介 芥川龍之介 芥川龍之介 芥川龍之介
##  [7] 芥川龍之介 芥川龍之介 芥川龍之介 芥川龍之介 太宰治     太宰治    
## [13] 太宰治     太宰治     太宰治     太宰治     太宰治     太宰治    
## [19] 太宰治     太宰治    
## Levels: 芥川龍之介 太宰治

散布図

par(family="HiraMaruProN-W4")
plot(lda.pred$x,type="n")
text(lda.pred$x,labels=as.character(rownames(lda.pred$x))) 

クロス集計表

lda.tab <- table(data1$作者, lda.pred$class)
lda.tab
##             
##              芥川龍之介 太宰治
##   芥川龍之介         10      0
##   太宰治              0     10

正判別率の計算

sum(diag(lda.tab)) / sum(lda.tab) *100
## [1] 100

線形判別分析の交差妥当化

CV: Cross Validation

lda.model.cv <- lda(作者 ~ ., data = data1, CV = TRUE)

クロス集計表

lda.cv.tab <- table(data1$作者, lda.model.cv$class)
lda.cv.tab
##             
##              芥川龍之介 太宰治
##   芥川龍之介          8      2
##   太宰治              2      8

誤判別作品

rownames(data1)[data1$"作者"!=lda.model.cv$class]
## [1] "A_邪宗門"   "A_羅生門"   "D_狂言の神" "D_猿面冠者"

正判別率の計算

sum(diag(lda.cv.tab)) / sum(lda.cv.tab) *100
## [1] 80

決定木

(石田・小林(2013)『Rで学ぶ日本語テキストマイニング』: p.173-185

mvpartパッケージのインストール

cf. rpartパッケージ

install.packages("mvpart_1.6-2.tar.gz", repos = NULL, type = "source") 

mvpartパッケージの呼び出し

library(mvpart) 

アクセントデータの読み込み

data2 <- read.delim("Lec09_data2.txt", header = TRUE)

データの確認

head(data2)
dim(data2)

疑似乱数の種の設定

set.seed(5) 

学習データと評価データを作成

n <- sample(1:258, 158) 
train <- data2[n, ] 
test <- data2[-n, ] 

決定木による判別

rp.model <- rpart(アクセント ~ ., data = train)
print(rp.model,digit=1)
## n= 158 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
##   1) root 158 60 中高型 (0.60 0.37 0.03)  
##     2) 緯度< 4e+01 100 20 中高型 (0.80 0.17 0.03)  
##       4) 経度>=1e+02 81 10 中高型 (0.86 0.14 0.00) *
##       5) 経度< 1e+02 19  9 中高型 (0.53 0.32 0.16)  
##        10) 年齢>=5e+01 9  2 中高型 (0.78 0.11 0.11) *
##        11) 年齢< 5e+01 10  5 頭高型 (0.30 0.50 0.20)  
##          22) 経度< 1e+02 6  2 頭高型 (0.33 0.67 0.00) *
##          23) 経度>=1e+02 4  2 平板型 (0.25 0.25 0.50) *
##     3) 緯度>=4e+01 58 20 頭高型 (0.26 0.72 0.02)  
##       6) 経度>=1e+02 36 10 頭高型 (0.36 0.61 0.03)  
##        12) 年齢>=2e+01 29 10 頭高型 (0.45 0.52 0.03)  
##          24) 緯度< 4e+01 6  2 中高型 (0.67 0.33 0.00) *
##          25) 緯度>=4e+01 23 10 頭高型 (0.39 0.57 0.04)  
##            50) 経度>=1e+02 19  7 頭高型 (0.37 0.63 0.00)  
##             100) 年齢< 6e+01 14  6 頭高型 (0.43 0.57 0.00)  
##               200) 年齢>=5e+01 4  1 中高型 (0.75 0.25 0.00) *
##               201) 年齢< 5e+01 10  3 頭高型 (0.30 0.70 0.00) *
##             101) 年齢>=6e+01 5  1 頭高型 (0.20 0.80 0.00) *
##            51) 経度< 1e+02 4  2 中高型 (0.50 0.25 0.25) *
##        13) 年齢< 2e+01 7  0 頭高型 (0.00 1.00 0.00) *
##       7) 経度< 1e+02 22  2 頭高型 (0.09 0.91 0.00) *

木の視覚化

par(xpd = NA)
par(family="HiraMaruProN-W4")
plot(rp.model, minbranch = 3) 
text(rp.model, use.n = TRUE, minbranch = 3)

木の剪定(より良い判別モデルの作成)

plotcp (rp.model)

rp.model.pr <- prune(rp.model, cp = 0.082)

木の視覚化

par(xpd = NA)
par(family="HiraMaruProN-W4")
plot(rp.model.pr, minbranch = 2) 
text(rp.model.pr, use.n = TRUE, minbranch = 2)

分類

rp.pred <- predict(rp.model.pr, test, type = "class")

クロス集計表

rp.tab <- table(test$アクセント, rp.pred)
rp.tab
##         rp.pred
##          中高型 頭高型 平板型
##   中高型     50      9      0
##   頭高型      9     28      0
##   平板型      1      3      0

正判別率の計算

sum(diag(rp.tab)) / sum(rp.tab) *100

ランダムフォレスト

(石田・小林(2013)『Rで学ぶ日本語テキストマイニング』: p.185-190

randomForestパッケージのインストール

install.packages("randomForest") 

randomForestパッケージの呼び出し

library(randomForest)
## randomForest 4.6-12
## Type rfNews() to see new features/changes/bug fixes.

疑似乱数の種の設定

set.seed(5) 

ランダムフォレストによる判別モデル

rf.model <- randomForest(アクセント ~ ., ntree = 1000, mtry = 2,
   proximity = TRUE, data = train)
rf.model
## 
## Call:
##  randomForest(formula = アクセント ~ ., data = train, ntree = 1000,      mtry = 2, proximity = TRUE) 
##                Type of random forest: classification
##                      Number of trees: 1000
## No. of variables tried at each split: 2
## 
##         OOB estimate of  error rate: 31.01%
## Confusion matrix:
##        中高型 頭高型 平板型 class.error
## 中高型     74     19      2   0.2210526
## 頭高型     23     35      1   0.4067797
## 平板型      3      1      0   1.0000000
plot(rf.model)

説明変数の寄与度

par(family="HiraMaruProN-W4")
varImpPlot(rf.model) 

多次元尺度法による視覚化

MDSplot(rf.model, train$アクセント,
   pch = as.numeric(train$アクセント))
legend("topleft", legend = unique(train$アクセント), col=c("blue","red","green"),pch = as.numeric(unique(train$アクセント)))

モデルによるテストデータの分類

rf.pred <- predict(rf.model, test)

クロス集計表

rf.tab <- table(test$アクセント, rf.pred)
rf.tab
##         rf.pred
##          中高型 頭高型 平板型
##   中高型     50      8      1
##   頭高型      7     29      1
##   平板型      1      3      0

正判別率の計算

sum(diag(rf.tab)) / sum(rf.tab) *100
## [1] 79

ランダムフォレスト(その2)

BCCWJデータの読み込み

data3 <- read.delim("Lec09_data3.txt", header = TRUE)

データの確認

head(data3)
colnames(data3)
dim(data3)

疑似乱数の種の設定

set.seed(1) 

ランダムフォレストによる判別モデル

rf.model.2 <- randomForest(ジャンル ~ ., data = data3, proximity = TRUE)
rf.model.2

クロス集計表

rf.model.2$confusion
##            国会会議録 書籍 白書 class.error
## 国会会議録         18    0    2        0.10
## 書籍                0   20    0        0.00
## 白書                5    0   15        0.25

説明変数の寄与度

par(family="HiraMaruProN-W4")
varImpPlot(rf.model.2) 

多次元尺度法による視覚化

MDSplot(rf.model.2, data3$ジャンル,
   pch = as.numeric(data3$ジャンル))
legend("topleft", legend = unique(data3$ジャンル), col=c("blue","green","red"),pch = as.numeric(unique(data3$ジャンル)))

疑似乱数の種の設定

set.seed(1) 

学習データと評価データを作成

n <- sample(1:60, 30) 
train.3 <- data3[n, ] 
test.3 <- data3[-n, ] 

ランダムフォレストによる判別モデル

rf.model.3 <- randomForest(ジャンル ~ ., data = train.3, proximity = TRUE, ntree = 500, mtry = 4)
rf.model.3

説明変数の寄与度

par(family="HiraMaruProN-W4")
varImpPlot(rf.model.3) 

多次元尺度法による視覚化

MDSplot(rf.model, train.3$ジャンル,
   pch = as.numeric(train.3$ジャンル))
legend("topleft", legend = unique(train.3$ジャンル), col=c("blue","red","green"),pch = as.numeric(unique(train.3$ジャンル)))

モデルによるテストデータの分類

rf.pred.3 <- predict(rf.model.3, test.3)

クロス集計表

rf.tab.3 <- table(test.3$ジャンル, rf.pred.3)
rf.tab.3
##             rf.pred.3
##              国会会議録 書籍 白書
##   国会会議録          9    0    1
##   書籍                0    9    0
##   白書                2    0    9

正判別率の計算

sum(diag(rf.tab.3)) / sum(rf.tab.3) *100
## [1] 90