一、CART树简介:
ClassificationAnd Regression Tree(CART)是决策树的一种,并且是非常重要的决策树,属于Top Ten Machine Learning Algorithm。顾名思义,CART算法既可以用于创建分类树(ClassificationTree),也可以用于创建回归树(Regression Tree)、模型树(Model Tree),两者在建树的过程稍有差异。
采用基于最小距离的基尼指数估计函数,用来决定由该子数据集生成的决策树的拓展形。如果目标变量是标称的,称为分类树;如果目标变量是连续的,称为回归树。分类树是使用树结构算法将数据分成离散类的方法。
CART算法的重要基础包含以下三个方面:
(1)二分(BinarySplit):在每次判断过程中,都是对观察变量进行二分。
CART算法采用一种二分递归分割的技术,算法总是将当前样本集分割为两个子样本集,使得生成的决策树的每个非叶结点都只有两个分枝。因此CART算法生成的决策树是结构简洁的二叉树。因此CART算法适用于样本特征的取值为是或非的场景,对于连续特征的处理则与C4.5算法相似。
(2)单变量分割(SplitBased on One Variable):每次最优划分都是针对单个变量。
(3)剪枝策略:CART算法的关键点,也是整个Tree-Based算法的关键步骤。 剪枝过程特别重要,所以在最优决策树生成过程中占有重要地位。有研究表明,剪枝过程的重要性要比树生成过程更为重要,对于不同的划分标准生成的最大树(Maximum Tree),在剪枝之后都能够保留最重要的属性划分,差别不大。反而是剪枝方法对于最优树的生成更为关键。
优点:
1)非常灵活,可以允许有部分错分成本,还可指定先验概率分布,可使用自动的成本复杂性剪枝来得到归纳性更强的树。
2)在面对诸如存在缺失值、变量数多等问题时 CART 显得非常稳健。
二、基本思路:
CART算法主要有以下两步组成:
1. 决策树生成:基于训练数据集生成决策树,生成的决策树要尽量大;
2. 决策树剪枝:用验证数据集对已生成的树进行剪枝并选择最优子树,这时损失函数最小作为剪枝的标准。
CART决策树的生成就是递归地构建二叉决策树的过程。CART决策树既可以用于分类也可以用于回归。本文我们仅讨论用于分类的CART。对分类树而言,CART用Gini系数最小化准则来进行特征选择,生成二叉树。 CART生成算法如下:
输入:训练数据集DataSet,判断停止条件。
输出:CART决策树。
根据训练数据集,从根结点开始,递归地对每个结点进行以下操作,构建二叉决策树:
1. 设结点的训练数据集为D,计算现有特征对该数据集的Gini系数。此时,对每一个特征A,对其可能取的每个值a,根据样本点对A=a的测试为“是”或 “否”将D分割成D1和D2两部分,计算A=a时的Gini系数。
2. 在所有可能的特征A以及它们所有可能的切分点a中,选择Gini系数最小的特征及其对应的切分点作为最优特征与最优切分点。依最优特征与最优切分点,从现结点生成两个子结点,将训练数据集依特征分配到两个子结点中去。
3. 对两个子结点递归地调用步骤l~2,直至满足停止条件。
4. 生成CART决策树。
算法停止计算的条件是结点中的样本个数小于预定阈值,或样本集的Gini系数小于预定阈值(样本基本属于同一类),或者没有更多特征。
关于过拟合以及剪枝问题:决策树很容易发生过拟合,也就是对训练数据集适应得非常好,但却在测试数据集上表现得不尽人如意。这个时候我们可以通过阈值控制终止条件避免树形结构分支过细,也可以通过对已经形成的决策树进行剪枝来避免过拟合。另外一个克服过拟合的手段就是采用基于Bootstrap的思想建立随机森林(Random Forest)实现分类问题。关于剪枝的内容可以参考其他文献。
(三)利用sklearn实现Cart树分类,回归树以后再讨论。
import numpy as np
from sklearn import preprocessing
from sklearn import tree
#clf = tree.DecisionTreeClassifier(criterion='gini')
class MYCartClassifier:
def __init__(self,Modul=tree.DecisionTreeClassifier,dataset=np.empty((3,3))):
self.modul=Modul
self.dataset=dataset
defReadFile(self,input_file):
# Reading the data
X = [];
with open(input_file,'r') as f:
for line inf.readlines():
# data=line.split(',')
data =line[:-1].split(',')
X.append(data)
X = np.array(X)
# Convert string datato numerical data
label_encoder = []
X_encoded =np.empty(X.shape)
for i,item inenumerate(X[0]):
label_encoder.append(preprocessing.LabelEncoder())
X_encoded[:, i] =label_encoder[-1].fit_transform(X[:, i])
X =X_encoded.astype(int)
self.dataset=X
def SetModule(self,Modul):
self.modul=Modul
def FitModule(self):
X=self.dataset[:,:-1]
y=self.dataset[:,-1]
self.modul.fit(X,y)
from sklearn importmodel_selection
accuracy =model_selection.cross_val_score(self.modul,X, y, scoring='accuracy', cv=3)
print("Accuracyof the classifier: " + str(round(100*accuracy.mean(), 2)) + "%")
clf = tree.DecisionTreeClassifier(criterion='gini')
MY=MYCartClassifier(Modul=clf)
MY.ReadFile("d:\\car.data.txt")
MY.FitModule()