EnsembleVoteClassifier: 多数投票分类器

多数投票分类器 EnsembleVoteClassifier 的实现。

from mlxtend.classifier import EnsembleVoteClassifier

概述

EnsembleVoteClassifier 是一个元分类器,用于通过多数或复数投票结合相似或概念上不同的机器学习分类器进行分类。(为简单起见,我们将多数投票和复数投票都称为多数投票。)

EnsembleVoteClassifier 实现了“硬投票”和“软投票”。在硬投票中,我们将最终类别标签预测为分类模型预测最频繁的类别标签。在软投票中,我们通过平均类别概率来预测类别标签(仅在分类器经过良好校准时推荐)。

注意

如果您对使用 EnsembleVoteClassifier 感兴趣,请注意它现在也可通过 scikit learn (>0.17) 获得,名称为 VotingClassifier

多数投票 / 硬投票

硬投票是多数投票中最简单的情况。在这里,我们预测类别标签通过每个分类器的多数(复数)投票:

假设我们组合三个分类器,它们对一个训练样本进行如下分类

  • 分类器 1 -> 类别 0
  • 分类器 2 -> 类别 0
  • 分类器 3 -> 类别 1

通过多数投票,我们将样本分类为“类别 0”。

加权多数投票

除了上一节中描述的简单多数投票(硬投票)外,我们可以通过关联一个权重与分类器:

其中是特征函数,并且是唯一类别标签的集合。

继续上一节的示例

  • 分类器 1 -> 类别 0
  • 分类器 2 -> 类别 0
  • 分类器 3 -> 类别 1

分配权重 {0.2, 0.2, 0.6} 将产生预测:

软投票

在软投票中,我们根据预测的概率来预测类别标签 -- 只有在分类器经过良好校准时才推荐使用此方法。

其中是可以分配给个分类器的权重。

假设上一节的示例是一个二元分类任务,类别标签为,我们的集成模型可以做出以下预测

使用均匀权重,我们计算平均概率

然而,分配权重 {0.1, 0.1, 0.8} 将产生预测:

参考文献

示例 1 - 使用不同分类模型对 Iris 花进行分类

from sklearn import datasets

iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
import numpy as np

clf1 = LogisticRegression(random_state=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()

print('5-fold cross validation:\n')

labels = ['Logistic Regression', 'Random Forest', 'Naive Bayes']

for clf, label in zip([clf1, clf2, clf3], labels):

    scores = model_selection.cross_val_score(clf, X, y, 
                                              cv=5, 
                                              scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]"
          % (scores.mean(), scores.std(), label))
5-fold cross validation:

Accuracy: 0.95 (+/- 0.04) [Logistic Regression]
Accuracy: 0.94 (+/- 0.04) [Random Forest]
Accuracy: 0.91 (+/- 0.04) [Naive Bayes]
from mlxtend.classifier import EnsembleVoteClassifier

eclf = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3], weights=[1,1,1])

labels = ['Logistic Regression', 'Random Forest', 'Naive Bayes', 'Ensemble']
for clf, label in zip([clf1, clf2, clf3, eclf], labels):

    scores = model_selection.cross_val_score(clf, X, y, 
                                              cv=5, 
                                              scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]" 
          % (scores.mean(), scores.std(), label))
Accuracy: 0.95 (+/- 0.04) [Logistic Regression]
Accuracy: 0.94 (+/- 0.04) [Random Forest]
Accuracy: 0.91 (+/- 0.04) [Naive Bayes]
Accuracy: 0.95 (+/- 0.04) [Ensemble]

绘制决策区域

import matplotlib.pyplot as plt
from mlxtend.plotting import plot_decision_regions
import matplotlib.gridspec as gridspec
import itertools

gs = gridspec.GridSpec(2, 2)

fig = plt.figure(figsize=(10,8))

labels = ['Logistic Regression', 'Random Forest', 'Naive Bayes', 'Ensemble']
for clf, lab, grd in zip([clf1, clf2, clf3, eclf],
                         labels,
                         itertools.product([0, 1], repeat=2)):

    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf)
    plt.title(lab)

png

from sklearn import datasets

iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target
%%capture --no-display

from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import EnsembleVoteClassifier

clf1 = LogisticRegression(random_state=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
eclf = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3], voting='soft')

params = {'logisticregression__C': [1.0, 100.0],
          'randomforestclassifier__n_estimators': [20, 200],}

grid = GridSearchCV(estimator=eclf, param_grid=params, cv=5)
grid.fit(iris.data, iris.target)

cv_keys = ('mean_test_score', 'std_test_score', 'params')

for r, _ in enumerate(grid.cv_results_['mean_test_score']):
    print("%0.3f +/- %0.2f %r"
          % (grid.cv_results_[cv_keys[0]][r],
             grid.cv_results_[cv_keys[1]][r] / 2.0,
             grid.cv_results_[cv_keys[2]][r]))

注意:如果使用多个相似的估计器对象初始化 EnsembleClassifier,估计器名称会添加连续的整数索引进行修改,例如

%%capture --no-display

clf1 = LogisticRegression(random_state=1)
clf2 = RandomForestClassifier(random_state=1)
eclf = EnsembleVoteClassifier(clfs=[clf1, clf1, clf2], 
                              voting='soft')

params = {'logisticregression-1__C': [1.0, 100.0],
          'logisticregression-2__C': [1.0, 100.0],
          'randomforestclassifier__n_estimators': [20, 200],}

grid = GridSearchCV(estimator=eclf, param_grid=params, cv=5)
grid = grid.fit(iris.data, iris.target)

注意

EnsembleVoteClass 也支持对 clfs 参数进行网格搜索。然而,由于 scikit-learn 中 GridSearchCV 的当前实现,无法同时搜索不同的分类器和分类器参数。例如,以下参数字典虽然有效

params = {'randomforestclassifier__n_estimators': [1, 100],
'clfs': [(clf1, clf1, clf1), (clf2, clf3)]}

它将使用 clf1clf2clf3 的实例设置,而不会用 'randomforestclassifier__n_estimators': [1, 100] 中的 'n_estimators' 设置覆盖它。

示例 3 - 使用在不同特征子集上训练的分类器进行多数投票

在 scikit-learn 中实现的特征选择算法以及 SequentialFeatureSelector 都实现了 transform 方法,该方法将减少后的特征子集传递给 Pipeline 中的下一个项目。

例如,方法

def transform(self, X):
    return X[:, self.k_feature_idx_]

给定数据集 X,返回最佳特征列 k_feature_idx_

因此,我们只需要构建一个由特征选择器和分类器组成的 Pipeline,以便为不同的算法选择不同的特征子集。在 拟合 (fitting) 过程中,最佳特征子集通过 GridSearchCV 对象自动确定,通过调用 预测 (predict),管道中已拟合的特征选择器仅传递这些列,这些列对于相应的分类器产生了最佳性能。

%%capture --no-display

from sklearn import datasets

iris = datasets.load_iris()
X, y = iris.data[:, :], iris.target

from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import EnsembleVoteClassifier
from sklearn.pipeline import Pipeline
from mlxtend.feature_selection import SequentialFeatureSelector

clf1 = LogisticRegression(random_state=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()

# Creating a feature-selection-classifier pipeline

sfs1 = SequentialFeatureSelector(clf1, 
                                 k_features=4,
                                 forward=True, 
                                 floating=False, 
                                 scoring='accuracy',
                                 verbose=0,
                                 cv=0)

clf1_pipe = Pipeline([('sfs', sfs1),
                      ('logreg', clf1)])

eclf = EnsembleVoteClassifier(clfs=[clf1_pipe, clf2, clf3], 
                              voting='soft')


params = {'pipeline__sfs__k_features': [1, 2, 3],
          'pipeline__logreg__C': [1.0, 100.0],
          'randomforestclassifier__n_estimators': [20, 200]}

grid = GridSearchCV(estimator=eclf, param_grid=params, cv=5)
grid.fit(iris.data, iris.target)



cv_keys = ('mean_test_score', 'std_test_score', 'params')

for r, _ in enumerate(grid.cv_results_['mean_test_score']):
    print("%0.3f +/- %0.2f %r"
          % (grid.cv_results_[cv_keys[0]][r],
             grid.cv_results_[cv_keys[1]][r] / 2.0,
             grid.cv_results_[cv_keys[2]][r]))

通过网格搜索确定的最佳参数是

grid.best_params_
{'pipeline__logreg__C': 1.0,
 'pipeline__sfs__k_features': 2,
 'randomforestclassifier__n_estimators': 200}

现在,我们将这些参数分配给集成投票分类器,在完整的训练集上拟合模型,并对 Iris 数据集中的 3 个样本执行预测。

eclf = eclf.set_params(**grid.best_params_)
eclf.fit(X, y).predict(X[[1, 51, 149]])
array([0, 1, 2])

手动方法

或者,我们可以使用 ColumnSelector 对象“手动”选择不同的列。在此示例中,我们仅为逻辑回归分类器(clf1)选择第一列(萼片长度)和第三列(花瓣长度)。

from mlxtend.feature_selection import ColumnSelector


col_sel = ColumnSelector(cols=[0, 2])

clf1_pipe = Pipeline([('sel', col_sel),
                      ('logreg', clf1)])

eclf = EnsembleVoteClassifier(clfs=[clf1_pipe, clf2, clf3],
                              voting='soft')
eclf.fit(X, y).predict(X[[1, 51, 149]])
array([0, 1, 2])

此外,我们可以将 SequentialFeatureSelector 单独拟合,放在网格搜索超参数优化管道之外。在这里,我们首先确定最佳特征,然后使用这些“固定”的最佳特征作为 ColumnSelector 的种子构建一个管道。

sfs1 = SequentialFeatureSelector(clf1, 
                                 k_features=2,
                                 forward=True, 
                                 floating=False, 
                                 scoring='accuracy',
                                 verbose=1,
                                 cv=0)

sfs1.fit(X, y)

print('Best features', sfs1.k_feature_idx_)

col_sel = ColumnSelector(cols=sfs1.k_feature_idx_)

clf1_pipe = Pipeline([('sel', col_sel),
                      ('logreg', clf1)])
[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done   4 out of   4 | elapsed:    0.0s finished
Features: 1/2[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done   3 out of   3 | elapsed:    0.0s finished
Features: 2/2

Best features (2, 3)
eclf = EnsembleVoteClassifier(clfs=[clf1_pipe, clf2, clf3], 
                              voting='soft')
eclf.fit(X, y).predict(X[[1, 51, 149]])
array([0, 1, 2])

示例 5 - 使用预训练分类器

from sklearn import datasets

iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target

假设我们之前已经拟合了我们的分类器

from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
import numpy as np

clf1 = LogisticRegression(random_state=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()

for clf in (clf1, clf2, clf3):
    clf.fit(X, y)

通过设置 fit_base_estimators=False,它将强制 use_clones 为 False,并且 EnsembleVoteClassifier 不会重新拟合这些分类器以节省计算时间

from mlxtend.classifier import EnsembleVoteClassifier
import copy
eclf = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3], weights=[1,1,1], fit_base_estimators=False)

labels = ['Logistic Regression', 'Random Forest', 'Naive Bayes', 'Ensemble']

eclf.fit(X, y)

print('accuracy:', np.mean(y == eclf.predict(X)))
accuracy: 0.96


/Users/sebastian/miniforge3/lib/python3.9/site-packages/mlxtend/classifier/ensemble_vote.py:166: UserWarning: fit_base_estimators=False enforces use_clones to be `False`
  warnings.warn("fit_base_estimators=False "

但是,请注意,fit_base_estimators=False 与例如在 model_selection.cross_val_scoremodel_selection.GridSearchCV 中进行的任何形式的交叉验证不兼容,因为它要求分类器重新拟合到训练折叠。因此,只有当您想直接进行预测而无需交叉验证时,才使用 fit_base_estimators=False

示例 6 - 使用在不同特征子集上操作的分类器集成

如果需要,可以将不同的分类器拟合到训练数据集中不同的特征子集。以下示例说明了如何在技术层面使用 scikit-learn 管道和 ColumnSelector 实现这一点

from sklearn.datasets import load_iris
from mlxtend.classifier import EnsembleVoteClassifier
from mlxtend.feature_selection import ColumnSelector
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression

iris = load_iris()
X = iris.data
y = iris.target

pipe1 = make_pipeline(ColumnSelector(cols=(0, 2)),
                      LogisticRegression())
pipe2 = make_pipeline(ColumnSelector(cols=(1, 2, 3)),
                      LogisticRegression())

eclf = EnsembleVoteClassifier(clfs=[pipe1, pipe2])

eclf.fit(X, y)
EnsembleVoteClassifier(clfs=[Pipeline(steps=[('columnselector',
                                              ColumnSelector(cols=(0, 2))),
                                             ('logisticregression',
                                              LogisticRegression())]),
                             Pipeline(steps=[('columnselector',
                                              ColumnSelector(cols=(1, 2, 3))),
                                             ('logisticregression',
                                              LogisticRegression())])])

示例 7 - 关于 Scikit-Learn SVM 和软投票的注意事项

本节提供了一些关于在 voting='soft' 时如何使用概率的附加技术见解。

请注意,scikit-learn 估计 SVM 概率(更多信息请参阅:https://scikit-learn.cn/stable/modules/svm.html#scores-probabilities)的方式可能与 SVM 预测的类别标签不一致。这是一个极端的例子,但假设我们有一个包含 3 个类别标签 0、1 和 2 的数据集。对于给定的训练示例,SVM 分类器可能预测类别 2。然而,类别隶属度概率可能如下所示

  • 类别 0: 99%
  • 类别 1: 0.5%
  • 类别 2: 0.5%

下面显示了这种情况的一个实际示例

import numpy as np
from mlxtend.classifier import EnsembleVoteClassifier
from sklearn.svm import SVC
from sklearn.datasets import load_iris

iris = load_iris()
X, y = iris.data, iris.target

clf2 = SVC(probability=True, random_state=4)
clf2.fit(X, y)
eclf = EnsembleVoteClassifier(clfs=[clf2], voting='soft', fit_base_estimators=False)
eclf.fit(X, y)

for svm_class, e_class, svm_prob, e_prob, in zip(clf2.predict(X),
                                                 eclf.predict(X),
                                                 clf2.predict_proba(X),
                                                 eclf.predict_proba(X)):
    if svm_class != e_class:
        print('============')
        print('Probas from SVM            :', svm_prob)
        print('Class from SVM             :', svm_class)
        print('Probas from SVM in Ensemble:', e_prob)
        print('Class from SVM in Ensemble :', e_class)
        print('============')
============
Probas from SVM            : [0.00921708 0.49415165 0.49663127]
Class from SVM             : 1
Probas from SVM in Ensemble: [0.00921708 0.49415165 0.49663127]
Class from SVM in Ensemble : 2
============


/Users/sebastian/miniforge3/lib/python3.9/site-packages/mlxtend/classifier/ensemble_vote.py:166: UserWarning: fit_base_estimators=False enforces use_clones to be `False`
  warnings.warn("fit_base_estimators=False "

示例 7 - 关于 Scikit-Learn SVM 和软投票的注意事项

基于概率,我们期望 SVM 预测类别 2,因为它具有最高的概率。由于 EnsembleVoteClassifier 在内部使用 argmax 函数(当 voting='soft' 时),即使集成仅包含一个 SVM 模型,它在这种情况下确实会预测类别 2。

请注意,在实践中,这个微小的技术细节无需您担心,但如果您想了解仅使用一个 SVM 模型组成的集成与单独使用该 SVM 相比的结果差异,记住这一点会很有用——这并不是一个 bug。

示例 8 - 使用 Nelder-Mead 优化集成权重

在本节中,我们将了解如何使用启发式搜索方法(如 Nelder-Mead)来优化集成权重。

假设我们有以下示例场景,我们在训练数据集的不同子集上拟合 3 个独立的分类器

from mlxtend.classifier import EnsembleVoteClassifier
from mlxtend.data import mnist_data
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier

X, y = mnist_data()

X_train, X_val, y_train, y_val = train_test_split(
    X, y, test_size=0.5, shuffle=True, random_state=1
)

clf1 = GaussianNB()
clf2 = LogisticRegression(random_state=123, solver='newton-cg')
clf3 = DecisionTreeClassifier(random_state=123, max_depth=2)

clf1.fit(X_train[500:1000], y_train[500:1000])
clf2.fit(X_train[750:1250], y_train[750:1250])
clf3.fit(X_train[1250:2000], y_train[1250:2000]);

然后,我们从这 3 个分类器构建一个集成分类器,其中每个分类器都以权重 1 平均贡献

eclf = EnsembleVoteClassifier(
    clfs=(clf1, clf2, clf3),
    voting="soft",  # the same would also work with "hard" voting
    weights=(1, 1, 1),
    use_clones=False,
    fit_base_estimators=False,
)
eclf.fit(X_train, y_train)
eclf.score(X_val, y_val)
/Users/sebastian/miniforge3/lib/python3.9/site-packages/mlxtend/classifier/ensemble_vote.py:166: UserWarning: fit_base_estimators=False enforces use_clones to be `False`
  warnings.warn("fit_base_estimators=False "





0.8012

我们看到在验证集上达到了 80% 的准确率。我们可以做得更好吗?也许这些独立的分类器不应该平均贡献。或许,我们可以使用 scipy.optimize 中的优化算法来找到这些独立分类器的更好的相对权重。

让我们设置一个目标函数,我们希望通过 SciPy 的 minimize 来最小化它

from scipy.optimize import minimize


def function_to_minimize(weights, fitted_clfs):

    w1, w2 = weights  # these are the new weights!

    newclf = EnsembleVoteClassifier(
        voting="soft",
        use_clones=False,
        fit_base_estimators=False,
        clfs=fitted_clfs,
        weights=(w1, w2, 1.),  # use the new weights
    )

    newclf.fit(X_train, y_train)
    score = newclf.score(X_val, y_val)

    # change accuracy to error so that smaller is better
    score_to_minimize = 1 - score

    return score_to_minimize

注意以下几点

  1. 我们只优化 3 个分类器权重中的 2 个。这是因为权重是相互关联的,同时优化权重 3 将是过度(且自由度过多)的。

  2. 我们像之前一样设置 use_clones=False & fit_base_estimators=False,这是为了确保我们在集成分类器中使用预拟合的分类器。

  3. 我们不优化准确率,而是优化分类错误率,即 score_to_minimize = 1 - score。这是因为我们使用的是 minimize 函数,其中值越低越好。

接下来,让我们选择一些初始权重值并运行优化。通过 bounds,我们指定每个权重的范围(下限和上限),以防止搜索过程出现异常

%%capture --no-display

init_weights = [1., 1.]

results = minimize(
    function_to_minimize,
    init_weights,
    args=((clf1, clf2, clf3),),
    bounds=((0, 5), (0, 5)),
    method="nelder-mead",
)

让我们看看结果!

print(results)
 final_simplex: (array([[0.575     , 1.40625   ],
       [0.57500153, 1.40622215],
       [0.57508965, 1.40617647]]), array([0.1324, 0.1324, 0.1324]))
           fun: 0.13239999999999996
       message: 'Optimization terminated successfully.'
          nfev: 60
           nit: 21
        status: 0
       success: True
             x: array([0.575  , 1.40625])

看来搜索成功了,并返回了以下权重

solution = results["x"]
print(solution)
[0.575   1.40625]

让我们在我们的集成分类器中使用这些新权重

eclf = EnsembleVoteClassifier(
    clfs=(clf1, clf2, clf3),
    voting="soft",
    weights=(solution[0], solution[1], 1),
    use_clones=False,
    fit_base_estimators=False,
)

eclf.fit(X_train, y_train)
eclf.score(X_val, y_val)
/Users/sebastian/miniforge3/lib/python3.9/site-packages/mlxtend/classifier/ensemble_vote.py:166: UserWarning: fit_base_estimators=False enforces use_clones to be `False`
  warnings.warn("fit_base_estimators=False "





0.8676

正如我们所见,验证集上的结果 (0.8676) 相较于原始结果 (0.8012) 有所提高。太棒了!

API

EnsembleVoteClassifier(clfs, voting='hard', weights=None, verbose=0, use_clones=True, fit_base_estimators=True)

scikit-learn 估计器的软投票/多数规则分类器。

参数

  • clfs : 类数组对象, 形状 = [n_分类器数量]

    分类器列表。如果在 use_clones=True (默认) 和 fit_base_estimators=True (默认) 的情况下调用 VotingClassifierfit 方法,将拟合这些原始分类器的克隆版本并存储在类属性中。

  • voting : str, {'hard', 'soft'} (默认='hard')

    如果为 'hard',则使用预测的类别标签进行多数规则投票。如果为 'soft',则基于预测概率总和的 argmax 预测类别标签,这对于由经过良好校准的分类器组成的集成是推荐的。

  • weights : 类数组对象, 形状 = [n_分类器数量], 可选 (默认=None)

    权重序列(floatint),用于加权预测类别标签的出现次数(hard 投票)或在平均之前加权类别概率(soft 投票)。如果为 None,则使用均匀权重。

  • verbose : int, 可选 (默认=0)

    控制构建过程的详细程度。- verbose=0 (默认): 不打印任何信息 - verbose=1: 打印正在拟合的分类器数量和名称 - verbose=2: 打印有关正在拟合的分类器参数的信息 - verbose>2: 将底层分类器的 verbose 参数更改为 self.verbose - 2

  • use_clones : bool (默认: True)

    如果为 True (默认),则克隆分类器用于堆叠分类,否则使用原始分类器,原始分类器将在调用 fit 方法时重新拟合数据集。因此,如果 use_clones=True,则在使用 StackingClassifier 的 fit 方法时,原始输入的分类器将保持不变。如果您使用的估计器支持 scikit-learn fit/predict API 接口,但与 scikit-learn 的 clone 函数不兼容,建议设置 use_clones=False

  • fit_base_estimators : bool (默认: True)

    如果为 True,则重新拟合 clfs 中的分类器;否则使用对 clfs 的引用(假设分类器已拟合)。注意:fit_base_estimators=False 将强制 use_clones 为 False,并且与大多数 scikit-learn 封装器不兼容!例如,如果进行任何形式的交叉验证,这将需要重新拟合分类器到训练折叠,如果在 fit_base_estimators=False 时会引发 NotFitterError。(mlxtend v0.6 新增)

属性

  • classes_ : 类数组对象, 形状 = [n_预测数量]

  • clf : 类数组对象, 形状 = [n_预测数量]

    输入的分类器;如果 use_clones=False 可能会被覆盖

  • clf_ : 类数组对象, 形状 = [n_预测数量]

    已拟合的输入分类器;如果 use_clones=True 则为克隆

示例

```
>>> import numpy as np
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.naive_bayes import GaussianNB
>>> from sklearn.ensemble import RandomForestClassifier
>>> from mlxtend.sklearn import EnsembleVoteClassifier
>>> clf1 = LogisticRegression(random_seed=1)
>>> clf2 = RandomForestClassifier(random_seed=1)
>>> clf3 = GaussianNB()
>>> X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
>>> y = np.array([1, 1, 1, 2, 2, 2])
>>> eclf1 = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3],
... voting='hard', verbose=1)
>>> eclf1 = eclf1.fit(X, y)
>>> print(eclf1.predict(X))
[1 1 1 2 2 2]
>>> eclf2 = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3], voting='soft')
>>> eclf2 = eclf2.fit(X, y)
>>> print(eclf2.predict(X))
[1 1 1 2 2 2]
>>> eclf3 = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3],
...                          voting='soft', weights=[2,1,1])
>>> eclf3 = eclf3.fit(X, y)
>>> print(eclf3.predict(X))
[1 1 1 2 2 2]
>>>

For more usage examples, please see
https://mlxtend.cn/mlxtend/user_guide/classifier/EnsembleVoteClassifier/

```

方法


fit(X, y, sample_weight=None)

从训练数据学习每个分类器的权重系数。

参数

  • X : {类数组对象, 稀疏矩阵}, 形状 = [n_样本数量, n_特征数量]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

  • y : 类数组对象, 形状 = [n_样本数量]

    目标值。

  • sample_weight : 类数组对象, 形状 = [n_样本数量], 可选

    样本权重,作为 sample_weights 传递给回归器列表中的每个回归器以及元回归器。如果某些回归器的 fit() 方法不支持 sample_weight,则引发错误。

返回值

  • self : 对象

fit_transform(X, y=None, **fit_params)

拟合数据,然后转换它。

Fits transformer to `X` and `y` with optional parameters `fit_params`
and returns a transformed version of `X`.

参数

  • X : 形状为 (n_样本数量, n_特征数量) 的类数组对象

    输入样本。

  • y : 形状为 (n_样本数量,) 或 (n_样本数量, n_输出数量) 的类数组对象, 默认=None

    目标值(对于无监督转换为 None)。

  • **fit_params : dict

    额外的拟合参数。

返回值

  • X_new : 形状为 (n_样本数量, n_新特征数量) 的 ndarray 数组

    转换后的数组。


get_params(deep=True)

返回用于 GridSearch 支持的估计器参数名称。


predict(X)

预测 X 的类别标签。

参数

  • X : {类数组对象, 稀疏矩阵}, 形状 = [n_样本数量, n_特征数量]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

返回值

  • maj : 类数组对象, 形状 = [n_样本数量]

    预测的类别标签。


predict_proba(X)

预测 X 的类别概率。

参数

  • X : {类数组对象, 稀疏矩阵}, 形状 = [n_样本数量, n_特征数量]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

返回值

  • avg : 类数组对象, 形状 = [n_样本数量, n_类别数量]

    每个样本每个类别的加权平均概率。


score(X, y, sample_weight=None)

返回给定测试数据和标签上的平均准确率。

In multi-label classification, this is the subset accuracy
which is a harsh metric since you require for each sample that
each label set be correctly predicted.

参数

  • X : 形状为 (n_样本数量, n_特征数量) 的类数组对象

    测试样本。

  • y : 形状为 (n_样本数量,) 或 (n_样本数量, n_输出数量) 的类数组对象

    X 的真实标签。

  • sample_weight : 形状为 (n_样本数量,) 的类数组对象, 默认=None

    样本权重。

返回值

  • score : float

    self.predict(X) 相对于 y 的平均准确率。


set_params(**params)

设置此估计器的参数。

The method works on simple estimators as well as on nested objects
(such as :class:`~sklearn.pipeline.Pipeline`). The latter have
parameters of the form ``<component>__<parameter>`` so that it's
possible to update each component of a nested object.

参数

  • **params : dict

    估计器参数。

返回值

  • self : 估计器实例

    估计器实例。


transform(X)

返回 X 的类别标签或每个估计器的概率。

参数

  • X : {类数组对象, 稀疏矩阵}, 形状 = [n_样本数量, n_特征数量]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

返回值

  • 如果voting='soft'`` : 类数组对象 = [n_分类器数量, n_样本数量, n_类别数量]

    每个分类器计算的类别概率。

  • 如果voting='hard'`` : 类数组对象 = [n_分类器数量, n_样本数量]

    每个分类器预测的类别标签。

Python