决策树/判定树:是一个类似于流程图的树结构,其中,每个内部结点表示在一个属性上的测试,每个分支代表一个属性输出,而每个树叶结点代表类或类分布。树的最顶层是根结点。
熵(entropy)概念:信息量的度量就等于不确定性的多少。一条信息的信息量大小和它的不确定性有直接的关系,要搞清楚一件非常不确定的事情,需要了解大量的信息。
变量的不确定性越大,熵也就越大。
决策树(DTs)是一种用于分类和回归的非参数监督学习方法。目标是创建一个模型,通过从数据特性中推导出简单的决策规则来预测目标变量的值。
常见的算法包括 CART (Classification And Regression Tree)、ID3、C4.5、随机森林 (Random Forest) 等。
决策树是附加概率结果的一个树状的决策图,是直观的运用统计概率分析的图法。机器学习中决策树是一个预测模型,它表示对象属性和对象值之间的一种映射,树中的每一个节点表示对象属性的判断条件,其分支表示符合节点条件的对象。树的叶子节点表示对象所属的预测结果。
信息增益
信息熵表示的是不确定度。均匀分布时,不确定度最大,此时熵就最大。当选择某个特征对数据集进行分类时,分类后的数据集信息熵会比分类前的小,其差值表示为信息增益。信息增益可以衡量某个特征对分类结果的影响大小。
信息增益表示数据集在某特征的作用后,其信息熵减少的值。
对于决策树节点最合适的特征选择,就是 Gain值最大的特征。Gain值越小,则数据集的纯度越高。
在分类模型建立的过程中,很容易出现过拟合的现象。过拟合是指在模型学习训练中,训练样本达到非常高的逼近精度,但对检验样本的逼近误差随着训练次数而呈现出先下降后上升的现象。过拟合时训练误差很小,但是检验误差很大,不利于实际应用。也就是说在决策树学习过程中,为了尽可能正确分类训练样本,结点划分过程将不断重复,有时会造成决策树分支过多,这时就可能因训练样本学的“太好”,以致于把训练集自身的一些特点当作所有数据都具有的一般性质而导致过集合,因此,可通过主动去掉一些分支来降低过拟合的风险。也就是剪枝。
剪枝分为预先剪枝和后剪枝两种。
预先剪枝指在决策树生长过程中,使用一定条件加以限制,使得产生完全拟合的决策树之前就停止生长。预先剪枝的判断方法也有很多,比如信息增益小于一定阀值的时候通过剪枝使决策树停止生长。但如何确定一个合适的阀值也需要一定的依据,阀值太高导致模型拟合不足,阀值太低又导致模型过拟合。预剪枝使得决策树的很多分支都没有展开,这不仅降低了过拟合的风险,还显著减少了决策树的训练时间开销和测试时间开销。但另一方面,有些分支的当前划分虽不能提升泛化性能、甚至可能导致泛化性能暂时下降,但在其基础上进行的后续划分却有可能导致性能显著提高;预剪枝基于“贪心”本质禁止这些分支展开,给预剪枝决策树带来了欠拟合的风险。
后剪枝是在决策树生长完成之后,按照自底向上的方式修剪决策树。后剪枝有两种方式,一种用新的叶子节点替换子树,该节点的预测类由子树数据集中的多数类决定。另一种用子树中最常使用的分支代替子树。
预先剪枝可能过早的终止决策树的生长,后剪枝一般能够产生更好的效果。但后剪枝在子树被剪掉后,决策树生长的一部分计算就被浪费了。
后剪枝决策树通常比预剪枝决策树保留了更多的分支,一般情形下,后剪枝决策树的欠拟合风险很小,泛化性能往往优于预剪枝决策树,但后剪枝过程是在生成完全决策树之后进行的,并且要自底向上对树中的所有非叶结点进行逐一考察,因此其训练时间开销比未剪枝决策树和预剪枝决策树都要大很多。
决策树的优点:直观,便于理解,小规模数据集有效
决策树的缺点:
处理连续变量不好
类别较多时,错误增加的比较快
可规模性一般
决策树应用:
data.xls是需要训练的数据集,dataTest.xls是测试集
#!/usr/bin/python # -*- coding: utf-8 -*- import pandas as pd from sklearn.tree import DecisionTreeClassifier as DTC data_train = pd.read_excel('decisionTree/data.xls', index_col=u'序号')#指定以"序号"为索引 data_test = pd.read_excel('decisionTree/dataTest.xls', index_col=u'序号') ''' data_train['天气'] = data_train['天气'].map({'好':'1', '坏':'0'}) data_train['是否周末'] = data_train['是否周末'].map({'是':'1', '否':'0'}) data_train['是否有促销'] = data_train['是否有促销'].map({'是':'1', '否':'0'}) data_train['销量'] = data_train['销量'].map({'高':'1', '低':'0'}) ''' #数据是类别标签,要将它转换为数据 #用1来表示“好”、“是”、“高”这三个属性,用0来表示“坏”、“否”、“低” data_train[data_train == u'好'] = 1 data_train[data_train == u'是'] = 1 data_train[data_train == u'高'] = 1 data_train[data_train != 1] = 0 data_test[data_test == u'好'] = 1 data_test[data_test == u'是'] = 1 data_test[data_test != 1] = 0 x = data_train.iloc[:,:3].as_matrix().astype(int) y = data_train.iloc[:,3].as_matrix().astype(int) print('真实结果:%s'%y) data_test = data_test.iloc[:,:3].as_matrix().astype(int) dtc = DTC(criterion='entropy') dtc.fit(x, y) y_pred = dtc.predict(data_test) print('预测结果:%s'%y_pred)
应用例子2:
from sklearn import tree import pandas as pd import numpy as np from sklearn.model_selection import train_test_split ''' 约会样本数据说明datingTestSet.txt, 以tab键分开: 1、FlyMiles: 每年获得的飞行常客里程数; 2、PlayTime: 玩视频游戏所耗费的时间百分比 3、IceCream: 每周消费的冰淇淋公斤数 4、对约会对象的感觉 ''' #url表示数据文件存放的地址 url = 'Data/datingTestSet.txt' data = pd.read_table(url, sep=' ', header=None, names=['FlyMiles', 'PlayTime', 'IceCream', 'LikeDegree']) #将LikeDegree一列由字符串转化为数字 like_mapping = {label: idx for idx, label in enumerate(np.unique(data['LikeDegree']))} data['LikeDegree'] = data['LikeDegree'].map(like_mapping) #将前三列特征值赋值给X,最后一列结果赋值给y X = data.iloc[:, 0:3] y = data.iloc[:, -1] #划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=32) #开始学习 clf = tree.DecisionTreeClassifier() clf.fit(X_train, y_train) #计算学习结果 score = clf.score(X_test, y_test) print("the rate is : %f" % score)