目录
一、决策树
决策树是一个预测模型,它代表的是对象属性与对象值之间的一种映射关系。树中每个节点表示某个对象,而每个分叉路径则代表某个可能的属性值,而每个叶节点则对应从根节点到该叶节点所经历的路径所表示的对象的值。
从数据产生决策树的机器学习技术叫做决策树学习,通俗说就是决策树。
决策树 |
优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。 |
缺点:可能会产生过度匹配问题。 |
适用数据类型:数值型和标称型 |
二、决策树的构造
首先,确定当前数据集上的决定性特征,为了得到该决定性特征,必须评估每个特征,完成测试之后,原始数据集就被划分为几个数据子集,这些数据子集会分布在第一个决策点的所有分支上,如果某个分支下的数据属于同一类型,则当前无序阅读的垃圾邮件已经正确的划分数据分类,无需进一步对数据集进行分割,如果不属于同一类,则要重复划分数据子集,直到所有相同类型的数据均在一个数据子集内。
检测数据集中每个子项是否属于同一类:
If so return 类标签:
Else
寻找划分数据集的最好特征
划分数据集
创建分支节点
for 每个划分的子集
调用函数createBranch()并增加返回结果到分支节点中
return 分支节点
决策树的一般流程 |
1、收集数据:可以使用任何方法。 |
2、准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。 |
3、分析数据:可以使用任何方法,决策树构造完成之后,我们可以检查决策树图形是否符合预期。 |
4、训练算法:构造树的数据结构。 |
5、测试算法:使用经验树计算错误率。 |
6、使用算法:此步骤可以使用适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。 |
1、信息增益
组织杂乱无章数据的一种方法就是使用信息论度量信息。
在划分数据集之前之后信息发生的变化称为信息增益。获得信息增益最高的特征就是最好的选择。集合信息的度量方法称为香农熵或者简称熵。
如果待分类的事务可能划分在多个分类之中,则符合的信息定义为
其中是选择该分类的概率。
为了计算熵,我们需要计算所有类别可能值包含的信息期望值,通过下面的公式得到:
2、划分数据集
分类算法除了需要测量信息熵,还需要划分数据集,度量划分数据集的熵,以便判断当前是否正确地划分了数据集。我们将对每个特征划分数据集的结果计算一次信息熵, 然后判断按照哪个特征划分数据集是最好的划分方式。
3、递归构造决策树
从数据集构造决策树算法的工作原理如下:得到原始数据集,然后基于最好的属性值划分数据集,由于特征值可能多于两个,因此可能存在大于两个分支的数据集划分。第一次划分之后,数据将被向下传递到树分支的下一个节点,在这个节点上,我们可以再次划分数据。因此我们可以采用递归的原则处理数据集。
递归结束的条件是:程序遍历完所有划分数据集的属性,或者每个分支下的所有实例都具有相同的分类。如果所有实例具有相同的分类,则得到一个叶子节点或者终止块。任何到达叶子节点的数据必然属于叶子节点的分类,参见图1所示。
图1 划分数据集时的数据路径
三、实例
一个西瓜数据集
python代码如下:
import pandas as pd
import numpy as np
#计算信息熵
def cal_information_entropy(data):
data_label = data.iloc[:,-1]
label_class =data_label.value_counts() #总共有多少类
Ent = 0
for k in label_class.keys():
p_k = label_class[k]/len(data_label)
Ent += -p_k*np.log2(p_k)
return Ent
#计算给定数据属性a的信息增益
def cal_information_gain(data, a):
Ent = cal_information_entropy(data)
feature_class = data[a].value_counts() #特征有多少种可能
gain = 0
for v in feature_class.keys():
weight = feature_class[v]/data.shape[0]
Ent_v = cal_information_entropy(data.loc[data[a] == v])
gain += weight*Ent_v
return Ent - gain
#获取标签最多的那一类
def get_most_label(data):
data_label = data.iloc[:,-1]
label_sort = data_label.value_counts(sort=True)
return label_sort.keys()[0]
#挑选最优特征,即信息增益最大的特征
def get_best_feature(data):
features = data.columns[:-1]
res = {}
for a in features:
temp = cal_information_gain(data, a)
res[a] = temp
res = sorted(res.items(),key=lambda x:x[1],reverse=True)
return res[0][0]
##将数据转化为(属性值:数据)的元组形式返回,并删除之前的特征列
def drop_exist_feature(data, best_feature):
attr = pd.unique(data[best_feature])
new_data = [(nd, data[data[best_feature] == nd]) for nd in attr]
new_data = [(n[0], n[1].drop([best_feature], axis=1)) for n in new_data]
return new_data
#创建决策树
def create_tree(data):
data_label = data.iloc[:,-1]
if len(data_label.value_counts()) == 1: #只有一类
return data_label.values[0]
if all(len(data[i].value_counts()) == 1 for i in data.iloc[:,:-1].columns): #所有数据的特征值一样,选样本最多的类作为分类结果
return get_most_label(data)
best_feature = get_best_feature(data) #根据信息增益得到的最优划分特征
Tree = {best_feature:{}} #用字典形式存储决策树
exist_vals = pd.unique(data[best_feature]) #当前数据下最佳特征的取值
if len(exist_vals) != len(column_count[best_feature]): #如果特征的取值相比于原来的少了
no_exist_attr = set(column_count[best_feature]) - set(exist_vals) #少的那些特征
for no_feat in no_exist_attr:
Tree[best_feature][no_feat] = get_most_label(data) #缺失的特征分类为当前类别最多的
for item in drop_exist_feature(data,best_feature): #根据特征值的不同递归创建决策树
Tree[best_feature][item[0]] = create_tree(item[1])
return Tree
#{'纹理': {'清晰': {'根蒂': {'蜷缩': 1, '稍蜷': {'色泽': {'青绿': 1, '乌黑': {'触感': {'硬滑': 1, '软粘': 0}}}}, '硬挺': 0}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
def predict(Tree , test_data):
first_feature = list(Tree.keys())[0]
second_dict = Tree[first_feature]
input_first = test_data.get(first_feature)
input_value = second_dict[input_first]
if isinstance(input_value , dict): #判断分支还是不是字典
class_label = predict(input_value, test_data)
else:
class_label = input_value
return class_label
if __name__ == '__main__':
#读取数据
data = pd.read_csv("C://Users//21888//Downloads//data_word.csv")
#统计每个特征的取值情况作为全局变量
column_count = dict([(ds, list(pd.unique(data[ds]))) for ds in data.iloc[:, :-1].columns])
#创建决策树
dicision_Tree = create_tree(data)
print(dicision_Tree)
print('\n')
#测试数据
test_data_1 = {'色泽':'青绿','根蒂':'蜷缩','敲声':'浊响','纹理':'稍糊','脐部':'凹陷','触感':'硬滑'}
result = predict(dicision_Tree,test_data_1)
print('分类结果为好瓜'if result == 1 else '分类结果为坏瓜')
print('\n')
test_data_2 = {'色泽': '乌黑', '根蒂': '稍蜷', '敲声': '浊响', '纹理': '清晰', '脐部': '凹陷', '触感': '硬滑'}
result = predict(dicision_Tree,test_data_2)
print('分类结果为好瓜'if result == 1 else '分类结果为坏瓜')
得到的决策树以字典形式显示:
测试结果: