欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

[机器学习]集成建模/集成学习:结合多种模型,实现更好的预测

最编程 2024-04-16 20:36:23
...

1. 概述

1.1 什么是集成模型/集成学习

"模型集成"和"集成学习"是相同的概念。它们都指的是将多个机器学习模型组合在一起,以提高预测的准确性和稳定性的技术。通过结合多个模型的预测结果,集成学习可以减少单个模型的偏差和方差,并提供更可靠的预测结果。

集成学习原名为Classifier combination / ensemble learning,它是根据训练数据构造一组基分类器(base classifier),通过聚合每个基分类器的输出来进行分类。

基分类器,就是一个小的分类器,单个基分类器的性能取决于它选择的分类算法和训练集。 对于单个性能比较弱的基分类器,我们称为弱分类器。 对于单个性能比较强的基分类器,我们称为强分类器

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

多个基分类器集成的思想源于下列直觉

  • 考虑到几个基分类器的分类意见,而不是仅仅依靠一个基分类器的意见 。
  • 许多弱分类器的组合至少可以和一个强分类器一样好。
  • 一些强分类器的组合(通常)至少和基分类器中最好的一个一样好。

集成是建立各种模型的过程,然后将它们混合以产生更好的预测。与单个模型相比,集成能够实现更精确的预测。在ML比赛中,利用集成通常会带来优势。你可以找到CrowdFlower winners的团队采访,他们用集成赢得了比赛:https://medium.com/kaggle-blog/crowdflower-winners-interview-3rd-place-team-quartet-cead438f8918

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

1.2 分类器集成的结果

多个分类器集成后的性能一定更好吗?我们带着这个疑问来看下面的例子:

C_{1}, C_{2}, C_{3}

分别代表了3个基分类器,

C^{*}

表示的是三个分类器的结合的最终结果:

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

由结果可以看出,多个基分类器的集合不一定犹豫单个基分类器的性能,那么:

什么时候选择集成呢? 基础分类器不会犯同样的错误。 每个基础分类器都是相当准确的。

1.3 构造基分类器的三种方法

实例操作:通过抽样产生多个训练集,并在每个数据集上训练一个基础分类器。

特征操作:通过不同的特征子集生成多个训练集,并在每个数据集上训练一个基础分类器。

算法操作:半随机地调整给定算法中的内部参数,在给定的数据集上生成多个基础分类器。

1.4 多个基分类器如何进行分类

在多个基分类器上进行分类的最简单手段是投票

对于离散类,在测试集上运行多个基分类器,并选择由最多基分类器预测的类(少数服从多数)。例如一个二分类的数据集,,构造了5个基分类器,对于某个样本有三个基分类器的输出结果是1, 两个是0那么这个时候,总和来看结果就应该是1。

对于连续数值类,对我们基分类器预测的数字进行平均,将平均数作为最终的预测结果。

2. 单一模型存在的问题

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

单一模型是指只使用一个基础模型来进行预测或分类的方法,例如决策树、支持向量机、神经网络等。 单一模型的优点是简单、易于理解和实现,但也存在一些缺点,主要有以下几个方面:

  • 泛化能力不足:单一模型容易受到数据噪声、异常值和过拟合的影响,导致在新的数据上表现不佳。
  • 稳定性不高:单一模型对数据的分布和特征的选择非常敏感,稍微改变数据或特征就可能导致预测结果的变化。
  • 表达能力有限:单一模型往往只能捕捉数据的某些方面的信息,难以表达数据的复杂性和多样性。

为了解决单一模型存在的问题,我们可以使用集成模型来组合多个基础模型,从而提高预测性能和泛化能力。

3. 简单的集成模型应用

集成模型背后的想法很简单:为什么不使用多个模型并结合它们的预测,而不是依赖一个模型?这样,我们就可以利用不同模型的多样性和互补性,获得更稳健、更准确的预测。

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

例如,假设我们想要根据客户的年龄、性别、收入和浏览历史来预测客户是否会购买产品。我们可以使用单一模型,例如逻辑回归或决策树,但它可能只能捕获数据中的一些细微差别和模式。或者,我们可以使用多种模型,例如逻辑回归、决策树、k 最近邻和支持向量机,并使用某种规则或算法组合它们的预测。这是集成模型的示例。 创建和组合多个模型的方法有多种。根据集成模型的实现方式,我们可以将集成模型分为五种主要类型:投票、平均、堆叠、装袋、提升。

3.1 投票

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

装袋的一个特殊情况是将模型用于分类而不是回归。例如,如果你有三个模型用于预测巴黎是否会下雨,可以进行多数投票,得到“是”作为最终预测结果。这也被称为多数投票集成或多数派集成。

多数投票的优点在于它降低了预测的错误率,意味着它们更有可能是正确的。缺点是它不考虑每个预测的置信度或概率,这意味着它可能忽略了一些有用的信息。

要在Python中使用scikit-learn实现多数投票集成,可以使用VotingClassifier类,将其voting参数设置为’hard’。这个类允许我们指定一个模型列表和一个投票方法(如’hard’或’soft’)来组合它们的预测。

以下是如何使用多数投票进行分类的示例:

from sklearn.ensemble import VotingClassifier 
from sklearn.linear_model import LogisticRegression 
from sklearn.tree import DecisionTreeClassifier 
from sklearn.svm import SVC 
from sklearn.datasets import make_classification 
from sklearn.model_selection import train_test_split 

# 生成分类的随机数据集
X, y = make_classification(n_samples = 1000 , random_state= 42 ) 

# 将数据集分割为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.2 , random_state= 42 ) 

# 定义三个不同的模型
model1 = LogisticRegression(random_state= 42 ) 
model2 = DecisionTreeClassifier(random_state= 42 ) 
model3 = SVC(random_state= 42 ,probability= True ) 

# 使用多数投票集成组合模型
= VotingClassifier(estimators=[( 'lr' , model1), ( 'dt' , model2) , ( 'svc' , model3)], Voting= 'hard' ) 

# 在训练数据上拟合集成 ensemble.fit
 (X_train, y_train) 

# 在测试数据上评估集成的性能
print ( f"整体精准度:{ensemble.score(X_test, y_test)* 100 } %" )

3.2 平均

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

将多个模型的预测结果取平均值是组合多个模型的最简单方式。例如,如果你有三个模型分别预测巴黎的温度为15°C、18°C和20°C,你可以将它们的平均值计算出来,得到最终的预测值为17.67°C。这也被称为均值集成。

取平均的优点在于它降低了预测的方差,意味着它们不太可能偏离真实值太远。缺点在于它也降低了预测的偏差,意味着它们不太可能接近真实值。换句话说,取平均值使得预测更加一致,但也更加保守。

要在Python中使用scikit-learn实现平均集成,对于回归问题,我们可以使用VotingRegressor类,对于分类问题,我们可以使用VotingClassifier类。这些类允许我们指定一组模型和一个投票方法(如’hard’或’soft’)来组合它们的预测。

以下是如何在回归问题中使用平均集成的示例:

# 导入库
from sklearn.linear_model import LinearRegression 
from sklearn.tree import DecisionTreeRegressor 
from sklearn.neighbors import KNeighborsRegressor 
from sklearn.ensemble import VotingRegressor 
from sklearn.datasets import fetch_california_housing 
from sklearn.metrics importmean_squared_error #

加载数据
california = fetch_california_housing (as_frame=真) 
X = california.data 
y = california.target 

# 定义模型
lr = LinearRegression() 
dt = DecisionTreeRegressor() 
knn = KNeighborsRegressor() 

# 创建平均集成
avg = VotingRegressor(estimators=[( 'lr' , lr), ( 'dt ' , dt), ( 'knn' , knn)]) 

# 对数据进行集成
avg.fit(X, y) 

# 进行预测
y_pred = avg.predict(X) 

# 评估性能
mse = Mean_squared_error(y, y_pred) 
print ( f'MSE: {mse: .2 f} ' )

3.3 堆叠

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

另一种组合多个模型的方法是将它们用作另一个模型的输入。例如,如果你有三个模型分别预测巴黎的温度为15°C、18°C和20°C,你可以使用它们的预测作为第四个模型的特征,该模型学习如何加权它们并进行最终的预测。这也被称为元学习器或二级学习器。

堆叠的优点在于它可以从每个模型的优点和缺点中学习,从而做出更准确的预测。缺点在于它可能更加复杂,并容易过拟合,意味着它可能在训练数据上表现良好,但在新数据上表现不佳。

要在Python中使用scikit-learn实现堆叠集成,对于回归问题,我们可以使用StackingRegressor类,对于分类问题,我们可以使用StackingClassifier类。这些类允许我们指定一组模型作为基本估算器,以及另一个模型作为最终估算器。

以下是如何在分类问题中使用堆叠集成的示例:

# 导入库
from sklearn.linear_model import LogisticRegression 
from sklearn.tree import DecisionTreeClassifier 
from sklearn.neighbors import KNeighborsClassifier 
from sklearn.ensemble import StackingClassifier 
from sklearn.datasets import load_iris 
from sklearn.metrics import precision_score 

# 加载数据
X, y = load_iris(return_X_y= True ) 

# 定义模型
lr = LogisticRegression() 
dt = DecisionTreeClassifier() 
knn = KNeighborsClassifier() 

# 创建堆叠集成
stack = StackingClassifier(estimators=[( 'lr' , lr), ( 'dt' , dt), ( ' knn' , knn)], Final_estimator=LogisticRegression()) 

# 对数据进行集成
stack.fit(X, y) 

# 进行预测
y_pred = stack.predict(X) 

# 评估性能
acc = precision_score(y, y_pred) 
acc = acc* 100 
print ( f'准确度: {acc: .2 f} %' )

3.4 装袋

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

第四种组合多个模型的方法是使用数据的不同子集来训练它们。例如,如果你有一个包含1000个观测值的数据集,你可以随机采样500个观测值(可以有重复的观测值),然后使用它们来训练一个模型。你可以多次重复这个过程,从而得到在数据不同子集上训练的不同模型。这也被称为自助聚合或自助法。

自助法的优点在于它降低了预测的方差,意味着它们不太可能偏离真实值太远。缺点在于它不降低预测的偏差,意味着它们仍然有可能接近真实值。换句话说,自助法使预测更加一致但不一定更准确。

要在Python中使用scikit-learn实现自助法集成,对于回归问题,我们可以使用BaggingRegressor类,对于分类问题,我们可以使用BaggingClassifier类。这些类允许我们指定一个基本估算器和创建的自助样本数量。

以下是如何在回归问题中使用bagging ensemble的示例:

# 导入库
from sklearn.tree import DecisionTreeClassifier 
from sklearn.ensemble import BaggingClassifier 
from sklearn.datasets import load_iris 
from sklearn.metrics import precision_score 

# 加载数据
X, y = load_iris(return_X_y= True ) 

# 定义基础模型
dt = DecisionTreeClassifier() 

#创建装袋集成
bag = BaggingClassifier(base_estimator=dt, n_estimators= 10 ) 

# 在数据上拟合
集成 bag.fit(X, y) 

# 进行预测
y_pred = bag.predict(X) 

# 评估性能
acc = precision_score(y, y_pred ) 
acc = acc * 100 
print ( f'准确度: {acc: .2 f} %' )

3.5 提升

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

组合多个模型的最后一种方法是以顺序和迭代的方式使用它们。例如,如果你有一个模型预测巴黎的温度为15°C,你可以使用其误差或残差作为另一个模型的输入,该模型试图纠正这些误差并做出更好的预测。你可以多次重复这个过程,得到相互从彼此错误中学习的不同模型。这也被称为自适应提升或AdaBoost。

提升的优点在于它降低了预测的方差和偏差,意味着它们更有可能接近并准确地反映真实值。缺点在于它可能对异常值和噪声更为敏感,意味着它可能对数据过拟合或欠拟合。

要在Python中使用scikit-learn实现提升集成,对于回归问题,我们可以使用AdaBoostRegressor类,对于分类问题,我们可以使用AdaBoostClassifier类。这些类允许我们指定一个基本估算器和提升迭代的次数。

以下是如何在回归问题中使用提升集成的示例:

# 导入库
from sklearn.tree import DecisionTreeRegressor 
from sklearn.ensemble import AdaBoostRegressor 
from sklearn.datasets import load_iris 
from sklearn.metrics importmean_squared_error #

加载数据
X, y = load_iris(return_X_y= True ) 

# 定义基础模型
dt = DecisionTreeRegressor() 

#创建增强集成
boost = AdaBoostRegressor(base_estimator=dt, n_estimators= 10 ) 

# 根据数据拟合集成
boost.fit(X, y) 

# 进行预测
y_pred = boost.predict(X) 

# 评估性能
mse = Mean_squared_error(y, y_pred)
打印(f'MSE:{mse:.2 f} ')

4. 分析预测模型的泛化误差

从模型角度看:

  • Bias(偏置):衡量一个分类器进行错误预测的趋势。
  • Variance(变异度):衡量一个分类器预测结果的偏离程度。

如果一个模型有更小的Bias和Variance 就代表这个模型的泛化性能很好。

5. 几何直观地理解集成学习的四大类型

5.1 装袋法 Bagging(实例操作)

在这里插入图片描述
在这里插入图片描述
  1. 将大小为
n

的原始数据

D_n

,进行Bootstrap抽样(有放回抽样),因此在各抽样数据集

D_i'

中,存在部分元素重复;各抽样数据集的样本容量

m_i≤n
  1. 将抽样后的数据集,分别独立进行模型学习
  2. 然后将
k

个模型进行聚合;分类:多数投票;回归:平均数、中位数

  • 没有一个模型是在整个数据集上训练的
  • 如果原始数据集部分元素发生异常变化,可能会影响子模型,而不影响聚合后的模型,
  • 因此:“取偏差小 、方差大的基础模型,将其聚合,得到偏差小、方差小的模型”

Bagging = bootstrap aggregating(自举汇聚法)

装袋法思想源于数据越多,性能越好的直觉判断。

具体方法:

通过随机抽样与替换相结合的方式构建新的数据集 。

将原始数据集进行有放回的随机采样次,得到了个数据集,针对这些数据集一共产生个不同的基分类器。对于这个分类器,让他们采用投票法来决定最终的分类结果。

例子:

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

袋装法存在的问题:

因为袋装法是有放回的随机采样

N

次,那就有可能有些样本可能永远不会被随机到。因为

N

个样本,每个样本每次被取到的概率为

\frac{1}{N}

,那么一共取

N

次没取到的概率为

\left ( 1-\frac{1}{N} \right )^{N}

这个值在

N

很大的时候的极限值

\approx 0.37

装袋法的特点:

  • 始终使用相同的基分类算法。
  • 减少预测的
Variance

(通过接受一些

Bias

)。

  • 对不稳定的分类器(训练集的微小变化会导致预测的巨大变化)有效。
  • 可能会使稳定分类器的性能略有下降。
  • 基于抽样(构造基分类器的三种方法中的实例操作)和投票的简单方法。
  • 多个单独的基分类器可以同步并行进行计算。
  • 可以有效的克服数据集中的噪声数据,因为异常值可能会消失(
\approx 0.63

)。

  • 性能通常比基分类器要好得多,只是偶尔会比基分类器差。

5.2 随机森林法 Random Forest(特征操作)

具有良好深度的决策树就是 低偏差 和 高方差 的模型;因此用决策树做基础模型的Bagging(装袋算法),也称随机森林

在这里插入图片描述
在这里插入图片描述
  • 对于原始数据集的 行:进行Bootstrap抽样(有放回抽样),大小为 m 的样本容量
  • 对于原始数据集的 列:随机选择一个特征子集
  • 在每个行抽样的数据集中,剩下的数据点(也称袋外点)可以用于相应子模型的交叉验证(以了解每个基础学习者的性能)
  1. 随着基础模型数量的增加 ,聚合的模型的方差减少
  2. 偏差(单个模型) ≈ 偏差(聚合后)
  3. 列采样率:
\frac{d'}{d}

;行采样率:

\frac{m}{n}

;如果这两个比值减小,基础模型方差也减小,因此聚合模型的方差也会减少,一般情况固定,不需要认为优化

  1. 基础模型的个数 k ,为超参数,可以根据交叉验证进行确认最优
  2. 特征重要性:对每个基础模型的特征的信息增益求和,再在各特征中进行比较,较大信息增益为较重要特征

随机森林法的基分类器是随机树:一棵决策树,但每个节点只考虑一些可能的属性。

可以通过下图回忆什么是决策树:

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

也就是说随机树使用的特征空间不是训练集全部的特征空间

  • 例如,采用一个固定的比例来选择每个决策树的特征空间大小。
  • 随机森林中的每棵树的建立都比一个单独的决策树要简单和快速;但是这种方法增加了模型的 。

森林就是多个随机树的集合

  • 每棵树都是用不同的袋装训练数据集建立的。
  • 综合分类是通过投票进行的。
在这里插入图片描述
在这里插入图片描述

随机森林的超参数:

树的数量B,可以根据“out-of-bag”误差进行调整。

特征子样本大小:随着它的增加,分类器的强度和相关性都增加

\left ( \left \lfloor log_{2}\left | F \right | + 1 \right \rfloor \right )

。因为随机森林中的每棵树使用的特征越多,其与森林中其他树的特征重合度就可能越高,导致产生的随机数相似度越大。

可解释性:单个实例预测背后的逻辑可以通过多棵随机树共同决定。

随机森林的特点

  • 随机森林非常强大,可以高效地进行构建。
  • 可以并行的进行。
  • 对过拟合有很强的鲁棒性。
  • 可解释性被牺牲了一部分,因为每个树的特征都是特征集合中随机选取的一部分。

5.3 演进法 Boosting(算法操作)

演进法的思想源于调整基础分类器,使其专注于难以分类的实例的直觉判断。

具体方法:

迭代地改变训练实例的分布和权重,以反映分类器在前一次迭代中的表现。

  • 从初始训练集训练出一个基学习器;这时候每个样本的权重都为。
  • 每个都会根据上一轮预测结果调整训练集样本的权重。
  • 基于调整后的训练集训练一个新的基学习器。
  • 重复进行,直到基学习器数量达到开始设置的值。
  • 将个基学习器通过加权的投票方法(weighted voting)进行结合。

例子:

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

对于boosting方法,有两个问题需要解决:

  • 每一轮学习应该如何改变数据的概率分布
  • 如何将各个基分类器组合起来

Boosting集成方法的特点:

  • 他的基分类器是决策树或者 OneR 方法。
  • 数学过程复杂,但是计算的开销较小;整个过程建立在迭代的采样过程和加权的投票(voting)上。
  • 通过迭代的方式不断的拟合残差信息,最终保证模型的精度。
  • 比bagging方法的计算开销要大一些。
  • 在实际的应用中,boosting的方法略有过拟合的倾向(但是不严重)。
  • 可能是最佳的词分类器(gradient boosting)。
5.3.1 演进法实例:AdaBoost

Adaptive Boosting(自适应增强算法):是一种顺序的集成方法(随机森林和 Bagging 都属于并行的集成算法)。

具体方法: 有T个基分类器:

C_{1},C_{2},...,C_{i},..,C_{T}

。 训练集表示为

\left \{ x_{i},y_{j}|j=1,2,...,N \right \}

。 初始化每个样本的权重都为

\frac{1}{N}

,即:

\left \{ w_{j}^{(1)=\frac{1}{N}}|j=1,2,...,N \right \}

在每个iteration i 中,都按照下面的步骤进行:

计算错误率 error rate

\xi _{i}=\sum _{j=1}^{N} w_{j}^{(i)}\delta (C_{j}(x_{j})\neq y_{j})
\delta \left ( \right)

是一个indicator函数,当函数的条件满足的时候函数值为1;即,当弱分类器

C_{i}

对样本

x_{j}

进行分类的时候如果分错了就会累积

w_{j}

使用

\xi _{i}

来计算每个基分类器

C_{i}

的重要程度(给这个基分类器分配权重

\alpha _{i}

\alpha _{i}=\frac{1}{2}ln\frac{1-\varepsilon _{i}}{\varepsilon _{i}}

从这个公式也能看出来,当

C_{i}

判断错的样本量越多,得到的

\xi _{i}

就越大,相应的

\alpha _{i}

就越小(越接近0) 根据

\alpha _{i}

来更新每一个样本的权重参数,为了第i+1个iteration做准备:

w_{j}^{(i+1)}=\frac{w_{j}^{(i)}}{Z^{(i)}}\times \left\{\begin{matrix} e^{-\alpha _{i}} &ifC_{i}(x_{j})=y_{j} \\ e^{\alpha _{i}} & ifC_{i}(x_{j})\neq y_{j} \end{matrix}\right.

样本j的权重由

w_{j}^{(i)}

变成

w_{j}^{(i+1)}

这个过程中发生的事情是:如果这个样本在第i个iteration中被判断正确了,他的权重就会在原本KaTeX parse error: Expected '}', got 'EOF' at end of input: w_{j}^{(i)}的基础上乘以

e^{-\alpha _{i}}

;根据上面的知识

\alpha _{i} > 0

因此

-\alpha _{i} < 0

所以根据公式我们可以知道,那些被分类器预测错误的样本会有一个大的权重;而预测正确的样本则会有更小的权重。

Z^{(i)}

是一个normalization项,为了保证所有的权重相加之和为1。

最终将所有的

C_{i}

按照权重进行集成

持续完成从i=2,…,T的迭代过程,但是当

\varepsilon_{i} > 0.5

的时候需要重新初始化样本的权重最终采用的集成模型进行分类的公式:

C^{*}(x)=argmax_{y}\sum _{i=1}^{T}\alpha _{i}\delta (C_{i}(x)=y)

这个公式的意思大概是:例如我们现在已经得到了3个基分类器,他们的权重分别是0.3, 0.2, 0.1所以整个集成分类器可以表示为:

C(x)=\sum _{i=1}^{T}\alpha _{i}C_{i}(x)=0.3C_{1}(x)+0.2C_{2}(x)+0.1C_{3}(x)

如果类别标签一共只有0, 1那就最终的C(x)对于0的值大还是对于1的值大了。 只要每一个基分类器都比随机预测的效果好,那么最终的集成模型就会收敛到一个强很多的模型。

5.3.2 装袋法/随机森林和演进法对比

装袋法和演进法的对比:

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

装袋法/随机森林 以及演进法对比

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

5.4 堆叠法 Stacking

堆叠法的思想源于在不同偏置的算法范围内平滑误差的直觉。

方法:采用多种算法,这些算法拥有不同的偏置

在基分类器(level-0 model) 的输出上训练一个元分类器(meta-classifier)也叫level-1 model 了解哪些分类器是可靠的,并组合基分类器的输出 使用交叉验证来减少偏置

Level-0:基分类器 给定一个数据集 ( X , y ) 可以是SVM, Naive Bayes, DT等

Level-1:集成分类器 在Level-0分类器的基础上构建新的attributes 每个Level-0分类器的预测输出都会加入作为新的attributes;如果有M个Level-0分离器最终就会加入M个attributes 删除或者保持原本的数据X 考虑其他可用的数据(NB概率分数,SVM权重) 训练meta-classifier来做最终的预测

可视化这个stacking过程:

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

stacking方法的特点:

  • 结合多种不同的分类器
  • 数学表达简单,但是实际操作耗费计算资源
  • 通常与基分类器相比,stacking的结果一般好于最好的基分类器

PS:读到这里你大概已经了解集成学习了,如果你想更深入了解的话可以继续读下去

6. 深入介绍集成技术

6.1 集成学习介绍

我们通过一个例子来理解集成学习的概念。假设你是一名电影导演,你依据一个非常重要且有趣的话题创作了一部短片。现在,你想在公开发布前获得影片的初步反馈(评级)。有哪些可行的方法呢?

A:可以请一位朋友为电影打分。

于是完全有可能出现这种结果:你所选择的人由于非常爱你,并且不希望给你这部糟糕的影片打1星评级来伤害你脆弱的小心脏。

B:另一种方法是让你的5位同事评价这部电影。

这个办法应该更好,可能会为电影提供更客观诚实的评分。但问题依然存在。这5个人可能不是电影主题方面的“专家”。当然,他们可能懂电影摄制,镜头或音效,但他们可能并不是黑色幽默的最佳评判者。

C:让50个人评价这部电影呢?

其中一些可以是你的朋友,可以是你的同事,甚至是完完全全的陌生人。

在这种情况下,回应将更加普遍化和多样化,因为他们拥有不同的技能。事实证明,与我们之前看到的情况相比,这是获得诚实评级的更好方法。

通过这些例子,你可以推断,与个人相比,不同群体的人可能会做出更好的决策。与单一模型相比,各种不同模型也是这个道理。机器学习中的多样化是通过称为集成学习(Ensemble learning)的技术实现的。

现在你已经掌握了集成学习的要旨,接下来让我们看看集成学习中的各种技术及其实现。

6.2 简单集成技术

这一节中,我们会看一些简单但是强大的技术,比如:

  • 最大投票法
  • 平均法
  • 加权平均法

6.2.1 最大投票法

最大投票方法通常用于分类问题。这种技术中使用多个模型来预测每个数据点。每个模型的预测都被视为一次“投票”。大多数模型得到的预测被用作最终预测结果。

例如,当你让5位同事评价你的电影时(最高5分); 我们假设其中三位将它评为4,而另外两位给它一个5。由于多数人评分为4,所以最终评分为4。你可以将此视为采用了所有预测的众数(mode)。

最大投票的结果有点像这样:

示例代码:

这里x_train由训练数据中的自变量组成,y_train是训练数据的目标变量。验证集是x_test(自变量)和y_test(目标变量)。

model1 = tree.DecisionTreeClassifier() model2 = KNeighborsClassifier() model3= LogisticRegression() model1.fit(x_train,y_train) model2.fit(x_train,y_train) model3.fit(x_train,y_train) pred1=model1.predict(x_test) pred2=model2.predict(x_test) pred3=model3.predict(x_test) final_pred = np.array([]) for i in range(0,len(x_test)): final_pred =np.append(final_pred, mode([pred1[i], pred2[i], pred3[i]]))

或者,你也可以在sklearn中使用“VotingClassifier”模块,如下所示:

from sklearn.ensemble import VotingClassifier model1 = LogisticRegression(random_state=1) model2 = tree.DecisionTreeClassifier(random_state=1) model = VotingClassifier(estimators=[(‘lr’, model1), (‘dt’, model2)], voting=‘hard’) model.fit(x_train,y_train) model.score(x_test,y_test)

6.2.2 平均法

类似于最大投票技术,这里对每个数据点的多次预测进行平均。在这种方法中,我们从所有模型中取平均值作为最终预测。平均法可用于在回归问题中进行预测或在计算分类问题的概率时使用。

例如,在下面的情况中,平均法将取所有值的平均值。

即(5 + 4 + 5 + 4 + 4)/ 5 = 4.4

示例代码:

model1 = tree.DecisionTreeClassifier() model2 = KNeighborsClassifier() model3= LogisticRegression() model1.fit(x_train,y_train) model2.fit(x_train,y_train) model3.fit(x_train,y_train) pred1=model1.predict_proba(x_test) pred2=model2.predict_proba(x_test) pred3=model3.predict_proba(x_test) finalpred=(pred1+pred2+pred3)/3

2.3 加权平均法

这是平均法的扩展。为所有模型分配不同的权重,定义每个模型的预测重要性。例如,如果你的两个同事是评论员,而其他人在这方面没有任何经验,那么与其他人相比,这两个朋友的答案就更加重要。

计算结果为[(5 * 0.23)+(4 * 0.23)+(5 * 0.18)+(4 * 0.18)+(4 * 0.18)] = 4.41。

示例代码:

model1 = tree.DecisionTreeClassifier() model2 = KNeighborsClassifier() model3= LogisticRegression() model1.fit(x_train,y_train) model2.fit(x_train,y_train) model3.fit(x_train,y_train) pred1=model1.predict_proba(x_test) pred2=model2.predict_proba(x_test) pred3=model3.predict_proba(x_test) finalpred=(pred1 0.3+pred20.3+pred3*0.4)

6.3 高级集成技术

我们已经介绍了基础的集成技术,让我们继续了解高级的技术。

6.3.1 堆叠(Stacking)

堆叠是一种集成学习技术,它使用多个模型(例如决策树,knn或svm)的预测来构建新模型。该新模型用于对测试集进行预测。以下是简单堆叠集成法的逐步解释:

第一步:把训练集分成10份

第二步:基础模型(假设是决策树)在其中9份上拟合,并对第10份进行预测。

第三步:对训练集上的每一份如此做一遍。

第四步:然后将基础模型(此处是决策树)拟合到整个训练集上。

第五步:使用此模型,在测试集上进行预测。

第六步:对另一个基本模型(比如knn)重复步骤2到4,产生对训练集和测试集的另一组预测。

第七步:训练集预测被用作构建新模型的特征。

第八步:该新模型用于对测试预测集(test prediction set,上图的右下角)进行最终预测。

示例代码:

我们首先定义一个函数来对n折的训练集和测试集进行预测。此函数返回每个模型对训练集和测试集的预测。

def Stacking(model,train,y,test,n_fold): folds=StratifiedKFold(n_splits=n_fold,random_state=1) test_pred=np.empty((test.shape[0],1),float) train_pred=np.empty((0,1),float) for train_indices,val_indices in folds.split(train,y.values): x_train,x_val=train.iloc[train_indices],train.iloc[val_indices] y_train,y_val=y.iloc[train_indices],y.iloc[val_indices] model.fit(X=x_train,y=y_train) train_pred=np.append(train_pred,model.predict(x_val)) test_pred=np.append(test_pred,model.predict(test)) return test_pred.reshape(-1,1),train_pred

现在我们将创建两个基本模型:决策树和knn。

model1 = tree.DecisionTreeClassifier(random_state=1) test_pred1 ,train_pred1=Stacking(model=model1,n_fold=10, train=x_train,test=x_test,y=y_train) train_pred1=pd.DataFrame(train_pred1) test_pred1=pd.DataFrame(test_pred1) model2 = KNeighborsClassifier() test_pred2 ,train_pred2=Stacking(model=model2,n_fold=10,train=x_train,test=x_test,y=y_train) train_pred2=pd.DataFrame(train_pred2) test_pred2=pd.DataFrame(test_pred2)

创建第三个模型,逻辑回归,在决策树和knn模型的预测之上。

df = pd.concat([train_pred1, train_pred2], axis=1) df_test = pd.concat([test_pred1, test_pred2], axis=1) model = LogisticRegression(random_state=1) model.fit(df,y_train) model.score(df_test, y_test)

为了简化上面的解释,我们创建的堆叠模型只有两层。决策树和knn模型建立在零级,而逻辑回归模型建立在第一级。其实可以随意的在堆叠模型中创建多个层次。

6.3.2 混合(Stacking)

混合遵循与堆叠相同的方法,但仅使用来自训练集的一个留出(holdout)/验证集来进行预测。换句话说,与堆叠不同,预测仅在留出集上进行。留出集和预测用于构建在测试集上运行的模型。以下是混合过程的详细说明:

第一步:原始训练数据被分为训练集合验证集。

第二步:在训练集上拟合模型。

第三步:在验证集和测试集上进行预测。

第四步:验证集及其预测用作构建新模型的特征。

第五步:该新模型用于对测试集和元特征(meta-features)进行最终预测。

示例代码:

我们将在训练集上建立两个模型,决策树和knn,以便对验证集进行预测。

model1 = tree.DecisionTreeClassifier() model1.fit(x_train, y_train) val_pred1=model1.predict(x_val) test_pred1=model1.predict(x_test) val_pred1=pd.DataFrame(val_pred1) test_pred1=pd.DataFrame(test_pred1) model2 = KNeighborsClassifier() model2.fit(x_train,y_train) val_pred2=model2.predict(x_val) test_pred2=model2.predict(x_test) val_pred2=pd.DataFrame(val_pred2) test_pred2=pd.DataFrame(test_pred2)

结合元特征和验证集,构建逻辑回归模型以对测试集进行预测。

df_val=pd.concat([x_val, val_pred1,val_pred2],axis=1) df_test=pd.concat([x_test, test_pred1,test_pred2],axis=1) model = LogisticRegression() model.fit(df_val,y_val) model.score(df_test,y_test)

6.3.3 Bagging

Bagging背后的想法是结合多个模型的结果(例如,所有决策树)来获得泛化的结果。这有一个问题:如果在同样一组数据上创建所有模型并将其组合起来,它会有用吗?这些模型极大可能会得到相同的结果,因为它们获得的输入相同。那我们该如何解决这个问题呢?其中一种技术是自举(bootstrapping)。

Bootstrapping是一种采样技术,我们有放回的从原始数据集上创建观察子集,子集的大小与原始集的大小相同。

Bagging(或Bootstrap Aggregating)技术使用这些子集(包)来获得分布的完整概念(完备集)。为bagging创建的子集的大小也可能小于原始集。

第一步:从原始数据集有放回的选择观测值来创建多个子集。

第二步:在每一个子集上创建一个基础模型(弱模型)。

第三步:这些模型同时运行,彼此独立。

第四步:通过组合所有模型的预测来确定最终预测。

6.3.4 Boosting

在我们进一步讨论之前,这里有另一个问题:如果第一个模型错误地预测了某一个数据点,然后接下来的模型(可能是所有模型),将预测组合起来会提供更好的结果吗?Boosting就是来处理这种情况的。

Boosting是一个顺序过程,每个后续模型都会尝试纠正先前模型的错误。后续的模型依赖于之前的模型。接下来一起看看boosting的工作方式:

第一步:从原始数据集创建一个子集。

第二步:最初,所有数据点都具有相同的权重。

第三步:在此子集上创建基础模型。

第四步:该模型用于对整个数据集进行预测。

第五步:使用实际值和预测值计算误差。

第六步:预测错误的点获得更高的权重。(这里,三个错误分类的蓝色加号点将被赋予更高的权重)

第七步:创建另一个模型并对数据集进行预测(此模型尝试更正先前模型中的错误)。

第八步:类似地,创建多个模型,每个模型校正先前模型的错误。

第九步:最终模型(强学习器)是所有模型(弱学习器)的加权平均值。

因此,boosting算法结合了许多弱学习器来形成一个强

推荐阅读