机器学习sklearn(6)决策树分类
原理:
由某种原则(信息熵或是基尼系数)来确定决策条件先后顺序,进而通过这一系列条件来实现对数据进行分类。
优点:
- 简单直观,生成的决策树很直观
- 基本不需要预处理,不需要提前归一化,处理缺失值
- 使用决策树预测的代价是O()。m为样本数
- 既可以处理离散值也可以处理连续值
- 可以处理多维度输出的分类问题
- 相比于神经网络之类的黑盒分类模型,在逻辑上可以得到很好的解释
- 可以通过交叉验证的剪枝来选择模型,从而提高泛化能力
- 对于异常点的容错能力好,健壮性高
缺点:
- 非常容易过拟合,导致泛华能力不强。可以通过设置节点最少样本数和限制决策树深度来改进
- 会因为样本发生一点点的改动,导致树结构的剧烈改变。可以通过集成学习之类的方法来解决
- 容易陷入局部最优,可以通过集成学习之类的方法来改善
- 有些比较复杂的关系,比如异或,决策树很难学习,一般这种关系可以换神经网络分类方法来解决
- 如果某些特征的样本比例过大,生成决策树容易偏向于这些特征,可以通过调节样本权重来改善
三种决策树算法:
熵:
联合熵:
条件熵:
信息增益:
基尼系数:
class sklearn.tree.
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)
参数含义:
- criterion:特征选择标准,默认值为‘gini’。(entropy, gini)默认gini,即CART算法。
- splitter:特征划分标准,默认值为‘best’。(best, random)best在特征的所有划分点中找出最优的划分点,random随机的在部分划分点中找局部最优的划分点。默认的‘best’适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐‘random’。
- max_depth:决策树最大深度。默认值是‘None’。(int, None)一般数据比较少或者特征少的时候可以不用管这个值,如果模型样本数量多,特征也多时,推荐限制这个最大深度,具体取值取决于数据的分布。常用的可以取值10-100之间,常用来解决过拟合。
- min_samples_split:内部节点再划分所需最小样本数。默认值为2。(int, float)如果是int,则取传入值本身作为最小样本数;如是float,取ceil(min_samples_split*样本数量)作为最小样本数。(向上取整)
- min_samples_leaf:叶子节点最少样本数。如果是int,则取传入值本身作为最小样本数;如果是float,则取ceil(min_samples_leaf*样本数量)的值作为最小样本数。这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。
- min_weight_fraction_leaf:叶子节点最小的样本权重和。默认为0。(float)这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。默认是0,就是不考虑权重问题,所有样本的权重相同。一般来说如果我们有较多样本有缺失值或者分类树样本的分布类别偏差很大,就会引入样本权重,这时就要注意此值。
- max_features:在划分数据集时考虑的最多的特征值数量。int值,在每次split时最大特征数;float值表示百数,即(max_features*n_features);
- random_state:默认是None,(int, randomSate instance, None)
- max_leaf_nodes:最大叶子节点数。默认为None。(int, None)通过设置最大叶子节点数,可以防止过拟合,默认情况下是不设置最大叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征多,可以加限制,具体的值可以通过交叉验证得到。
- min_impurity_decrease:节点划分最小不纯度。默认值为‘0’。(float, optional (default=0.))限制决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小与这个阈值,则该节点不再生成子节点。
- min_impurity_split:信息增益的阀值。决策树在创建分支时,信息增益必须大于这个阀值,否则不分裂。
- class_weight:类别权重。默认为None,(dict, list of dicts, balanced)指定样本各类别的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。balanced,算法自己计算权重,样本量少的类别所对应的样本权重会更高。如果样本类别分布没有明显的偏倚,则可以不管这个参数。不适用于回归树,sklearn.tree.DecisionTreeRegressor.
- presort:bool,默认是False,表示在进行拟合之前,是否预分数据来加快树的构建。对于数据集非常庞大的分类,presort=true将导致整个分类变得缓慢;当数据集较小,且树的深度有限制,presort=true才会加速分类。
from sklearn.tree import DecisionTreeClassifier
import pandas as pd
导入数据集
names=['age', 'prescript', 'astigmatic', 'tearrate', 'class']
data_path = r"C:\Users\Machine Learning\lenses.txt"
lenses = pd.read_csv(data_path, sep='\t', names=names)
print(lenses.head())
age prescript astigmatic tearrate class
0 young myope no reduced no lenses
1 young myope no normal soft
2 young myope yes reduced no lenses
3 young myope yes normal hard
4 young hyper no reduced no lenses
转换成array格式,拆分特征量和标签
import numpy as np
lenses = np.array(lenses)
lenses_data = lenses[:,:-1]
lenses_target = lenses[:,-1]
DecisionTreeClassifier.fit()不能接收string类型数据,需要先对数据集进行编码
data = np.zeros(shape = lenses_data.shape)
from sklearn import preprocessing
le = preprocessing.LabelEncoder()
for i in range(0, lenses.shape[1]-1):
le.fit(lenses_data[:,i])
data[:,i] = le.transform(lenses_data[:,i])
clf = DecisionTreeClassifier(max_depth=4, criterion='entropy')
clf.fit(data, lenses_target)
DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=4,
max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, presort=False, random_state=None,
splitter='best')
from sklearn.externals.six import StringIO
import pydotplus
可视化决策树
dot_data = StringIO()
from sklearn import tree
tree.export_graphviz(clf, out_file=dot_data,
feature_names=names[:-1],
class_names=clf.classes_,
filled=True, rounded=True,
special_characters=True) #filled:颜色填充 rounded:拐角圆滑处理
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_pdf("tree_.pdf")
True
内容有点多不太好理解,可以对照原始数据一起来看
data_imp = np.column_stack((data, lenses_target)) #不能直接用np.hstack(),因为稀疏矩阵时会报错
data_pd = pd.DataFrame(data_imp, columns=names)
data_pd
#samples表示当前节点样本个数,values表示当前节点不同标签(“hard”,“no lenses”,“soft”,按照英文字母顺序排列)的样本个数,class表示当前节点三个不同标签中样本数最多的标签
根据生成的决策树进行预测
print(clf.predict([[1,0,1,0]]))
['no lenses']