根据菜菜的课程进行整理,方便记忆理解
代码位置如下:
泰坦尼克号幸存者的预测
泰坦尼克号的沉没是世界上最严重的海难事故之一,今天我们通过分类树模型来预测一下哪些人可能成为幸存者。数据集在www.kaggle.com/c/titanic。数据集包含两个csv格式文件,data为我们接下来要使用的数据,test为kaggle提供的测试集。
导入所需要的库
from sklearn.tree import DecisionTreeClassifier
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split,cross_val_score,GridSearchCV
导入数据集,探索数据
df = pd.read_csv("./data.csv",index_col=0)
df.head()
df.shape
df.columns
# 首先看到数据之后的分析shape就是891条数据,11列(10个特征,一个标签)
# df.head() 展示数据前五条数据,用于查看数据结构
# df.columns column的名称列表是['Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp', 'Parch', 'Ticket','Fare', 'Cabin', 'Embarked']
# df.info() 展示数据的整体信息,数据的索引从 1 to 891
# 数据列信息 Survived 无空值 类型 int64
# Pclass 无空值 类型 int64
# Name 无空值 类型 object 字符串
# Sex 无空值 类型 object
# Age 无空值 类型 float64
# SibSp 无空值 类型 int64
# Parch 无空值 类型 int64
# Ticket 无空值 类型 object
# Fare 无空值 类型 float64
# Cabin 无空值 类型 int64
# Embarked 无空值 类型 int64
# 展示所有的类型数据的数量 dtypes: float64(2), int64(4), object(5)
# 内存占用 memory usage: 83.5+ KB
df.info()
对数据集进行预处理
# 注意删除列的时候,我们需要添加参数axis=1进行指定,否则默认是删除行
df.drop(["Name","Ticket","Cabin"],inplace=True,axis=1)
df.head()
# Age的缺失值的数量比较少,我们可以使用平均值进行填充
df["Age"] = df["Age"].fillna(df["Age"].mean())
# 删除Embarked中无关紧要的两条缺失值数据
# 可以使用两种方式进行删除空值行,第一种方式 直接调用df.dropna(inplace=True) 第二种方式通过索引进行删除 df[df["Embarked"].isnull()].index 布尔索引
df.dropna() # 并没有实质删除
# 快速查找缺失值的索引
df[df["Embarked"].isnull()].index
df.dropna(inplace=True)
# 转化object数据变成数值型数据,因为决策树在进行模型构建和预测的时候都是需要数值型数据
# 将Sex的二数值型数据变成【0,1】 使用bool索引并且使用astype变成int
df["Sex"] = (df["Sex"] == "male").astype("int")
# 将Embarked的多数值型数据变成【0,1,2,3】 使用索引的方式进行替换
# 我们可以将数据的种类提取出来形成一个列表
unique_list = df["Embarked"].unique().tolist()
# 使用unique的列表的索引的部分进行数据替换,注意apply的使用
df["Embarked"] = df["Embarked"].apply(lambda x:unique_list.index(x))
提取标签和特征矩阵,分测试集和训练集
# 数据划分,Survived 标签列 其他列:特征列
X = df.loc[:,df.columns != "Survived"]
Y = df.loc[:,df.columns == "Survived"]
X.head()
Y.head()
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,Y,test_size = 0.3)
Xtrain.head()
# 在我们使用train_test_split进行分割数据之后,我们发现数据的索引变的杂乱无序,我们可以重置索引
Ytrain.head()
# 重置索引
Xtrain.index = [*range(len(Xtrain))]
Ytrain.index = [*range(len(Ytrain))]
Ytest.index = [*range(len(Ytest))]
Xtest.index = [*range(len(Ytest))]
导入模型,粗略跑一下查看结果
# 进行训练和测试 普通 fir + score 交叉验证
dtc = DecisionTreeClassifier(random_state=25)
dtc.fit(Xtrain,Ytrain)
score = dtc.score(Xtest,Ytest)
score
# 交叉验证
score_c = cross_val_score(dtc,X,Y,cv=10).mean()
score_c
在不同max_depth下观察模型的拟合状况
# 跑max_depth的学习曲线
fit_list = []
cross_list = []
for i in range(1,11):
dtc = DecisionTreeClassifier(random_state=30,max_depth=i+1,criterion="gini")
dtc.fit(Xtrain,Ytrain)
score_f = dtc.score(Xtest,Ytest)
score_c = cross_val_score(dtc,X,Y,cv=10).mean()
fit_list.append(score_f)
cross_list.append(score_c)
plt.figure()
plt.plot(range(1,11),fit_list,label="fit_score",color="r")
plt.plot(range(1,11),cross_list,label="cross_score",color="b")
print(max(cross_list))
plt.xlabel("Max_depth")
plt.ylabel("Score")
plt.title("ten time")
plt.legend()
plt.show()
用网格搜索调整参数
# 网格搜索
gini_thresholds = np.linspace(0,0.5,20)
parameters = {
"splitter":("best","random")
,"criterion":("gini","entrogy")
,"max_depth":[*range(1,10)]
,"min_samples_leaf":[*range(1,50,5)]
,"min_impurity_decrease":[*np.linspace(0,0.5,20)]
}
dtc = DecisionTreeClassifier(random_state=30)
GS = GridSearchCV(dtc,parameters,cv=10)
GS.fit(Xtrain,Ytrain)
# 网格搜索的属性
# 最好分数
GS.best_score_ # 0.8246
# 最好的属性组合
GS.best_params_
"""
{'criterion': 'gini',
'max_depth': 4,
'min_impurity_decrease': 0.0,
'min_samples_leaf': 6,
'splitter': 'best'}
"""