说明:
- 模型:决策树
- 数据集:西瓜书2.0
- 任务:用模型来区别好瓜和坏瓜(二分类)
"""导库"""
from sklearn import tree
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score as acc
from sklearn.model_selection import train_test_split as tts
import graphviz
import matplotlib.pyplot as plt
"""导数据集"""
data = pd.read_excel('watermelon.xlsx')
"""查看数据"""
data
可以看到,特征都是文字,也没有缺失值,模型不认识,需要转化成模型认识的特征。由于数据量小,可以直接查看,如果数据量大,很难发现缺失值,那么可以用data.info来查看数据的信息。
数据预处理
只做了ont-hot编码
"""特征间没有大小或者运算关系,直接做one-hot编码"""
dummy_df = pd.get_dummies(data.loc[:,data.columns[1:-1]])
data_dm = pd.concat([data,dummy_df],axis=1)
data_dm = data_dm.drop(data.columns[1:-1],axis=1)
data_dm
"""模型,其实可以理解为函数,每个x对应一个y"""
x = data_dm.iloc[:,2:]
y = data_dm.iloc[:,1]
# 查看一下x
x
# 查看一下y
y
可见,y还是文字,我们需要把它改成模型认识的数值。
# 对y进行0,1转化,1代表好瓜,0代表坏瓜
y = LabelEncoder().fit_transform(y)
# 再来查看一下y
y
可见,转化成功。
没有做特征工程,感觉没啥好做的,但是并不是没得做,有兴趣的可以探索一下。
# 切分训练集和测试集
Xtrain, Xtest, Ytrain, Ytest = tts(x,y,test_size = 0.3,random_state=30)
建立模型
# 训练,默认参数,默认选节点的指标是基尼系数
model = tree.DecisionTreeClassifier()
model = model.fit(Xtrain,Ytrain)
# 测试
p = model.predict(Xtest)
score = acc(p,Ytest)
score
可见,默认参数建立的模型,准确率只有0.66…,不算高。
来观察这一棵树是怎么来做决策的。
dot_data = tree.export_graphviz(model
,out_file = None
,feature_names= data_dm.columns[2:]
,class_names=["好瓜","坏瓜"]
,filled=True
,rounded=True
)
graph = graphviz.Source(dot_data)
graph
# 我瞎调一下模型的参数,在这里只做对两个参数的探究:min_samples_leaf,min_samples_split
model = tree.DecisionTreeClassifier(criterion="entropy"
,random_state=30
,splitter="random"
,min_samples_leaf=3
,min_samples_split=2
)
model = model.fit(Xtrain,Ytrain)
p = model.predict(Xtest)
score = acc(p,Ytest)
score
可见,准确率上来了,但是,这是不是最优的呢?
那就要去探索一下了。
分享两种调参方法
- 画学习曲线:一般是探索某一个参数
- 网格搜索:探索多个参数的最优参数组合。
画学习曲线
在这里只探索min_samples_leaf
test = []
for i in range(5):
model = tree.DecisionTreeClassifier(criterion="entropy"
,random_state=30
,splitter="random"
,min_samples_leaf=i+1
,min_samples_split=2
)
clf = model.fit(Xtrain, Ytrain)
score = model.score(Xtest, Ytest)
test.append(score)
plt.plot(range(1,6),test,color="red",label="min_samples_leaf")
plt.legend()
plt.show()
可见,有一个准确率达到了1.0。即在这个测试集上,能达到100%的准确率。
那么我们来看一下是不是真的?
model = tree.DecisionTreeClassifier(criterion="entropy"
,random_state=30
,splitter="random"
,min_samples_leaf=2
,min_samples_split=2
)
model = model.fit(Xtrain,Ytrain)
p = model.predict(Xtest)
score = acc(p,Ytest)
score
嗯,确实如此。
网格搜索
from sklearn.model_selection import GridSearchCV
gs = GridSearchCV(model, {'min_samples_leaf':range(1,5), 'min_samples_split':range(2,5)})
gs
观察网格搜索出来的参数,min_samples_leaf=2,min_samples_split=2。
我们把搜索出来的参数全都填进去。观察是不是最优的参数?
model = tree.DecisionTreeClassifier(ccp_alpha=0.0, class_weight=None,
criterion='gini', max_depth=None,
max_features=None,
max_leaf_nodes=None,
min_impurity_decrease=0.0,
min_impurity_split=None,
min_samples_leaf=2,
min_samples_split=2,
min_weight_fraction_leaf=0.0,
presort='deprecated',
random_state=30,
splitter='best')
model = model.fit(Xtrain,Ytrain)
p = model.predict(Xtest)
score = acc(p,Ytest)
score
嗯,也确实如此。
Thank you!!!