机器学习-多元分类/回归决策树模型(tree包); j. L: i' |+ k: p( l
+ U# \2 o# q! N1 s+ l
决策树(Decision Tree):Tree-Based方法用于多元数据的分类和回归。决策树点是再现了人类做决策的过程,树可以图形化显示,很容易解释。但是树的分类和回归准确度比不上其他分类和绘图模型。决策树是随机森林、boosting等组合方法的基本组件,组合大量的树通常会显著提高模型的预测准确度,但会损失一些解释性。定性与定量变量均可用于Tree-Based方法。tree\rpart\mvpart均可进行多元树分析及绘图。此文介绍如何使用tree包进行多元分类/回归决策树分析。' C( v7 T) P u6 r8 M6 n8 g W
- }+ ` Q8 G9 v9 ?0 ` 一、 准备数据# v- L5 o0 S# P3 t, d! n) z
, K d D- [2 G* |( C5 |8 w1 o
虚构微生物组和环境因子数据,包含75个样本。1 y. [! R* y N2 q
" \; ~* u" N" x
# 1.1 导入数据0 M5 u6 k& c; p+ m. B
## 微生物组数据 ) b) X3 U0 P$ Wspe = read.csv("spe.csv",row.names = 1,header = TRUE,check.names = TRUE,stringsAsFactors = TRUE) # q @* {, ^$ x1 T m. V, g
dim(spe)/ N& q8 a2 A7 n' E) d+ ~
head(spe)1 u1 T% j0 G. k% m* f+ `& W+ U
( V; b E0 i! x2 B7 b5 T4 j, n; z## 环境因子数据 - w- P) W* U$ I& o7 venv = read.csv("env.csv",row.names = 1,header = TRUE,check.names = TRUE,stringsAsFactors = TRUE) ) |& L+ C0 J" b4 O# F/ I* C5 ^2 q8 `dim(env) : h2 c j$ S2 fhead(env) : D* D( C) J3 G : N* b; n% Y1 \ p' w9 m- Y# y% d+ s$ I8 I$ A! b
图1|原始otu表,spe.csv。前两列为分类信息。 ^! n: M) ?* m' U/ ]. N ; P7 n4 j( Y1 j! P 5 X4 ~8 m1 l* [. ? m e# F1 n: e4 R- q4 ]3 c
图2|环境因子数据,env.csv。4 f2 r# ^( S# w$ M8 }) M* u- v
7 A, A4 _$ ?! z+ W9 I$ W
二、决策树回归模型 $ G2 F; _3 |- g, j当因变量为定量变量时,决策树进行回归分析。分析时先基于自变量划分预测空间Rj,此时残差平方和(residual sum of squares,RSS)值最小,然后对于落入某一预测空间的样本,做相同的预测。( S U+ I$ |% u5 E& [( n I
) J# C) ^9 A6 A8 p F" a6 I- Y! ?4 g8 {% a# N! c4 i2 B
- U/ ] z- I2 P' u3 c一般模型越复杂,偏差越低,方差越高;简单模型一般偏差较高,方差较低,所以构建总误差较低的模型需要找到合适的模型复杂度。3 q9 p: W" y) ]3 ?" {7 K; x
: J/ E# A0 ~$ r; i E5 b
# 2.2.1 交叉验证寻找最佳终端节点数/ A5 R* }; m* l
set.seed(12345) 0 h* m! y$ x7 B2 h0 greg.cv = cv.tree(reg.tre,K=10)- I, A8 d5 _) J# o+ @
reg.cv 3 w7 m; m& v) \4 l/ D4 }plot(reg.cv$size,reg.cv$dev,type="b") # 终端节点为2是偏差最小9 s* i$ t5 ?: m# v/ O- H# n9 r& ]6 W
" x3 @% s$ {: X# 2.2.2 剪枝优化模型 ) e' d. ]" W3 Y& W. ]9 Jreg.prune.tre = prune.tree(reg.tre,best=2)& a2 S ]$ J1 G( T: D5 u8 L
reg.prune.tre* P4 `! a) u! X2 ^( M
& W$ F+ [( X7 i( O$ i; E% J8 x
# 2.2.3 绘图 2 M$ l, ^! G9 E5 \% m: }+ iplot(reg.prune.tre) 7 a8 g: {' _% L; ctext(reg.prune.tre,pretty=0); y! a. C# v/ O# B! \9 ~; y. o
) U! A" U4 b1 {% ^# 2.2.4 修剪树预测测试数据; k# H* G; g5 X
reg.prune.pred = predict(reg.prune.tre,newdata = test.spe[,-c(1:3)]) ( b# @9 o0 p N( Oreg.prune.pred $ v1 y0 r9 {7 l
## 预测结果与原始结果绘图 - `( V5 Y; E& Z9 l# Tplot(reg.prune.pred,test.env$env1)+ L& l" _+ g! Q5 Q3 x
abline(0,1)7 I, i1 T s1 \# N0 ?/ e0 W
]; z7 e3 e, Q5 b+ W; T## 计算均方误差(MSE)和标准化均方误差(NMSE) - Q' A7 r- u0 J8 v, k$ P/ CMSE1 = mean((reg.prune.pred-test.env$env1)^2) U, z$ e1 j/ ]' D0 U# H, NMSE1 ; r4 q8 F' o% F5 F; j* O
NMSE1 = mean((test.env$env1-reg.prune.pred)^2)/mean((test.env$env1-mean(test.env$env1))^2) 5 L# S) J/ e7 ~6 E* `' ]NMSE17 }$ A0 u: @6 Y
2 S. z6 u. o$ n, D ' s$ R3 V' b; k k7 J/ ~ 3 ^% _2 |, b. ^( J图9|交叉验证结果,reg.cv。当终端节点为2时,交叉验证偏差值最小。/ n4 K6 Z4 r c3 U
I* y. _9 H$ }$ e0 t2 Y
: {$ p$ A1 |; @7 j, g r* D
; M6 x; ^6 j" E7 J: U图10|交叉验证结果-终端节点数与对应偏差绘图。' D6 m( @, T. K4 M1 c1 y Z
: N: _( m; L; r: D! i8 N; A: r' o7 f5 @2 k
_. C4 E* S$ K图11|剪枝后预测结果的MSE与NMSE值。剪枝后模型的NMSE值仍然大于1,而且值反而增大了,因为原始模型就没有什么意义,剪枝对原本就没有意义的模型,达不到优化效果。 / }( K" k' Q# {9 G K: ? P& p9 C/ U三、决策树分类模型 / C1 T. N$ Y) H) C3 d! d
+ | L3 Z1 G5 d6 z5 i3 S
分类决策树的因变量是定性变量,构建的模型也是用于对观测值进行分类预测。模型对变量进行递归二进制分裂来使树生长。分类误差(classification error rate)对树生长不够敏感,因此常用Gini index和cross-entropy两个指数对分类决策树模型准确率进行判断。9 g- j, D: J- I1 d
2 B0 n+ ]; S4 \, T4 x: j9 B% N h. F: G9 ?6 w: D
' {; M8 f, ~$ c L( h2 i# y2 E3 \( A' r+ j0 Q
2 {; a" X* y$ x$ |8 m
Gini index是节点纯度(purity)的检测值,其值较小,表示节点包含的样本更多属于单个分类。$ e# [" V' h# {- G1 P$ O
( o! O% S" ?; o, p
1 a$ ~) w, Q8 y1 Y6 D* R5 |
4 D8 s1 A( z, F, I# [/ z
_9 g/ h, d" l" k
5 ^8 _" `: p3 M, Q& {; F7 r3.1 tree包用于构建分类决策树(Classification Trees) , H1 V, B' [ ~% t6 Q" n* _; L6 I: e3 ]) g" x! f
利用微生物组数据,以grazing为因变量,其它变量为自变量,构建决策树。 , T- k6 W) R5 ?$ V+ _4 T7 R& [& G l! }+ [5 Z1 H6 ` w X
# 3.1.1 分类决策树/ t! i$ W1 _' Q
tre = tree::tree(grazing~.,train.spe[,-1],# 用于构建决策树的变量可以是分类变量或者定量变量。0 q. v4 L0 y) I3 u+ D' G
na.action = na.omit,' x( c1 ?# T9 H4 V' _% c
split = "gini",# "deviance", "gini"$ Q1 R; @4 H7 o
x=TRUE,3 [ i: R7 u3 s% c" ]% ?! @
y=TRUE,& K7 V1 U* }" u8 D
#wts = TRUE # 设置了样本weights参数,则返回权重值。 + P, a* \) T, f- S$ H( b ) - G, L; S4 C9 k" ]" N3 | ]; n- i7 y
tre ! ~9 ?1 N Z- L' E## output % p- K: z" e+ r Lwrite.table(tre$frame,"class_tre_res.txt",sep="\t",quote = FALSE,row.names = FALSE) 5 x( c: T; G$ D) ?& i+ w C 0 i) u" U* l8 I8 R# 3.1.2 描述统计& p* \2 J( K/ M$ o; x
tre.res = summary(tre) # 输出用于中间节点拆分的变量,终端节点数目和error rate。 2 W" r4 w3 T$ _4 X0 n0 ptre.res 6 @, f( U' {7 N! Ntre.res$call( d$ |: I. J. M
tre.res$type . n6 W. T. h: X: @1 `9 Ktre.res$used # 用于中间节点拆分的变量 . c( V y* l R4 j( Y& wtre.res$size # 节点数目# h. W: N9 r, N/ B2 Z
df = tre.res$df # 自由度=样本数-终端节点数目2 h! O% V6 V: E% N: |. {: {: x
df( r' s& m/ w) k9 K) o# z+ e2 P' g
dev = tre.res$dev # 所有节点包含的分类偏差8 l. C: q, a, a' [) Z
dev 3 `, U$ l' M& p. W; ^1 c t- ^tre.res$misclass # 错误分类样本与总样本数目 8 W( h( j% j1 ]! P9 ?% t6 v& ~ + V! Y% A& U& B+ h u6 v* R q. {0 D c+ b& Q
& s v* @* u! y* ~
* o5 a6 B! m/ ]$ F/ J2 P6 G, R图12|分类树输出结果,class_tre_res.txt。var:用于拆分节点的变量及终端节点(<leaf>);n:每个节点的样本数量;dev:每个节点的偏差;yval:拟合结果,回归树为节点包含样本的因变量均值,分类树为该节点样本最多属于的分类水平;split: 节点拆分,2列分别是属于左侧或右侧的标签。yprob:回归树,此为NULL;分类树则为因变量各水平的拟合比率(即每个节点中属于各分类水平的样本的比例),此数据有5个处理,所以有5列。; c+ c- W M( }" C
3 }3 x5 d& O' U4 t1 u9 w