分类树实例:泰坦尼克号生存预测
代码分解
需要导入的库
"""导入所需要的库""" import pandas as pd import numpy as np from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.model_selection import GridSearchCV from sklearn.model_selection import cross_val_score import matplotlib.pyplot as plt
导入数据集
"""导入数据集,探索数据""" data_train = pd.read_csv('./need/Taitanic_data/data.csv',index_col=0) data_test = pd.read_csv('./need/Taitanic_data/test.csv',index_col=0) data = pd.concat([data_train,data_test],axis=0) data.head() data.info()
对数据集进行预处理
"""对数据集进行预处理""" #删除缺失值过多的列,和观察判断来说和预测的y没有关系的列 data.drop(["Cabin","Name","Ticket"],inplace=True,axis=1) #处理缺失值,对缺失值较多的列进行填补,有一些特征只确实一两个值,可以采取直接删除记录的方法 data["Age"] = data["Age"].fillna(data["Age"].mean()) data = data.dropna() #将分类变量转换为数值型变量 #将二分类变量转换为数值型变量 #astype能够将一个pandas对象转换为某种类型,和apply(int(x))不同,astype可以将文本类转换为数字,用这 个方式可以很便捷地将二分类特征转换为0~1 data["Sex"] = (data["Sex"]== "male").astype("int") #将三分类变量转换为数值型变量 labels = data["Embarked"].unique().tolist() data["Embarked"] = data["Embarked"].apply(lambda x: labels.index(x)) #查看处理后的数据集 data.head()
提取标签和特征矩阵,分测试集和训练集
"""提取标签和特征矩阵,分测试集和训练集""" X = data.iloc[:,data.columns != "Survived"] y = data.iloc[:,data.columns == "Survived"] Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3) #修正测试集和训练集的索引(或者直接reset_index(drop=True,inplace=True)) for i in [Xtrain, Xtest, Ytrain, Ytest]: i.index = range(i.shape[0]) #查看分好的训练集和测试集 Xtrain.head()
导入模型,粗略跑一下查看结果
"""导入模型,粗略跑一下查看结果""" clf = DecisionTreeClassifier(random_state=25) clf = clf.fit(Xtrain, Ytrain) score_ = clf.score(Xtest, Ytest) print('单颗决策树精度',score_) score = cross_val_score(clf,X,y,cv=10).mean() print('10次交叉验证平均精度',score) """输出""" 单颗决策树精度 0.8164794007490637 10次交叉验证平均精度 0.7739274770173645
在不同max_depth下观察模型的拟合状况
"""在不同max_depth下观察模型的拟合状况""" tr = [] # 训练集精度 te = [] # 测试集交叉验证精度 for i in range(10): clf = DecisionTreeClassifier(random_state=25 ,max_depth=i+1 ,criterion="entropy" ) clf = clf.fit(Xtrain, Ytrain) score_tr = clf.score(Xtrain,Ytrain) score_te = cross_val_score(clf,X,y,cv=10).mean() tr.append(score_tr) te.append(score_te) print("测试集交叉验证均值最大值(精度)",max(te)) plt.figure(figsize=(12,8)) plt.plot(range(1,11),tr,color="red",label="train") plt.plot(range(1,11),te,color="blue",label="test") plt.xticks(range(1,11)) plt.legend() plt.show() #这里为什么使用“entropy”?因为我们注意到,在最大深度=3的时候,模型拟合不足,在训练集和测试集上的表现接 近,但却都不是非常理想,只能够达到83%左右,所以我们要使用entropy。 """输出""" 测试集交叉验证均值最大值(精度) 0.8177860061287026
用
网格搜索
调整参数"""用网格搜索调整参数""" gini_thresholds = np.linspace(0,0.5,20) parameters = {'splitter':('best','random') ,'criterion':("gini","entropy") ,"max_depth":[*range(1,10)] ,'min_samples_leaf':[*range(1,50,5)] ,'min_impurity_decrease':[*np.linspace(0,0.5,20)] } clf = DecisionTreeClassifier(random_state=25) GS = GridSearchCV(clf, parameters, cv=10) GS.fit(Xtrain,Ytrain) print('最佳参数',GS.best_params_) print('最佳精度',GS.best_score_) """输出""" 最佳参数 {'criterion': 'entropy' , 'max_depth': 9 , 'min_impurity_decrease': 0.0 , 'min_samples_leaf': 6 , 'splitter': 'best' } 最佳精度 0.815284178187404
由此可见,网格搜索并非一定比自己调参好,因为网格搜索无法舍弃无用的参数,默认传入的所有参数必须得都选上。
所有代码
所有代码
"""导入所需要的库""" import pandas as pd import numpy as np from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.model_selection import GridSearchCV from sklearn.model_selection import cross_val_score import matplotlib.pyplot as plt """导入数据集,探索数据""" data_train = pd.read_csv('./need/Taitanic_data/data.csv',index_col=0) data_test = pd.read_csv('./need/Taitanic_data/test.csv',index_col=0) data = pd.concat([data_train,data_test],axis=0) data.head() data.info() """对数据集进行预处理""" #删除缺失值过多的列,和观察判断来说和预测的y没有关系的列 data.drop(["Cabin","Name","Ticket"],inplace=True,axis=1) #处理缺失值,对缺失值较多的列进行填补,有一些特征只确实一两个值,可以采取直接删除记录的方法 data["Age"] = data["Age"].fillna(data["Age"].mean()) data = data.dropna() #将分类变量转换为数值型变量 #将二分类变量转换为数值型变量 #astype能够将一个pandas对象转换为某种类型,和apply(int(x))不同,astype可以将文本类转换为数字,用这 个方式可以很便捷地将二分类特征转换为0~1 data["Sex"] = (data["Sex"]== "male").astype("int") #将三分类变量转换为数值型变量 labels = data["Embarked"].unique().tolist() data["Embarked"] = data["Embarked"].apply(lambda x: labels.index(x)) #查看处理后的数据集 data.head() """提取标签和特征矩阵,分测试集和训练集""" X = data.iloc[:,data.columns != "Survived"] y = data.iloc[:,data.columns == "Survived"] Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3) #修正测试集和训练集的索引(或者直接reset_index(drop=True,inplace=True)) for i in [Xtrain, Xtest, Ytrain, Ytest]: i.index = range(i.shape[0]) #查看分好的训练集和测试集 Xtrain.head() """导入模型,粗略跑一下查看结果""" clf = DecisionTreeClassifier(random_state=25) clf = clf.fit(Xtrain, Ytrain) score_ = clf.score(Xtest, Ytest) print('单颗决策树精度',score_) score = cross_val_score(clf,X,y,cv=10).mean() print('10次交叉验证平均精度',score) """在不同max_depth下观察模型的拟合状况""" tr = [] # 训练集精度 te = [] # 测试集交叉验证精度 for i in range(10): clf = DecisionTreeClassifier(random_state=25 ,max_depth=i+1 ,criterion="entropy" ) clf = clf.fit(Xtrain, Ytrain) score_tr = clf.score(Xtrain,Ytrain) score_te = cross_val_score(clf,X,y,cv=10).mean() tr.append(score_tr) te.append(score_te) print("测试集交叉验证均值最大值(精度)",max(te)) plt.figure(figsize=(12,8)) plt.plot(range(1,11),tr,color="red",label="train") plt.plot(range(1,11),te,color="blue",label="test") plt.xticks(range(1,11)) plt.legend() plt.show() #这里为什么使用“entropy”?因为我们注意到,在最大深度=3的时候,模型拟合不足,在训练集和测试集上的表现接 近,但却都不是非常理想,只能够达到83%左右,所以我们要使用entropy。 """用网格搜索调整参数""" # gini系数最大为0.5最小为0、信息增益最大为1,最小为0 gini_thresholds = np.linspace(0,0.5,20) parameters = {'splitter':('best','random') ,'criterion':("gini","entropy") ,"max_depth":[*range(1,10)] ,'min_samples_leaf':[*range(1,50,5)] ,'min_impurity_decrease':[*np.linspace(0,0.5,20)] } clf = DecisionTreeClassifier(random_state=25) GS = GridSearchCV(clf, parameters, cv=10) GS.fit(Xtrain,Ytrain) print('最佳参数',GS.best_params_) print('最佳精度',GS.best_score_)