机器学习-8 集成学习

集成学习理论

集成学习概述

  • 集成学习是一种功能十分强大的机器学习方法,其基本思想是先通过一定的规则生成一定数量的基学习器,再采用某种集成策略将这些基学习器的预测结果组合起来,从而形成最终的理论。
  • 集成学习不是一个单独的机器学习方法,而是将多重或多个弱学习器组合成一个强学习器加粗样式,从而有效地提升分类效果

集成学习理论

  • 集成学习主要包括3个部分:
    ①个体的生成方法。
    ②基学习器(个体学习器)。
    ③结论的合成(集成)方法。

集成学习需要很好地解决如下两个问题:
①如何通过有效地训练,获得若干个基学习器?
②如何选择一个组合策略,将这些基学习器集合成为一个强学习器?

同质个体学习器按照个体学习器之间是否存在依赖关系又可以分为两类:

  • 个体学习器之间存在着强依赖关系,原理是利用基学习器之间的依赖关系,对之间训练中错误标记的样本赋以较高的权重值,以提高整体的预测效果。其代表算法是Boosting算法
  • 个体学习器之间不存在强依赖关系,可以并行生成这些个体学习器,并行方法的原理是利用基学习器之间的独立性,通过平均可以显著降低错误率,其代表算法是Bagging算法随机森林(Random Forest)算法
    注:一般而言,集成学习中的基学习器可以是同质的“弱学习器”,也可以是异质的“弱学习器”。目前,同质基学习器的应用最为广泛,同质基学习器使用最多的模型是CART决策树神经网络

根据集成学习的用途不同,结论合成的方法也各不相同:

  • 集成的输出通常由各个个体学习器的输出投票产生。通常采用绝对多数投票法或相对多数投票法。

在这里插入图片描述

  • 当集成学习用于回归估计时,集成的输出通常由各学习器的输出通过简单平均或加权平均产生。

随机森林

算法原理

1)抽样产生每棵决策树的训练数据集。随机森林从原始训练数据集中产生n个训练子集(假设要随机生成n棵决策树)。训练子集中的样本存在一定的重复,主要是为了在训练模型时,每一棵树的输入样本都不是全部的样本,使森林中的决策树不至于产生局部最优解
2)构建n棵决策树(基学习器)。每一个训练子集生成一棵决策树,从而产生n棵决策树组成的森林,每棵决策树不需要剪枝处理。由于随机森林在进行结点分裂时,随机地选择m个特征(一般取m= log ⁡ 2 M \log{2}^{M} log2M,m≪M,其中M是数据集特征总数)参与比较,而不是像决策树将所有特征都参与特征指标的计算。这样减少了决策树之间的相关性,提升了决策树的分类精度,从而达到结点的随机性。
3)生成随机森林。使用第(2)步n棵决策树对测试样本进行分类,随机森林将每棵子树的结果汇总,以简单多数的原则决定该样本的类别

注:由于从原始训练集中随机产生n个训练子集用于随机生成n棵决策树,且在构建具体的决策树过程中随机地选择m个属性,随机森林的这两个随机性设置可以很大程度上降低过拟合出现的概率虽然随机森林中的每一棵树分类的能力都很弱,但是多棵树组合起来就变得十分强大

Scikit-learn中的随机森林分类器

函数原型sklearn.ensemble.RandomForestClassifier(n_estimators=10,criterion='gini',max_depth=None,min_samples_split=2,min_samples_leaf=1,min_weight_fraction_leaf=0.0,max_features='auto',max_leaf_nodes=None,bootstrap=True,oob_score=False,n_jobs=1,random_state=None,verbose=0,warm_start=False)

主要参数

1)n_estimators:随机森林中树的数量。数据类型为整型,若不指定该参数值,则自动使用默认参数值10。
2)criterion:特征选择标准。数据类型为字符串,若不指定该参数值,则自动使用默认参数值gini。其可选值如:gini:表示切分时的评价准则时gini系数;entropy:表示切分的评价准则时信息熵。
3)max_depth:决策树的最大深度。数据类型为整型或None,与决策树中一致。
4)min_samples_split:子数据集再切分需要的最小样本数。数据类型为整型或浮点型,与决策树中一致。
5)min_samples_leaf:叶子结点上的最小样本数。数据类型为整型或浮点型,与决策树中一致。
6)min_weight_fraction_leaf:叶子结点最小的样本权重和。数据类型为浮点型,与决策树中一致。
7)max_features:划分结点以寻找最优划分特征时,设置允许搜索的最大特征个数。数据类型为整型、浮点型、字符串型或None,与决策树中一致。
8)max_leaf_nodes:最大叶子结点数。数据类型为整型或None,与决策树中一致。限制最大叶子结点数,可以防止过拟合。
9)bootstrap:建立决策树时,是否使用有放回抽样。数据类型为布尔型,若不指定该参数值,则自动使用默认参数值True,即放回抽样。
10)oob_score:估计泛化误差时是否使用袋外样本(out-of-bag samples)。数据类型为布尔型,若不指定该参数值,则自动使用默认参数值False,即不使用袋外样本。
11)n_jobs:用于拟合和预测的并行作业数量。数据类型为整型,若不指定该参数值,则自动使用默认参数值1。如果值为-1,则并行工作的数量被设置为CPU核的数量。
12)random_state:随机种子的设置。数据类型为整型,若不指定该参数值,则自动使用默认参数值None,即使用当前系统时间作为种子,每次随机结果不同。
13)verbose:控制决策树建立过程的冗余度。数据类型为整型,若不指定该参数值,则自动使用默认参数值0。
14)warm_start:数据类型为布尔型。若不指定该参数值,则自动使用默认参数值False。当被设置为True时,调用之前的模型,用来拟合完整数据集或添加更多的基学习器,反之则创建一个全新的随机森林。

主要属性

1)estimators_:决策树实例的数组,存放所有训练过的决策树。
2)classes_:类别标签。
3)n_classes_:类别的数量。
4)n_features_:训练时使用的特征数量。
5)n_outputs_:训练时输出的数量。
6)features_importances:特征的重要程度。该值越高,则该特征越重要。
7)oob_score_:训练数据使用包外估计时的得分。

主要方法

1)fit(X, y[, sample_weight]):训练模型。
2)predict(X):用模型进行预测,返回预测值。
3)predict_log_proba(X):返回一个数组,数组的元素依次是X预测为各个类别的概率的对数值。
4)predict_proba(X):返回一个数组,数组的元素依次是X预测为各个类别的概率值。
5)n_outputs_:训练时输出的数量。
6)score(X, y[, sample_weight]):返回在(X, y)上预测的准确率。

算法实例:对随机森林分类器和决策树分类器进行比较

代码实现

# 导入内置数据集模块
from sklearn.datasets import load_breast_cancer
# 导入sklearn模块中的决策树分类器类和随机森林分类器类
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
# 导入sklearn模块中的模型验证类
from sklearn.model_selection import train_test_split,cross_val_score
import matplotlib.pyplot as plt
# 导入乳腺癌数据集
cancer = load_breast_cancer()
# 使用train_test_split函数自动分割训练集与测试集,其中test_size为测试集所占比例
x_train, x_test, y_train, y_test = train_test_split(cancer.data,cancer.target,test_size=0.3)
# 定义一个决策树分类器对象用于做比较
dt = DecisionTreeClassifier(random_state=0)
# 定义一个随机森林分类器对象
rf = RandomForestClassifier(random_state=0)
dt.fit(x_train,y_train)
rf.fit(x_train,y_train)
score_dt = dt.score(x_test,y_test)
score_rf = rf.score(x_test,y_test)
# 输出准确率
print('Single Tree : ', score_dt)
print('Random Forest : ', score_rf)
dt_scores = []
rf_scores = []
# 使用cross_val_score进行交叉验证,其中:
# cv为份数,即将数据集划分为n分,依次取每一份做测试集,其他n-1份做训练集,
# 返回每次测试准确率评分的列表
for i in range(10):
    rf_score = cross_val_score(RandomForestClassifier(n_estimators=25),cancer.data, cancer.target,cv=10).mean()
    rf_scores.append(rf_score)
    dt_score = cross_val_score(DecisionTreeClassifier(),cancer.data, cancer.target, cv=10).mean()
    dt_scores.append(dt_score)
# 绘制评分对比曲线
plt.figure()
plt.title('Random Forest VS Decision Tree')
plt.xlabel('Index')
plt.ylabel('Accuracy')
plt.plot(range(10),rf_scores,label = 'Random Forest')
plt.plot(range(10),dt_scores,label = 'Decision Tree')
plt.legend()
plt.show()
# 观察弱分类器数量对分类准确度的影响
rf_scores = []
for i in range(1,50):
     rf = RandomForestClassifier(n_estimators=i)
     rf_score = cross_val_score(rf, cancer.data, cancer.target,cv=10).mean()
     rf_scores.append(rf_score)
plt.figure()
plt.title('Random Forest')
plt.xlabel('n_estimators')
plt.ylabel('Accuracy')
plt.plot(range(1,50),rf_scores)
plt.show()

实验效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

提升法

提升法原理

  • Boosting是一种可将弱学习器提升为强学习器的算法。
  • 这种算法先从初始训练集训练出一个基学习器,再根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续受到更多关注,然后基于调整后的样本分布来训练下一个基学习器。如此重复进行,直至基学习器数目达到事先指定的值T,最终将这T个基学习器进行加权结合。
  • Boosting拥有系列算法,如AdaBoost,GradientBoosting,LogitBoost等,其中最著名的代表是AdaBoost算法。Boosting中的个体分类器可以是不同类的分类器。

Boosting算法分为以下两个阶段:

  • 训练阶段。给定一个训练集X,随机地将其划分为3个子集X={ X 1 , X 2 , X 3 X_1,X_2,X_3 X1,X2,X3}。首先使用 X 1 X_1 X1训练基分类器 d 1 d_1 d1,接着提取 X 2 X_2 X2并将它作为 d 1 d_1 d1的输入,将 d 1 d_1 d1错误分类的所有样本以及 X 2 X_2 X2中被 d 1 d_1 d1正确分类的部分样本一起作为 d 2 d_2 d2的训练集。最后提取 X 3 X_3 X3,并将它输入给 d 1 d_1 d1 d 2 d_2 d2,其中用 d 1 d_1 d1 d 2 d_2 d2输出不一致的样本作为 d 3 d_3 d3的训练集。
  • 检验阶段。给定一个样本,首先将其提供给 d 1 d_1 d1 d 2 d_2 d2,如果二者输出一致,这就是输出结果,否则以 d 3 d_3 d3的输出作为最终输出结果。
    注:由于Boosting算法需要将训练集分割成多个子集,并且第二和第三个分类器只在其前面分类器犯错的实例数据子集上训练,因此要求训练集包含较多数量的样本,否则 d 2 d_2 d2 d 3 d_3 d3将无法拥有合理大小的训练集。

AdaBoost提升法

引入

  • 尽管Boosting非常成功,但是需要一个非常大的训练样本集将样本集一分为三。(很多场合不太现实
  • 1996年,Yoav Freund和Robert Schapire提出了提升的一个变种,即自适应提升(Adaptive Boosting,AdaBoost),它重复使用相同的训练集,而不再要求很大的数据集

算法机制

首先,训练集用初始权重训练出一个弱学习器1,根据弱学习的学习误差率表现来更新训练样本的权重,使得之前弱学习器1学习误差率高的训练样本点的权重变高,使得这些误差率高的点在后面的弱学习器2中得到更多的重视。
然后,基于调整权重后的训练集来训练弱学习器2,如此重复进行,直到训练到指定的弱学习器数量。
最后,将这些弱学习器通过集合策略进行整合,得到最终的强学习器。
在这里插入图片描述

Scikit-learn中的投票法分类器

函数原型

sklearn.ensemble.AdaBoostClassifier(base_estimator=None,n_estimators=50,learning_rate=1.0,algorithm='SAMME.R', random_state=None)

主要参数

1)base_estimator:基分类器,在该分类器基础上进行boosting。默认为决策树,理论上可以是任意一个分类器,但是如果使用其他分类器时需要指明样本权重。
2)n_estimators:基分类器提升(循环)次数。数据类型为整型,若不指定该参数值,则自动使用默认参数值50。这个值过大,模型容易过拟合,值过小,模型容易欠拟合。。
3)learning_rate:学习率,表示梯度收敛速度。数据类型为整型,若不指定该参数值,则自动使用默认参数值1。如果过大,容易错过最优值,如果过小,则收敛速度会很慢。该值需要和n_estimators进行一个权衡,当分类器迭代次数较少时,学习率可以小一些,当迭代次数较多时,学习率可以适当放大。
4)algorithm:模型提升准则。数据类型为字符串型,若不指定该参数值,则自动使用默认参数值SAMME.R。可选值如: SAMME:对样本集预测错误的概率进行划分;SAMME.R:对样本集的预测错误的比例,即错分率进行划分。
5)random_state:设置随机种子。数据类型为整型,若不指定该参数值,则自动使用默认参数值None。

主要属性

1)estimators_:所有训练过的基础分类器。
2)classes_:类别标签。
3)n_classes_:类别的数量。
4)estimator_weights_:每个基础分类器的权重。
5)feature_importances:每个特征的重要性。
6)estimator_errors_:每个基础分类器的分类误差。

主要方法

1)fit(X, y[, sample_weight]):训练模型。
2)predict(X):用模型进行预测,返回预测值。
3)predict_log_proba(X):返回一个数组,数组的元素依次是X预测为各个类别的概率的对数值。
4)predict_proba(X):返回一个数组,数组的元素依次是X预测为各个类别的概率值。
5)score(X, y[, sample_weight]):返回在(X, y)上预测的准确率。
6)staged_predict_proba(X):返回一个二维数组,数组的元素依次是每一轮迭代结束时尚未完成的集成分类器预测X为各个类别的概率值。
7)staged_predict(X):返回一个数组,数组的元素依次是每一轮迭代结束时尚未完成的集成分类器的预测值。
8)staged_score(X, y[, sample_weight]):返回一个数组,数组的元素依次是每一轮迭代结束时尚未完成的集成分类器的预测准确率。

算法实例:对AdaBoost分类器和决策树分类器进行比较:

代码实现

from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.model_selection import train_test_split,cross_val_score
import matplotlib.pyplot as plt
cancer = load_breast_cancer()
x_train, x_test, y_train, y_test = train_test_split(cancer.data,cancer.target, test_size=0.3, random_state=1)
abc = AdaBoostClassifier(DecisionTreeClassifier(), algorithm='SAMME', n_estimators=50, learning_rate=0.1)
dt = DecisionTreeClassifier()
abc.fit(x_train,y_train)
dt.fit(x_train,y_train)
score_abc = abc.score(x_test,y_test)
score_dt = dt.score(x_test,y_test)
# 输出准确率
print('Ada Boost : ', score_abc)
print('Decision Tree : ', score_dt)
# 测试n_estimators参数对分类效果的影响
abc_scores = []
for i in range(1,50):
    abc.estimators_ = i
    abc.fit(x_train,y_train)
    abc_score = abc.score(x_test,y_test)
    abc_scores.append(abc_score)
# 绘制结果
plt.figure()
plt.title('AdaBoost')
plt.xlabel('n_estimators')
plt.ylabel('Accuracy')
plt.plot(range(1,50),abc_scores)
plt.show()

实验结果

在这里插入图片描述
在这里插入图片描述

GBDT提升法

算法原理

梯度提升(Gradient Boosting)是一种用于回归和分类问题的集成学习方法,生成一个由弱学习器(通常是决策树)组成的强学习器。梯度提升的思想源于Leo Breiman的一次观察,提升可以被解释为基于一个合适的代价函数的优化算法。随后,Jerome H. Friedman开发了一个显式回归梯度提升算法,通过迭代选择一个指向负梯度方向上的函数(弱假设),优化函数空间上的成本函数,拟合一棵决策树。在回归问题中,称为梯度提升回归树(Gradient Boosting Rgression Tree,GBRT)。在分类问题中,又被称为提升决策树(Gradient Boosting Decision Tree,GBDT)。
提升决策树的弱学习器只使用CART回归树模型,迭代方法也与Adaboost有所不同。在GBDT的迭代中,假设前一轮迭代得到的强学习器是 f m − 1 ( x ) f_{m−1}(x) fm1(x),损失函数是 L ( y , f m − 1 ( x ) ) L(y,f_{m−1}(x)) L(y,fm1(x)),本轮迭代的目标是找到一棵CART回归树模型的弱学习器 h m ( x ) ℎ_m(x) hm(x),让本轮的损失 L ( y , f m ( x ) = L ( y , f m − 1 ( x ) ) + h m ( x ) ) L(y,f_m(x)=L(y,f_{m−1}(x))+ℎ_m(x)) L(y,fm(x)=L(y,fm1(x))+hm(x))最小,即本轮迭代找到的决策树,要使样本的损失尽量变得更小。

Scikit-learn中的梯度提升分类器

函数原型

sklearn.ensemble.GradientBoostingClassifier(learning_rate=0.1,n_estimators=100,subsample=1.0, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0,max_depth=3, random_state=None, max_features=None, verbose=0,max_leaf_nodes=None, presort=‘auto’)

主要参数

1)min_samples_split:子数据集再切分需要的最小样本数。数据类型为整型或浮点型,与决策树中一致。
2)min_samples_leaf:叶子结点上的最小样本数。数据类型为整型或浮点型,与决策树中一致。
3)min_weight_fraction_leaf:叶子结点最小的样本权重和。数据类型为浮点型,与决策树中一致。
4)max_depth:决策树的最大深度。数据类型为整型或None,与决策树中一致。
5)max_leaf_nodes:最大叶子结点数。数据类型为整型或None,与决策树中一致。
6)max_features:随机森林允许单个决策树使用特征的最大数量。数据类型为整型、浮点型、字符串型或None,与决策树中一致。
7)learning_rate:每个弱学习器的权重缩减系数。数据类型为浮点型,若不指定该参数值,则自动使用默认参数值1.0。
8)n_estimators:弱学习器的最大个数。数据类型为整型,若不指定该参数值,则自动使用默认参数值100。
9)subsample:放回抽样比例。数据类型为浮点型,取值范围为[0,1],若不指定该参数值,则自动使用默认参数值1。如果取值为1,则全部样本都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低,推荐在[0.5, 0.8]之间。
10)random_state:随机种子的设置。数据类型为整型,与决策树中一致。
11)verbose :控制决策树建立过程的冗余度。数据类型为整型,与决策树中一致。
12)persort:是否进行预排序。数据类型为布尔型,与决策树中一致。

主要属性

1)estimators_:每棵基础决策树。
2)init:初始预测使用的分类器。
3)oob_improvement_:输出一个数组,给出了每增加一棵基础决策树,在包外估计的损失函数的改善情况。
4)train_score_:输出一个数组,给出了每增加一棵基础决策树,在训练集上的损失函数的值。
5)feature_importances:每个特征的重要性。

主要方法

1)fit(X, y[, sample_weight, monitor]):训练模型。其中monitor是一个可调用对象,它在当前迭代过程结束时调用。如果返回True,则训练过程提前终止。
2)predict(X):用模型进行预测,返回预测值。
3)predict_log_proba(X):返回一个数组,数组的元素依次是X预测为各个类别的概率的对数值。
4)predict_proba(X):返回一个数组,数组的元素依次是X预测为各个类别的概率值。
5)score(X, y[, sample_weight]):返回在(X, y)上预测的准确率。
6)staged_predict_proba(X):返回一个二维数组,数组的元素依次是每一轮迭代结束时集成分类器预测X为各个类别的概率值。
7)staged_predict(X):返回一个数组,数组的元素依次是每一轮迭代结束时集成分类器的预测值。

算法实例:对梯度提升分类器和决策树分类器进行比较

代码实现

from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split,cross_val_score
import matplotlib.pyplot as plt
import numpy as np
cancer = load_breast_cancer()
x_train, x_test, y_train, y_test = train_test_split(cancer.data,cancer.target,test_size=0.3, random_state=1)
gbc = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1)
dt = DecisionTreeClassifier()
gbc.fit(x_train,y_train)
dt.fit(x_train,y_train)
score_gbc = gbc.score(x_test,y_test)
score_dt = dt.score(x_test,y_test)
# 输出准确率
print('Gradient Boost : ', score_gbc)
print('Decision Tree : ', score_dt)
# 测试learning_rate参数对分类效果的影响
gbc_scores = []
for i in np.arange(0.1,1,0.05):
    gbc.learning_rate = i
    gbc.fit(x_train,y_train)
    gbc_score = gbc.score(x_test,y_test)
    gbc_scores.append(gbc_score)
# 绘制测试结果
plt.figure()
plt.title('Gradient Boost')
plt.xlabel('learning_rate')
plt.ylabel('Accuracy')
plt.plot(range(len(gbc_scores)),gbc_scores)
plt.show()
gbc_scores = []
dt_scores = []
# 使用cross_val_score进行交叉验证
for i in range(20):
    gbc_score = cross_val_score(gbc, cancer.data, cancer.target,cv=10).mean()
    gbc_scores.append(gbc_score)
    dt_score = cross_val_score(dt, cancer.data, cancer.target,cv=10).mean()
    dt_scores.append(dt_score)
# 绘制评分对比曲线
plt.figure()
plt.title('Gradient Boost VS Decision Tree')
plt.xlabel('Index')
plt.ylabel('Accuracy')
plt.plot(range(20),dt_scores,label = 'Decision Tree')
plt.plot(range(20),gbc_scores,label = 'Gradient Boost')
plt.legend()
plt.show()
plt.show()

实验效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

偏差与方差

基本概念

偏差bias

偏差指预测结果与真实值之间的差异,排除噪声的影响,偏差更多的是针对某个模型输出的样本误差,偏差是模型无法准确表达数据关系导致,比如模型过于简单,非线性的数据关系采用线性模型建模,偏差较大的模型是错的模型。

方差variance

模型方差不是针对某一个模型输出样本进行判定,而是指多个(次)模型输出的结果之间的离散差异,注意这里写的是多个模型或者多次模型,即不同模型或同一模型不同时间的输出结果方差较大,方差是由训练集的数据不够导致一方面量 (数据量) 不够,有限的数据集过度训练导致模型复杂,另一方面样本质量不行,测试集中的数据分布未在训练集中,导致每次抽样训练模型时,每次模型参数不同,输出的结果都无法准确的预测出正确结果。

注:从同一个数据集中,用科学的采样方法得到几个不同的子训练集,用这些训练集训练得到的模型往往并不相同。
在这里插入图片描述

为什么会有偏差和方差?

  • 对学习算法除了通过实验估计其泛化性能之外,人们往往还希望了解它为什么具有这样的性能。“偏差-方差分解”(bias-variance decomposition)就是从偏差和方差的角度来解释学习算法泛化性能的一种重要工具,Bias和Variance分别从两个方面来描述我们学习到的模型与真实模型之间的差距
  • 泛化误差可以分解为偏差(Biase)、方差(Variance)和噪声(Noise)
  • 如果我们能够获得所有可能的数据集合,并在这个数据集合上将损失最小化,那么学习得到的模型就可以称之为“真实模型”。当然,在现实生活中我们不可能获取并训练所有可能的数据,所以“真实模型”肯定存在,但是无法获得。我们的最终目的是学习一个模型使其更加接近这个真实模型。
  • Bias是用所有可能的训练数据集训练出的所有模型的输出的平均值与真实模型的输出值之间的差异
  • Variance是不同的训练数据集训练出的模型输出值之间的差异
  • 噪声的存在是学习算法所无法解决的问题,数据的质量决定了学习的上限。假设在数据已经给定的情况下,此时上限已定,我们要做的就是尽可能的接近这个上限。

偏差与方差详解

如图,红色的圆心代表理想的优化目标,黑色的点代表在不同的采样集合上训练模型的优化结果。可以看到左边一列低方差的优化结果要比右边一列高方差的优化结果更为集中,上边一行低偏差的优化结果要比下边一行高偏差的优化结果更靠近中心。
在这里插入图片描述

  • Bias的对象是单个模型,是期望输出与真实标记的差别。它描述了模型对本训练集的拟合程度。
  • Variance的对象是多个模型,是相同分布的不同数据集训练出模型的输出值之间的差异。它刻画的是数据扰动对模型的影响。

数学公式定义偏差、方差、噪声

对于一个回归问题,假设样本( x → \overrightarrow{x} x ,y)服从的真实分布为 P ( x → , y ) P(\overrightarrow{x},y) P(x ,y) 。设D表示含噪采样点集, ( x → \overrightarrow{x} x , y D y_D yD)服从分布D, y D y_D yD为输入 x → \overrightarrow{x} x 在实际分布D中的标记,而噪声一般服从高斯分布,则模型随机变量 f D ( x → ) f_D(\overrightarrow{x}) fD(x )在所有可能的样本集合分布D上的期望为: E D [ f D ( x → ) ] E_D[f_D(\overrightarrow{x})] ED[fD(x )],则有:
偏差:期望输出与真实标记的差别,度量了学习算法的期望预测与真实结果的偏离程度,即刻画了学习算法本身的拟合能力。
b i a s ( x → ) = ( E D [ f D ( x → ) − y ] ) 2 bias(\overrightarrow{x})=(E_D[f_D(\overrightarrow{x})-y])^2 bias(x )=(ED[fD(x )y])2 b i a s D ( x → ) = E D [ ( E D [ f D ( x → ) − y ] ) 2 ] bias_D(\overrightarrow{x})=E_D[(E_D[f_D(\overrightarrow{x})-y])^2] biasD(x )=ED[(ED[fD(x )y])2]
方差:使用样本数相同的不同训练集产生的方差,度量了同样大小的训练集的变动所导致的学习性能的变化,即刻画了数据扰动所造成的影响。
v a r ( x → ) = E D [ ( f D ( x → ) − E D [ f D ( x → ) ] ) 2 ] var(\overrightarrow{x})=E_D[(f_D(\overrightarrow{x})-E_D[f_D(\overrightarrow{x})])^2] var(x )=ED[(fD(x )ED[fD(x )])2]

偏差-方差分解

噪声的含义:噪声则表达了在当前任务上任何学习算法所能达到的期望泛化误差的下界,即刻画了学习问题本身的难度。
ε 2 = E D [ ( y D − y ) 2 ] \varepsilon^2=E_D[(y_D-y)^2] ε2=ED[(yDy)2]
也就是说,泛化误差可以通过一系列公式分解运算证明:泛化误差为偏差、方差与噪声之和
泛化误差 = 错误率 ( e r r o r ) = b i a s 2 ( x ) + v a r ( x ) + ε 2 泛化误差=错误率(error)=bias^2(x)+var(x)+\varepsilon^2 泛化误差=错误率(error)=bias2(x)+var(x)+ε2
注:泛化性能是由学习算法的能力、数据的充分性以及学习任务本身的难度所共同决定的。给定学习任务,为了取得好的泛化性能,则需使偏差较小,即能够充分拟合数据,并且使方差较小,即使得数据扰动产生的影响小。

泛化误差、偏差和方差的关系

偏差-方差窘境
实际在选择模型时,随着模型复杂度的增加,模型的偏差越来越小,而方差会越来越大。
如图所示,存在某一时刻,模型的方差和偏差之和最小,此时模型性能在误差及泛化能力方面达到最优。
在这里插入图片描述

偏差、方差与过拟合、欠拟合的关系

一般来说,简单的模型会有一个较大的偏差和较小的方差,复杂的模型偏差较小方差较大

  • 欠拟合:模型不能适配训练样本,有一个很大的偏差。
  • 过拟合:模型很好的适配训练样本,但在测试集上表现很糟,有一个很大的方差。

如何解决偏差、方差问题?

整体思路
首先,要知道偏差和方差是无法完全避免的,只能尽量减少其影响
(1)在避免偏差时,需尽量选择正确的模型,一个非线性问题而我们一直用线性模型去解决,那无论如何,高偏差是无法避免的。
(2)有了正确的模型,我们还要慎重选择数据集的大小,通常数据集越大越好,但大到数据集已经对整体所有数据有了一定的代表性后,再多的数据已经不能提升模型了,反而会带来计算量的增加。而训练数据太小一定是不好的,这会带来过拟合,模型复杂度太高,方差很大,不同数据集训练出来的模型变化非常大
(3)最后,要选择合适的模型复杂度,复杂度高的模型通常对训练数据有很好的拟合能力。

针对偏差和方差的思路
偏差:实际上也可以称为避免欠拟合。
1、寻找更好的特征 – 具有代表性。
2、用更多的特征 – 增大输入向量的维度,增加模型复杂度。
方差:避免过拟合 。
1、增大数据集合 – 使用更多的数据,减少数据扰动所造成的影响
2、减少数据特征 – 减少数据维度,减少模型复杂度
3、正则化方法
4、交叉验证法

算法实例:基于梯度下降树实现波士顿房价预测

代码实现

from sklearn.datasets import load_boston
from sklearn.ensemble import GradientBoostingRegressor as GBDT
from sklearn.model_selection import train_test_split
boston=load_boston()
x_train,x_test,y_train,y_test=train_test_split(boston.data,boston.target)
model=GBDT(n_estimators=50)
model.fit(x_train,y_train)
train_score=model.score(x_train,y_train)
test_score=model.score(x_test,y_test)
print(train_score,test_score)
from sklearn.datasets import load_boston
from sklearn.ensemble import GradientBoostingRegressor as GBDT
from sklearn.model_selection import validation_curve
import matplotlib.pyplot as plt
boston=load_boston()
param_range=range(20,150,5)
train_scores,val_scores=validation_curve(
    GBDT(max_depth=3),boston.data,boston.target,
    param_name='n_estimators',
    param_range=param_range,
    cv=5,
)
train_mean=train_scores.mean(axis=-1)
train_std=train_scores.std(axis=-1)
val_mean=val_scores.mean(axis=-1)
val_std=val_scores.std(axis=-1)
_,ax=plt.subplots(1,2)
ax[0].plot(param_range,train_mean)
ax[1].plot(param_range,val_mean)
ax[0].fill_between(param_range,train_mean-train_std,train_mean+train_std,alpha=0.2)
ax[1].fill_between(param_range,val_mean-val_std,val_mean+val_std,alpha=0.2)
plt.show()

实验效果
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

so.far_away

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值