"""主要是存储本人的笔记为主,但是希望和各位进行交流""
简介:该代码主要会用 train_test_split 及 cross_val_score验证模型的有效度。 此外,还会用GridSearchCV找出模型最优的参数。
step 1:对数据进行处理,比如填补或者删除缺失值。此外, 决策树无法处理文字,所以,我们需要把性别(sex)及 船票号码(embark)转换数字。比如,0,1,2等无意义的数字。
import pandas as pd
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
import numpy as np
import graphviz
"""读取数据及观察数据"""
data = pd.read_csv("data【瑞客论坛 www.ruike1.com】.csv")
data.info()
data.head()
"""处理数据"""
##删除缺失值过多的列,和观察判断来说和预测的y没有关系的列
# inplace 是指将原有的数据进行合并。axis = 1 是指列00
data.drop(["Cabin","Name","Ticket","Cabin"],inplace=True,axis=1)
data.info()
#以整体年龄的平均数填充缺失值年龄,
data["Age"] = data["Age"].fillna(data["Age"].mean())
data.info()
#将缺失值的“行” 一并删除。 括号内 默认是“0”, 0 是指行的意思,反之1则是列的意思
data = data.dropna()
data.info()
#tolist是将数据转换成list的形式,而 unique主要是找出该数据含有那几种分类
label_1 = data["Embarked"].unique().tolist()
#将数据以 o 1 3 进行替换。 替换的原因是 decision tree classifier是不接受中文字的运算
data["Embarked"] = data["Embarked"].apply(lambda x: label_1.index(x))
#这是另外一种投机的转换方法。 因为 male 和femal 是以 true 和 false 的数据形式进行表达。
#我们直接按照下面的代码进行强制转换便可
data["Sex"] = (data["Sex"]== "male").astype("int")
Step 2 建立模型。
"""建立模型"""
#取出 所有行 的所有列的columns不等于 survivied的值
x = data[["Pclass","Sex","Age","SibSp","Fare","Embarked"]]
y = data["Survived"]
print(y)
#拆分数据集
x_train, x_test, y_train, y_test = train_test_split(x,y, test_size = 0.3)
Step 3 粗略看看模型的分数(用train test split 及 cross validation(交叉验证)的方法)。
注意到:由于在step 2, 我们用了train test split 分割了数据。 数据的索引会有所混乱(ie,0 1 2,30,29,60之类的情况)。 所以在下面代码的 for 循环 是为了将代码的索引整理成 0 1 2 3. 这个步骤是为了在后面进行更好的测试模型的效能。
#由于索引在拆分的时候已经出现了混乱, 所以为了更好的进行modeling的操作,所以需要进行重新排列索引
for i in [x_train, x_test, y_train, y_test]:
i.index = range(i.shape[0])
clf = DecisionTreeClassifier(random_state=(25))
clf = clf.fit(x_train, y_train)
#这个是第一种验证模型的有效度
score_1 = clf.score(x_test, y_test)
score_1
#这是第二种方法验证模型的有效度
score_2 = cross_val_score(clf, x,y, cv=10).mean()
score_2
从上图可以看到两个score 的分数差异很大(0.58及0.78. 满分为1)。说明model还有很大的改善空间。
Step 4 找出模型的最优的参数。
1.train and test split 和 cross_val_score 的方法
我们会用matplotlip 进行数据可视化。看看cross_val_score 和cross_val_score 的有效度有没有出现过大的偏差。如果有的话,会用其他方法参数将模型的表现进行最大的提高。
"""数据可视化,看看model的有效度"""
tr = []
td = []
for i in range(10):
clf = DecisionTreeClassifier(random_state=(25), max_depth=(i +1),criterion="entropy",min_samples_leaf =16)
clf.fit(x_train,y_train)
score_tr = clf.score(x_train,y_train)
score_td = cross_val_score(clf, x,y,cv =10).mean()
tr.append(score_tr)
td.append(score_td)
print(max(td))
plt.plot(range(1,11),tr, color = "red",label ="train")
plt.plot(range(1,11),td, color = "blue",label ="test")
plt.legend()
plt.show()
#利用上面得到的参数重新建模,看看实际效果
X_train, X_test, y_train, y_test = train_test_split(x,y, test_size=0.3,random_state=0)
clf =tree.DecisionTreeClassifier(criterion ="entropy"
,max_depth=3
)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
从上图可以看到,train(红线) 和 test(蓝线)最接近重叠的地方是当max_depth= 3的时候。因此,我们会选择 maxd_depth 等于 3的结果。基于个人的经验, 我觉得criterion改为“entropy'会令model的性能更加好。
当我们套入这个参数(max_depth= 3)及criterion = entropy',我们可以看到分数是0.79分数。比step 3的分数要好很多。
2. 用GridSearchCV的方法找出最优的参数。但是这个方法并非完美的。因为,这个方法是基于下列的所以参数中找出最高的score,但是也许不要 min samples leaf 的参数或许能得到更高的分数
""利用用网格搜索调整参数,找出最高的有效度的决策树。但是这并非最精准的。因为,这个方法是基于下列的所以参数中找出最高的score,
但是也许不要 min samples leaf 的参数或许能得到更高的分数"""
gini_thresholds = np.linspace(0,0.5,20)
arameters = {'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(x_train,y_train)
GS.best_params_
GS.best_score_
#利用上面得到的参数重新建模,看看实际效果
X_train, X_test, y_train, y_test = train_test_split(x,y, test_size=0.3,random_state=0)
clf =tree.DecisionTreeClassifier(criterion ="entropy"
,splitter="best"
,max_depth=6
,min_samples_leaf =1
,min_samples_split =10
,min_impurity_decrease= 0
)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
Step 5: 我们基于 Step 4已经找到了最优模型的参数,选择可以用graphviz 进行决策树的可视化了。
"""选取最优的分数进行graphviz可视化"""
X_train, X_test, y_train, y_test = train_test_split(x,y, test_size=0.3,random_state=0)
clf =tree.DecisionTreeClassifier(criterion ="entropy"
,splitter="best"
,max_depth=6
,min_samples_leaf =1
,min_samples_split =10
,min_impurity_decrease= 0
)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
feature_name =["Pclass","Sex","Age","SibSp","Fare","Embarked"]
dot_data = tree.export_graphviz(clf
, feature_names = feature_name
, class_names =["生","死"]
, filled = True#圆头的意思
, rounded =True#颜色的意思
)
graphviz.Source(dot_data)
最后的结果如下啦:
我对于 这一步可视化的代码并不是特别熟悉。希望各位能提供更好的代码及解释,感谢!
完整代码如下:
import pandas as pd
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
import numpy as np
import graphviz
"""读取数据及观察数据"""
data = pd.read_csv("data【瑞客论坛 www.ruike1.com】.csv")
data.info()
data.head()
"""处理数据"""
##删除缺失值过多的列,和观察判断来说和预测的y没有关系的列
# inplace 是指将原有的数据进行合并。axis = 1 是指列00
data.drop(["Cabin","Name","Ticket","Cabin"],inplace=True,axis=1)
data.info()
#以整体年龄的平均数填充缺失值年龄,
data["Age"] = data["Age"].fillna(data["Age"].mean())
data.info()
#将缺失值的“行” 一并删除。 括号内 默认是“0”, 0 是指行的意思,反之1则是列的意思
data = data.dropna()
data.info()
#tolist是将数据转换成list的形式,而 unique主要是找出该数据含有那几种分类
label_1 = data["Embarked"].unique().tolist()
#将数据以 o 1 3 进行替换。 替换的原因是 decision tree classifier是不接受中文字的运算
data["Embarked"] = data["Embarked"].apply(lambda x: label_1.index(x))
#这是另外一种投机的转换方法。 因为 male 和femal 是以 true 和 false 的数据形式进行表达。
#我们直接按照下面的代码进行强制转换便可
data["Sex"] = (data["Sex"]== "male").astype("int")
data.head()
"""建立模型"""
#取出 所有行 的所有列的columns不等于 survivied的值
x = data[["Pclass","Sex","Age","SibSp","Fare","Embarked"]]
y = data["Survived"]
print(y)
#拆分数据集
x_train, x_test, y_train, y_test = train_test_split(x,y, test_size = 0.3)
#由于索引在拆分的时候已经出现了混乱, 所以为了更好的进行modeling的操作,所以需要进行重新排列索引
for i in [x_train, x_test, y_train, y_test]:
i.index = range(i.shape[0])
clf = DecisionTreeClassifier(random_state=(25))
clf = clf.fit(x_train, y_train)
#这个是第一种验证模型的有效度
score_1 = clf.score(x_test, y_test)
score_1
#这是第二种方法验证模型的有效度
score_2 = cross_val_score(clf, x,y, cv=10).mean()
score_2
"""数据可视化,看看model的有效度"""
tr = []
td = []
for i in range(10):
clf = DecisionTreeClassifier(random_state=(25), max_depth=(i +1),criterion="entropy",min_samples_leaf =16)
clf.fit(x_train,y_train)
score_tr = clf.score(x_train,y_train)
score_td = cross_val_score(clf, x,y,cv =10).mean()
tr.append(score_tr)
td.append(score_td)
print(max(td))
plt.plot(range(1,11),tr, color = "red",label ="train")
plt.plot(range(1,11),td, color = "blue",label ="test")
plt.legend()
plt.show()
#利用上面得到的参数重新建模,看看实际效果
X_train, X_test, y_train, y_test = train_test_split(x,y, test_size=0.3,random_state=0)
clf =tree.DecisionTreeClassifier(criterion ="entropy"
,max_depth=3
)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
"""利用用网格搜索调整参数,找出最高的有效度的决策树。但是这并非最精准的。因为,这个方法是基于下列的所以参数中找出最高的score,
但是也许不要 min samples leaf 的参数或许能得到更高的分数"""
gini_thresholds = np.linspace(0,0.5,20)
arameters = {'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(x_train,y_train)
GS.best_params_
GS.best_score_
#利用上面得到的参数重新建模,看看实际效果
X_train, X_test, y_train, y_test = train_test_split(x,y, test_size=0.3,random_state=0)
clf =tree.DecisionTreeClassifier(criterion ="entropy"
,splitter="best"
,max_depth=6
,min_samples_leaf =1
,min_samples_split =10
,min_impurity_decrease= 0
)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
"""选取最优的分数进行graphviz可视化"""
X_train, X_test, y_train, y_test = train_test_split(x,y, test_size=0.3,random_state=0)
clf =tree.DecisionTreeClassifier(criterion ="entropy"
,splitter="best"
,max_depth=6
,min_samples_leaf =1
,min_samples_split =10
,min_impurity_decrease= 0
)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
feature_name =["Pclass","Sex","Age","SibSp","Fare","Embarked"]
dot_data = tree.export_graphviz(clf
, feature_names = feature_name
, class_names =["生","死"]
, filled = True#圆头的意思
, rounded =True#颜色的意思
)
graphviz.Source(dot_data)