决策树:一种有监督的机器学习分类算法,可以训练已知数据,做出对未知数据的预测。
机器学习中的分类任务殊途同归,都是要根据已知的数据特征获得最佳的分类方法。对于一个有多个特征的数据,我们需要知道根据哪些特征、怎么使用这些特征来分类能达到最好的分类效果。决策树能够形成一棵分类树,每个分叉处都是根据已知特征选取的局部最优的分类办法,最后得到一套完整的分类方法,也就是一棵决策树。那么如何获得每个分叉处的局部最优解?就要引入信息熵、条件熵的概念。具体公式网络上已有充分的资料可供学习:/am290333566/article/details/81187124
抽象而言,
信息熵就是衡量信息不确定性的指标。
条件熵是已知一些信息后,目标信息的不确定性。
信息增益=信息熵-条件熵。也就是知道了某个新信息后,目标的不确定性减小了多少。
在一个分类树中,一个父节点根据某些条件分成了多个子节点。而父节点和子节点各自都有出现的概率(可以用熵来表示),决策树的目标,是使得每次分叉信息增益最大。
实例:根据糖尿病数据做出预测
数据集:Pima Indians Diabetes Database,数据都是女性,包含多个特征:年龄、血压、怀孕次数、BMI指数、皮肤厚度等。/uciml/pima-indians-diabetes-database#diabetes.csv
# 导入数据包
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn import metrics
col_names = ['pregnant', 'glucose', 'bp', 'skin', 'insulin', 'bmi', 'pedigree', 'age', 'label']
pima = pd.read_csv("pima-indians-diabetes.csv", header=None, names=col_names)
其中label一列是需要预测的因变量,其他特征为自变量。label如果是1,表示有糖尿病,如果是0,表示无糖尿病。
X = pima[feature_cols] # 特征,也就是除了因变量label以外的自变量
y = pima.label # 类别标签
用train_test_split()方法划分训练、测试集,指定比例和随机数种子random state。
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3, random_state=1)#训练:测试=7:3
创建决策树分类器
clf = DecisionTreeClassifier(criterion='entropy',max_depth=3,min_weight_fraction_leaf=0.01)
criterion选取的是之前介绍的最大熵算法,另一种算法是gini。
max_depth是树的最大深度,根据多次测试可以发现,更大的树不一定是更好的树。min_weight_fraction_leaf意思是最末端的类别所包含的数据量所占比例。这个值越大表示分得越粗,越小表示分得越细。可以调小来避免过拟合。同样,分得最细的不一定是最好的,它可能只是事儿多,却没有抓住重点。
# fit训练模型
clf = clf.fit(X_train,y_train)
# 使用训练好的模型做预测,打印准确度
y_pred = clf.predict(X_test)
print("Accuracy:",metrics.accuracy_score(y_test, y_pred))
准确度0.744,看上去不是很高,就要引入决策树的升级版——随机森林
随机森林的本质是集成学习算法,方法是随机产生多个决策树,结合决策树的分类结果决定最终的分类结果。这个过程是由投票实现的,比如树(1,2,3)分别认为小A的诊断结果(1,0,0),那么小A就被判定为没有糖尿病,因为0的次数比较多。
随机体现在:带放回地随机选取k个子集训练k个树、在选择分叉的特征时随机选择子集(数据随机+分叉随机)
随机森林的优势在于消除因为只用一次分类树而产生的不确定性。通过调整参数(树的数量)获取最佳的结果。
for i in range(1,20):#循环调参:分别试一试1-20棵分类树的结果怎样
rf = RandomForestClassifier(
criterion='entropy',
n_estimators=i,
max_depth=5,
min_samples_split=10, # 定义至少多少个样本的情况下才继续分叉
min_weight_fraction_leaf=0.05 # 定义叶子节点最少需要包含多少个样本(使用百分比表达), 防止过拟合
)
# 训练模型
rf.fit(X_train, y_train)
# 做预测
y_pred = rf.predict(X_test)
# 模型的准确率
print("i=number_of_trees=:",i,',accuricy=',metrics.accuracy_score(y_test, y_pred))
打印结果为
可以发现当树的数量=6的时候,准确率最高,达到了约81%。也就是说,用数据集中70%的数据训练,就能较为准确地对剩下的数据进行预测,只根据特征就能判断这个人有没有患糖尿病。和实际情况对比,准确率达到81%。