课程地址:《菜菜的机器学习sklearn课堂》_哔哩哔哩_bilibili
第一期:sklearn入门 & 决策树在sklearn中的实现第二期:随机森林在sklearn中的实现第三期:sklearn中的数据预处理和特征工程第四期:sklearn中的降维算法PCA和SVD第五期:sklearn中的逻辑回归第六期:sklearn中的聚类算法K-Means第七期:sklearn中的支持向量机SVM(上)第八期:sklearn中的支持向量机SVM(下)第九期:sklearn中的线性回归大家族第十期:sklearn中的朴素贝叶斯第十一期:sklearn与XGBoost第十二期:sklearn中的神经网络
目录
sklearn入门
决策树(Decision Tree,DT)
(一)决策树是如何工作的
(二)sklearn中的决策树
分类树DecisionTreeClassifier与红酒数据集
重要参数
(一)criterion:用来决定不纯度的计算方法
(二)random_state & splitter:控制随机性
(三)剪枝参数(5个)
(四)目标权重参数(完成样本标签平衡的参数,不常用)
重要属性和接口
总结
回归树DecisionTreeRegressor与波士顿房价数据集
重要参数、属性及接口
(一)criterion(回归树衡量分枝质量的指标)
(二)属性
(三)接口
(四)交叉验证
实例:一维回归的图像绘制
决策树的优缺点
sklearn入门
scikit-learn是一个开源的基于Python的机器学习工具包
分析采集到的数据,根据数据特征选择适合的算法,在工具包中调用算法,调整算法的参数,获取需要的信息,从而实现算法效率和效果之间的平衡
解析sklearn的全面应用,了解不同机器学习算法有哪些可调参数、有哪些可用接口,这些接口和参数对算法来说有什么含义,又会对算法的性能及准确性有什么影响 —— 讲解sklearn中对算法的说明、调参、属性、接口,以及实例应用
sklearn官网:scikit-learn: machine learning in Python — scikit-learn 1.2.0 documentation
分类、回归、聚类、降维、模型选择、数据预处理
决策树(Decision Tree,DT)
(一)决策树是如何工作的
是一种非参数(不限制数据的结构和类型,几乎可以用它来处理各种各样的数据)的有监督学习(要给标签)方法,能够从一系列有特征和标签的数据中总结出决策规则,并用树状图的结构来呈现这些规则,以解决分类和回归问题
以树模型为核心的各种集成算法(如Adaboost、随机森林)本质是一种图结构,只需要问一系列问题就可以对数据进行分类了
决策树算法的核心是要解决两个问题:
如何从数据表中找出最佳节点和最佳分枝?(如何找出正确的特征来进行提问?)
定义了用来衡量分枝质量的指标——不纯度,分类树的不纯度用基尼系数或信息熵来衡量,回归树的不纯度用MSE均方误差来衡量
每次分枝时,决策树对所有的特征进行不纯度计算,选取不纯度最低的特征进行分枝,分枝后,又再对被分枝的不同取值下,计算每个特征的不纯度,继续选取不纯度最低的特征进行分枝
如何让决策树停止生长,防止过拟合?
每分枝一层,树整体的不纯度会越来越小,决策树追求的是最小不纯度。因此,决策树会一直分枝,直到没有更多的特征可用,或整体的不纯度指标已经最优,决策树就会停止生长
(二)sklearn中的决策树
模块sklearn.tree,包含五个类(还有两个类分别是高随机版本的分类树和回归树,不常用):
tree.DecisionTreeClassifier:分类树tree.DecisionTreeRegressor:回归树tree.export_graphviz:将生成的决策树导出为DOT格式,画图专用
sklearn的基本建模流程:
在这个流程下,分类树对应的代码是:
from sklearn import treeclf = tree.DecisionTreeClassifier() # 实例化clf = clf.fit(X_train,y_train) # 用训练集数据训练模型result = clf.score(X_test,y_test) # 导入测试集,从接口中调用需要的信息(对分类模型来说就是accuracy)
分类树DecisionTreeClassifier与红酒数据集
sklearn.tree.DecisionTreeClassifier — scikit-learn 1.2.0 documentation
重要参数
(一)criterion:用来决定不纯度的计算方法
为了要将表格转化成一棵树,决策树需要找出最佳节点和最佳分枝方法。对分类树来说,衡量这个最佳的指标是不纯度
不纯度越低,决策树对训练集的拟合越好基于节点来计算,子节点的不纯度一定低于父节点在同一棵决策树上,叶子节点的不纯度一定最低
sklearn提供了两种选择:
entropy:信息熵(实际计算的是基于信息熵的信息增益,即父节点的信息熵和子节点的信息熵之差。子节点的信息熵一定小于父节点,所以信息增益越大,这一层分枝对决策树的贡献就越大),取值范围为0~1gini:基尼系数(默认),取值范围为0~0.5
对比:
信息熵对不纯度更加敏感,所以信息熵作为指标时,决策树的生长会更加精细,因此对于高维数据或噪音很多的数据,信息熵很容易过拟合,基尼系数在这种情况下效果往往比较好当模型拟合程度不足时,即当模型在训练集和测试集上都表现不太好时,使用信息熵
决策树的基本流程可以简单概括为:
计算全部特征的不纯度指标 ——> 选取不纯度指标最优的特征来分枝 ——> 在第一个特征的分枝下,计算全部特征的不纯度指标 ——> 选取不纯度指标最优的特征继续分枝... ——> 直到没有更多的特征可用,或整体的不纯度指标已经最优,决策树就会停止生长
from sklearn import treefrom sklearn.datasets import load_wine # datasets是sklearn自带的含有各种各样数据的库,包含波士顿房价、鸢尾花、红酒数据等from sklearn.model_selection import train_test_splitwine = load_wine() # 数据实例化# wine是一个字典,wine.data取数据,wine.target取标签wine.data.shape # 13个特征wine.target # 三分类# 将wine变成一张表import pandas as pdpd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
wine.feature_nameswine.target_names# 分训练集和测试集Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)# 建立模型clf = tree.DecisionTreeClassifier(criterion="entropy") # 实例化,criterion默认为giniclf = clf.fit(Xtrain, Ytrain) # 把数据带进去训练score = clf.score(Xtest, Ytest) # 返回预测的准确度accuracyscore
# 画树feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']import graphvizdot_data = tree.export_graphviz(clf # 已经训练好的模型,feature_names = feature_name,class_names=["琴酒","雪莉","贝尔摩德"],filled=True # 填充颜色(不纯度越低,颜色越深),rounded=True # 框的形状) graph = graphviz.Source(dot_data) # 越往下,不纯度entropy越低。不纯度为0时,就可以选出标签类别了graph
# 特征重要性(没有使用的特征,为0)clf.feature_importances_ # 对决策树贡献越大的,重要性越高(根节点对特征重要性的贡献一定是最大的)[*zip(feature_name,clf.feature_importances_)]
上述代码每次运行得到的结果都不一样,这是为什么?
无论决策树模型如何进化,在分枝上的本质都还是追求某个不纯度相关指标的优化不纯度是基于节点来计算的,即决策树在建树时,是靠优化节点来追求一棵优化的树,但最优的节点不能保证一定是最优的树sklearn基本思想则是,既然一棵树不能保证最优,那就建更多不同的树,然后从中取最好的怎样从一组数据集中建不同的树?在每次分枝时,不使用全部特征,而是随机选取一部分特征,从中选取不纯度相关指标最优的作为分枝用的节点,这样,每次生成的树也就不同了
(二)random_state & splitter:控制随机性
random_state:用来设置分枝中的随机模式的参数。输入任意整数,会一直长出同一棵树,让模型稳定下来splitter:用来控制决策树中的随机选项,有两种输入值,best(默认)/ random- best:决策树在分枝时虽然随机,但还是会优先选择更重要的特征进行分枝(重要性可以通过属性 feature_importances_ 查看)
- random:决策树在分枝时会更加随机,树会因为含有更多不必要的信息而更深更大,并因这些不必要的信息而降低对训练集的拟合(也是防止过拟合的一种方式)
树一旦建成,使用剪枝参数来防止过拟合
(三)剪枝参数(5个)
在不加限制的情况下,一棵决策树会生长到衡量不纯度的指标最优,或者没有更多的特征可用为止,这样的决策树往往会过拟合(训练集上表现好,测试集上表现差)我们收集的样本数据不可能和整体的状况完全一致,因此,当一棵决策树对训练数据有了过于优秀的解释性,它找出的规则必然包含了训练样本中的噪声,并使它对未知数据的拟合程度不足为了让决策树有更好的泛化性,要对决策树进行剪枝sklearn为我们提供了不同的剪枝策略:
max_depth:超过设定深度的树枝全部剪掉。在高维度低样本量时有效,一般从=3开始尝试min_samples_leaf:限定一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生。设置的太小会引起过拟合,设置的太大会阻止模型学习数据,一般从=5开始使用。如果叶节点中含有的样本量变化很大,输入浮点数作为样本量的百分比来使用min_samples_split:限定一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝max_features:限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。如果希望通过降维的方式防止过拟合,建议使用PCA、ICA或者特征选择模块中的降维算法min_impurity_decrease:限制信息增益的大小,信息增益小于设定数值的分枝不会发生
确定最优的剪枝参数:超参数学习曲线,是一条以超参数的取值为横坐标,模型的度量指标为纵坐标的曲线,它是用来衡量不同超参数取值下模型的表现的线
import matplotlib.pyplot as plttest = []for i in range(10):clf = tree.DecisionTreeClassifier(max_depth=i+1 # 1-10,criterion="entropy",random_state=30,splitter="random")clf = clf.fit(Xtrain, Ytrain)score = clf.score(Xtest, Ytest)test.append(score)plt.plot(range(1,11),test,color="red",label="max_depth")plt.legend()plt.show()
(四)目标权重参数(完成样本标签平衡的参数,不常用)
class_weight:对样本标签进行一定的均衡,给少量的标签更多的权重,让模型更偏向少数类min_weight_fraction_leaf:有了权重之后,样本量就不再是单纯地记录数目,而是受输入的权重影响,此时剪枝需要基于权重的剪枝参数min_weight_fraction_leaf。它将比不知道样本权重的标准(如min_samples_leaf)更少偏向主导类重要属性和接口
属性:在模型训练之后,能够调用查看的模型的各种性质。对决策树来说,属性feature_importances_能够查看各个特征对模型的重要性
接口:
fit 和 score:几乎每个算法都可以使用apply:输入测试集,返回每个测试样本所在的叶子节点的索引predict:输入测试集,返回每个测试样本的分类/回归结果
所有接口中要求输入 X_train 和 X_test 的部分,输入的特征矩阵必须至少是一个二维矩阵(sklearn不接受任何一维矩阵作为特征矩阵被输入)
如果数据只有一个特征,必须用reshape(-1,1)来给矩阵增维如果数据只有一个特征和一个样本,使用reshape(1,-1)来给数据增维
总结
分类树的八个参数、一个属性(feature_importances_)、四个接口(fit,score,apply,predict)
八个参数:
criterion两个随机性相关的参数:random_state,splitter五个剪枝参数:max_depth,min_samples_split,min_samples_leaf,max_feature,min_impurity_decrease
回归树DecisionTreeRegressor与波士顿房价数据集
sklearn.tree.DecisionTreeRegressor — scikit-learn 1.2.0 documentation
在回归树中,没有标签分布是否均衡的问题,故没有class_weight这样的参数
重要参数、属性及接口
(一)criterion(回归树衡量分枝质量的指标)
mse:均方误差(样本真实数据与回归结果的差异)friedman_mse:费尔德曼均方误差mae:绝对平均误差在回归树中,MSE不只是分枝质量衡量指标,也是最常用的衡量回归树回归质量的指标
在使用交叉验证获取回归树的结果时,往往选择MSE作为评估(在分类树中是score代表的accuracy)
(二)属性
feature_importances_
(三)接口
score返回的是R²(默认),不是MSE
R²可以为正为负,取值范围是 ﹣∞ ~ 1(越接近1越好)MSE永远为正
(四)交叉验证
将数据划分为n份,依次使用其中一份作为测试集,其他n-1份作为训练集,多次计算模型的精确性来评估模型的平均准确程度
训练集和测试集的划分会干扰模型的结果,因此用交叉验证n次的结果求出的平均值,是对模型效果的一个更好的度量
交叉验证的过程包含了fit
from sklearn.datasets import load_bostonfrom sklearn.model_selection import cross_val_scorefrom sklearn.tree import DecisionTreeRegressorboston = load_boston() # 字典# boston.data取数据,boston.target取标签(连续型变量)regressor = DecisionTreeRegressor(random_state=0) #实例化# 交叉验证传入的是完整数据,不需要划分训练集和测试集# cv=10意味着十折,1份测试,9份训练。默认为5cross_val_score(regressor, boston.data, boston.target, cv=10, scoring="neg_mean_squared_error").mean()
实例:一维回归的图像绘制
用回归树来拟合正弦曲线,并添加一些噪声来观察回归树
.rand(x):随机生成x个0-1之间的随机数
.rand(x,y):x行y列的数组
np.random.rand(数组结构):生成随机数组
np.sort(axis=0):从小到大排序(按行)
.ravel():降维函数,n维降维n-1维,多次运行可以一直降到1维
np.newaxis:增维切片
l = np.array([1,2,3,4]) # (4,)l[: , np.newaxis] # (4,1)l[np.newaxis, :] # (1,4)
import numpy as np # 生成数据点,即正弦曲线from sklearn.tree import DecisionTreeRegressorimport matplotlib.pyplot as plt# 创建一条含有噪声的正弦曲线'''基本思路:先创建一组随机的、分布在0-5上的横坐标轴的取值(x),然后将这一组值放到sin函数中去生成纵坐标的值(y),接着再到y上去添加噪声'''rng = np.random.RandomState(1) #随机数种子(一种固定的随机)'''接口不允许导入一维数组,故X生成的是二维的'''X = np.sort(5 * rng.rand(80,1), axis=0) #生成0~5之间随机的x的取值'''输入的X是二维的,故np.sin(X)生成的结果也一定是二维的。但是导入回归树的标签必须是一维的,否则会报错故使用.ravel()降维'''y = np.sin(X).ravel() #生成正弦曲线'''y[::5]中的5为步长,故取出16个数'''y[::5] += 3 * (0.5 - rng.rand(16)) #在正弦曲线上加噪声plt.figure() # 画布plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data") # s为点的大小
# 实例化&训练模型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()
如果树的最大深度(由max_depth控制)设置的太高,则决策树学习的太精细,它从训练数据中学了很多细节(包括噪声的呈现),从而使模型偏离真实的正弦曲线,过拟合