决策树

决策树

在决策时,我们通常会考虑某一条件满不满足,判断完之后,再确定下一步的该怎么办。这样就形成了一个树状的决策形式。这就是决策树的主要思想--根据某一特征对数据进行分组直至特征用完或者全是某一类,根据此节点的样本的比例作为先验概率。

选择特征

首先要面临的问题特征的选择顺序,应该先用哪个特征值来分支,随便选肯定可行,但会引起很多问题,比如有多少特征就有多少层递归,整个树随着特征的个数节点数指数增加。对于很多特征(即使有些特征值用处不大)的问题不能处理,剪枝操作也不容易实现。

熵是一种衡量整个系统混乱程度的度量。将其引入信息论,来表示不确定性。

首先如何衡量一段信息的不确定性,就比如对于“我爱你”和“我非常爱你”这两句话如何判断其信息量呢?首先如果是将两端信息发给你的object,对于“我”,“爱”和“你”这三个字基本不增加信息量,只有“非常”两字有信息量。因为对于你的object来说她肯定知道你爱她,她想要的知道的是“爱”的程度。那如果你将这两条说给你的同性朋友,他其实不关心程度,更关心你表达的意义是什么(0.99999 ->0.999999),仅仅三个字就含有极其丰富的信息量,以至于你朋友想确认自己是不是这对话的接受对象了,通过这三个字可以将你是“南通”的概率极具上升(0.01 -> 0.51)。这其实是因为你和你的object的这些话的概率非常大,她习惯了。而后者你基本不会说,而你说出来就表明你的一些特质。

假设信息量用\(l\)表示

\[l := -log_2(p) \]

\(p\)表示信息表示的事发生的概率。

这只是能够自洽的一种定义(是奥卡姆剃刀的选择)。

那信息熵该如何表示,还是看上面的例子,我们现在把你和除了你之外的所有人说“我爱你”看做事件的全集,那这里熵应该表示你的“混乱程度”。如果你之和你的object说过,那么这句话的信息量非常小,最终会得到一个很小的值,证明你很专一。

信息增益划分

为了减少划分的次数,我们肯定是希望在一次划分后的每一个部分进可能的纯(是一个类的),划分过后熵应该尽可能的小。所以我们需要按照每个特征划分求得熵,使用熵最小的特征结划分。划分结束后的每个划分由于变得更“纯”,在每个分类里再按照此特征划分,不再是最小值。

\[\operatorname{Gain}(D, a)=\operatorname{Ent}(D)-\sum_{v=1}^{V} \frac{\left|D^{v}\right|}{|D|} \operatorname{Ent}\left(D^{v}\right) \]

信息增益率

如果对于每个样本都有唯一的标识,那么如果按照标识划分一定能得到最小的熵。但这不是我们要的结果,这样的熵纯粹是由于分类太多导致,所以我们要如果划分的够好,需要去掉因为划分的类别的影响。

\[\text { Gain_ratio }(D, a)=\frac{\operatorname{Gain}(D, a)}{\operatorname{IV}(a)} \ \ \ \text{其中 } \operatorname{IV}(a)=-\sum_{v=1}^{V} \frac{\left|D^{v}\right|}{|D|} \log _{2} \frac{\left|D^{v}\right|}{|D|}\]

基尼系数

基尼系数是另一种作为划分依据的指标,表征着从总集中任意取两个样本不是一个分类里的概率。越小表示分类约纯。

\[\begin{aligned} \operatorname{Gini}(D) &=\sum_{k=1}^{|\mathcal{Y}|} \sum_{k^{\prime} \neq k} p_{k} p_{k^{\prime}} \\ &=1-\sum_{k=1}^{|\mathcal{Y}|} p_{k}^{2} . \end{aligned}\]

import numpy as np
import pandas as pd
import matplotlib as plt

data = pd.read_csv("train.csv")
data = data[['Pclass', 'Age', 'Sex', 'Survived']]
data['Age'] = data['Age'].fillna(data['Age'].mean())
data['Sex'] = (data['Sex'] == 'male').astype('int')
#X = data[['Pclass','Age','Sex']].values #几等仓、年龄、性别
X = data[['Pclass','Sex']].values #几等仓、性别
y = data[['Survived']].values #是否幸存
   
X
array([[3, 1],
       [1, 0],
       [3, 0],
       ...,
       [3, 0],
       [1, 1],
       [3, 1]])
from sklearn import tree
import pydotplus  # 用于可视化
import graphviz
 
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X, y) 
 
dot_data = tree.export_graphviz(clf, out_file=None) 
graph = pydotplus.graph_from_dot_data(dot_data) 
graph = graphviz.Source(dot_data)
graph
Warning: Could not load "/home/ran/.conda/envs/least/lib/graphviz/libgvplugin_pango.so.6" - file not found

image

predict_y = clf.predict([[1, 1]]) 
predict_y
array([0])
predict_y = clf.predict([[2, 0]]) 
predict_y
array([1])
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

n = 100
X = np.random.multivariate_normal((1, 1), [[0.49, 0], [0, 0.49]], size = int(n/2))
X = np.insert(X, 50, np.random.multivariate_normal((3, 3), [[0.49, 0], [0,0.49]], size = int(n/2)),0)
X = np.insert(X, 0, 1, 1)
m = X.shape[1]
y = np.array([1]*50+[-1]*50).reshape(-1,1)
plt.scatter(X[:50, -2], X[:50, -1])
plt.scatter(X[50:, -2], X[50:, -1], c = "#ff4400")

<matplotlib.collections.PathCollection at 0x7fb0571efb20>

image

from sklearn import tree
import pydotplus  # 用于可视化
import graphviz
 
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X, y) 
 
dot_data = tree.export_graphviz(clf, out_file=None) 
graph = pydotplus.graph_from_dot_data(dot_data) 
graph = graphviz.Source(dot_data)
graph
Warning: Could not load "/home/ran/.conda/envs/least/lib/graphviz/libgvplugin_pango.so.6" - file not found

image

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

n = 100
X = np.random.normal(1, 1, size = (1000,1))
y = np.random.normal(1, 1, size = (1000))
y[:] = X.reshape(-1)
plt.scatter(X, y)
<matplotlib.collections.PathCollection at 0x7fb028e48b50>

image

from sklearn import tree
import pydotplus  # 用于可视化
import graphviz
 
clf = tree.DecisionTreeRegressor()
clf = clf.fit(X, y) 
 
dot_data = tree.export_graphviz(clf, out_file=None) 
graph = pydotplus.graph_from_dot_data(dot_data) 
graph = graphviz.Source(dot_data)
graph
Warning: Could not load "/home/ran/.conda/envs/least/lib/graphviz/libgvplugin_pango.so.6" - file not found

⬇此处有图片,太大,需要点开

image

↑点看到了啥,是不是没渲染出来

test_X = np.random.normal(1, 0.01, size = (100,1))
predict_y = clf.predict(test_X)
plt.scatter(test_X, predict_y, c="#ff4400")
predict_y
array([0.99076752, 0.97974621, 1.00561411, 1.00561411, 1.00561411,
       1.00561411, 1.00561411, 0.98089205, 0.98758017, 0.99497934,
       0.98087143, 0.98758017, 0.99497934, 1.02034784, 1.02034784,
       0.99497934, 1.01475612, 1.00561411, 0.98418531, 1.01008883,
       0.99497934, 1.00561411, 0.99497934, 0.98418531, 0.99497934,
       0.99304458, 0.99497934, 0.99497934, 0.98418531, 1.00561411,
       0.99497934, 0.98758017, 1.00561411, 1.00561411, 1.01008883,
       1.00561411, 0.99154679, 1.00561411, 0.99076752, 1.01008883,
       1.00561411, 1.01008883, 0.99076752, 1.00561411, 1.01008883,
       1.01475612, 1.01475612, 1.00561411, 1.00561411, 0.99497934,
       1.01475612, 0.99497934, 0.98758017, 0.99076752, 0.99304458,
       0.99497934, 0.99154679, 1.00561411, 0.99497934, 0.99497934,
       0.99076752, 1.00561411, 1.00561411, 1.00561411, 1.01541973,
       1.00561411, 1.01008883, 0.98758017, 0.99497934, 0.98418531,
       0.99497934, 1.01475612, 1.00561411, 1.00561411, 0.98418531,
       1.00561411, 1.00561411, 0.99497934, 1.00561411, 0.97974621,
       0.99497934, 1.01008883, 1.00561411, 0.99304458, 0.99497934,
       1.00561411, 0.99204886, 0.98758017, 1.00561411, 0.98758017,
       0.98758017, 1.00561411, 0.99497934, 0.99497934, 0.99497934,
       1.00561411, 1.01008883, 0.99497934, 0.99076752, 0.98089205])

image

posted @ 2022-10-27 21:56  孑然520  阅读(84)  评论(0)    收藏  举报