* {0 Q4 g( |! Z2 t3 \( N# 载入汽车数据, 判断顾客要不要买 2 H7 L% u( R0 s* h# f+ l* ^) Rclass load_car: " M# E) } M! v9 P # 在表格中,最后一列是分类结果 2 h, P @) L2 a$ D* T% p- t # feature_names: 属性名列表 ) U r! x( h+ r5 \/ H6 U8 v2 J # target_names: 标签(分类)名 _6 O7 D+ |/ \! ?
# data: 属性数据矩阵, 每行是一个数据, 每个数据是每个属性的对应值的列表 ) E7 T5 y2 g" ^0 Y2 e/ U # target: 目标分类值列表; k( ^# b& e C: U1 k+ P' l
def __init__(self):4 }& t. A7 T: L. k- Y
df = pd.read_csv('../dataset/car/car_train.csv') 1 ^6 a( ^( p) h1 g1 q! l labels = df.columns.values 3 K3 _, ^' n. [- P, F data_array = np.array(df[1:])2 w: t8 f3 `, |7 U0 T
self.feature_names = labels[0:-1] 1 w1 L/ n# q, e& S) F0 x self.target_names = labels[-1] / `8 w" [% ?2 r, s5 W) M# n0 k self.data = data_array[0:,0:-1] / D- L; _1 M& q! d! r4 L self.target = data_array[0:,-1] - B+ G1 O; P6 Z + Y" \: K; i, @! J. [& D. w# 载入蘑菇数据, 鉴别蘑菇是否有毒 / i. m& N! A" ] _# P$ j: ~class load_mushroom: 2 O- W; E1 [) ] # 在表格中, 第一列是分类结果: e 可食用; p 有毒.; _2 f* \7 N. {' r9 L9 H
# feature_names: 属性名列表 * h2 l& U: b4 b: j5 E6 D: _ # target_names: 标签(分类)名: G2 a5 K$ R9 o9 _5 m
# data: 属性数据矩阵, 每行是一个数据, 每个数据是每个属性的对应值的列表 . k9 Z. \5 ~) V4 i; ?; T # target: 目标分类值列表; s* Y# i. }, G" B4 W
def __init__(self):, T; c7 K+ ~7 @ [3 [1 M8 s
df = pd.read_csv('../dataset/mushroom/agaricus-lepiota.data')3 \3 {" H6 t! H1 i
data_array = np.array(df) , ^- i4 E0 s; d; q" a: n B0 E labels = ["edible/poisonous", "cap-shape", "cap-surface", "cap-color", "bruises", "odor", "gill-attachment",+ _6 r! D2 C" `) z& x! I+ M
"gill-spacing", "gill-size", "gill-color", "stalk-shape", "stalk-root", "stalk-surface-above-ring", ! L1 J2 M& J* W "stalk-surface-below-ring", "stalk-color-above-ring", "stalk-color-below-ring", 4 R5 V( o7 E. E- s "veil-type", "veil-color", "ring-number", "ring-type", "spore-print-color", "population", "habitat"] 6 X- F, k2 [# O! U( p self.feature_names = labels[1:] : ~" G, e. S. e# c1 W& i, _, q self.target_names = labels[0] ; Z n% e- P" d, n& C self.data = data_array[0:,1:]" G- U( i2 S2 u3 ^6 _; N$ E
self.target = data_array[0:,0], R; E [: w. _% g: X- i
, @. N1 l, q- \' ]+ G9 n. Z7 U
# 创建一个临时的子数据集, 在划分测试集和训练集时使用 $ O6 c, H( R# f, I" Uclass new_dataset: ; W t2 s; k% ` # feature_names: 属性名列表 - N0 H7 V; R+ G" z! Q M # target_names: 标签(分类)名1 ? D- x4 p. D# {
# data: 属性数据矩阵, 每行是一个数据, 每个数据是每个属性的对应值的列表* Z* O& _' ]0 V2 h! O: p
# target: 目标分类值列表 ; ^3 {5 P& k( p4 R K def __init__(self, f_n, t_n, d, t): & Y) d% D! k7 I6 _, f self.feature_names = f_n * Q) R; A' ?+ l( _ T self.target_names = t_n * _$ Z1 Y! x2 d, t# m self.data = d/ V; ^, B: f8 V6 L0 T! d+ \" q# ]
self.target = t ( `6 ^+ v+ L! y2 n , p, r6 V) ~3 w2 f/ M# 计算熵, 熵的数学公式为: $H(V) = - \sum_{k} P(v_k) \log_2 P(v_k)$+ g6 c# T; r7 W8 v) I. b- Y! d+ _
# 其中 P(v_k) 是随机变量 V 具有值 V_k 的概率 6 F9 j9 I+ a4 e7 @# target: 分类结果的列表, return: 信息熵 e# M& Q" B+ D" E
def get_h(target): ) l" N T. c# G' K- G, z target_count = {}0 K$ _, Q& g. k1 h+ r" i
for i in range(len(target)): * w+ @: |5 \4 h2 c# z5 m) Y label = target# E7 j3 W/ J" Q G& `9 ?& H% v
if label not in target_count.keys():% I% Q/ C+ t! o. i
target_count[label] = 1.0: u- K; m, _# F( S( @* r
else: 1 f/ J. N, {2 W {5 p6 p target_count[label] += 1.0) |5 }0 u- y( Y( L i2 f- S+ J, E
h = 0.0; S( Y) f( P6 c7 u) G0 y G6 T% V
for k in target_count:. ?. Z* X$ f- ~* b5 D9 `
p = target_count[k] / len(target) 1 o$ ^/ G: d9 c8 [5 W. F h -= p * log(p, 2)- a( D7 r! H8 p
return h : }0 G' w" r. Y7 X. v* t3 _ ) K d0 x- W! }4 c5 Z# 取数据子集, 选择条件是原数据集中的属性 feature_name 值是否等于 feature_value + Z1 I" G- m- ?: m, {' a# 注: 选择后会从数据子集中删去 feature_name 属性对应的一列 / q9 b# V2 h6 hdef get_subset(dataset, feature_name, feature_value): : a' S6 q% m& L9 W1 F" B" @ sub_data = []- [& X( x, c) o- @3 B
sub_target = [] 0 r# E! L; w$ L( _. H$ F f_index = -1 9 Y* C7 h4 A/ m- ^ for i in range(len(dataset.feature_names)): $ B7 x. D. `6 O if dataset.feature_names == feature_name: $ H2 h- i0 h; `, l3 c# a2 s f_index = i / v- y$ \( N# ?" Y5 j! Y/ U break* {. ?6 i( Q. B2 f W* u4 }
9 d' O, S& f6 u1 |% T2 h5 S for i in range(len(dataset.data)): . [, Q8 ?% ]2 P' T if dataset.data[f_index] == feature_value:" j4 l2 }% a6 J
l = list(dataset.data[:f_index]); a0 w7 }% X4 H' Z$ [( F# X6 B7 n
l.extend(dataset.data[f_index+1:])9 L" L( O; u# H$ ~) L( P3 A, m) i
sub_data.append(l) . ~+ [1 E C6 \6 F# P sub_target.append(dataset.target). c; t5 Y1 \' _! H ]3 Z5 |( b
y9 e o( i5 ?/ s; k% V sub_feature_names = list(dataset.feature_names[:f_index]) & r) i* w5 t: T/ P( B5 D sub_feature_names.extend(dataset.feature_names[f_index+1:]) $ O+ n8 P D5 j) z) r return new_dataset(sub_feature_names, dataset.target_names, sub_data, sub_target) 7 h3 u" n. h7 Z( ^ , ?1 ^3 d* |3 _# 寻找并返回信息收益最大的属性划分 O: I3 M8 m# e v3 Q& p% x2 m# 信息收益值划分该数据集前后的熵减 # g% K1 ?( a) N- ~: @* G W# 计算公式为: Gain(A) = get_h(ori_target) - sum(|sub_target| / |ori_target| * get_h(sub_target))$ 0 S, P8 u. t4 I" ^. {/ B/ e6 ^def best_spilt(dataset): % ]+ h' g9 R$ j4 s; I7 H8 E9 F& N! i% z) \
base_h = get_h(dataset.target) ' Y P3 d% _3 Y- M( J4 u" P- @& w& [ best_gain = 0.0$ f G+ ^8 v& `
best_feature = None 4 P: L C$ a* D0 }9 } for i in range(len(dataset.feature_names)): ) V$ K, S1 S- ]; J3 c* ~, H) y feature_range = []( ]; k, c* r: x7 a" f1 x6 B" H4 A g
for j in range(len(dataset.data)):. D9 d' S7 ^& t# Y6 W1 l; w2 i" I: s$ ? o
if dataset.data[j] not in feature_range: \4 k' w4 H& Y) @
feature_range.append(dataset.data[j])) F2 E/ G' `. S1 t1 q7 T
7 P* K5 f6 F _9 \6 v0 _ spilt_h = 0.0 p f1 E8 R1 O% G
for feature_value in feature_range: / M. w5 o( @, U! @3 C/ s; M/ h! S. W subset = get_subset(dataset, dataset.feature_names, feature_value) * ?7 j" l$ W) F- I( H4 n; J spilt_h += len(subset.target) / len(dataset.target) * get_h(subset.target) * v; p" Y$ Z& j; T# r. j/ L 5 d1 l2 m, |" a7 t }) O$ N l if best_gain <= base_h - spilt_h:; z! S6 q" ~& M
best_gain = base_h - spilt_h) @) l% i/ D% A# k5 @ f4 f
best_feature = dataset.feature_names2 x2 k; z8 v9 ?/ n5 ?" r" |. r
9 ?; X1 W1 ~, ~5 p2 S
return best_feature3 ]; V8 q1 N, q j
8 l9 P. v# w% s+ U6 Y
# 返回数据集中一个数据最可能的标签 6 f; l# X' v7 X) q& d4 V gdef vote_most(dataset): 2 F4 ?+ d% t# g target_range = {} & Y! U- R7 M2 R3 \% j best_target = None + y3 a( i9 f9 q, Q$ W best_vote = 0 % Z7 J4 P& `, L7 {' _1 d J 4 x! b& v( {, s [0 _) k( K4 v+ L for t in dataset.target: + c" ?, o4 f! O. S8 r if t not in target_range.keys(): # S) }2 F5 c! g) T+ S target_range[t] = 1" g+ d+ g! A- O& H" K! c
else: S6 T& l" N2 G) ?1 D target_range[t] += 1 ; f3 o# J1 Y& f6 a / z5 f; ~8 ^( V+ l. H; [7 a for t in target_range.keys(): / [; X6 V9 \) T3 U if target_range[t] > best_vote:6 ~. j, V4 s& n$ U/ H" l
best_vote = target_range[t]' A" Z0 k& [% T
best_target = t/ D$ K) v- t) l4 s
- L% `; u9 J j9 e return best_target" [' U" k4 Q. G6 u! w
3 B, o/ C. o6 p& G
# 返回测试的正确率6 }7 b: ^8 y' T; _# a% q
# predict_result: 预测标签列表, target_result: 实际标签列表 7 E8 [. ?. T6 l& E/ Vdef accuracy_rate(predict_result, target_result):' z. V$ [* @( ~
# print("Predict Result: ", predict_result) 5 r, E' b3 V. A # print("Target Result: ", target_result) 2 p& I1 u- Q) B+ l accuracy_score = 0 + Y* o" [2 T5 L3 {, x: M for i in range(len(predict_result)): j7 D' D- S. F9 k1 p$ l1 a" M if predict_result == target_result:. E6 i. B9 T8 t* v* P, J% e' B
accuracy_score += 1 $ u/ R9 H; V7 M2 y) J return accuracy_score / len(predict_result) 4 }1 ~' r( L* m1 J: c2 `( R) R % q p! I8 A! N" P1 H# 决策树的节点结构0 P' t: V! q3 K- R5 Z
class dt_node: . _% `' |6 u- L# V/ t* s , ?& _( _% x# W3 m# b' @0 q def __init__(self, content, is_leaf=False, parent=None): 5 j' A$ o' o8 l6 l3 h global nonce " O2 V7 b& c+ `" G/ m8 E self.id = nonce # 为节点赋予一个全局ID, 目的是方便画图 c0 j2 X1 y7 B) b! O X nonce += 1 " p( R! G' Y/ T. L self.feature_name = None1 t7 ^5 `; A/ j$ q
self.target_value = None; i6 R$ q* [. P/ I4 A! j
self.vote_most = None # 记录当前节点最可能的标签' c! f# z: t. v7 G* v* J. X, E1 k
if not is_leaf: 4 a7 X; h5 T2 {4 A! W self.feature_name = content # 非叶子节点的属性名 # Q: G* B8 g1 h3 g/ D/ U) |" @ else: , z; t- m- U; f" u self.target_value = content # 叶子节点的标签. H9 G" o7 e. O( p* q' ]5 T
( r) b2 D& U0 ]+ k# F
self.parent = parent$ _0 L1 p6 t- \" ~' x4 p
self.child = {} # 以当前节点的属性对应的属性值作为键值 % m& Z9 G3 l+ u7 q7 ]7 Q% s' k X1 P; d3 h, i/ ^3 C
# 决策树模型 % g6 l, r2 l* f) nclass dt_tree:0 B8 `& Z/ e0 W5 d, x, u
: c2 t+ |6 J5 O0 T i5 U- V( x6 |- w
def __init__(self): 1 R- K4 L; ]6 @5 ]# {; X self.tree = None # 决策树的根节点 : K, G8 O5 }$ _% o9 [ self.map_str = """& Y4 }; c" ^9 ]' q
digraph demo{( S7 k2 a. V) {2 t; l
node [shape=box, style="rounded", color="black", fontname="Microsoft YaHei"];! O) q5 V; G) D f1 y
edge [fontname="Microsoft YaHei"]; 3 ^" _* w6 {5 | """ # 用于作图: pydotplus 格式的树图生成代码结构" `& c& v7 {: t
self.color_dir = {} # 用于作图: 叶子节点可选颜色, 以标签值为键值/ h4 \, L5 G0 S6 z" u% Z
+ A' M; v T7 A" T; {/ Z2 `
# 训练模型, train_set: 训练集 - b; P# k# ?1 [; q' B/ ~ def fit(self, train_set): ! k5 h: u3 \6 A' [* |" ]/ t. K : {/ f1 t0 m D, x3 Q7 K if len(train_set.target) <= 0: # 如果测试集数据为空, 则返回空节点, 结束递归6 Q3 b7 O* {" u7 T% z
return None 4 Y; J' }, e6 p' U. b- ], S* e, _/ H1 r% V9 x
target_all_same = True # @3 r& ]! ?% W4 t5 a" n" b for i in train_set.target:5 H. L# e4 A V- q( E( F% m& w
if i != train_set.target[0]:' S7 a! _! [% Z# X! v
target_all_same = False 2 H4 _4 A% y' s8 \ break & K' h! @' @! x , F0 N2 N8 G/ J* x& p, d2 e if target_all_same: # 如果测试集数据中所有数据的标签相同, 则构造叶子节点, 结束递归- q$ {, w m1 ~' q! {3 k4 z; q
node = dt_node(train_set.target[0], is_leaf=True)3 M/ a" j: n4 p' q, P. b
if self.tree == None: # 如果根节点为空,则让该节点成为根节点 + v& p) t) G K/ i self.tree = node ; y; E& [ q, m) K$ @ 5 z! }7 T& M2 H+ `: o" R( j # 用于作图, 更新 map_str 内容, 为树图增加一个内容为标签值的叶子节点; [% J2 _; `% i
node_content = "标签:" + str(node.target_value)' Z# y( I2 @7 Y: r! e
self.map_str += "id" + str(node.id) + "[label=\"" + node_content + "\", fillcolor=\"" + self.color_dir[node.target_value] + "\", style=filled]\n" * N+ n) f2 x: A5 l, F$ P! ? 0 B; Z+ X8 s8 P9 v% {. a return node ; D, t2 q" O0 U elif len(train_set.feature_names) == 0: # 如果测试集待考虑属性为空, 则构造叶子节点, 结束递归2 F; U, p/ t! r
node = dt_node(vote_most(train_set), is_leaf=True) # 这里让叶子结点的标签为概率上最可能的标签 ( [* T5 X- z. M0 s7 @; ], h" k if self.tree == None: # 如果根节点为空,则让该节点成为根节点 & J E, z) {8 q self.color_dir[vote_most(train_set)] = color_set[0]9 a# _/ [2 s1 n2 ~- c ]/ i
self.tree = node5 i. v7 Y1 o/ R4 q
' T; H6 y( `- y' Y # 用于作图, 更新 map_str 内容, 为树图增加一个内容为标签值的叶子节点$ [/ _. n8 Q* y; e3 F, @
node_content = "标签:" + str(node.target_value)1 e% u% M/ P3 i! w1 c$ M' {
self.map_str += "id" + str(node.id) + "[label=\"" + node_content + "\", fillcolor=\"" + self.color_dir[node.target_value] + "\", style=filled]\n"+ n# g; G6 g& z; l3 c5 y
4 D/ [( k# v3 H8 J
return node / h& C* {* \5 `, P6 ]3 _- V% h8 k else: # 普通情况, 构建一个内容为属性的非叶子节点 ! |. o o' y! u/ l( @5 z, R best_feature = best_spilt(train_set) # 寻找最优划分属性, 作为该结点的值4 |. d/ `8 B! ]6 \; n
best_feature_index = -1 ) d+ o2 b4 |; T# j5 c for i in range(len(train_set.feature_names)):2 ?0 | m. n8 T; N7 N
if train_set.feature_names == best_feature:; b2 ^) ~8 b2 N( l2 |. s7 N) @
best_feature_index = i3 Q2 s/ Z' D8 ]$ K. k& Z
break 4 L1 C8 _! Q0 x: U @+ _" x , T3 w [3 Y, J/ I7 z+ A: ^9 c node = dt_node(best_feature)& m- `* @) j) ^* K* ]
node.vote_most = vote_most(train_set)3 U; h/ M3 z+ N# _- R6 H: W! I
if self.tree == None: # 如果根节点为空,则让该节点成为根节点 : e. I; K, G2 p3 J self.tree = node : R2 l' H$ l& e4 M # 用于作图, 初始化叶子节点可选颜色 3 D( B4 H8 Z1 i3 X. T+ G for i in range(len(train_set.target)):) z: }7 d! S- v" v% n' f1 d
if train_set.target not in self.color_dir: ( X3 v5 P% N; z |& [ h global color_i P# o! K, v, I3 W" I self.color_dir[train_set.target] = color_set[color_i] 4 N) H. L3 A; m6 e4 @6 A5 I color_i += 1 * I& _% J5 M4 Z- N* I color_i %= len(color_set)$ z8 E0 Y: m) [7 I
: g) W9 z. W! y4 }- N9 u' D
feature_range = [] # 获取该属性出现在数据集中的可选属性值 & M5 u0 v8 z1 h3 _) [/ {0 h- [ for t in train_set.data: 8 D/ L7 q$ ?) q- ^4 l! `$ V if t[best_feature_index] not in feature_range:1 J/ }% X- j$ Q' _# `2 [: l5 D
feature_range.append(t[best_feature_index])4 t4 H: { Y) d; [/ k' E
! \" n8 T+ K2 }" p
# 用于做图, 创建一个内容为属性的非叶子节点 ) W# X% r5 w0 V' A. N$ G node_content = "属性:" + node.feature_name( @/ c+ j) W- ~3 Q
self.map_str += "id" + str(node.id) + "[label=\"" + node_content + "\", fillcolor=\"#AADDFF\", style=filled]\n" # R9 [* G- r8 y2 D$ `9 f " H" ~ n, I6 ` for feature_value in feature_range: 1 O, O" d' V9 a subset = get_subset(train_set, best_feature, feature_value) # 获取每一个子集) ^: B, a+ m2 ~5 u; R; m
node.child[feature_value] = self.fit(subset) # 递归调用 fit 函数生成子节点# K0 X# U% A X0 H
if node.child[feature_value] == None:) K# O4 V1 k8 ]+ B; l& h, x! s
# 如果创建的子节点为空, 则创建一个叶子节点作为其子节点, 其中标签值为概率上最可能的标签1 h% J. T. o" m9 y6 N
node.child[feature_value] = dt_node(vote_most(train_set), is_leaf=True)4 N f& I! `+ [9 a
node.child[feature_value].parent = node( l; B6 A( L0 b0 s
: |" I' N2 m, u$ `3 H7 \
# 用于做图, 创建当前节点到所有子节点的连线 1 F+ ?# w9 q! k5 _' V self.map_str += "id" + str(node.id) + " -> " + "id" + str(node.child[feature_value].id) + "[label=\"" + str(feature_value) + "\"]\n"" b! g; F2 ? E' |8 j
7 y" o4 s! o& T
# print("Rest Festure: ", train_set.feature_names)$ \; |- X; n Y1 w
# print("Best Feature: ", best_feature_index, best_feature, "Feature Range: ", feature_range) a9 w( V! ^4 ?5 L4 {4 P # for feature_value in feature_range:1 l* O0 C2 Z0 R) v$ W
# print("Child[", feature_value, "]: ", node.child[feature_value].feature_name, node.child[feature_value].target_value)$ l# M4 p* a ?' J$ L: S* y
return node ; V3 U- v/ g9 s% c, k+ L& V/ [( g+ q
# 测试模型, 对测试集 test_set 进行预测 ( s2 f! I8 F, z- A1 s def predict(self, test_set):; ~$ E9 h6 s* E, m. V8 e* x
test_result = [] ( S: w2 g2 o# z* }) \ for test in test_set.data: # G" X# b& f5 D+ \& i1 N, X node = self.tree # 从根节点一只往下找, 知道到达叶子节点 9 L) }: P D2 m+ h4 G8 Q! o' T while node.target_value == None:9 d5 q1 ?& H7 W3 t5 ^
feature_name_index = -14 v5 U& y, u% ~
for i in range(len(test_set.feature_names)): 7 W! \- U9 \8 \5 e! r) o if test_set.feature_names == node.feature_name:! O) z* D1 ~8 h
feature_name_index = i* m8 _9 s b3 S0 O: o3 m- {
break3 d8 {5 z9 v" _4 i8 A4 r
if test[feature_name_index] not in node.child.keys():% i( v0 Q b- U8 m
break9 i% Q$ o- c7 Y3 n$ l
else: O7 m, x) A( t: H9 h
node = node.child[test[feature_name_index]] " y) {& J' g% V; Q' n % F3 }9 R' D4 { W/ O% H. w if node.target_value == None: & r. x" }. f- F/ k e( _8 I' a test_result.append(node.vote_most)' C' J9 m" Y# I$ B* U
else: # 如果没有到达叶子节点, 则取最后到达节点概率上最可能的标签为目标值$ P9 ^3 k- Z+ P7 h5 s/ D! X
test_result.append(node.target_value): t+ k6 u( v6 A5 z8 }
$ ]/ S% ^8 i* R. l, _( r return test_result 6 i0 W: h8 i: t9 r3 e & B* q6 }/ K5 o: v$ u: }0 B" N # 输出树, 生成图片, path: 图片的位置 : a6 @4 \# r8 T: t" I def show_tree(self, path="demo.png"): 8 V" `4 b1 E. ~- `! G2 m map = self.map_str + "}" , O' ^2 W2 E# J* z# q* ~7 M9 ` print(map) ) q7 g2 M: u6 v, { c/ Y graph = pdp.graph_from_dot_data(map). X9 \0 n: {8 |; `+ F9 C$ ~
graph.write_png(path) % s3 m/ j6 }5 p$ m1 \ $ h3 N% ?9 {6 B. t8 N3 R" w& N# 学习曲线评估算法精度 dataset: 数据练集, label: 纵轴的标签, interval: 测试规模递增的间隔 5 E3 ]) o, n" ^ o& G& \: H! I0 C. @def incremental_train_scale_test(dataset, label, interval=1): 9 B: N* Y b+ @3 ?. G+ m3 \$ M$ m2 n; i. C c = dataset ; ]4 y( B0 |1 E2 k: _ r = range(5, len(c.data) - 1, interval) 9 l, G5 R7 c. @6 n* G$ g# o& ~4 }2 @ rates = [] 4 d0 ^' z! T5 U4 ^6 Z( d# i, f( \( v/ ? for train_num in r: . Y' @) x7 _6 S/ A$ l print(train_num) + }8 K$ e4 k' p train_set = new_dataset(c.feature_names, c.target_names, c.data[:train_num], c.target[:train_num]) q: i2 [( N! J9 |1 S9 P) _6 h
test_set = new_dataset(c.feature_names, c.target_names, c.data[train_num:], c.target[train_num:]) " ?2 d5 L; p9 G4 u) A5 i! Z/ K5 q( L. } dt = dt_tree() # b1 E# o6 o" S' ^ dt.fit(train_set)" g/ j. V$ a% l [1 q$ Y
rates.append(accuracy_rate(dt.predict(test_set), list(test_set.target))) - v2 x. u- O: N8 k ^, [7 S4 U: m( P) Z7 U
print(rates) - P5 o4 i5 P/ U1 ^% D plt.plot(r, rates) " K: J8 ]$ Y- v! a$ N' U/ f; Q/ h" d0 s plt.ylabel(label)6 Z5 f" y8 t g ^7 T
plt.show() 5 v3 \# z; F1 j) L" @4 {4 a0 F9 r. K: R `4 G3 p
if __name__ == '__main__':; e' l3 V7 w+ m
% K" Y: _9 L( g4 }1 b9 t j c = load_car() # 载入汽车数据集 ' D# U/ w4 G' h( F& j6 a # c = load_mushroom() # 载入蘑菇数据集 2 s# I T- `" V, ~# \ train_num = 1000 # 训练集规模(剩下的数据就放到测试集) " Q! ^7 P" _& O, x$ ^ train_set = new_dataset(c.feature_names, c.target_names, c.data[:train_num], c.target[:train_num])* k9 D; n; C' }9 B+ k ]; P
test_set = new_dataset(c.feature_names, c.target_names, c.data[train_num:], c.target[train_num:]) 3 A3 x1 i8 }5 A' V& i i2 z- | B' C# O6 u4 X/ f1 B( Y
dt = dt_tree() # 初始化决策树模型1 i( Q7 p: e! T+ v! ]
dt.fit(train_set) # 训练, s* k# Q9 p. g5 f. S
dt.show_tree("../image/demo.png") # 输出决策树图片 + n; \) X8 C: ^: ^! R print(accuracy_rate(dt.predict(test_set), list(test_set.target))) # 进行测试, 并计算准确率吧! |4 B1 Q# K; V5 G% ?, f5 V& S) t
' t. A6 \$ G! h8 s& J
# incremental_train_scale_test(load_car(), "car")7 x/ w& k# v1 ^0 B" y
# incremental_train_scale_test(load_mushroom(), "mushroom", interval=20)" r6 p: [& ^0 d! B$ c' x8 u
" L+ }* N B+ L S1 i5 N$ [6 R) z
* w9 Y' K" V( c5 M+ ?* L/ A+ T
1 , V0 E, A, E) m9 R2 3 K% z4 }9 q$ [; U' Q" I" ?, u" g3 B4 s% R6 H* P& r: k: Z& i4 ! ^: I s# l3 \6 b( D; c: F5! n/ |* \+ o9 [" R! v/ e
6 0 z0 \$ v8 R3 m6 g: z& E |# s- `7+ c# l0 R3 m/ O) L1 D" l+ d, t5 X4 |
86 C U" A; T0 C# a( A; ~* v3 c
9 E% N5 E! F0 m( y. C+ P
10 7 |6 H2 ^" N/ X" n5 X/ h# E; B11( y8 T; L, e3 q( o: M
12 2 t( W: ^3 m: r+ `13 6 h& M$ E# j+ @% K+ b14 [/ G: U p$ e/ x' i7 ~, n# ~2 }
15& [; S! u! J: l4 F7 `' S0 \7 f9 C3 U
16# u+ V6 E: \' t" k+ [, k' K
17/ z2 G" B# s N/ n: l( [
18) c5 ]8 R8 l' _. S* k( [5 r
19% f4 I5 g) M) ^. b) m% i
20+ B- `# T8 o% D
212 w( ^5 m9 z. A# s
22 ' [# Z2 v& u. B" O* O! w7 o23) D% w3 k* d' D0 z4 p' O7 H/ a% n- J
24 & q7 m/ `; z, |) W25 |. {3 g! Q0 |4 o9 J26 - F; n6 N5 g0 O. [( d5 g- H8 @' ^274 u- s I! T/ c9 x
28 ( E8 t. u2 J' t& G, s$ m29 : n0 o6 z' O+ ^" ]1 _3 v5 _30! _2 M# ]. i1 M- y8 w$ S# h
31$ A3 ~4 l8 h0 m8 p7 q
32' p- D3 L8 S' S5 M* ~' M
33 , P% T& U- z# f0 W& R8 z34 - K$ E8 b) u2 Q3 q/ I1 k$ _35* l; K7 } R- e
36% J0 w0 f% @ B1 A' b4 a3 [) n9 V8 e
37: }. K( S1 d( ^% j9 M* O
38 5 o/ q0 M- w% y+ G390 `+ R+ s& U" ]1 [9 \/ l
40 ) @+ z2 ~7 j5 L7 p5 H( V+ \41 , b: Z, |: u, F7 F% G7 p42% g' m# F" @2 s! `
43 , A9 m% w) M3 Y- ~8 e$ `# i2 q! a* m44 ' z" u$ E0 [3 J* Z& i45 ) P& u# M. ?) T/ h46 D: d3 I/ ^, t7 E, t$ _47 2 f9 D# i8 ?; \1 H) R+ G5 K48 1 h3 J! o1 w9 c! @' `49; b4 y' p% h3 b7 K( {: ~6 b6 S, R
50+ V! \6 e3 |; m
51 ( c. j; P7 i" W/ I$ M/ o9 H52 ; z4 U( u0 t- j- _8 @" `( p1 X53 4 b0 K, O/ Q5 O3 {0 W54* y8 G$ U/ ?+ ]( F
55 . r( n7 H- f" y+ I7 w( J+ ?, Z0 C56+ W% Q$ J1 l: j6 Q( b
57% P1 @# f$ p/ S- f) u6 i
580 i& @) @+ k! {- T8 F/ x
590 f% Q) O, R; x( O7 }& O2 o
60% O- ~9 A! |. H2 I2 o5 a, f
61 , l' x4 x( [5 b* H6 K+ P62 ' N4 P9 o0 Z. }# V; P) B) R" {63. G7 U9 M# z6 e' j( y
64) t9 M% j% `* }# r" p
65- j+ D- E! ~" K( L% @
66 " V; |. \; ~8 o67* B/ F- x& d0 _, }5 L! l( Q- R
682 |7 r! g5 g0 E: v, o& Y
69 + j' t! u* Q! b6 |, I- ~70/ E! E6 [7 X! v& Z Z5 L, X) X0 }
71 * u6 U8 W0 X0 T. {( D72; G4 w0 z4 x% N/ H
732 X& @9 p$ A$ D3 u4 e5 y
74 7 w1 F0 {: n& d* p8 T75" X% D( U) S4 X. b- F: B9 s: k
76 9 N3 I: Z+ p4 @! J( H77 9 T8 M+ }- c0 U- ^* b78 : f: C( v ^7 J6 X/ c79! ^: _! b$ K+ w4 i' k
80$ b H \5 [6 s3 ~1 |
81 $ ?2 g# }* L) h% i* G82 3 L7 b4 N# \# y; E4 ~/ \ t831 `. e0 ?" T A! {9 v
84 9 q. h" v. F7 V+ ?85 & Z! S2 N& R% m86 0 }5 l+ i' x3 V0 L3 _; K. a87 ; u6 P1 n: n! K" B+ u; p88% y D1 y. }9 m
89: W. P# c J; [4 l
90 * K6 b4 _- }$ M# ?* \9 \91 ! D& L3 ]4 L$ O% I; ~92. L) j- e, d: G
93 ( Z1 W2 T5 q8 a( [' c94 5 W8 A& w8 s; I+ Z95 5 h, [+ k# m; q- j& ~0 d) `4 |. t96 / Z+ ~5 u4 X) d& X' {; G4 J97# v. K4 t4 ?4 V$ ^2 t0 }6 Z
989 \6 k/ z/ U; Q& r: t6 h0 O
99$ o! Q- o- o8 Z' d
100 3 c3 }+ t. @. o' [1 S/ F# C; E' F' C101/ \+ v7 ^# Y" T
102" r% e+ u/ ]0 a4 T
103 9 H6 I3 @; J! p: C* B9 {104, y1 ~. r i; o" t8 d% Q) F
105/ T% E1 [! U5 B1 A! g2 j, k
106 / M5 S" z6 N$ F9 y Z9 P107- @3 R& B ^4 k9 _8 w' Q
108) d8 E5 V6 [! X9 ?+ q4 {. a# P
109 1 a# R$ X" `2 ^) Q110/ L: ]6 _5 @; \
111 & d n% H2 `4 s112 , q8 T/ u( ^+ t/ j( k113. d p; N0 K" p- {& E& z
114 - p& w2 c4 ?% F7 j115 2 p& @* e* _$ v- X' G9 H& [4 W116 % A) `# Z" P6 X4 p117 : y% u W& h' j2 d# G1184 n( h/ ]9 t2 m4 r
119 : F9 P. E& c: d3 M0 w1 u" n7 S120 $ j- @2 [7 m+ |; @5 k1213 @/ E1 z8 R h- J. B1 A0 g
122 $ C; @) Q" J+ X5 b- B123 2 d. ]) I- B# D( X! X* ^1247 X- k: ~9 a9 J+ X1 F7 \
125 + B- n/ s$ f1 E7 N3 y; V- H126 1 Q2 a# x; ^6 d2 n) W3 E8 d/ m127 4 a7 |0 g) D8 a. e128( p- H5 ]3 I; A" P! V2 f
129 6 R: y, s' L3 V/ \& T130" ~2 j; e. N J: ~- }
1319 l; O3 C4 b6 J6 N2 f+ y4 h
132 ) k$ j) ?) T1 l( y/ g2 D133 & L( n5 d& }6 K8 w5 h9 N134 4 ~! X7 p3 J$ P135 & |4 U' J. b7 z) p R136/ O* ?- Z/ K- E# K$ v5 a) Z0 N( g( n
137 " C9 \/ |6 j6 J) ^- Z, A( H138% x+ C9 g& ?1 s! a3 y7 ?3 c, c' v
139 1 v5 C" z5 `1 z5 @1 t5 {7 @140" ~1 r* c2 U* O9 _% k% ]
141 3 t' p) A# h, e142, e, {+ l( ]) R$ F5 B7 ?; s0 C
1431 F& L( G, a2 a! X0 K; H
144 * H3 y6 H$ f- H( e5 E9 K9 d& d& t$ R145: ~% Q2 T. I# F" c3 A d
146 C! H3 U( _2 i1 b, r
147# W: Z0 h& ?+ i1 @
148 ' z3 T( z* R* M" L8 }+ J# {; O+ h149 + V1 A% \7 e9 {/ G7 ~8 Q# t150 a$ F% a& {! x h' m7 D( U151: i5 J6 i$ P( q2 J E9 I, J
152- B. w! H! {; G' F# F$ R- N1 \
153 5 G1 z. ^' @8 o* n4 Z# k, n$ B154 ' H/ J8 C: N# R0 z155/ l1 D# O8 w2 `. |4 C6 b5 H( i
156 ; k7 X! Z1 k9 J0 @" e157 1 E {' w. w, M: @( A6 ?- C' ]; Q% I158, R/ r9 M0 }9 k% r- R
159( I1 K$ W X p4 j
160% o$ m, Z& s& E
1613 r2 o* I; e3 x g
1627 ?4 V5 F7 l* Q' P2 |8 }6 W
163 * j5 N: l# G: e- s) j3 f164 7 Q$ K) N; S0 E165 ; d z9 R" I i. H7 }166 ) a) ~9 U# ?- ?+ _, O$ K" {* |. U2 ?1677 P; u+ v+ z5 |$ T; O
168) _7 Z% g5 \0 h" w" T$ l" c: z. z3 ]
169 + ^: E! ^* [3 n V1700 N! @! d- K1 P7 }: ?
171. b$ b1 G8 H: | n3 C
172" V" }- \ e \4 m4 T. @
173 ' b5 l7 j3 V7 S2 j; W2 E174 8 D' ^: p T: r. z175 ; @! V( n) N/ V1766 j6 |, w; u9 m4 _- A) \
177/ Z4 M, J0 q( P U- B
178 | s! g; _& h$ M# x7 i179 # k y! R( {9 n6 M0 O180 5 G/ B& c0 J2 @5 X5 o$ [) o181. k0 |2 |9 k C8 P3 ? c
182( h$ b, _4 ?1 b5 q& U! ]1 r
183 4 z/ [, H# V* e, N$ @5 l1840 {7 R" D1 e5 p$ K8 A
1851 e& [( k2 w7 Y. g/ G
186" f/ q" z: ?3 ]+ N
187! w1 [, S2 V1 H" D
188 ^( G' K- j3 R, A% \+ o3 n) ?
1891 q: h+ y2 e( j( n
190 & o" Q" M! \/ O7 O191' k( t5 V" b5 x
192 0 F j2 k4 ]# }/ W0 H b w* _193* n2 b$ f" e) w! r
194% n+ v- x+ m. [7 w
195# `- U' S' i- O2 z8 q. G
196- z: u) s6 D" T Y1 W% Y
197+ P$ \& @; @1 X4 t9 O7 |6 z0 f
198 + u( e5 ^, ^/ E/ B199 D9 Y2 J4 D7 G2 T, q- |: v
200- E' @! ^) ` V2 ^8 f" ^$ U
201 1 d4 G0 l) Q+ h202- g0 \; ~, P, I! Z
203 8 m a2 O7 Z- h E! K B" K) `2045 j' Z1 [' [) u, z. W( W( ~! {
205 4 H& U1 [# r9 p206 % W H/ C' T( i- q1 @- T8 {1 Y207 / r O2 @0 Y8 `# S5 Z208 " J1 j0 [. ?1 A% p) C; [6 k! N209! o7 c2 h R7 S+ {( k$ T9 e9 C3 G
210 1 h; F: l- G u+ l2118 X. y0 k5 p4 F' M& `; O
212 3 c% I& N8 \) D; ]3 L- ~$ ~213 ! D- a6 m' G% @: Y( P214 # ?' z" e1 e0 Q( q, g2 W215 & q1 v$ s' T' n216 ; ~( l7 u2 N$ w4 S+ }217 R2 v: ?2 b( a; ^218 # u1 E' v& H3 a6 t% Z0 U! z9 c2198 e5 l% E3 |) a
220 ; |6 E* x8 p$ T* q2214 F) i2 U9 i. X% A
222 6 N9 | ]# t: A0 \6 J( ?223& ?2 E6 G+ U6 N7 f& k% M+ x& N6 M& t
224/ j, L: [4 X1 r
225. t, E5 A( B, q" X7 _
226( F2 K/ ~" h6 g4 ] J
227 ) K0 C; }: }/ z0 ~2 j228* G! c/ Y, O/ O1 t
2291 D9 T. n1 t6 ]. E7 s4 {* J
2309 G! K5 I( |: t( w9 |2 ^
231' O+ J( W( J" G2 ]( H1 }& q
2325 H9 d+ x0 W% ~$ p
233% F7 A8 j+ f* m, \. ?
234 ' d+ Y4 M) d5 U% w9 q" t6 X Z7 U- M235( v9 f6 P5 Z6 C0 m) A! a
236+ \+ f! E1 K6 L: e) h
237& m# b" F& w; z- R2 Z
238: V2 X& V/ h7 p
239$ k$ ]5 t1 O) f6 L
240% D4 i$ R7 [ o' O1 i f
2415 c. Q5 |) p5 Z a/ D1 N
242 0 C+ o; k) u3 A: v4 \. }2433 J: I6 ^0 R9 g, V
244/ D% f+ R( @- X& h+ B! q/ b/ I
245 ) s" ~$ @6 P r$ z# r246 z8 ^" K3 J' d( ]; s/ ~/ i247 ' n" c7 K0 `! h' z6 X248& A" {& j* ?9 W
249 3 d4 R. L, m- S( Z! c; ?250 7 o! q" F0 K- \3 {/ F' r7 ?251* A% w$ e7 L) C
252 8 ?5 B5 g% h! D- t9 Q; R253# s0 P2 a3 A' B3 T# o6 Y5 \4 a4 B
254 + w# L( ]9 H1 A% `+ _$ `7 V$ p255. H% t% r$ v! C7 ?
256# R, J2 V: E/ V) @6 S
257 $ t' W; ~+ e& B+ X- g3 ?: q% {258& n' D- T6 j2 P7 }
259 - g/ o. b; d- u+ i! U3 T260 5 v) F: f4 T' {: B& n" Z261 - T3 o/ o( i( y9 p, |6 s6 Q$ n7 d262- t4 M: Z7 u! D, s
263 # d( S# t9 Q) {/ ]; N/ c0 z0 q264' b" v4 `& C! a. R0 L4 p
265* }: K7 P Y; b: n& ~! x
266& b( q' n/ N: X3 M0 G
267 6 i- |9 i6 a' { A; r" { w9 [268 & o) Z3 c) V* v* H0 h) B7 w- ^269 " p% R+ ?: [( j/ s& d% a5 b270$ F; t0 U2 U" ` i; ]
2713 o' F& l+ u# O
272% d/ t+ L) s" g2 z1 v3 W# Z/ v4 J
273- W% I' V/ f( r5 Q
274 0 L& z9 e, l' d* E: ^275 , j/ q, C8 B& y& a276 , i9 N \, B( \9 l0 \) y% E277 " h4 @& W# D( g- D278 . e; F1 k7 }3 n# N279 e& ^0 A. ~! c7 M5 g
280 ( ~. s, G7 Y# ?0 J, m. e7 S281 6 X$ \0 \8 [+ @; q: z282, A0 Y) [ B" ]& u) U
283 * X% o! p3 C6 z# a' u% v284 2 {- |2 Q) f2 D1 S6 u) L& n285 4 i" g& I, Q# G g' @3 z$ x* L286# K4 u% R/ c/ R8 X o; J+ C) h
287 N1 v- @# u! p# `) G5 z! N) d
288! y' E7 R0 P4 B* b% K
289: K5 Q* i* f& F3 B
290 % Q/ P# n* [0 K/ k3 d0 d7 T8 F291- t9 t- `4 `" \
292, k, S) \+ G- i- S7 T' m* o6 _% D
293; V! G) \& {$ V# ]; X3 E6 g
294 ; J3 s% Z0 V1 K% c O E! d% j: e295 9 o& I+ H5 W( @# u" `( B. F$ e296$ ~6 T! L- J' ^
297 ' z8 R7 B1 u# ^; m298 6 l! L8 |9 f. U$ _& d299 8 p! m! F# }! Y k- @; K300 6 ^7 S* B. S; ^7 P1 L301 Z+ C# n& Q2 h
302" Y+ T/ W% k6 D, H
3037 d/ j+ ^0 V. y
3048 W& q6 v4 f0 I( y1 U% e
3053 A, ?, O. f7 L' [2 K( i
306 1 n | x# [5 T* ~+ O307 , ]8 ?! E0 g3 x( N C- L308 ! H6 O, e$ ?0 M. f9 @309# u9 L1 Y& o G
310! _3 J# |9 @) W: G5 }( N4 O
311 6 y3 \9 P: |* c- F8 G312$ U, B' D7 q4 ~) P# ~, |
3137 }3 h* v/ o7 L% q* G0 p
314* l' f1 S; K' k7 R
315$ C# u6 ~/ J5 Z- S' _
316 4 o& i6 P! s' @4 p317' x, L+ A, @* J4 k* c' N9 ]
318 , U# Y' z$ }! y ~9 g# J: w$ F319 ) s. r o @3 H7 P4 Z320 X, P8 Q$ j6 w# m
321! |: o- i7 Z& o& s" D9 S! y
322 " M% z0 s* G1 {5 A323/ U1 O& c- h. r+ g: ^+ E
324 ; u, o5 c0 ~" r. X9 d325 ) v' \' Z3 K' \+ |* }326 4 |: A! z) D) S327 9 ?( a* q# m: [1 ^. }5 t3282 f' f4 v" g, S7 V# l
329' W9 n: v, M! N
330; r' F' g2 H# K8 E; c
3319 z1 D* R" A4 n2 R9 v6 b0 j
$ W( R' ^8 ]2 a
" _$ w) z/ J( L0 e; v: F
0 f% V- l. b' R: _& V4 ? ! N( J/ w v2 H0 l / f9 b0 K8 W0 K! }% a. o! l5 O2 X . O9 T+ S9 E1 c& p1 Q% R * }2 F1 O5 Q, P: ~: s+ ` B- s5 T b g
- B5 W7 x, g5 {