赞
踩
决策树原理这篇文章讲的很详细。
本文仅写代码实现。
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets.california_housing import fetch_california_housing
housing = fetch_california_housing()
housed = pd.DataFrame(housing.data)
housed.head()
housed.shape
先导入数据集(我这里用的是sklearn库自带的房价数据集),如果网络超时的话也可以从网站 https://ndownloader.figshare.com/files/5976036下载下来解压之后,用pd.read_csv读入data那个文件,记得把head=None。输出如下
切分数据集为训练集和验证集
from sklearn.model_selection import train_test_split
#导入数据切分函数
data_train, data_test, target_train, target_test = \
train_test_split(housing.data, housing.target, test_size = 0.2, random_state = 42)
dtr = tree.DecisionTreeRegressor(random_state = 42)
先建立一个回归树dtr1
from sklearn import tree
dtr1 = tree.DecisionTreeRegressor(max_depth = 3)
#实例化树模型,max_depth指定最大深度
dtr1.fit(data_train,target_train)
#传入样本和label
dtr1.score(data_test,target_test)
输出如下,说明你的树dr1训练成功并且参数也标记出来了,同时也可以看出准确率很低仅有0.521
dtr2=tree.DecisionTreeClassifier(max_depth=3,criterion='gini',min_samples_split=200)
#再建立一个分类树
dtr2.fit(data_train,target_train.astype("int"))
dtr2.score(data_test,target_test.astype('int'))
成功建立并且训练分类树dr2,准确率也不高只有0.523
不论回归树还是分类树,都有以下常用参数
要可视化显示 首先需要安装 graphviz 安装过程参照这篇文章,还需要安装pydotplus库,直接pip install pydotplus就好,装好之后
dot_data1= tree.export_graphviz( dtr2,#改成你要画的树,这里我们画dtr2 out_file = None, feature_names = housing.feature_names,#改成需要的特征名 filled = True, impurity = True,#是否显示gini系数或者熵值 rounded = True, special_characters=True, class_names=str(housing.target)#分类树的类别名,回归树不用指定 ) import pydotplus graph = pydotplus.graph_from_dot_data(dot_data1) graph.get_nodes()[1].set_fillcolor("#2DF3DF") from IPython.display import Image Image(graph.create_png()) graph.write_png("dtr2_.png")#保存图片
得到如下的树
无论是回归树还是分类树,问题都很明显:准确率太低,为了解决这一问题,我们使用随机森林来建立模型。
from sklearn.ensemble import RandomForestRegressor
rfr = RandomForestRegressor(random_state = 42)
rfr.fit(data_train, target_train)
rfr.score(data_test, target_test)
可以看出,准确率有明显提升达到了0.806
我们如何使模型更加精准?有两种思路:
一是调整模型的参数,随机森林本质即为多个决策树,所以随机森林的参数和决策树是相通的。
二是对数据下手,去掉对模型影响甚小的数据,使得数据的特征更加集中。
GridSearchCV相当于一个巨大的for循环,遍历所给候选参数的结果进行交叉验证后得到最合适的参数,用法如下
from sklearn.model_selection import GridSearchCV
#GridSearchCV网络搜索交叉验证,用来遍历找出最合适的参数
tree_param_grid = { 'min_samples_split': list(range(3,8)),'n_estimators':list((80,100,120))}
grid = GridSearchCV(RandomForestRegressor(),param_grid=tree_param_grid, cv=3)
#先指定算法,然后把想找的参数写成字典传给param_grid,cv是交叉验证次数
grid.fit(data_train, target_train)
然后可以用以下代码查看结果
grid.cv_results_#查看训练详细结果,比较长就不截图了
grid.best_params_#看最终得到的参数
grid.best_score_#查看遍历过程中最高的score
接着我们用找到的参数,再次建立新模型,查看是否有变化
rfr = RandomForestRegressor( min_samples_split=7,n_estimators = 120,random_state = 42)
rfr.fit(data_train, target_train)
rfr.score(data_test, target_test)
虽然差距很小从0.8062变成了0.8068,但是确实变好了。我这里寻找参数范围很小,如果机器性能可以并且追求结果可以尝试扩大范围。但是树的个数不用太大,树的个数超过一两百课之后和模型的效果就不是正相关了。也就是超过一定的阈值,树的个数再大模型效果也不会变好
import numpy as np
from sklearn.feature_selection import SelectKBest, f_classif
selector = SelectKBest(f_classif, k=5)#选前5重要的
selector.fit(housed,housing.target)
scores = -np.log10(selector.pvalues_)
plt.bar(range(len(scores)),scores)
plt.xticks(range(len(housing.feature_names)),housing.feature_names,rotation=45)
可以看出这些特征对结果重要性的影响排名
topk=selector.get_support(True)#返回前K个特征
dataed_train=data_train[:,topk]
dataed_test=data_test[:,topk]
rfr = RandomForestRegressor(random_state = 42)
rfr.fit(dataed_train, target_train)
rfr.score(dataed_test, target_test)
可以看到准确率有0.816,之前辛辛苦苦遍历找参数都没有对数据做处理提升的多,可见数据预处理的重要性。
思路很简单用循环可视化森林里的每棵树就好了,代码如下
import pydotplus from IPython.display import Image for idx, estimator in enumerate(rfr.estimators_): dot_data= tree.export_graphviz( estimator,#改成自己的树 out_file = None, feature_names = np.array(housing.feature_names)[topk],#改成需要的特征名 filled = True, impurity = True,#是否显示gini系数或熵值 rounded = True, special_characters=True, class_names=str(housing.target) ) graph = pydotplus.graph_from_dot_data(dot_data) graph.get_nodes()[1].set_fillcolor("#2DF3DF") #Image(graph.create_png()) graph.write_png("D:\dtr{}_.png".format(idx))#保存图片
可以看到最终在我指定的位置生成了三棵树的图片
这是其中的一颗
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。