決策樹為資料分類的一種方法,其中 CHAID (Chi-square Automatic Interaction Detector, 卡方自動交叉檢驗)是一種常用決策樹分類方式。該演算法源自 AID 與 thaid ,依靠卡方檢驗來尋找最佳的劃分屬性。目前該演算法支援分類變數的資料。而若要在連續資料上進行 CHAID 決策樹的分類則需要先將連續資料進行離散化處理,將離散資料進行類別化。
CHAID 演算法主要分成底下 3 步驟,合併、分裂與停止。
合併透過將各特徵(\(X\))對要預測的變數(結果,\(Y\))進行卡方檢驗,並透過計算 P 值的顯著性來確認是否要合併特徵。
分裂點可能在合併過程中出現,在合併過程中會比較每一個調整後的 P 值來選擇分裂點。
停止表示合併或分裂的條件。
install_Package <- function(pkgName) {
if(!(pkgName %in% rownames(installed.packages()))) {
if(pkgName != "CHAID") {
install.packages(pkgName)
} else {
install.packages("http://download.r-forge.r-project.org/src/contrib/CHAID_0.1-2.tar.gz", repos = NULL)
}
}
}
packageName <- c("partykit", "grid", "libcoin", "mvtnorm", "rpart", "CHAID")
for(i in packageName) {
install_Package(i)
}
library("CHAID")
## Loading required package: partykit
## Loading required package: grid
## Loading required package: libcoin
## Loading required package: mvtnorm
## Loading required package: rpart
使用程式本身的資料集 “USvote”,這是關於美國總統選舉的樣本資料,其中變數 vote3 表示為候選人,即 Gore 與 Bush,其他變數包含選民的性別(gender)、年齡(ager)、受雇(empstat)與否、學歷(educr)與結婚(marstat)與否等。其中以 vote3 為預設變數,其他變數為特徵時,建立 CHAID 樹。
# 確認結果一致
set.seed(290875)
data("USvote")
# 取得資料
training <- sample(1:nrow(USvote), 3000)
testing <- USvote[-training,]
USvoteSample <- USvote[training,]
print(USvoteSample[1:10,])
## vote3 gender ager empstat educr marstat
## 5455 Bush male 65+ yes Post Coll divorced
## 623 Bush male 45-54 yes College married
## 9680 Gore female 55-64 yes College married
## 4199 Gore female 55-64 retired HS widowed
## 7036 Bush male 45-54 yes >HS married
## 2485 Gore female 18-24 no >HS never married
## 5495 Gore female 35-44 yes Post Coll divorced
## 3170 Gore male 65+ retired College widowed
## 800 Gore female 55-64 no >HS widowed
## 8703 Bush female 35-44 yes College married
# prototype of chaid_control
# |- alpha2: 特徵水準值合併中的顯著水準
# |- alpha3: 特徵在合併後要拆分時使用的顯著水準
# |- alpha4: 樹生長中,對主要特徵進行分支時使用的顯著水準
# |- minsplit: 節點中的最小分裂樣本數
# |- minbucket: 葉節點的最小樣本數
# |- minprob: 葉節點的最小樣本比例,即所含樣本佔總樣本的比例
# |- stump: 只對根節點進行分裂
ctl <- chaid_control(alpha2 = 0.05, alpha3 = -1, alpha4 = 0.05, minsplit = 20, minbucket = 7, minprob = 0.01, stump = FALSE)
# prototype of chaid
# |- formula: 生成模型的運算式
# |- data: 指定的資料集
# |- subset: 指定用資料中那些子集進行分析
# |- weights: 權重
# |- na.action: 出現缺失值的處理方式
# |- control: 控制樹生成的參數,可透過 chaid_control 函式進行設定
chaid(formula, data, subset = NULL, weights = NULL, na.action = na.omit, control = chaid_control())
# 建立模型演算法所需參數
ctl <- chaid_control(minsplit = 500, minbucket = 100, minprob = 0)
# 透過 CHAID 演算法建立分類樹
chaidRes <- chaid(vote3~., data = USvoteSample, control = ctl)
print(chaidRes)
##
## Model formula:
## vote3 ~ gender + ager + empstat + educr + marstat
##
## Fitted party:
## [1] root
## | [2] marstat in married
## | | [3] ager in 18-24, 25-34: Bush (n = 239, err = 34.7%)
## | | [4] ager in 35-44, 45-54
## | | | [5] empstat in yes, retired: Bush (n = 795, err = 47.2%)
## | | | [6] empstat in no: Bush (n = 90, err = 25.6%)
## | | [7] ager in 55-64: Gore (n = 274, err = 45.6%)
## | | [8] ager in 65+: Bush (n = 295, err = 43.4%)
## | [9] marstat in widowed, divorced, never married
## | | [10] gender in male: Gore (n = 457, err = 49.9%)
## | | [11] gender in female
## | | | [12] ager in 18-24, 25-34, 35-44, 45-54: Gore (n = 394, err = 27.7%)
## | | | [13] ager in 55-64, 65+: Gore (n = 352, err = 43.5%)
##
## Number of inner nodes: 5
## Number of terminal nodes: 8
# 先匯出結果圖
png(filename="images/chaid.png", width = 1024, height = 512)
plot(chaidRes)
dev.off()
## png
## 2
底下可以看出決策樹分類的結果,若重新將訓練樣本進行分類,發現在 CHAID 演算方式下,仍與原本的結果有差異,可以透過比較原本樣本來調整 CHAID 的訓練參數。
summary(predict(chaidRes, USvoteSample))
## Gore Bush
## 1544 1456
summary(USvoteSample$vote3)
## Gore Bush
## 1545 1455
可以由上方看出,決策樹建立後來比較訓練資料與已知結果,可將兩者結果當作是調整參數的依據。而調整參數的方法可以先視節點為大群體(相對參數 minsplit),葉子為細節小群體(相對參數 minbucket),而大群體值應較細節小群體之值數倍 (*N) 為佳。
predRes <- predict(chaidRes, testing)
oriRes <- testing$vote3
compare <- cbind(oriRes, predRes)
print(paste(seq(1:2),levels(predRes), sep=":"))
## [1] "1:Gore" "2:Bush"
print(compare[1:10,])
## oriRes predRes
## 1 2 2
## 2 2 2
## 3 2 2
## 4 2 2
## 5 2 2
## 8 2 2
## 9 2 2
## 10 2 2
## 11 1 1
## 13 1 1
print(
paste("Number of Same Results", length(which(compare[,1] == compare[,2])), sep=": ")
)
## [1] "Number of Same Results: 4328"
print(
paste("Number of Different Results",length(which(compare[,1] != compare[,2])), sep=": ")
)
## [1] "Number of Different Results: 3317"
由上結果可以看出預測投票結果與原投票結果大約有 40% 是錯誤值。原因是決策樹為機率基礎的分類方式,會直接將輸入值透過決策樹找出最大的機率分類結果。
其次,於 chaid_control 定義中 minsplit, minbucket, minprob 等數個參數都是相當重要要去調整,因此數個參數將影響整棵樹的生成。
最後是資料本身,大多數的機器學習狀況為由少部分的特徵中,找出能解釋全貌的模型,但在選擇特徵或甚至是在起初決定要用那些特徵時就會大大影響機器學習的訓練結果,以此為例可以清楚了解到,選舉不能單看這單純的數個因素,否則學習結果會相當差。