# K W3 @$ |8 y%形成递归,一个特征的按每个类别再往下分 0 C: q1 |3 ^0 Y! m5 sfor i=1:length(uniqueVals)6 c- ]+ j, s) O
subLabels = labels('; ; A( t& P* K- x& ]$ ?7 M# y6 a A
value = char(uniqueVals(i)); 1 E( \+ u, I8 x r subdata = splitDataset(dataset,bestFeature,value); %取出该特征值为value的所有样本,并去除该属性 B; o. t, G/ P1 n* n1 F9 B4 o
leaf(value) = ID3(subdata,subLabels); ) M `% ]+ ?4 ?! i) z: L- X( m myTree(char(bestFeatureLabel)) = leaf; 1 c, T* ]. B! ~7 Yend 6 w( f5 q( W. @4 T1 ]4 Q* Z0 L 6 T+ m: i3 r+ r' {end . U: C$ ~' t0 x- n 6 c' |9 r6 K, ~9 K) v构建决策树过程中根据基尼指数选择特征的代码:# t; d0 e! ?" T! h
2 z* G( v% Q1 B/ P: F
function bestFeature=chooseFeatureGini(dataset,~) / p. b/ D# P: d9 M1 j% 选择基尼指数最小的属性特征% V$ ~/ L' _0 r, p) W
0 Q f- }7 ^+ `6 A: P: Q: P %数据预处理0 x( w3 P: ]/ q: @
[N,M]=size(dataset); %样本数量N ; q; c$ w& |2 Q! tM=M-1; %特征个数M5 Z4 q! p* G: _# E& R2 u5 B$ ^. T" J
y=strcmp(dataset(:,M+1),dataset(1,M+1)); %标签y(以第一个标签为1)4 V: Y( M& n, g, T# { o7 A
x=dataset(:,1:M); %数据x* p' e8 ]$ q* M4 a
Gini_index = zeros(1,M); %创建一个数组,用于储存每个特征的信息增益. B3 c* U+ M |0 E9 z
%bestFeature; %最大基尼系数的特征/ i K9 ?7 B. m
% C! `1 H2 o: w& e0 V8 D% g& j R%计算基尼指数 4 [% R/ ~ w/ l' Z; m# zfor i=1:M$ r4 l9 r6 h. K9 v1 C
% 计算第i种属性的基尼指数 # C' p n# P! D) x temp=tabulate(x(:,i)); ! M4 Y0 @# l- ? value=temp(:,1); %属性值6 Q) g+ b# X4 U2 X$ n
count=cell2mat(temp(:,2)); %不同属性值的各自数量: H' z: u. J1 y" P& m/ p: z& e
Kind_Num=length(value); %取值数目 ( l2 U! o1 O! @2 a9 Q( C& \+ j Gini=zeros(Kind_Num,1); " _. b0 c3 n; s/ \% q % i属性下 j取值的基尼指数) h& W+ j3 x( D1 j, W
for j=1:Kind_Num w$ W1 }. _' l& k' E& Q' E' g
% 在第j种取值下正例的数目 + |# \: K% x2 U' W# N! y Gini(j)= getGini( y(strcmp(x(:,i),value(j))) ); / T: c% w a, ]$ J! z' r end/ O. `, G6 F7 P8 K) K2 d) i! {8 f
Gini_index(i)=count'/N*Gini;7 q% R. E' @( d+ |2 u. [
end / o {, \+ p" w' [9 s1 L%随机挑选一个最小值 n7 P8 L' Y4 ~' x6 X4 w) U. R# v. r
min_GiniIndex=find(Gini_index==min(Gini_index));" F/ i0 o6 {( E1 H6 X
choose=randi(length(min_GiniIndex)); - Y# v# f" Z6 m% ibestFeature=min_GiniIndex(choose); ) X- ^# n- j# m8 b# K x& `9 oend' N# x2 ~+ r* F# @/ m7 J; k
% N& N6 g# I. O" Y0 S4 f* s+ d9 u! E+ t计算基尼指数的代码如下:* L+ P* J- f, ^ k7 {
m% z" j; e1 x2 ?* O! e6 G
function Gini = getGini(y) " q% c n% z" ?. W* J( ^/ y% 计算基尼系数7 B0 F, K, j: j! y; S. Z
% y对应的标签,为1或0,对应正例与反例4 [: N9 n' e; N
%%%%%%===============================================================================; j4 H C# [( }* t8 K- J, e
N=length(y); %标签长度# S, D: Q7 A0 J
P_T=sum(y)/N; %正例概率+ } P% B( m. U& w; m
P_F=1-P_T; %正例概率3 c) |4 m' D1 \# D% H4 R% _
Gini=1-P_T*P_T-P_F*P_F; %基尼系数 ; O8 `- W l1 q8 y# a6 W7 b+ Y%%%%%%=============================================================================== * z3 J& D2 t# @0 q5 Nend0 \8 h m: M7 P! a+ V- v
构造决策树的过程中,划分数据集的方法: 2 W" q. u. [% W/ j7 E9 w! z1 `4 l
function subDataset = splitDataset(dataset,axis,value) 2 L9 o- p; m' v0 E# f# S3 |; `, Q%划分数据集,axis为某特征列, 取出该特征值为value的所有样本,并去除该属性 # h# t( S& a' R4 n( y. b y ) _7 T& V5 P* H" {: n( ~subDataset = {};) N6 V+ W% }) N/ g
data_size = size(dataset);9 Z5 s) {" _$ N+ Y* l4 q; g/ W- p
: k. q( {) P. Q" ^7 Q%取 该特征列 该属性 对应的数据集% d" N6 }! [ K! m
for i=1:data_size(1)! Z# I9 ?) v9 h c
data = dataset(i,; ! U4 V! @& K" |* o3 v if strcmp(cellstr(data(axis)),cellstr(value)) 0 k* Z5 ?$ N# l! i/ K6 _ subDataset = [subDataset;[data(1:axis-1) data(axis+1:length(data))]]; %取 该特征列 该属性 对应的数据集- e' E; N$ k$ v6 }+ _# v! S
end9 S8 |7 s$ f: B# _1 |& X2 p
end, G/ g: P6 |/ W( @, m
end 2 [; ^" z/ l0 z8 |& s遍历决策树的方法: 0 Q. b5 c. n4 Q$ K2 R; o" a 2 K- t% o3 M9 R# j' K+ a) bfunction [nodeids_,nodevalue_,branchvalue_] = print_tree(tree) 9 `1 k+ ^& v' {% 层序遍历决策树,返回nodeids(节点关系),nodevalue(节点信息),branchvalue(枝干信息)' S3 J- b! J8 @. k. k: u$ J
nodeids(1) = 0;2 b5 a" L7 K7 }
nodeid = 0; ) @: h8 G% b3 W2 G, Z' D, h& Znodevalue={};0 u, p/ w8 O& x& R4 w. F6 e. }
branchvalue={};/ s/ ^# L; p+ t& L d% m
& r$ e5 z; S- O2 e+ p" X
queue = {tree} ; %形成队列,一个一个进去2 H/ Q% j/ ~7 x
while ~isempty(queue) $ v4 j: d% Z8 ?# \& Q8 b8 p node = queue{1};, _+ s7 g2 n/ C# V$ o f, h) S: ]
queue(1) = []; %在队列中除去该节点- ^: I( E: @1 h, j( C( H+ \
if strcmp(cellstr(class(node)),'containers.Map') == 0 %叶节点的话(即走到底了) 4 I! B2 f: e6 y nodeid = nodeid+1; 5 I- Q% E% S& J, k) ]* a nodevalue = [nodevalue,{node}];/ L" m# p) |$ s0 d( m5 H
elseif length(node.keys)==1 %节点的话 : Y. ~9 ]) |6 ]3 ~# _2 h nodevalue = [nodevalue,node.keys]; %储存该节点名 7 x" T6 ~6 ^( x7 U, e$ I% ?5 F node_info = node(char(node.keys)); %储存该节点下的属性对应的map " Q ]2 B6 B2 h" U- f nodeid = nodeid+1; " }- b3 l K$ \ g8 V' \ branchvalue = [branchvalue,node_info.keys]; %每个节点下的属性! t$ u, l' v5 a9 @+ e0 i! H& R
for i=1:length(node_info.keys)% n! _- b0 d* f$ u! V0 |" L+ ]
nodeids = [nodeids,nodeid];9 Y5 w& R( n3 f& R. E
end8 _' b4 w; U& I" s8 X* C; Y' p7 I
end 2 p( u- D( x* I1 g; g" y* b9 ` 9 Z+ r# g% V# x' v% b7 l if strcmp(cellstr(class(node)),'containers.Map')+ f9 a7 D( n/ I. a: t
keys = node.keys(); + e5 @) q0 [( c* M3 c* Q for i = 1:length(keys). r8 `% S" M$ n' j" s
key = keys{i};! s, c1 \; d/ @ L
queue=[queue,{node(key)}]; %队列变成该节点下面的节点 & j2 z2 l, U2 i end , D, A3 k' y; w4 v end: H' K: n. ~3 T1 N( E) e+ F( }
nodeids_=nodeids;! G" a5 b: b' {4 ]
nodevalue_=nodevalue;4 j4 V' R9 w( _' X2 C# s
branchvalue_ = branchvalue;9 G, ^3 z5 }7 S
end" v6 w, S# R) u3 g" _
d6 Y+ X! i8 |3 u* z q3 z绘制决策树的方法:0 w, o: C$ |1 ~' u* @1 c8 M f( N
# u% J5 A4 t) q. w7 o6 N' }! ~$ s: H% V
function tree_plot(p,nodevalue,branchvalue) ; L- W$ z) g8 S% 参考treeplot . c5 |, r ^4 U* M3 H ?3 P( c- G. M/ W/ O }
[x,y,h] = treelayout(p); %x:横坐标,y:纵坐标;h:树的深度9 F3 ^1 d8 ^8 T# ?
f = find(p~=0); %非0节点 ! ~% o8 L9 R r% m) R& h# Hpp = p(f); %非0值' {/ B! x$ a- x1 R" J
X = [x(f); x(pp); NaN(size(f))];# b1 c! E( d! b7 A
Y = [y(f); y(pp); NaN(size(f))];+ s1 h8 z V- z
1 R! i/ ~$ _& j
X = X(;! C6 l2 R# u% l7 {+ ?
Y = Y(;. v0 h$ J! R7 C1 |. \* z2 h5 e
" O4 t, ^* x5 f( B
n = length(p); 4 D" j8 o( W% M Eif n<500- R6 X! g; T- |5 _$ m
hold on; : d3 X1 ?3 r& U! ]: C plot(x,y,'ro',X,Y,'r-') ( T& _- q2 y9 T& G4 F( M) `5 @/ } nodesize = length(x); . B. Q4 o2 Y* q( v for i=1:nodesize; d8 N8 K% q+ T5 N# T
text(x(i)+0.01,y(i),nodevalue{1,i}); 7 Q% h) i5 c: B1 v end1 p2 ] S7 P; }4 f
for i=2:nodesize0 O; Z' t3 w9 r+ M# W
j = 3*i-5; " I' a3 J6 P# d7 m: Y' }7 x; I text((X(j)+X(j+1))/2-length(char(branchvalue{1,i-1}))/200,(Y(j)+Y(j+1))/2,branchvalue{1,i-1}) - I* O0 h) D4 K& T end. O) u% X4 o% r# F# f
hold off2 F, `- n. @$ c/ I% }
else& T1 [1 l: j/ k$ E% G" }4 x' s0 `
plot(X,Y,'r-'); 7 F. G1 o+ T- X$ I- Oend! e! O6 S3 r' e- S8 m+ q) q0 X
xlabel(['height = ' int2str(h)]);; {' q; n. q# S" s0 [7 D
axis([0 1 0 1]); & V1 [1 w, Z2 P3 m) Send K' n0 y! \% }9 D , r0 G* Q, y/ R测试集进行预测的方法: 9 o& j e Z' P& C4 f4 ]) D" ?' V1 b5 ^- `2 u2 Y& U7 \
function y_test=predict(x_test,mytree,feature_list) 6 N7 l# _6 b+ U; z+ E! X% {%测试9 A; P& w# c' |$ G- Z
: v& h* p, w' |9 d
y_test = {}; 7 h' @% Z$ u& Srow = size(x_test);, H% }3 v" Z k& e; Y5 b
, Z% y) q( y; _/ ^5 f C
5 U2 u& Q5 X! W7 P
for j= 1:row(1)/ i5 O5 L% _ I: ^$ H; s) v
queue = {mytree}; %形成队列,一个一个进去 ; ` B, \7 J8 C$ F" H feature_name = 0; . T" T/ C0 `) m" P: _! Q2 g feature = 0; 5 O4 [8 R+ s- M$ x7 [* }! Q- c7 X4 `% C
while ~isempty(queue)3 g) K, X: v' f0 B0 e
node = queue{1};; _0 Z) @* c; x- c" W% B% e
queue(1) = []; %在队列中除去该节点 % c: @: `# e3 j d" b3 ]3 T1 {1 B
tag = 2;8 I' S5 J8 l3 `, O6 ~$ _5 Z2 _
if strcmp(cellstr(class(node)),'containers.Map') == 0%叶节点的话(即走到底了). Z9 j& N6 \( a/ {9 w# E
y_test{j} = node; %走到底就是我们需要的标签! _( ?1 q2 \" G e
continue + J/ p% N: E7 R7 f elseif length(node.keys)==1 %节点的话, k- c# k: V% ^. i# P; J- {* Z6 N$ v
feature_name = char(node.keys); %得到mytree节点的名字4 I H2 i) D4 X3 v% [" S( l
id = ismember(feature_list,feature_name); %mytree该特征所在的坐标 \- v$ l+ c! [$ n% T5 @& v: O3 ~
x = x_test(j,; W+ _, K7 B% ~. [0 E+ e feature = x(id); %得到测试数据的特征属性" v" M H- u* b+ z( [3 @6 r& G8 m
tag = 1; 1 o9 s& S; U+ t A% ^9 D+ C! p) @
end" {9 Z+ T F R- u/ n7 C" L
) O5 c/ h* s; o8 N" ]0 Q- ^" h$ R) {1 c( g9 b3 C9 h9 m% V, I
%tag==2 即要走入下个节点 / l3 f; y) n. F/ ]5 ]0 F if tag==2 , d2 m3 r' o3 C: H* ~, d6 ? if strcmp(cellstr(class(node)),'containers.Map')- H* M% f% ?# B- u
hasKeys=0;7 p6 U" l) L- Q% m! ^
keys = node.keys(); 9 W4 t1 M1 G% R, b# k2 h for i = 1:length(keys) + @9 v. |9 M' Z' q3 ] key = keys{i};' R0 T# L+ @: m3 r0 g
c = char(feature);* ]/ p. T. L* c' x$ U5 L# x# D
if strcmp(key,c) ) g) T# c7 d; C" L7 Q: x2 |. e* T! Z queue=[queue,{node(key)}]; %队列变成该节点下面的节点! R5 Q) x( z* x/ H2 S0 h% S& c
hasKeys=1;& B" r* u( a* ~
end : ]! w8 Y$ \) h. E$ f" _7 D! k end0 Y% R8 \% \6 k+ L9 }% \
if(~hasKeys)4 j0 x* ~% L8 ~/ ?7 v
key = keys{randi(length(keys))};' r+ u. [' j+ c% j. `# O7 l; g3 F
queue=[queue,{node(key)}]; %队列变成该节点下面的节点 2 o7 @6 K, ~& C7 V. O end% P; [% O. F) A/ r N6 [( r* l
end # m) V5 o. {$ n0 J3 y end 0 {+ [: ~+ z* Q$ m" n" J M0 \2 K& }) _, k0 v5 z$ V1 x
%tag==1 即要选则符合测试数据的特征属性,这样就不用历遍整个mytree& u, O" }( H* l% I" v1 [
if tag==1 1 k# R$ g ]: Y* k: D3 D if strcmp(cellstr(class(node)),'containers.Map') 9 T# I) S8 j' D+ G7 ^ keys = node.keys(); $ T0 G9 o# D' y: Q for i = 1:length(keys) . C0 f( a" _- G& m1 Z) b' h key = keys{i}; " n. j& O; o% c& v/ | queue=[queue,{node(key)}]; %队列变成该节点下面的节点 ' X8 I$ M( Y% d5 N1 b- E' g end % V- k9 {" s, L0 R& h' N end _3 A' n: k T end 0 K* M. Q. X" V& `% U end 1 u/ g9 z& Z0 ^* U: {9 k5 t if length(y_test)<j 5 W' x7 M0 V/ s @7 c* D test=1; , ?1 _; {9 q9 E$ C; y9 q2 j end5 v2 C, h5 B% r
end % @0 y' Y8 S% z4 v; @ * j* ]4 H x M( |end; o- l t( b* z ?( L9 l" y1 h C3 x
: r2 i) T. u3 Z! k/ V6 N2 M二、随机森林 3 L n; p& E5 Y+ z1 U2.1、随机森林的算法原理 2 V1 ?, N. U5 D3 g: u我们首先看卡集成算法,也可以叫集成学习,目的是让机器的学习效果更好,常见的又bagging,boosting和stacking,其中bagging是训练多个取平均值,boosting是训练多个组合加权,stacking是聚合多个分类,就是融合多个算法。( _- r: B8 R% h# e" n# C: q4 |, _
' z' {; d2 ^( b! d' [# ]2 {/ P
& f2 \' Q$ N2 j) s) r
# P0 @. m4 {9 i `* h 我们看一下Bagging模型,典型的Bagging模型就是随机森林,并行的训练一堆分类器,数据随机采样,特征选择随机,建立多个决策树,即多个分类器,将多个分类器放到一起就组成了森林。3 O! M) n: C* g6 o4 e, H
' \) T+ f' i; O4 \
2 z8 M8 R. L) R8 I2 z) z
2 _" {& N }- o8 @; n+ _* ^* l+ D
通过2重随机性,就是随机采样,随机获取特征,使得构造的决策树具有多样性,最后的平均才能取得更好的效果,更具有说服力。 7 a" O* c! d6 i 7 O6 V a. {7 v8 U! U7 G& \7 H7 N0 w4 P R+ h
7 ?/ G% s/ S6 S2.2、随机森林的优势与特征重要指标 3 }) D# {, P. T6 t [/ v- h6 M随机森林的可解释性很强,神经网络虽然也可以用来预测和分类,但是神经网络的隐含层不具有可解释性,我们只知道输入和输出,具体内部怎么做的,细节无从得知。随机森林方便进行可视化展示,可以自动做特征筛选,并行速度较快。" A/ o& ]/ P& N1 E. q, k* Z