1、认识决策树
简单来说就是我们程序中if判断的过程,比如下图就是一个简单的决策过程:
图中根据年龄,长相,收入,是否是程序员来判断是否见面。这就是一个简单的决策过程。
为什么把年龄判断放在第一个判断,不把长相,收入,就是为了减少不确定性。
在相亲过程中可能年龄这个特征比较重要,但是在实际其他应用中,我们把哪个特征放在第一位?
怎么知道哪个特征比较重要?
这里引入一个名词:信息熵(单位bit)
关于信息熵的定义可以去看这篇文章:
https://www.zhihu.com/question/22178202
简单来说信息熵越大,不确定性越大。(信息和消除不确定性是相联系的)
信息增益:满足一个条件之后,减少的信息熵大小。
这里根据信息熵计算出信息增益,信息增益最大的把他放在第一位进行决策。
信息增益就是决策树的分类依据之一。
2、决策树模块
sklearn.tree.DecisionTreeClassifier(criterion='gini',max_depth=None,random_state=None)
criterion:默认为gini系数,也就是分类依据,也可以选择entropy也就是信息增益
max_depth:树的深度大小
random_state:随机数种子
3、实例
泰坦里克号数据:根据票的类别,存货,年龄,性别等判断在事故中的存活状况。
数据来源:http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt
代码语言:javascript复制import pandas as pd
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.tree import DecisionTreeClassifier,export_graphviz
from sklearn.ensemble import RandomForestClassifier
def decision():
'''决策树预测泰坦尼克号存亡情况'''
# 获取数据
taitan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
# 处理数据
# 目标值为survived
# 特征值我选择:pclass,age,sex
x = taitan[['pclass','age','sex']]
y = taitan['survived']
# 处理age缺失值
x['age'].fillna(x['age'].mean(),inplace=True)
# 分割数据集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)
# 处理数据
# 对pclass,home.dest,room,sex进行one-hot编码
dict = DictVectorizer(sparse=False)
# to_dict转化成字典,orient="records"表示把每一行都转化成一个字典
x_train = dict.fit_transform(x_train.to_dict(orient="records"))
x_test = dict.transform(x_test.to_dict(orient="records"))
# 用决策树进行预测,暂时不写参数,需要用网格搜索和交叉验证
dec = DecisionTreeClassifier()
dec.fit(x_train,y_train)
print("预测的准确率:",dec.score(x_test,y_test))
'''
预测的准确率: 0.8115501519756839
'''
if __name__ == "__main__":
decision()
4、优缺点
优点:
树木可视化,可以运用Graphviz工具将决策图导出。
数据量准备较少,不用归一化处理
缺点:
决策树结构过于复杂,过拟合。
改进:
减枝cart算法(DecisionTreeClassifier中的min_samples_split和min_samples_leaf参数)
随机森林
随机森林
集成学习方法:比如一个分类,可以用k-近邻,朴素贝叶斯,决策树,各自独立学习作出预测,最后结合成单预测,优于其中的单个算法预测。而多个决策树集成学习就是随机森林。
随机森林建立多个决策树的过程:
现在有N个样本M个特征。
单个树建立:
1、随机选择N个样本中的一个样本,重复N次。随机选择样本可能重复
2、随机在M个特征中选择x个特征
随即有放回的抽样叫做bootstrap抽样。
随机抽样是为了每次的训练集不一样,如果都一样,就没有意义了。
随机森林模块;
sklearn.ensemble.RandomForestClassifier(n_estimators=10,riterion='gini',max_depth=None,bootstrap=True,random_state=None)
n_estimators:生成多少个决策树
riterion:默认为gini系数,也就是分类依据,也可以选择entropy也就是信息增益
max_depth:树的最大深度
bootstrap:是否随即有放回的抽样
random_state:每个决策树的最大特征数量
实例:
代码语言:javascript复制import pandas as pd
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.tree import DecisionTreeClassifier,export_graphviz
from sklearn.ensemble import RandomForestClassifier
def randdecision():
'''决策树预测泰坦尼克号存亡情况'''
# 获取数据
taitan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
# 处理数据
# 目标值为survived
# 特征值我选择:pclass,age,sex
x = taitan[['pclass','age','sex']]
y = taitan['survived']
# 处理age缺失值
x['age'].fillna(x['age'].mean(),inplace=True)
# 分割数据集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)
# 处理数据
# 对pclass,home.dest,room,sex进行one-hot编码
dict = DictVectorizer(sparse=False)
# to_dict转化成字典,orient="records"表示把每一行都转化成一个字典
x_train = dict.fit_transform(x_train.to_dict(orient="records"))
x_test = dict.transform(x_test.to_dict(orient="records"))
# 随机森林进行预测
rf = RandomForestClassifier()
# 网格搜索与交叉验证
# 构造参数字典
param = {"n_estimators":[10,30,50,70],"max_depth":[3,5,10]}
gc = GridSearchCV(rf,param_grid=param,cv=10)
gc.fit(x_train,y_train)
print("预测的准确率:",gc.score(x_test,y_test))
print("选择的数据模型为:",gc.best_params_)
'''
预测的准确率: 0.78419452887538
选择的数据模型为: {'max_depth': 3, 'n_estimators': 10}
'''
if __name__ == "__main__":
randdecision()
效果反而不好了!随机森林的优势是在大量数据和很多特征值的情况下,可能这里选择参数不是很匹配。
优点:
1、准确率
2、有效处理大数据
3、能够处理高维度的样本,不需要降维
4、能够评估各个特征在分类中的重要性