有監(jiān)督學(xué)習(xí)指為了實(shí)現(xiàn)根據(jù)一樣本的預(yù)測(cè)變量來(lái)預(yù)測(cè)相對(duì)應(yīng)的二分類(lèi)結(jié)果(class),而基于一組大量、已有的包含預(yù)測(cè)變量值和輸出變量值(即二分類(lèi)結(jié)果)的樣本單元數(shù)據(jù)進(jìn)行建模陈轿、驗(yàn)證。
思路為將所有樣本單元數(shù)據(jù)分為一個(gè)訓(xùn)練集(較多)和一個(gè)驗(yàn)證集(較少)链沼。先用訓(xùn)練集建立預(yù)測(cè)模型默赂,再用驗(yàn)證集驗(yàn)證模型的準(zhǔn)確性。得到一個(gè)有效的預(yù)測(cè)模型后括勺,就可去真實(shí)場(chǎng)景根據(jù)預(yù)測(cè)變量預(yù)測(cè)二分類(lèi)結(jié)果(class)了缆八。具體方法有邏輯回歸、決策樹(shù)疾捍、隨機(jī)森林奈辰、支持向量機(jī)等。一起來(lái)學(xué)習(xí)R語(yǔ)言的有關(guān)操作吧~
實(shí)驗(yàn)示例及數(shù)據(jù)預(yù)處理
實(shí)驗(yàn)數(shù)據(jù)來(lái)自UCI機(jī)器學(xué)習(xí)數(shù)據(jù)庫(kù)乱豆,為699個(gè)乳腺癌樣本觀測(cè)的11個(gè)醫(yī)學(xué)指標(biāo)(第11列為class列)奖恰。其中458個(gè)觀測(cè)為良性樣本單元;241個(gè)觀測(cè)為惡性樣本單元。(有16個(gè)樣本單元含有缺失值數(shù)據(jù)瑟啃,用?表示)
1论泛、讀取數(shù)據(jù)到R
loc <- "http://archive.ics.uci.edu/ml/machine-learning-databases/"
ds <- "breast-cancer-wisconsin/breast-cancer-wisconsin.data"
url <- paste(loc, ds, sep="")
#上述組成完整的數(shù)據(jù)獲取網(wǎng)址
breast <- read.table(url, sep=",", header=FALSE, na.strings="?")
#利用read.table()讀取
2、數(shù)據(jù)表修飾
breast
查看原始數(shù)據(jù)蛹屿,有一些需要修飾的地方屁奏。并且數(shù)據(jù)有如下特征:
- 預(yù)測(cè)變量數(shù)據(jù)經(jīng)過(guò)處理,轉(zhuǎn)化為特征得分错负;從1(最接近良性)到10(最接近病變)
- 最后一列類(lèi)別變量為輸出變量:2為良性坟瓢;4為惡性。
names(breast) <- c("ID", "clumpThickness", "sizeUniformity",
"shapeUniformity", "maginalAdhesion",
"singleEpithelialCellSize", "bareNuclei",
"blandChromatin", "normalNucleoli", "mitosis", "class")
#添加列/變量名
df <- breast[-1]
#刪除第一列Id值
df$class <- factor(df$class, levels=c(2,4),
labels=c("benign", "malignant"))
#將最后一列轉(zhuǎn)化為因子犹撒,并貼上標(biāo)簽
3折联、抽取訓(xùn)練集與驗(yàn)證集
train <- sample(nrow(df), 0.7*nrow(df))
#3/7分
df.train <- df[train,]
#抽取70%為訓(xùn)練集(489)
df.validate <- df[-train,]
#剩余的為驗(yàn)證集(210)
table(df.train$class)
table(df.validate$class)
- 訓(xùn)練集:良性樣本323個(gè);惡性樣本166個(gè)油航。
- 驗(yàn)證集:良性樣本135個(gè)崭庸;惡性樣本75個(gè)。
法一:邏輯回歸(logistic regression)
即為原先學(xué)的廣義線(xiàn)性模型的一種(詳見(jiàn)第十二節(jié))谊囚,使用基礎(chǔ)函數(shù)glm()
- 1怕享、擬合
fit.logit <- glm(class~., data=df.train, family=binomial())
# 注意表達(dá)式里的點(diǎn) . 表示表格里除了因變量(class)里的其它所有預(yù)測(cè)變量,方便的一種寫(xiě)法镰踏。
summary(fit.logit)
檢查模型函筋,觀察下預(yù)測(cè)變量系數(shù)是否有未通過(guò)顯著性檢驗(yàn)(p值大于1)的,后期可以考慮優(yōu)化一下奠伪。
- 2跌帐、驗(yàn)證
prob <- predict(fit.logit, df.validate, type="response")
#type="response"得到預(yù)測(cè)腫瘤為惡性的概率
logit.pred <- factor(prob > .5, levels=c(FALSE, TRUE),
labels=c("benign", "malignant"))
#概率大于0.5為T(mén)RUE,被貼上惡性的標(biāo)簽
- 3绊率、交叉表結(jié)果
logit.perf <- table(df.validate$class, logit.pred,
dnn=c("Actual", "Predicted"))
logit.perf
最終得到預(yù)測(cè)與實(shí)際情況對(duì)比的交叉表(混淆矩陣谨敛,confusion matrix),基于此可判斷擬合建模質(zhì)量如何
如果想去除顯著性低的預(yù)測(cè)變量滤否,從而減小誤差脸狸,可使用代碼
logit.fit.reduced <- step(fit.logic)
,然后再進(jìn)行驗(yàn)證藐俺。(我試了下炊甲,沒(méi)有太大作用好像,參看第七節(jié)的學(xué)習(xí))
法二:決策樹(shù)(classical decision tree)
經(jīng)典決策樹(shù)
1欲芹、算法--基于純度
(1)選定一個(gè)最佳預(yù)測(cè)變量卿啡,判定閾值標(biāo)準(zhǔn),將全部樣本單元分割為兩類(lèi)菱父,使得兩類(lèi)的純度最大化(一類(lèi)里良的盡量多颈娜,另一類(lèi)里惡的盡量多)
(2)對(duì)每一個(gè)子類(lèi)別繼續(xù)執(zhí)行步驟(1)
(3)重復(fù)步驟(1)與(2)剑逃、直到集中的子類(lèi)別所含的樣本單元過(guò)少、或者沒(méi)有分類(lèi)法能將不純度降低到一定標(biāo)準(zhǔn)揭鳞。最終集中的子類(lèi)別就是終端節(jié)點(diǎn)炕贵。根據(jù)每一個(gè)終端節(jié)點(diǎn)中樣本單元的類(lèi)別數(shù)眾數(shù)來(lái)判斷這一終端節(jié)點(diǎn)的所屬類(lèi)別。
(4)對(duì)于其它樣本野崇,從頭執(zhí)行決策樹(shù)称开,對(duì)應(yīng)到某一終端節(jié)點(diǎn),從而進(jìn)行類(lèi)別判斷乓梨。
- 綜上通常會(huì)得到一顆過(guò)大的樹(shù)鳖轰,出現(xiàn)過(guò)擬合,普適性弱扶镀,需要采用10折交叉驗(yàn)證法選擇誤差較小的樹(shù)蕴侣。
2、具體步驟
(1)生成初始樹(shù)
library(rpart)
dtree <- rpart(class ~ ., data=df.train, method="class",
parms=list(split="information"))
(2)剪枝
dtree$cptable
返回的信息有--
- CP為復(fù)雜度參數(shù)臭觉,為后面剪枝的重要依據(jù)昆雀;
- nsplit為分支數(shù),終端節(jié)點(diǎn)比分支數(shù)多一個(gè)蝠筑;
- rel error 訓(xùn)練集中各種樹(shù)對(duì)應(yīng)的誤差狞膘;
- xerror 為交叉驗(yàn)證誤差;
- xstd 為交叉驗(yàn)證誤差的標(biāo)準(zhǔn)差什乙。
選擇最優(yōu)的樹(shù)的原則基于兩個(gè)條件:一是其交叉驗(yàn)證誤差在返回的最小的交叉驗(yàn)證誤差(0.17)一個(gè)標(biāo)準(zhǔn)差范圍內(nèi)(0.03)內(nèi)挽封;二是終端節(jié)點(diǎn)最少。
基于上圖結(jié)果臣镣,即選取原則辅愿, 這次做的結(jié)果就直接推薦僅兩個(gè)分支,基于一個(gè)變量標(biāo)準(zhǔn)的小小樹(shù)忆某,還是很詫異的点待,看看驗(yàn)證結(jié)果如何吧
dtree.pruned <- prune(dtree, cp=.0392)
library(rpart.plot)
prp(dtree.pruned, type = 2, extra = 104,
fallen.leaves = TRUE, main="Decision Tree")
#繪制決策樹(shù)
關(guān)于prp()
函數(shù)繪制決策圖的參數(shù)說(shuō)明
- type = 2 畫(huà)出每個(gè)標(biāo)簽下分隔的標(biāo)簽(變量)
- extra = 104 畫(huà)出每一類(lèi)的總概率(樣本數(shù)/總樣本數(shù))及該節(jié)點(diǎn)出良/惡的比例;
- fallen.leaves = TRUE 在圖的底端顯示出終端節(jié)點(diǎn)
(3)驗(yàn)證與交叉表
dtree.pred <- predict(dtree.pruned, df.validate, type="class")
dtree.perf <- table(df.validate$class, dtree.pred,
dnn=c("Actual", "Predicted"))
dtree.perf
竟然只有一個(gè)變量標(biāo)準(zhǔn)準(zhǔn)確率還有90%以上弃舒。要么是這個(gè)變量很重要亦鳞,要么是數(shù)據(jù)太少了~ 總之我覺(jué)得就是怪怪的。我之前做的是建議分成5個(gè)終端節(jié)點(diǎn)棒坏,書(shū)上的結(jié)果是建議4個(gè),看來(lái)抽樣對(duì)于建樹(shù)影響挺大的遭笋。
條件推斷樹(shù)(conditional inference tree)
1坝冕、算法--基于顯著性檢驗(yàn)
(1)對(duì)輸出變量與每個(gè)預(yù)測(cè)變量間的關(guān)系計(jì)算p值;
(2)選取p值最小的變量瓦呼;(p值小喂窟,不表明最相關(guān)测暗,而是表明最有可能正確)
(3)在因變量(應(yīng)該指class值)與被選中的變量間嘗試所有可能的二元分割(通過(guò)排列檢驗(yàn)),并選取最顯著的分割磨澡;
(4)將數(shù)據(jù)集分成兩群碗啄,并對(duì)每個(gè)子群重復(fù)上述步驟;
(5)重復(fù)至所有分割都不顯著或已達(dá)到最小節(jié)點(diǎn)為止稳摄。
2稚字、具體步驟
(1)生成樹(shù)并繪制--不必剪枝了
library(party)
fit.ctree <- ctree(class~., data=df.train)
plot(fit.ctree, main="Conditional Inference Tree")
#繪制條件推斷樹(shù),陰影區(qū)域代表這個(gè)節(jié)點(diǎn)的惡性腫瘤比例厦酬。
(2)驗(yàn)證與交叉表
ctree.pred <- predict(fit.ctree, df.validate, type="response")
ctree.perf <- table(df.validate$class, ctree.pred,
dnn=c("Actual", "Predicted"))
ctree.perf
- 在本例中條件推斷樹(shù)的驗(yàn)證結(jié)果比經(jīng)典決策樹(shù)好一些胆描。
法三:隨機(jī)森林(Random forest)
- 特點(diǎn):組成式的有監(jiān)督學(xué)習(xí)方法----同時(shí)生成多個(gè)預(yù)測(cè)模型,并將模型的結(jié)果匯總以提升分類(lèi)準(zhǔn)確率仗阅。
- 思路:對(duì)樣本單元和變量進(jìn)行抽樣昌讲,從而生成大量決策樹(shù)。對(duì)于每個(gè)樣本來(lái)說(shuō)减噪,所有決策樹(shù)依次對(duì)其進(jìn)行分類(lèi)短绸。所有決策樹(shù)預(yù)測(cè)類(lèi)別中的眾數(shù)類(lèi)別即為隨機(jī)森林所預(yù)測(cè)的這一樣本單元的類(lèi)別。(詳見(jiàn)p368)
- randomForest包中的randomForest()函數(shù)用于生成隨機(jī)變量筹裕,默認(rèn)生成500顆樹(shù)(經(jīng)典決策樹(shù))醋闭,并且默認(rèn)在每個(gè)節(jié)點(diǎn)處抽取sqrt(M)個(gè)變量,最小節(jié)點(diǎn)為1饶碘。
party()包的cforest()函數(shù)可基于條件推斷樹(shù)生成隨機(jī)森林目尖。
- 具體步驟如下:
(1)生成隨機(jī)森林
library(randomForest)
fit.forest <- randomForest(class~., data=df.train,
na.action=na.roughfix,
importance=TRUE)
- 默認(rèn)在每棵樹(shù)的每個(gè)節(jié)點(diǎn)隨機(jī)抽取三個(gè)節(jié)點(diǎn),生成500顆樹(shù)扎运;
- na.action=na.roughfix 將變量中的缺失值替換成對(duì)應(yīng)列的中位數(shù)瑟曲。(若是類(lèi)別型變量,則替換成眾數(shù))豪治;
- importance=TRUE 設(shè)置評(píng)價(jià)變量重要性
(2)查看變量重要性
importance(fit.forest, type=2)
#type=2 參數(shù)設(shè)置變量相對(duì)重要性的原理洞拨,詳見(jiàn)p370
由下圖可看出,sizeUniformity為最重要的預(yù)測(cè)變量负拟;mitosis為最不重要的變量烦衣。
(3)驗(yàn)證與交叉表
forest.pred <- predict(fit.forest, df.validate)
forest.perf <- table(df.validate$class, forest.pred,
dnn=c("Actual", "Predicted"))
forest.perf
- 結(jié)果看起來(lái)還不錯(cuò)
法四:支持向量機(jī)(support vector machine,SVM)
- 一類(lèi)可用于分類(lèi)和回歸的有監(jiān)督機(jī)器學(xué)習(xí)模型,這里只學(xué)習(xí)其在二元分類(lèi)問(wèn)題中的應(yīng)用掩浙。
簡(jiǎn)單來(lái)說(shuō)花吟,SVM旨在多為空間中找到一個(gè)能將全部樣本單元分成兩類(lèi)的最優(yōu)平面,這一平面應(yīng)使兩類(lèi)中距離最近的點(diǎn)的間距(margin)盡可能的大厨姚,在間距邊上的點(diǎn)被稱(chēng)為支持向量(support vector衅澈,它們決定間距),分割的超平面位于間距的中間谬墙。對(duì)于一個(gè)N維空間(N個(gè)變量)來(lái)說(shuō)今布,最優(yōu)超平面(即線(xiàn)性決策面经备,linear decision surface)為N-1維。詳細(xì)原理見(jiàn)p370
1部默、 默認(rèn)參數(shù)法
library(e1071)
fit.svm <- svm(class~., data=df.train)
svm.pred <- predict(fit.svm, na.omit(df.validate))
svm.perf <- table(na.omit(df.validate)$class,
svm.pred, dnn=c("Actual", "Predicted"))
svm.perf
結(jié)果也還行
2侵蒙、選擇調(diào)和參數(shù)(原理詳見(jiàn)p372)
- 上述用法中g(shù)amma默認(rèn)為預(yù)測(cè)變量個(gè)數(shù)的倒數(shù)、成本參數(shù)默認(rèn)為1傅蹂。
- 在建模時(shí)纷闺,我們也可以嘗試變動(dòng)參數(shù)值建立不同的模型,從中選擇最佳的組合
tuned <- tune.svm(class~., data=df.train,
gamma=10^(-6:1),
cost=10^(-10:10))
tuned
gamma的8種變化與cost的21種變化贬派,共168個(gè)模型急但,從中選最佳。發(fā)現(xiàn)gamma為0.1搞乏,cost為1時(shí)最優(yōu)
fit.svm2 <- svm(class~., data=df.train, gamma=.01, cost=1)
svm.pred 2<- predict(fit.svm, na.omit(df.validate))
svm.perf 2<- table(na.omit(df.validate)$class,
svm.pred, dnn=c("Actual", "Predicted"))
svm.perf2
并未改善波桩,但是一般來(lái)說(shuō)為SVM模型選擇調(diào)和參數(shù)可以得到更好的結(jié)果,比如我之前嘗試的一次请敦。
評(píng)價(jià)分類(lèi)模型
1镐躲、評(píng)價(jià)指標(biāo)
- 敏感度Sensitivity:所有患者里,有多少被成功預(yù)測(cè)(實(shí)際有病樣本為基數(shù))侍筛;
- 特異性Specificity:所有健康人里萤皂,有多少被成功預(yù)測(cè)(實(shí)際沒(méi)病樣本為基數(shù));
- 正例命中率Positive Predictive Value:被預(yù)測(cè)為有病的人里匣椰,有多少是預(yù)測(cè)正確的(預(yù)測(cè)有病樣本為基數(shù))裆熙;
- 負(fù)例命中率Positive Predictive Value:被預(yù)測(cè)為沒(méi)病的人里,有多少是預(yù)測(cè)正確的(預(yù)測(cè)沒(méi)病樣本為基數(shù))禽笑;
- 準(zhǔn)確率Accuracy:被正確分類(lèi)的樣本單元所占比重入录,也叫ACC;
對(duì)于癌癥等疾病診斷角度來(lái)說(shuō)佳镜,敏感度指標(biāo)格外重要僚稿。此外敏感度與特異度是相互權(quán)衡,此消彼長(zhǎng)的關(guān)系蟀伸,可以通過(guò)設(shè)定閾值加以調(diào)整蚀同。P376
2、生成計(jì)算上述指標(biāo)的函數(shù)
performance <- function(table, n=2){
if(!all(dim(table) == c(2,2)))
stop("Must be a 2 x 2 table") #一定要是2×2形式的二聯(lián)表
tn = table[1,1]
fp = table[1,2]
fn = table[2,1]
tp = table[2,2]
#分別對(duì)應(yīng)位置取值
sensitivity = tp/(tp+fn)
#計(jì)算敏感度
specificity = tn/(tn+fp)
#計(jì)算特異度
ppp = tp/(tp+fp)
#計(jì)算正例命中率
npp = tn/(tn+fn)
#計(jì)算負(fù)例命中率
hitrate = (tp+tn)/(tp+tn+fp+fn)
#計(jì)算準(zhǔn)確率
result <- paste("Sensitivity = ", round(sensitivity, n) , #原來(lái)n是設(shè)置了保留的位數(shù)
"\nSpecificity = ", round(specificity, n), # /n 為換行符
"\nPositive Predictive Value = ", round(ppp, n),
"\nNegative Predictive Value = ", round(npp, n),
"\nAccuracy = ", round(hitrate, n), "\n", sep="")
cat(result)
}
3啊掏、評(píng)價(jià)獲得的模型結(jié)果
performance(logit.perf)
performance(dtree.perf)
performance(ctree.perf)
performance(forest.perf)
performance(svm.perf)
此外蠢络,教材中還介紹了利用rattel()包提供圖像式交互界面來(lái)做上述以及更多的數(shù)據(jù)分析。由于相關(guān)軟件安裝失敗迟蜜,未能實(shí)際演練刹孔,以后有機(jī)會(huì)的吧。詳見(jiàn)p376
數(shù)據(jù)挖掘一般先嘗試相對(duì)簡(jiǎn)單的方法(邏輯回歸小泉、決策樹(shù))和一些復(fù)雜的方法(隨機(jī)森林芦疏、支持向量機(jī))。如果與簡(jiǎn)單的方法相比微姊,復(fù)雜方法在預(yù)測(cè)效果方面沒(méi)有顯著提升酸茴,則傾向于選擇簡(jiǎn)單的方法。
參考教材《R語(yǔ)言實(shí)戰(zhàn)(第二版)》