机器学习入门 13-2 Soft Voting Classifier

2021-04-07 00:11:21 浏览数 (1)

前言

上一小节介绍了集成学习算法,简单来说让多个机器学习算法在同一个问题上分别进行学习并预测,最终根据 "少数服从多数" 的原则作出最终预测,这种所谓少数服从多数的投票方式称为 Hard Voting。

在很多情况下,少数服从多数的方式并不合理。在社会学中有一个名词叫做民主暴政,如果一个人一票采用完全民主的方式,最终投票的结果反而非常不好,更合理的方式应该是为不同人的投票赋予不同的权值,这种思想在集成学习中被称为 Soft Voting。比如,对选手投票的唱歌比赛中,专业的音乐评审投票的权值相对高一些,而大众评审投票的权重相对的低一些。

Voting Classifier

举一个例子,假设现在整个 Voting Classifier 集合了 5 个二分类模型,分别命名为模型 1、2、3、4、5。当预测时,二分类模型把样本划分某个类别的依据是计算样本属于某个类别的概率值。数据集中一共有 A,B 两个类别,下图是 5 个训练好的二分类模型对同一个样本预测分别属于 A, B 两个类别的概率值。

如果使用 "少数服从多数" 的 Hard Voting,最终预测样本属于 B 类。

不过通过上面的数据会发现一些问题:

  • 虽然只有模型 1 和模型 4 两个模型将样本预测为 A 类,但是这两个模型非常确定这个样本属于 A 类(模型 1 预测样本属于 A 类的概率为 99%,模型 4 预测样本属于 A 类的概率为 90%);
  • 虽然模型 2、模型 3 和模型 5 都将样本预测为了 B 类,但是这三个模型并没有非常确定这个样本属于 B 类(模型 2 预测样本属于 B 类的概率为 51%,模型 3 预测样本属于 B 类的概率为 60%,模型 5 预测样本属于 B 类的概率为 70);

虽然将样本预测成 A 类的模型只有两个(少于预测为 B 的三个模型),但是这两个模型非常确定的认为样本为类别 A,很自然的想法就是为它们赋予更高的权重,这就是 Soft Voting。具体使用 Soft Voting,我们把模型预测样本不同类别的概率作为权值,样本最终类别的概率值为所有模型预测该样本为对应类别概率的平均值。

通过 Soft Voting,最终将样本预测为类别 A。Soft Voting 不仅要看所有模型中预测为类别 A 和类别 B 的模型数量,而且还应该考虑各个模型有多大概率确认将样本预测为类别 A 和类别 B。

Soft Voting 的使用条件

了解了 Soft Voting 的思想,使用 Soft Voting 集成的每一个算法模型都必须要能够估计概率值。下面来看看之前学习的几个算法,看看它们是否可以估计概率。

  • 逻辑回归算法

逻辑回归算法本身就是一个基于概率模型的算法, 显然逻辑回归算法可以估计概率。

  • kNN 算法

使用 kNN 算法来解决分类问题,比如设置超参数 k 为 3 的话,要看距离新的样本(绿色点)最近的三个样本点所属的类别,下图中距离绿色样本点最近的三个样本点中,红色类别的样本点为 2 个,蓝色类别的样本点有 1 个,通过投票的方式,最终 kNN 算法会将绿色新的样本点预测为红色类别。如果想要计算绿色样本点属于红色类别的概率的话,只需要计算 距离最近的红色类别样本个数超参数值,即 。如果考虑权重的话,只需要计算概率时加上对应的权重即可。

  • 决策树

对于决策树来说,预测样本需要从已经构建好的决策树中的根节点出发,根据条件进入决策树的不同分支,最终到达满足匹配预测样本的叶子节点中。如果此时叶子节点上的基尼系数(信息熵)并不为 0,意味着叶子节点中包含有不同类别的样本。此时决策树预测样本为所到达叶子节点中相同类别最多的类别。

如果想要计算样本属于预测类别的概率,只需要计算 样本点到达叶子节点中相同类别最多的样本个数样本点达到叶子节点中的所有样本个数 的值即可。这个思路其实和 kNN 算法得到概率值的思路非常像,这是因为决策树和 kNN 算法都属于非参数学习算法,因此它们有一定的一致性和共同性。

  • SVM 算法

之前学习的算法中,最复杂的就是 SVM 算法。SVM 算法解决分类问题,寻找一个 margin 的最大值,算法本身并没有考虑概率。不过 SVM 算法依然可以使用一些方式来计算出这个概率,这些方式的代价就是更多的计算资源。

在 sklearn 中,使用 SVM 算法解决分类问题需要使用 SVC 类,在实例化 SVC 时,有一个默认值为 False 的 probability 参数,当将 probability 参数设置为 True 的时候,相应的 SVC 算法就可以估计出每个样本属于某个类别的概率值。需要注意这会牺牲一定的计算时间

“probabilitybool, default=False Whether to enable probability estimates. This must be enabled prior to calling fit, will slow down that method as it internally uses 5-fold cross-validation, and predict_proba may be inconsistent with predict. ”

sklearn 实现 Soft Voting Classifier

sklearn 实现 Soft Voting 非常简单。我们首先回顾上一小节实现的 Hard Voting Classifier,最后实现 Soft Voting Classifier。

代码语言:javascript复制
import numpy as np
import matplotlib.pyplot as plt

本小节使用分布呈现交错半圆形的二分类虚拟数据集,使用 sklearn.datasets 包下的 make_moons 函数即可生成这样的虚拟数据集。

代码语言:javascript复制
from sklearn import datasets
    
X, y = datasets.make_moons(n_samples = 500,
                           noise = 0.3,
                           random_state = 42)

在使用 make_moons 函数时指定三个参数:

  • n_samples,生成样本点的总数。默认为 100 个,由于本章需要的数据量相对比较大,因此将 n_samples 设置为 500;
  • noise,加到数据集中的高斯噪声的标准差。默认为 None,noise 的值越小,生成的数据集呈现交错半圆形的分布形状越明显,noise 的值越大,生成的数据集呈现交错半圆形的分布形状越不明显,此时将 noise 设置为相对比较大的 0.3;
  • random_state,随机种子。设置固定的随机种子,能够保证多次试验结果的一致性;

使用散点图将生成的虚拟数据集绘制出来。

代码语言:javascript复制
plt.scatter(X[y == 0, 0], X[y == 0, 1])
plt.scatter(X[y == 1, 0], X[y == 1, 1])
plt.show()

使用 train_test_split 方法将数据集划分为训练集和测试集。

代码语言:javascript复制
from sklearn.model_selection import train_test_split
       
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42)

首先回顾上一小节的 Hard Voting Classifier。

代码语言:javascript复制
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import VotingClassifier

voting_clf = VotingClassifier(estimators = [
    ('log_clf', LogisticRegression()),
    ('svm_clf', SVC()),
    ('dt_clf', DecisionTreeClassifier(random_state = 10))
], voting = 'hard')


voting_clf.fit(X_train, y_train)
voting_clf.score(X_test, y_test)
# 0.912

sklearn 实现的决策树在生成过程中有一定的随机因素,因此在实例化决策树时,设置随机种子 random_state。最终 Hard Voting Classifier 准确率为 91.2%。

最后来实现 Soft Voting Classifier。在 sklearn 中 Soft Voting Classifier 的整个实现流程和 Hard Voting Classifier 基本一致。

代码语言:javascript复制
voting_clf2 = VotingClassifier(estimators = [
    ('log_clf', LogisticRegression()),
    ('svm_clf', SVC(probability = True)), # 估值概率值
    ('dt_clf', DecisionTreeClassifier(random_state= 10))
], voting = 'soft')

使用 Soft Voting Classifier 只需在实例化 VotingClassifier 时为 voting 参数指定为 soft 即可。需要注意,Soft Voting Classifier 中集成的算法需要支持估计概率,前面提到逻辑回归、kNN 和决策树算法天然支持估计概率,而 SVM 算法进行分类的原理是寻找最大的 margin 值,因此本身并不支持估计概率,不过可以以耗费时间代价的方式转换成估计概率,在 sklearn 中可以直接在实例化 SVC 类时传入 probability 参数指定 True 来使 SVM 算法支持估计概率。

依然是通过 fit 函数训练拟合,并通过 score 函数计算在测试集上的准确率。

代码语言:javascript复制
voting_clf2.fit(X_train, y_train)
voting_clf2.score(X_test, y_test)
# 0.928

通过结果可以发现,Soft Voting Classifier 比 Hard Voting Classifier 的效果要好。一旦算法支持估计概率,就可以使用 Soft Voting 将这些算法集成起来,在 sklearn 中调用 Soft Voting 非常容易,而且很多时候 Soft Voting 的效果要比 Hard Voting 要好。

References: Python3入门机器学习 经典算法与应用: https://coding.imooc.com/class/chapter/169.html#Anchor

0 人点赞