tree.DecisionTreeClassifier | 分类树 |
---|---|
tree.DecisionTreeRegressor | 回归树 |
tree.export_graphviz | 将生成的决策树导出为DOT格式,画图专用 |
tree.ExtraTreeClassifier | 高随机版本的分类树 |
tree.ExtraTreeRegressor | 高随机版本的回归树 |
from sklearn import tree #导入需要的模块
clf = tree.DecisionTreeClassifier() #实例化
clf = clf.fit(X_train,y_train) #用训练集数据训练模型
result = clf.score(X_test,y_test) #导入测试集,从接口中调用需要的信息
不纯度介绍:
1.衡量分类数的指标,数值越低说明拟合效果越好;
2.基于节点计算,每个结点都有不纯度;
3.子结点不纯度低于父节点,即叶子结点不纯度最低
criterion参数:
用来决定不纯度的计算方法,Entropy(信息熵)或者gini(基尼系数-默认)
说明:
1.t代表指定结点,i代表标签的任意分类,p(i|t)代表标签分类i在节点t上所占比例
2.信息熵的计算基于信息增益,即父节点信息熵和子节点信息熵的差
3.信息熵对不存度更敏感,计算较基尼系数慢(对数)。
4.信息熵对于高纬数据和噪音较多的数据容易过拟合,此时基尼系数一般效果更好
5.模型在训练集合测试集上都表现不好时,即拟合程度不足时,使用信息熵
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
wine = load_wine()
import pandas as pd
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
Xtrain, Xtest, Ytrain, Ytest =train_test_split(wine.data,wine.target,test_size=0.75)
步骤四:调用DecisionTreeClassifier进行分类并且评估
clf = tree.DecisionTreeClassifier(criterion="entropy")
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
import graphviz
dot_data = tree.export_graphviz(clf
,feature_names = feature_name
,class_names = ["琴酒","雪梨","贝尔摩德"]
,filled=True
,rounded=True)
#filled:颜色,深度越深越纯 ;rounded:轮廓
graph = graphviz.Source(dot_data)
clf.feature_importances_
决策树在每次分枝时,不从使用全部特征,而是随机选取一部分特征,从中选取不纯度相关指标最优的作为分枝用的节点。所以即使每次划分的数据集合训练集一样,最后的结果还是不同
random_state & splitter
random_state:用来设置分枝中的随机模式的参数,默认None,在高维度时随机性会表现更明显,低维度的数据(比如鸢尾花数据集),随机性几乎不会显现。输入任意整数,会一直长出同一棵树,让模型稳定下来。
splitter:用来控制决策树中的随机选项的,有两种输入值,输入”best",决策树在分枝时虽然随机,但是还是会优先选择更重要的特征进行分枝,输入“random",决策树在分枝时会更加随机,树会因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合。这是防止过拟合的一种方式。
剪枝参数
参数名 | 意义 |
---|---|
max_depth | 限制树的最大深度,超过设定深度的树枝全部剪掉 |
min_samples_leaf | 一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生 |
min_samples_split | 一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生 |
max_features | 限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃 |
min_impurity_decrease | 限制信息增益的大小,信息增益小于设定数值的分枝不会发生 |
说明:
目标权重参数
class_weight & min_weight_fraction_leaf
样本不平衡:在一组数据集中,标签的一类天生占有很大的比例。比如,在银行要判断“一个办了信用卡的人是否会违约”,就是是vs否(1%:99%)的比例。这种分类状况下,即便模型什么也不做,全把结果预测成“否”,正确率也能有99%。因此我们要使用class_weight参数对样本标签进行一定的均衡,给少量的标签更多的权重,让模型更偏向少数类,向捕获少数类的方向建模。
class_weight 默认None,表示自动给与数据集中的所有标签相同的权重。有了权重之后,样本量就不再是单纯地记录数目,而是受输入的权重影响了,因此这时候剪枝,就需要搭配min_weight_fraction_leaf这个基于权重的剪枝参数来使用。另请注意,基于权重的剪枝参数(例如min_weight_fraction_leaf)将比不知道样本权重的标准(比如min_samples_leaf)更少偏向主导类。如果样本是加权的,则使用基于权重的预修剪标准来更容易优化树结构,这确保叶节点至少包含样本权重的总和的一小部分
名称 | 作用 |
---|---|
feature_importances_(接口) | 查看各个特征对模型的重要性 |
apply | 输入测试集返回每个测试样本所在的叶子结点的索引 |
predict | 输入测试集返回每个测试样本的标签 |
回归树中,没有标签分布是否均衡的问题,因此没有class_weight这样的参数。其它与分类数一模一样!
criterion参数
支持三种标准:
MSE表达式:本质是样本真实数据与回归结果的差异
M S E = 1 n ∑ i = 1 N ( f i − y i ) 2 MSE=\frac{1}{n}\sum_{i=1}^{N}(f_i-y_i)^2 MSE=n1i=1∑N(fi−yi)2
N为样本数量,i为每一个数据样本, f i f_i fi是模型回归出的数值, y i y_i yi是样本实际的数值标签
回归树接口score返回R的平方(越接近1越好),而不是MSE。R定义为:
R 2 = 1 − u v R^2=1-\frac{u}{v} R2=1−vu
u = ∑ i = 1 N ( f i − y i ) 2 v = ∑ i = 1 N ( y i − y ^ ) 2 u=\sum_{i=1}^{N}(f_i-y_i)^2 \qquad v=\sum_{i=1}^{N}(y_i-\widehat{y})^2 u=i=1∑N(fi−yi)2v=i=1∑N(yi−y )2
u是残差平方和,v是总平方和,N是样本数量,i是每一个数据样本,fi是模型回归出的数值,yi是样本点i实际的数值标签。y帽是真实数值标签的平均数。R平方可以为正为负,而均方误差永远为正。
虽然均方误差永远为正,但是sklearn当中使用均方误差作为评判标准时,却是计算”负均方误差“。这是因为sklearn在计算模型评估指标的时候,会考虑指标本身的性质,均方误差本身是一种误差,所以被sklearn划分为模型的一种损失(loss),因此在sklearn当中,都以负数表示。真正的均方误差MSE的数值,其实就是neg_mean_squared_error去掉负号的数字。
交叉验证是用来观察模型的稳定性的一种方法,将数据划分为n份,依次使用其中一份作为测试集,其他n-1份作为训练集,多次计算模型的精确性来评估模型的平均准确程度。训练集和测试集的划分会干扰模型的结果,因此用交叉验证n次的结果求出的平均值是对模型效果的一个更好的度量。
简单代码举例:
from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor
boston = load_boston()
regressor = DecisionTreeRegressor(random_state=0)
cross_val_score(regressor, boston.data, boston.target, cv=10)
步骤一:所需库的导入,以及numpy创建训练集
import numpy as np
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt
rng = np.random.RandomState(1)
X = np.sort(5 * rng.rand(80,1),axis=0)
y = np.sin(X).ravel()
plt.figure()
plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")
y[::5] += 3*(0.5 - rng.rand(16))
plt.figure()
plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")
regr_1 = DecisionTreeRegressor(max_depth=2)
regr_2 = DecisionTreeRegressor(max_depth=5)
regr_1.fit(X, y)
regr_2.fit(X, y)
步骤四:导入测试集并开始预测
X_test = np.arange(0.0,5.0,0.01)[:,np.newaxis]
y_1 = regr_1.predict(X_test)
y_2 = regr_2.predict(X_test)
步骤五:图像的绘制
plt.figure()
plt.scatter(X, y, s=20, edgecolor="black",c="darkorange",label="data")
plt.plot(X_test, y_1, color="cornflowerblue",label="max_depth=2",linewidth=2)
plt.plot(X_test, y_2, color="yellowgreen",label="max_depth=5",linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()
可见,回归树学习了近似正弦曲线的局部线性回归。如果树的最大深度设置得太高,则决策树学习得太精细,它从训练数据中学了很多细节,包括噪声得呈现,从而使模型偏离真实的正弦曲线,形成过拟合。
步骤一:库与数据的导入
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pylab as plt
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
data = pd.read_csv("./data/data.csv")
data.info()
步骤二:数据预处理
Cabin、Name、Ticket无关紧要,删除!
data.drop(['Cabin','Name','Ticket'],inplace=True,axis=1)
# 记住,axis=1表示列
Age缺失200左右,且是连续值,需要填充!
Embarked 只缺两个,直接删!
处理字符型的数据,转成数字
labels = data["Embarked"].unique().tolist()
data["Embarked"] = data["Embarked"].apply(lambda x: labels.index(x))
data["Sex"] = (data["Sex"] == "male").astype("int")
data.head()
x = data.iloc[:,data.columns != "Survived"]
y = data.iloc[:,data.columns == "Survived"]
from sklearn.model_selection import train_test_split
Xtrain, Xtest ,Ytrain, Ytest = train_test_split(x,y,test_size=0.3)
for i in [Xtrain, Xtest ,Ytrain, Ytest]:
i.index = range(i.shape[0])
clf = DecisionTreeClassifier(random_state=25)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
score
tr = []
te = []
for i in range(10):
clf = DecisionTreeClassifier(random_state=25
,max_depth=i+1
)
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.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()
import numpy as np
gini_threholds = np.linspace(0,0.5,50)
parameters = {"criterion":("gini","entropy")
,"splitter":("best","random")
,"max_depth":[*range(1,10)]
,"min_samples_leaf":[*range(1,50,5)]
,"min_impurity_decrease":[*np.linspace(0,0.5,50)]
}
clf = DecisionTreeClassifier(random_state=25)
GS = GridSearchCV(clf,parameters,cv=10)
GS = GS.fit(Xtrain,Ytrain)
GS.best_params_
GS.best_score_
优点:
缺点: