分类树实例:泰坦尼克号生存预测
代码分解
-
需要导入的库
"""导入所需要的库""" 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_)