决策树[sklearn.tree/DecisionTreeClassifier/scatter/np.meshgrid/np.concatenate/Kfold/Cross-validation]

决策树

概念举栗子

import numpy as np

引入数据:

s= '''在1948年,香农引入了信息熵,将其定义为离散随机事件出现的概率,一个系统越是有序,信息熵就越低,反之一个系统越是混乱,它的信息熵就越高。所以信息熵可以被认为是系统有序化程度的一个度量。'''
s_l = list(s)
len(s_l)
Out:93

# 打乱顺序
index = np.arange(93)
np.random.shuffle(index)

# 使用乱序作为下标
s_new = np.array(s_l)[index]
np.array(s_l)[index]
Out:
array(['熵', '序', '为', '入', '化', '息', '混', '低', '8', ',', '序', '散', '可',
       '一', '9', '。', '将', '就', '是', '了', '以', '现', '息', '有', '一', '它',
       '有', '越', '的', '义', ',', '出', '个', ',', '信', '统', '在', ',', '离',
       '随', '统', '度', '4', '系', '反', '为', '所', '之', '熵', '是', '概', '息',
       ',', '息', '乱', ',', '度', '熵', '系', '一', '个', '越', '熵', '信', '1',
       '信', '农', '被', '件', '信', '率', '其', '的', '定', '以', '的', '越', '统',
       '认', '是', '引', '程', '年', '越', '量', '个', '高', '就', '。', '事', '系',
       '机', '香'], dtype='

原理

【关键词】树,信息增益

决策树的优缺点

优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。既能用于分类,也能用于回归

缺点:可能会产生过度匹配问题

一、决策树的原理

predict()

【二十个问题的游戏】

游戏的规则很简单:参与游戏的一方在脑海里想某个事物,其他参与者向他提问题,只允许提20个问题,问题的答案也只能用对或错回答。问问题的人通过推断分解,逐步缩小待猜测事物的范围。决策树的工作原理与20个问题类似,用户输人一系列数据 ,然后给出游戏的答案。

我们经常使用决策树处理分类问题。近来的调查表明决策树也是最经常使用的数据挖掘算法。它之所以如此流行,一个很重要的原因就是使用者基本上不用了解机器学习算法,也不用深究它是如何工作的。

如果以前没有接触过决策树,完全不用担心,它的概念非常简单。即使不知道它也可以通过简单的图形了解其工作原理。

决策树分类的思想类似于找对象。现想象一个女孩的母亲要给这个女孩介绍男朋友,于是有了下面的对话:

女儿:多大年纪了?
母亲:26。
女儿:长的帅不帅?
母亲:挺帅的。
女儿:收入高不?
母亲:不算很高,中等情况。
女儿:是公务员不?
母亲:是,在税务局上班呢。
女儿:那好,我去见见。

这个女孩的决策过程就是典型的分类树决策。相当于通过年龄、长相、收入和是否公务员对将男人分为两个类别:见和不见。假设这个女孩对男人的要求是:30岁以下、长相中等以上并且是高收入者或中等以上收入的公务员,那么这个可以用下图表示女孩的决策逻辑:

上图完整表达了这个女孩决定是否见一个约会对象的策略,其中绿色节点表示判断条件,橙色节点表示决策结果,箭头表示在一个判断条件在不同情况下的决策路径,图中红色箭头表示了上面例子中女孩的决策过程。

这幅图基本可以算是一颗决策树,说它“基本可以算”是因为图中的判定条件没有量化,如收入高中低等等,还不能算是严格意义上的决策树,如果将所有条件量化,则就变成真正的决策树了。

有了上面直观的认识,我们可以正式定义决策树了:

决策树(decision tree)是一个树结构(可以是二叉树或非二叉树)。其每个非叶节点表示一个特征属性上的测试,每个分支代表这个特征属性在某个值域上的输出,而每个叶节点存放一个类别。使用决策树进行决策的过程就是从根节点开始,测试待分类项中相应的特征属性,并按照其值选择输出分支,直到到达叶子节点,将叶子节点存放的类别作为决策结果。

可以看到,决策树的决策过程非常直观,容易被人理解。目前决策树已经成功运用于医学、制造产业、天文学、分支生物学以及商业等诸多领域。

之前介绍的K-近邻算法可以完成很多分类任务,但是它最大的缺点就是无法给出数据的内在含义,决策树的主要优势就在于数据形式非常容易理解。

决策树算法能够读取数据集合,构建类似于上面的决策树。决策树很多任务都是为了数据中所蕴含的知识信息,因此决策树可以使用不熟悉的数据集合,并从中提取出一系列规则,机器学习算法最终将使用这些机器从数据集中创造的规则。专家系统中经常使用决策树,而且决策树给出结果往往可以匹敌在当前领域具有几十年工作经验的人类专家。

知道了决策树的定义以及其应用方法,下面介绍决策树的构造算法。

二、决策树的构造

分类解决离散问题,回归解决连续问题

  • 决策树:信息论
  • 逻辑斯底回归、贝叶斯:概率论

不同于逻辑斯蒂回归和贝叶斯算法,决策树的构造过程不依赖领域知识,它使用属性选择度量来选择将元组最好地划分成不同的类的属性。所谓决策树的构造就是进行属性选择度量确定各个特征属性之间的拓扑结构。

构造决策树的关键步骤是分裂属性。所谓分裂属性就是在某个节点处按照某一特征属性的不同划分构造不同的分支,其目标是让各个分裂子集尽可能地“纯”。尽可能“纯”就是尽量让一个分裂子集中待分类项属于同一类别。分裂属性分为三种不同的情况:

  1、属性是离散值且不要求生成二叉决策树。此时用属性的每一个划分作为一个分支。

  2、属性是离散值且要求生成二叉决策树。此时使用属性划分的一个子集进行测试,按照“属于此子集”和“不属于此子集”分成两个分支。

  3、属性是连续值。此时确定一个值作为分裂点split_point,按照>split_point和<=split_point生成两个分支。

构造决策树的关键性内容是进行属性选择度量,属性选择度量是一种选择分裂准则,它决定了拓扑结构及分裂点split_point的选择。

属性选择度量算法有很多,一般使用自顶向下递归分治法,并采用不回溯的贪心策略。这里介绍常用的ID3算法。

ID3算法

划分数据集的大原则是:将无序的数据变得更加有序。

我们可以使用多种方法划分数据集,但是每种方法都有各自的优缺点。组织杂乱无章数据的一种方法就是使用信息论度量信息,信息论是量化处理信息的分支科学。我们可以在划分数据之前使用信息论量化度量信息的内容。

在划分数据集之前之后信息发生的变化称为信息增益,知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。

在可以评测哪种数据划分方式是最好的数据划分之前,我们必须学习如何计算信息增益。集合信息的度量方式称为香农熵或者简称为熵,这个名字来源于信息论之父克劳德•香农。

entropy

熵定义为信息的期望值,在明晰这个概念之前,我们必须知道信息的定义。如果待分类的事务可能划分在多个分类之中,则符号x的信息定义为:

其中p(x)是选择该分类的概率

为了计算熵,我们需要计算所有类别所有可能值包含的信息期望值,通过下面的公式得到:

其中n是分类的数目。

在决策树当中,设D为用类别对训练元组进行的划分,则D的熵(entropy)表示为:

其中pi表示第i个类别在整个训练元组中出现的概率,可以用属于此类别元素的数量除以训练元组元素总数量作为估计。熵的实际意义表示是D中元组的类标号所需要的平均信息量。

现在我们假设将训练元组D按属性A进行划分,则A对D划分的期望信息为:

而信息增益即为两者的差值:

ID3算法就是在每次需要分裂时,计算每个属性的增益率,然后选择增益率最大的属性进行分裂。下面我们继续用SNS社区中不真实账号检测的例子说明如何使用ID3算法构造决策树。为了简单起见,我们假设训练集合包含10个元素:

其中s、m和l分别表示小、中和大。

设L、F和H表示日志密度、好友密度、是否使用真实头像,下面计算各属性的信息增益。

# 账号是否真实的信息熵
# no 0.3
# yes 0.7
info_D = -(0.3*np.log2(0.3) + 0.7*np.log2(0.7))
info_D
Out:0.8812908992306927

因此日志密度的信息增益是0.276。

用同样方法得到F和H的信息增益分别为0.553和0.033。

因为F具有最大的信息增益,所以第一次分裂选择F为分裂属性,分裂后的结果如下图表示:

在上图的基础上,再递归使用这个方法计算子节点的分裂属性,最终就可以得到整个决策树。

练习

计算上图的信息熵,确定下一个分类的特征

  • # 账号是否真实的信息熵
  • # 根据属性对目标值进行分类
  • # 属性:是否使用真实头像、好友密度、日志密度
  • # 三个属性作为决策树的树顶,都可以,谁更好???
  • # 计算机只能信息熵的变化,来决定使用哪个属性作为树顶更好
  • # 分别计算

根据好友密度进行决策树构造:

  • # 0.4 s -----> 3no(0.75) 1yes(0.25)
    # 0.4 m -----> 4yes(1.0)
    # 0.2 l -----> 2yes(1.0)
'''根据好友密度进行决策树构造,
# 0.4 s -----> 3no(0.75) 1yes(0.25)
# 0.4 m -----> 4yes(1.0)
# 0.2 l -----> 2yes(1.0)'''
info_F_D = -0.4*(0.75*np.log2(0.75) + 0.25*np.log2(0.25))  - 0.4*(1.0*np.log2(1)) - 0.2*(np.log2(1))
info_F_D
Out: 0.32451124978365314
'''信息熵变小,根据好友密度进行划分,数据结构变的有顺序了'''

info_D - info_F_D
Out: 0.5567796494470396

根据日志密度进行决策的构造:

  • # 0.3s  ---->2no(2/3) 1yes(1/3)
  • # 0.4m  ---->1no(0.25) 3yes(0.75)
  • # 0.3l  ---->3yes(1.0)
     
# 根据日志密度进行决策的构造
# 0.3s  ---->2no(2/3) 1yes(1/3)
# 0.4m  ---->1no(0.25) 3yes(0.75)
# 0.3l  ---->3yes(1.0)

info_L_D = -0.3*((2/3)*np.log2(2/3) + (1/3)*np.log2(1/3)) - 0.4*(0.25*np.log2(0.25) + 0.75*np.log2(0.75))
info_L_D
Out:0.6

info_D - info_L_D
Out:0.2812908992306927

DecisionTreeClassifier和DecisionTreeRegressor 重要参数调参注意点

 转载:https://blog.csdn.net/akon_wang_hkbu/article/details/77621631 

为了便于比较,这里我们用表格的形式对DecisionTreeClassifier和DecisionTreeRegressor重要参数要点做一个比较。

参数 DecisionTreeClassifier DecisionTreeRegressor

特征选择标准criterion

可以使用"gini"或者"entropy",前者代表基尼系数,后者代表信息增益。一般说使用默认的基尼系数"gini"就可以了,即CART算法。除非你更喜欢类似ID3, C4.5的最优特征选择方法。 

 可以使用"mse"或者"mae",前者是均方差,后者是和均值之差的绝对值之和。推荐使用默认的"mse"。一般来说"mse"比"mae"更加精确。除非你想比较二个参数的效果的不同之处。

特征划分点选择标准splitter

可以使用"best"或者"random"。前者在特征的所有划分点中找出最优的划分点。后者是随机的在部分划分点中找局部最优的划分点。

默认的"best"适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐"random" 

划分时考虑的最大特征数max_features

可以使用很多种类型的值,默认是"None",意味着划分时考虑所有的特征数;如果是"log2"意味着划分时最多考虑$log_2N$个特征;如果是"sqrt"或者"auto"意味着划分时最多考虑$\sqrt{N}$个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。

一般来说,如果样本特征数不多,比如小于50,我们用默认的"None"就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。

决策树最大深max_depth

 决策树的最大深度,默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。

内部节点再划分所需最小样本数min_samples_split

这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。我之前的一个项目例子,有大概10万样本,建立决策树时,我选择了min_samples_split=10。可以作为参考。

叶子节点最少样本数min_samples_leaf

 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。之前的10万样本项目使用min_samples_leaf的值为5,仅供参考。

叶子节点最小的样本权重和min_weight_fraction_leaf

这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。

最大叶子节点数max_leaf_nodes

 通过限制最大叶子节点数,可以防止过拟合,默认是"None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。

类别权重class_weight

指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。这里可以自己指定各个样本的权重,或者用“balanced”,如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的"None"  不适用于回归树

节点划分最小不纯度min_impurity_split

 这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值,则该节点不再生成子节点。即为叶子节点 。

数据是否预排序presort

这个值是布尔值,默认是False不排序。一般来说,如果样本量少或者限制了一个深度很小的决策树,设置为true可以让划分点选择更加快,决策树建立的更加快。如果样本量太大的话,反而没有什么好处。问题是样本量少的时候,我速度本来就不慢。所以这个值一般懒得理它就可以了。

除了这些参数要注意以外,其他在调参时的注意点有:

  • 1)当样本少数量但是样本特征非常多的时候,决策树很容易过拟合,一般来说,样本数比特征数多一些会比较容易建立健壮的模型
  • 2)如果样本数量少但是样本特征非常多,在拟合决策树模型前,推荐先做维度规约,比如主成分分析(PCA),特征选择(Losso)或者独立成分分析(ICA)。这样特征的维度会大大减小。再来拟合决策树模型效果会好。
  • 3)推荐多用决策树的可视化(下节会讲),同时先限制决策树的深度(比如最多3层),这样可以先观察下生成的决策树里数据的初步拟合情况,然后再决定是否要增加深度。
  • 4)在训练模型先,注意观察样本的类别情况(主要指分类树),如果类别分布非常不均匀,就要考虑用class_weight来限制模型过于偏向样本多的类别。
  • 5)决策树的数组使用的是numpy的float32类型,如果训练数据不是这样的格式,算法会先做copy再运行。
  • 6)如果输入的样本矩阵是稀疏的,推荐在拟合前调用csc_matrix稀疏化,在预测前调用csr_matrix稀疏化。

三、实战

【注意】 参数max_depth越大,越容易过拟合

1、使用自带的iris数据集

导包:

# 决策树
'''
 DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None, 
 min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None,
 random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, 
 min_impurity_split=None, class_weight=None, presort=False)
'''
from sklearn.tree import DecisionTreeClassifier

import sklearn.datasets as datasets

from sklearn.model_selection import train_test_split

数据集:

iris = datasets.load_iris()

X = iris['data']
y = iris['target']

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.3)
X.shape
OUt:(150,4)

使用决策树算法:

max_depth=5

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.3)
tree = DecisionTreeClassifier(max_depth=5)

tree.fit(X_train,y_train)

tree.score(X_test,y_test)
Out: 0.8888888888888888

max_depth=3

tree = DecisionTreeClassifier(max_depth=3)

tree.fit(X_train,y_train)

tree.score(X_test,y_test)
Out: 0.9555555555555556

max_depth=1

tree = DecisionTreeClassifier(max_depth=1)

tree.fit(X_train,y_train)

tree.score(X_test,y_test)
Out:0.6444444444444445

使用KNN算法:

n_neighbors=5

'''KNeighborsClassifier(n_neighbors=5, weights='uniform', algorithm='auto', 
leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=1, **kwargs)
'''
from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=5)

knn.fit(X_train,y_train)

knn.score(X_test,y_test)
Out:
0.9333333333333333

n_neighbors=15

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=15)

knn.fit(X_train,y_train)

knn.score(X_test,y_test)
Out: 0.9333333333333333

n_neighbors=1

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=1)

knn.fit(X_train,y_train)

knn.score(X_test,y_test)
Out: 0.9777777777777777

导绘图包

import matplotlib.pyplot as plt
%matplotlib inline

目标数据的分类作为颜色,一个分类一个颜色

y
Out:
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
'''plt.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, 
vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, hold=None, data=None, 
**kwargs)'''
plt.scatter(X[:,2],X[:,3],c = y)

使用逻辑斯蒂回归算法:

from sklearn.linear_model import LogisticRegression
'''LogisticRegression(penalty='l2', dual=False, tol=0.0001, C=1.0, fit_intercept=True,
 intercept_scaling=1, class_weight=None, random_state=None, solver='liblinear', 
 max_iter=100, multi_class='ovr', verbose=0, warm_start=False, n_jobs=1)'''
logistic = LogisticRegression()

logistic.fit(X_train,y_train)

logistic.score(X_test,y_test)
Out: 0.9777777777777777

logistic.coef_
Out:
array([[ 0.38715484,  1.35756217, -2.0889337 , -0.96149223],
       [ 0.18305144, -1.11389252,  0.58911239, -1.12108665],
       [-1.30172323, -1.63587224,  2.03041769,  2.29236273]])

logistic.intercept_
Out:
array([ 0.26267869,  0.58829742, -0.8724249 ])
# 150个数据鸢尾花的数据4个属性,从中取出来两个属性,进行学习预测
plt.scatter(X[:,0],X[:,1],c = y)

使用 np.meshgrid(x,y) 绘制画布

'''np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)'''
x = np.linspace(4,8,100)
y = np.linspace(1.8,4.5,100)
''' np.meshgrid(*xi, **kwargs)'''
X,Y = np.meshgrid(x,y)
X.shape ——>(100, 100)
plt.scatter(X,Y)

a = np.array([2,3,4])
b = np.array([-1,-2,-3])
A,B = np.meshgrid(a,b)
display(A,B)
plt.scatter(A,B)
Out:
array([[2, 3, 4],
       [2, 3, 4],
       [2, 3, 4]])
array([[-1, -1, -1],
       [-2, -2, -2],
       [-3, -3, -3]])

使用级联讲两个数据联合到一个表格中

ab = np.concatenate([A.reshape(-1,1),B.reshape(-1,1)],axis = 1 )
plt.scatter(ab[:,0],ab[:,1])

设置背景数据:

# X.shape = (100,100)
X_test_1 = np.concatenate([X.reshape(-1,1),Y.reshape(-1,1)],axis = 1)

# 计算机创造的10000个鸢尾花(花萼长度、花萼宽度)
X_test_1.shape
Out : (10000, 2)

绘制图形:

X_train = iris['data'][:,[0,1]]

y_train = iris['target']
tree = DecisionTreeClassifier(max_depth=3)

# 花萼长宽属性
# ValueError: Unknown label type: 'continuous'
tree.fit(X_train,y_train)

# 预测分类边界
y_ = tree.predict(X_test_1)

plt.scatter(X_test_1[:,0],X_test_1[:,1],c = y_)
'''plt.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None,
 vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, hold=None, data=None,
 **kwargs)'''
plt.scatter(X_train[:,0],X_train[:,1],c = y_train,cmap = 'ocean')

使用逻辑斯蒂回归:

logistic = LogisticRegression()

logistic.fit(X_train,y_train)

y_ = logistic.predict(X_test)

plt.scatter(X_test[:,0],X_test[:,1],c = y_)

plt.scatter(X_train[:,0],X_train[:,1],c = y_train,cmap = 'ocean')

2、使用回归预测一个椭圆

  • 使用RandomState生成固定随机数
  • 创建-100到100之间的角度
  • 生成正弦值和余弦值
  • 添加噪声

创建-100到100的预测数据,间隔为0.01

  • 对数据进行预测
  • 显示图片
X = np.linspace(-100,100,100)

s = np.sin(X)
c = np.cos(X)

plt.scatter(s,c)
plt.axis('equal')
Out:
(-1.1053993341495696,
 1.1053993341495667,
 -1.110327464822749,
 1.111091380563182)

将2列数据级联成一个表

display(s.shape,c.shape)
Out:
(100,)
(100,)

y = np.concatenate([s.reshape(-1,1),c.reshape(-1,1)],axis = 1)
y.shape
Out: (100, 2)

创建不同深度的决策树,进行数据训练

from sklearn.tree import DecisionTreeRegressor
# X.shape :(100,)  y:(100,2)
tree_5 = DecisionTreeRegressor(max_depth= 5)
tree_5.fit(X.reshape(-1,1),y)

X_test = np.linspace(-100,100,300).reshape(-1,1)
y_ = tree_5.predict(X_test)

plt.scatter(y_[:,0],y_[:,1])
plt.axis('equal')

tree_20 = DecisionTreeRegressor(max_depth= 20)
tree_20.fit(X.reshape(-1,1),y)

X_test = np.linspace(-100,100,300).reshape(-1,1)
y_ = tree_20.predict(X_test)

plt.scatter(y_[:,0],y_[:,1])
plt.axis('equal')

 

tree_50 = DecisionTreeRegressor(max_depth= 100)
tree_50.fit(X.reshape(-1,1),y)

X_test = np.linspace(-100,100,300).reshape(-1,1)
y_ = tree_50.predict(X_test)

plt.scatter(y_[:,0],y_[:,1])
plt.axis('equal')

tree_1= DecisionTreeRegressor(max_depth= 1)
tree_1.fit(X.reshape(-1,1),y)

X_test = np.linspace(-100,100,300).reshape(-1,1)
y_ = tree_1.predict(X_test)

plt.scatter(y_[:,0],y_[:,1])
plt.axis('equal')

 

使用Kfold进行数据划分

sklearn中的数据集的划分

sklearn数据集划分方法有如下方法:

KFold,GroupKFold,StratifiedKFold,LeaveOneGroupOut,LeavePGroupsOut,LeaveOneOut,LeavePOut,ShuffleSplit,GroupShuffleSplit,StratifiedShuffleSplit,PredefinedSplit,TimeSeriesSplit,

①数据集划分方法——K折交叉验证:KFold,GroupKFold,StratifiedKFold,

  • 将全部训练集S分成k个不相交的子集,假设S中的训练样例个数为m,那么每一个自己有m/k个训练样例,相应的子集为{s1,s2,...,sk}
  • 每次从分好的子集里面,拿出一个作为测试集,其他k-1个作为训练集
  • 在k-1个训练集上训练出学习器模型
  • 把这个模型放到测试集上,得到分类率的平均值,作为该模型或者假设函数的真实分类率

这个方法充分利用了所以样本,但计算比较繁琐,需要训练k次,测试k次

---------------------------------------------------------------------------------------------

  • 思路:将训练/测试数据集划分n_splits个互斥子集,每次用其中一个子集当作验证集,剩下的n_splits-1个作为训练集,进行n_splits次训练和测试,得到n_splits个结果
  • 注意点:对于不能均等份的数据集,其前n_samples % n_splits子集拥有n_samples // n_splits + 1个样本,其余子集都只有n_samples // n_splits样本

参数说明:

  • n_splits:表示划分几等份
  • shuffle:在每次划分时,是否进行洗牌
  • ①若为Falses时,其效果等同于random_state等于整数,每次划分的结果相同
  • ②若为True时,每次划分的结果都不一样,表示经过洗牌,随机取样的
  • random_state:随机种子数

属性:

  • ①get_n_splits(X=None, y=None, groups=None):获取参数n_splits的值
  • ②split(X, y=None, groups=None):将数据集划分成训练集和测试集,返回索引生成器
  • 通过一个不能均等划分的栗子,设置不同参数值,观察其结果
  • ①设置shuffle=False,运行两次,发现两次结果相同

导包

from sklearn.model_selection import KFold
'''n_splits=3, shuffle=False, random_state=None'''
kFold = KFold(n_splits=3)
for train_index,test_index in kFold.split(X,y):
    print(train,test)

n_splits属性值获取方式

In [8]: kFold .split(X)
Out[8]: 
 
In [9]: kFold .get_n_splits()
Out[9]: 5
 
In [10]: kFold .n_splits
Out[10]: 5

交叉验证

from sklearn.cross_validation import cross_val_score

转载于: https://blog.csdn.net/qq_36523839/article/details/80707678

在构建模型时,调参是极为重要的一个步骤,因为只有选择最佳的参数才能构建一个最优的模型。但是应该如何确定参数的值呢?所以这里记录一下选择参数的方法,以便后期复习以及分享。

我知道的有两种方法:1、通过经常使用某个模型的经验和高超的数学知识。2、通过交叉验证的方法,逐个来验证。

很显然我是属于后者所以我需要在这里记录一下(如果你属于前者可以教教我)

sklearn的cross_val_score:

我使用是cross_val_score方法,在sklearn中可以使用这个方法。交叉验证的原理不好表述下面随手画了一个图:

有点丑,简单说下,比如上面,我们将数据集分为10折,做一次交叉验证,实际上它是计算了十次,将每一折都当做一次测试集,其余九折当做训练集,这样循环十次。通过传入的模型,训练十次,最后将十次结果求平均值。将每个数据集都算一次

交叉验证优点:

1:交叉验证用于评估模型的预测性能,尤其是训练好的模型在新数据上的表现,可以在一定程度上减小过拟合。
2:还可以从有限的数据中获取尽可能多的有效信息。

我们如何利用它来选择参数呢?

我们可以给它加上循环,通过循环不断的改变参数,再利用交叉验证来评估不同参数模型的能力。最终选择能力最优的模型。

下面通过一个简单的实例来说明:(iris鸢尾花)

from sklearn import datasets	#自带数据集
from sklearn.model_selection import train_test_split,cross_val_score	#划分数据 交叉验证
from sklearn.neighbors import KNeighborsClassifier  #一个简单的模型,只有K一个参数,类似K-means
import matplotlib.pyplot as plt
iris = datasets.load_iris()		#加载sklearn自带的数据集
X = iris.data 			#这是数据
y = iris.target 		#这是每个数据所对应的标签
train_X,test_X,train_y,test_y = train_test_split(X,y,test_size=1/3,random_state=3)	#这里划分数据以1/3的来划分 训练集训练结果 测试集测试结果
k_range = range(1,31)
cv_scores = []		#用来放每个模型的结果值
for n in k_range:
    knn = KNeighborsClassifier(n)   #knn模型,这里一个超参数可以做预测,当多个超参数时需要使用另一种方法GndSearchCV
    scores = cross_val_score(knn,train_X,train_y,cv=10,scoring='accuracy')  #cv:选择每次测试折数  accuracy:评价指标是准确度,可以不要
    cv_scores.append(scores.mean())
plt.plot(k_range,cv_scores)
plt.xlabel('K')
plt.ylabel('Accuracy')		#通过图像选择最好的参数
plt.show()
best_knn = KNeighborsClassifier(n_neighbors=3)	# 选择最优的K=3传入模型
best_knn.fit(train_X,train_y)			#训练模型
print(best_knn.score(test_X,test_y))	#看看评分

最后得分0.94

 

你可能感兴趣的:(特征工程,算法实例)