目录
参考资料:
决策树模型概述:
决策树是一类很常见的机器学习算法,通常用于处理二分类任务。顾名思义,决策树是通过树状结构进行决策的。在每一个决策节点,需要对一个问题进行判断,例如下图反映出决策树对一颗瓜是否为好瓜的判断过程:
通过这样的决策流程,我们可以对任何一个瓜的分类做出判断。
在决策树的基础上进行集成学习,衍生出了随机森林、Adaboost等机器学习算法,其性能显著强于单独的决策树。
决策树:
本文仅讲解 ID3 算法的实现过程,其他决策树算法从略。
信息增益
决策树根据信息增益决定是否分裂一个决策节点。假定样本为第 类的比例为 ,共有 个类别,则样本集合 的信息熵为
如果将样本集合 按照属性 分为两类,分别记为 和 ,其类别数为 和 ,样本为第 类的比例分别为 和 ,则分解后的信息熵为
通过节点 a 得到的信息增益为
不难证明,信息增益是一个恒大于等于 0 的量。信息增益越大,说明该节点划分后对决策树判断结果越有利——因为获得的信息量变多了。
在决策树的形成过程中,通常采取贪心方法,即每一步都选取特征集合中信息增益最大节点进行划分,直到划分至叶节点为止。
决策树优化
为了防止决策树模型对训练集数据过拟合,可以采取预剪枝和后剪枝两种方法来去除不利于模型泛化的节点。这两种方法都是根据每个决策节点在验证集上的表现来确定是否剪枝。由于可以提前计算,预剪枝具有时间开销小的优点;而后剪枝则充分延伸了分裂节点带来的信息增益,因此其欠拟合风险很小。
对于连续型的变量,决策树可以通过寻找最优划分点的方法来进行划分。如果有多个连续型变量,则可以对同一个属性进行多次节点分裂,以寻找到最优的分类点。然而,相比SVM、神经网络等模型,决策树因其较为简单的结构,和对高维度信息处理能力的欠缺,还是不善于处理连续型变量。
对于缺失值的处理,可以让样本以一定概率划分入该特征的类别中,也可以采取新建一个类别来容纳缺失类。
python决策树实例
作者将决策树应用于kaggle的入门题——泰坦尼克号生存分析,取得了85%的正确率。代码如下:
'''处理训练集数据'''
import csv
import pydotplus
from sklearn.feature_extraction import DictVectorizer
from sklearn import preprocessing
from sklearn import tree
titanic_data = open('train.csv', 'rt')
reader = csv.reader(titanic_data)
# 表头信息
headers = next(reader)
print(headers)
feature_list = [] # 特征值
result_list = [] # 结果值
for row in reader:
result_list.append(row[1]) # 仅保留一个元素
feature_list.append(dict(zip(headers[11:16], row[11:16])))
# print(result_list)
# print(feature_list)
for item in feature_list:
if item['Age'] == "":
item['Age'] = 'B'
elif float(item['Age'])<15:
item['Age'] = 'A'
elif float(item['Age'])<45:
item['Age'] = 'B'
else:
item['Age'] = 'C'
if item['Fare'] == "":
item['Fare'] = 'A'
elif float(item['Fare'])<10:
item['Fare'] = 'A'
elif float(item['Fare'])<60:
item['Fare'] = 'B'
else:
item['Fare'] = 'C'
# print(result_list, feature_list)
'''处理测试集数据'''
titanic_test = open('test.csv', 'rt')
reader = csv.reader(titanic_test)
# 表头信息
headers = next(reader)
print(headers[10:15])
feature_test = [] # 特征值
for row in reader:
# 去掉首尾两列,特征值只保留'type', 'country', 'gross'
feature_test.append(dict(zip(headers[10:15], row[10:15])))
for item in feature_test:
if item['Age'] == "":
item['Age'] = 'B'
elif float(item['Age'])<15:
item['Age'] = 'A'
elif float(item['Age'])<45:
item['Age'] = 'B'
else:
item['Age'] = 'C'
if item['Fare'] == "":
item['Fare'] = 'A'
elif float(item['Fare'])<10:
item['Fare'] = 'A'
elif float(item['Fare'])<60:
item['Fare'] = 'B'
else:
item['Fare'] = 'C'
# print(result_list, feature_list)
'''整合数据'''
feature = feature_test+feature_list
vec = DictVectorizer() # 实例化模型
dummyX = vec.fit_transform(feature).toarray()
dummyY = preprocessing.LabelBinarizer().fit_transform(result_list)
dummyX_test = dummyX[:418]
dummyX_train = dummyX[418:]
'''预测结果'''
clf = tree.DecisionTreeClassifier(criterion='entropy', random_state=0)
clf = clf.fit(dummyX_train, dummyY)
print("clf: " + str(clf))
predict_result = clf.predict(dummyX_test)
f = open('titanic_result.csv','w',encoding='utf-8',newline="")
csv_writer = csv.writer(f)
csv_writer.writerow(["PassengerId","Survived"])
for i in range(892,1310):
csv_writer.writerow([str(i),str(predict_result[i-892])])
f.close()
其他决策树模型在决策树的结构上与ID3算法一致,只是分裂节点时采取不同的判断标准,如 C4.5决策树算法采取增益率来选择最优划分特征,而CART决策树采取Gini指数来选择最优化分特征。可以参考这两篇博文:C4.5算法,CART决策树。
随机森林:
随机森林模型是一种基于决策树的集成学习模型,其个体学习器之间不存在强依赖关系,可并行生成结果。随机森林模型的前身是Bagging模型。
Bagging
决策树本身正确率很难令人满意,于是本着“三个臭皮匠,顶个诸葛亮”的想法,Bagging模型应运而生。这个模型中包含多个如决策树的弱分类器,每个弱分类器收集一小批样本进行训练。在输出结果时,多颗决策树采取投票制的方式,以票最多的结果作为整个Bagging模型的输出。这种方法在没有显著增加计算复杂度的基础上,还省下了一批样本用于进一步优化模型。从结果偏差的角度来讲,这样的集成方法降低了单个决策树模型带来的方差,也使得模型有更好的泛化性能。
随机森林
随机森林(Random Forest)在Bagging的基础上,添加了“分工合作”的思想,即生成弱学习器(决策树)时,并不在分裂节点的所有属性中选取信息增益最优者,而是在所有属性中随机抽取一些属性,选取其中信息增益最优者。这是“随机”的由来。另一词“森林”则是继承了Bagging的思想,使用多颗决策树,类似于森林的形状。
随机森林模型简单,容易实现,同时又具有这强大的泛化性能。
有关随机森林模型的代码实现有待作者进一步的实践,如有结果将会更新在这篇博文上。
Adaboost:
Adaboost是一种由决策树串行生成的集成学习方法。在训练时,Adaboost模型逐个地训练决策树,前一个决策树分类错误的样本会被赋予更大的关注度,以便让后一个决策树来处理这些样本。根据每颗决策树执行的任务,它们会被赋予不同的权重。
在输出时,Adaboost同样采取投票表决的方式,模型的输出结果为每颗决策树的结果乘以其相应权重的加和。
与Bagging类模型不同,Adaboost的主要效果是使输出结果偏差更小。模型会在训练集上表现的更为出色,但存在着过拟合的风险。
PS. 西瓜书上Adaboost这块的讲解实在是看不懂,只能大概学了学这个模型的原理。以后如果有机会会补上这块的详细介绍。关于Adaboost,可以参考这篇博文:Adaboost入门教程——最通俗易懂的原理介绍(图文实例)
参考资料:
周志华. 机器学习. 北京: 清华大学出版社, 2016.