Python-应用监督学习-二-

70 阅读1小时+

Python 应用监督学习(二)

原文:annas-archive.org/md5/d906d6d9346f8d8b7965d192afaf9a47

译者:飞龙

协议:CC BY-NC-SA 4.0

第五章:使用 Bagging 对模型进行打包

在本章中,我们讨论以下内容:

  • Bootstrap aggregation

  • 集成元估计器

  • Bagging 回归器

简介

分类器的组合可以帮助显著减少误分类错误。许多研究表明,这种集成方法可以显著减少预测模型的方差。已经提出了几种技术来实现方差减少。例如,在许多情况下,bootstrap aggregating (bagging) 分类树已被证明比单个分类树具有更高的准确性。Bagging 可以应用于基于树的算法以增强预测的准确性,尽管它也可以与基于树的算法以外的其他方法一起使用。

Bootstrap aggregation

Bootstrap aggregation,也称为Bagging,是一种由 Leo Breiman 于 1994 年提出的强大集成方法,用于防止过拟合。Bagging 背后的概念是将多个基础学习者的预测组合起来以创建更准确的输出。

Breiman 表明,Bagging 可以在不稳定的学习算法中成功实现预期结果,在这些算法中,训练数据的小幅变化可能导致预测结果的大幅变化。Breiman 证明了神经网络和决策树等算法是不稳定学习算法的例子。Bootstrap aggregation 在小型数据集上非常有效。

Bagging 的一般过程有助于降低具有高方差的算法的方差。Bagging 还支持分类和回归问题。以下图表显示了 Bootstrap aggregation 流程的工作方式:

图片

使用训练数据集X,我们生成 N 个 bootstrap 样本X1X2,……,XN

对于每个 bootstrap 样本,我们训练一个分类器,图片。组合分类器将平均所有这些单个分类器的输出,如下所示:

图片

在前面的公式中,N 代表样本数量。

在 Bagging 分类器中,使用投票来做出最终预测。Breiman 提出的 Bagging 分类器的伪代码如下:

图片

在 Bagging 回归器的情况下,最终预测是构建在每个 bootstrap 样本上的模型预测的平均值。以下伪代码描述了 Bagging 回归器:

图片

准备工作

我们首先导入所需的库并读取我们的文件。我们使用warnings.filterwarnings()函数从warnings库抑制任何警告:

import warnings
warnings.filterwarnings('ignore')

import os
import pandas as pd
import numpy as np

from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.utils import resample

import matplotlib.pyplot as plt

我们现在已设置好工作文件夹。从 GitHub 下载autompg.csv文件,并将其复制到工作文件夹中,如下所示:

os.chdir('.../.../Chapter 5')
os.getcwd()

我们使用read_csv()读取我们的数据,并在数据帧名称前加上df_前缀,以便更容易理解:

df_autodata = pd.read_csv("autompg.csv")

我们检查数据集是否有任何缺失值,如下所示:

# The below syntax returns the column names which has any missing value
columns_with_missing_values=df_autodata.columns[df_autodata.isnull().any()]

# We pass the column names with missing values to the dataframe to count the number
# of missing values
df_autodata[columns_with_missing_values].isnull().sum()

我们注意到horsepower变量有六个缺失值。我们可以使用horsepower变量现有值的均值来填充这些缺失值,以下代码如下:

df_autodata['horsepower'].fillna(df_autodata['horsepower'].median(), inplace=True)

我们注意到carname变量是一个标识符,在我们的模型构建练习中并不有用,因此我们可以将其删除,如下所示:

df_autodata.drop(['carname'], axis=1, inplace=True)

我们可以使用dataframe.head()命令查看数据:

df_autodata.head()

如何做到这一点...

在本节中,我们将了解如何使用 bootstrap 样本构建模型:

  1. 我们首先创建 bootstrap 样本。在第三章“重采样方法”中,我们编写了一个自定义函数create_bootstrap_oob(),用于创建 bootstrap 和袋外OOB)样本。

在以下代码块中,我们看到如何创建 bootstrap 和 OOB 样本:

def create_bootstrap_oob(df):
    global df_OOB
    global df_bootstrap_sample 
    # creating the bootstrap sample
    df_bootstrap_sample = resample(df, replace=True, n_samples=100)

    # creating the OOB sample 
    bootstrap_sample_index = tuple(df_bootstrap_sample.index)
    bootstrap_df = df.index.isin(bootstrap_sample_index)

    df_OOB = df[~bootstrap_df]
  1. 我们使用 bootstrap 样本构建模型,并对所有模型的成本函数进行平均。我们在每个 bootstrap 样本上使用SGDRegressor()。在以下代码块中,我们重用之前编写的自定义函数create_bootstrap_oob()来创建 bootstrap 和 OOB 误差样本:
iteration=50
mse_each_iterations = list()
lm=SGDRegressor()
total_mse=0
average_mse= list()

for i in range(iteration):
    create_bootstrap_oob(df_autodata)

    # Bootstrap sample features set
    X_BS = df_bootstrap_sample.iloc[:,1:8] 

    # bootstrap sample response variable
    Y_BS = df_bootstrap_sample.iloc[:,0] 

    X_OOB = df_OOB.iloc[:,1:8] #OOB sample features
    Y_OOB = df_OOB.iloc[:,0] #OOB sample response variable 

    # fit your model with bootstrap sample
    lm=SGDRegressor()
    lm.fit(X_BS, Y_BS)

    # test your model on out-of-bag sample 
    predictedvalues = lm.predict(X_OOB)

    # capture MSE for the predicted values against OOB actuals
    mse = mean_squared_error(Y_OOB, predictedvalues)

    # create a list of mse values
    mse_each_iterations.append(mse) 
  1. 现在我们将绘制每个构建的模型的均方误差(MSE):
import matplotlib.pyplot as plt
f, ax= plt.subplots(figsize=(8,6))

plt.plot(mse_each_iterations, 'c--', label='MSE by Iteration')

plt.xlabel('Iterations')
plt.ylabel('Mean Squared Error')
plt.legend(loc=1)
plt.show()

图表将如下所示:

图片

它是如何工作的...

步骤 1中,我们执行了自定义函数代码以创建create_bootstrap_oob()函数,该函数为我们创建 bootstrap 和 OOB 样本。在步骤 2中,我们执行以下步骤:

  1. 我们决定进行 50 次迭代,因此我们将iteration变量设置为50

  2. 在每次迭代中,create_bootstrap_oob()函数返回两个 DataFrame 对象,df_bootstrap_sampledf_OOB

  3. 我们分别使用df_bootstrap_sampledf_OOB作为我们的 bootstrap 和 OOB 样本。

  4. 我们将df_bootstrap_sampledf_OOB样本分别拆分为特征集和响应变量。

  5. 我们将SGDRegressor()拟合到我们的 bootstrap 样本以构建我们的模型。

  6. 我们将 OOB 样本传递给模型以预测我们的值。

  7. 我们将预测值与 OOB 样本中的响应变量进行比较。

  8. 我们计算了每次迭代的 MSE。

步骤 3中,我们创建了一个图表来显示直到第五十次迭代的 MSE。这个结果可能会因为随机性而有所不同。

参见

  • 《Leo Breiman 的《Bagging Predictors》》,1994 年 9 月

集成元估计器

Bagging 分类器和 Bagging 回归器是集成元估计器,分别将基础分类器和回归器模型拟合到原始数据集的随机子集。每个模型的预测被组合起来以创建最终预测。这类元估计器将随机化引入模型构建过程并汇总结果。对于数值目标变量,聚合平均迭代,以实现分类结果进行多数投票。

Bagging 分类器

Bagging 分类器在每个分类器模型上训练原始训练集的随机子集,然后汇总预测,并对分类结果进行多数投票。在下面的配方中,我们将查看一个带有自助样本的 Bagging 分类器的实现。

如何做...

  1. 我们从scikit-learn库中导入BaggingClassifierDecisionTreeClassifier。我们还按如下方式导入其他所需的库:
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
  1. 接下来,我们读取数据并查看其维度:
df_winedata = pd.read_csv('winedata.csv')
df_winedata.shape
  1. 我们将特征和响应集分开。我们还把数据分成训练集和测试集。
X = df_winedata.iloc[:,1:14]
Y = df_winedata.iloc[:,0]

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, random_state=1)
  1. 我们创建一个DecisionTreeClassifier类的实例,并将其传递给BaggingClassifier()
dt_model = DecisionTreeClassifier(criterion='entropy')
bag_dt_model = BaggingClassifier(dt_model, max_features=1.0, n_estimators=5, \
                                 random_state=1, bootstrap=True)

注意,在先前的代码块中,我们已声明bootstrap=True。这是默认值,表示以替换方式抽取样本。

  1. 我们将模型拟合到训练数据如下:
bag_dt_model.fit(X_train, Y_train)
  1. 我们可以看到将测试数据传递给模型后的得分:
bag_dt_model.score(X_test, Y_test)
  1. 我们使用predict函数如下预测响应变量:
predictedvalues = bag_dt_model.predict(X_test)
  1. 我们现在将使用代码来绘制混淆矩阵。请注意,此代码已从scikit-learn.org获取。我们执行以下代码以创建plot_confusion_matrix()函数:
# code from 
# http://scikit-learn.org/stable/auto_examples/model_selection/plot_confusion_matrix.html
def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    """
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, cm[i, j],
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('Actuals')
    plt.xlabel('Predicted')
  1. 我们使用前面的plot_confusion_matrix()函数来绘制我们的混淆矩阵:
# This variable holds the class labels of our target variable
target_names = [ '1', '2', '3']

import itertools
from sklearn.metrics import confusion_matrix

# Constructing the Confusion Matrix
cm = confusion_matrix(Y_test, predictedvalues)

# Plotting the confusion matrix
plt.figure(figsize=(3,3))
plot_confusion_matrix(cm, classes=target_names, normalize=False)
plt.show()

混淆矩阵图如下所示:

图片

它是如何工作的...

步骤 1中,我们导入了所需的库,使用 Bagging 分类器构建我们的决策树分类器模型。在步骤 2中,我们读取了我们的数据集,它是winedata.csv。在步骤 3中,我们分离了特征集和目标变量。我们还把数据分成训练集和测试集。在步骤 4中,我们创建了一个决策树分类器模型,并将其传递给BaggingClassifier()。在DecisionTreeClassifier()中,criterion参数的默认值是gini,但我们将其更改为entropy。然后我们将我们的决策树模型传递给BaggingClassfier()。在BaggingClassfier()中,我们有包括n_estimatorsbootstrap在内的参数。n_estimators是集成中基础估计器的数量,默认值为10bootstrap参数指示是否用替换方式抽取样本,默认设置为True

步骤 5步骤 6中,我们将模型拟合到训练数据,并查看测试集的分数。在步骤 7中,我们调用了predict()方法并传递了测试特征集。在步骤 8中,我们添加了来自scikit-learn.orgplot_confusion_matrix()的代码,它将混淆矩阵作为其输入参数之一,并绘制混淆矩阵。在步骤 9中,我们通过传递混淆矩阵来调用plot_confusion_matrix()函数以生成混淆矩阵图。

还有更多...

我们还可以使用来自sklearn.model_selectionGridSearchCV()来进行网格搜索最佳参数,并在BaggingClassifier中使用它们:

  1. 首先,我们导入所需的库:
from sklearn.model_selection import GridSearchCV
  1. 然后,我们设置我们的参数值:
param_values = {'n_estimators': [10, 20, 25, 30], 'base_estimator__max_leaf_nodes':[5, 10, 15, 20], 'base_estimator__max_depth':[3, 4, 5]}
  1. 我们实例化DecisionTreeClassifier类,并将其传递给BaggingClassifier()函数。请注意,我们将oob_score设置为True以评估基于 OOB 样本构建的模型:
dt_model = DecisionTreeClassifier()
bag_dt_model_grid = BaggingClassifier(base_estimator=dt_model, oob_score=True, random_state=1) 
  1. 我们使用GridSearchCV()来确定最佳参数:
bc_grid = GridSearchCV(estimator=bag_dt_model_grid, param_grid=param_values, cv=20, n_jobs=-1)
bc_grid.fit(X_train, Y_train)
best_params = bc_grid.best_params_
print(best_params)

前面的代码返回了最佳参数:

图片

  1. 现在,我们取bc_grid.bestparams返回的值,并使用BaggingClassfier()函数重新构建我们的决策树模型。我们将max_leaf_nodes设置为10max_depth设置为3n_estimators设置为20
best_dt_model = DecisionTreeClassifier(criterion='entropy', max_leaf_nodes=10, max_depth=3) 
final_bag_dt_model = BaggingClassifier(base_estimator=best_dt_model, n_estimators=150, bootstrap=True, random_state=1, oob_score=True)

在前面的代码块中,我们将n_estimators设置为150n_estimators参数表示我们想要构建的树的数量。我们将最终模型拟合到我们的训练数据,并使用我们的测试特征集进行预测。

  1. 然后,我们可以在以下代码块中查看我们的 OOB 样本的准确率:
final_bag_dt_model.fit(X_train, Y_train)
bag_predictedvalues = final_bag_dt_model.predict(X_test)

# See the OOB accuracy
acc_oob = final_bag_dt_model.oob_score_
print(acc_oob)

如果我们绘制混淆矩阵,我们可以看到我们在错误分类的数量上有所改进。在早期示例中,有两个类 2 的实例被错误地预测为类 3,但现在我们可以看到错误分类的数量减少到了一个:

图片

参考内容

Bagging 回归器

Bagging 回归器与 Bagging 分类器类似。它们在每个回归器模型上训练原始训练集的随机子集,并汇总预测。然后,由于目标变量是数值的,因此汇总平均在迭代中。在下面的配方中,我们将展示使用自助样本实现的 Bagging 回归器的实现。

准备工作

我们将分别从sklearn.ensemblesklearn.tree导入所需的库BaggingRegressorDecisionTreeRegressor

from sklearn.ensemble import BaggingRegressor
from sklearn.tree import DecisionTreeRegressor

我们读取数据集,它是bostonhousing.csv,并查看 DataFrame 的维度:

df_housingdata = pd.read_csv('bostonhousing.csv')
df_housingdata.shape

现在,我们继续创建我们的特征集和目标变量集。

如何实现...

  1. 我们首先将特征集和响应集分开。在下面的代码块中,我们还将数据分为训练集和测试集:
X = df_housingdata.iloc[:,1:14]
Y = df_housingdata.iloc[:,-1]

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, random_state=1)
  1. 然后,我们将创建一个DecisionTreeClassifier类的实例并将其传递给BaggingClassifier()函数:
dt_model = DecisionTreeRegressor()
bag_dt_model = BaggingRegressor(dt_model, max_features=1.0, n_estimators=5, bootstrap=True, random_state=1, )
  1. 我们将按照以下方式将我们的模型拟合到训练数据集:
bag_dt_model.fit(X_train, Y_train)
  1. 我们可以在以下代码块中看到模型得分:
bag_dt_model.score(X_test, Y_test)
  1. 我们使用predict()函数并将测试数据集传递给它来预测我们的目标变量,如下所示:
predictedvalues = bag_dt_model.predict(X_test)
  1. 我们使用以下代码绘制了我们的实际值和目标变量的预测值的散点图:
#We can plot the actuals and the predicted values 
plt.figure(figsize=(4, 4))
plt.scatter(Y_test, predictedvalues)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.tight_layout()

执行前面的代码给出了以下散点图:

matplotlib.pyplot.tight_layout()自动调整子图参数以创建指定的填充。

  1. 在以下代码中,我们将n_estimators参数更改为 30,并重新执行从步骤 3步骤 6的步骤:
bag_dt_model = BaggingRegressor(dt_model, max_features=1.0, n_estimators=30, bootstrap=True, random_state=1, )

这给出了以下得分:

  1. 实际值与预测值的图表如下。这表明,与我们将n_estimator参数的值从5改为30的前一个案例相比,预测值更加准确:

它是如何工作的...

步骤 1中,我们将特征和目标变量集分开。我们还把我们的数据分成训练集和测试集。在步骤 2中,我们创建了一个决策树回归器模型并将其传递给BaggingRegressor()函数。请注意,我们还向BaggingRegressor()函数传递了n_estimator=5参数。如前所述,n_estimator是我们希望算法构建的森林中树的数量。在步骤 3中,我们训练了我们的模型。

步骤 4中,我们查看了模型得分,为 0.71。在步骤 5中,我们使用predict()函数预测测试子集中的目标变量。之后,在步骤 6中,我们绘制了一个散点图来探索实际目标值和预测目标值之间的关系。

步骤 7中,我们将n_estimator参数的值从5改为30并重新构建了我们的模型。这次,我们注意到模型得分提高到了 0.82。在步骤 8中,我们绘制了实际值和预测值,并发现实际值和预测值之间的相关性比我们之前使用n_estimators=5的模型要好得多。

参见

第六章:当有疑问时,使用随机森林

在本章中,我们将涵盖以下食谱:

  • 随机森林简介

  • 使用 scikit-learn 实现随机森林以预测信用卡违约

  • 使用 H2O 实现预测信用卡违约的随机森林

随机森林简介

随机森林是一种基于集成学习的监督机器学习算法,用于回归和分类问题。随机森林背后的基本思想是构建多个决策树并将它们聚合以获得准确的结果。决策树是一种确定性算法,这意味着如果给定的相同数据,每次都会产生相同的树。它们有过度拟合的倾向,因为它们使用给定数据构建最佳树,但在提供未见数据时可能无法泛化。构成随机森林的所有决策树都是不同的,因为我们使用不同的随机子集构建每棵树。随机森林通常比单个决策树更准确,因为它最小化了过度拟合。

以下图表展示了从源样本中进行的引导采样。在每个样本上构建模型,然后将预测组合起来以得出最终结果:

图片

随机森林中的每棵树都是按照以下步骤构建的,其中 A 代表整个森林,a 代表单个树,对于 a = 1A

  1. 使用替换方法创建一个从 xy 标签的 X[a][, ]Y[a] 训练的引导样本,D 训练

  2. X[a]Y[a] 上训练树 f[a]

  3. 取平均值或进行多数投票以得出最终预测

在回归问题中,通过取所有树做出的预测的平均值来对测试实例进行预测。这可以表示如下:

图片

在这里,N 是随机森林中树的总数。a=1 代表森林中的第一棵树,而森林中的最后一棵树是 A。(图片(图片)) 代表单个树的预测。

如果我们有一个分类问题,则使用多数投票或最常见的答案。

使用 scikit-learn 实现预测信用卡违约的随机森林

scikit-learn 库通过提供两个估计器实现随机森林:RandomForestClassifierRandomForestRegressor。它们接受各种参数,其中一些如下所述:

  •  n_estimators:此参数是算法在采取最大投票或平均预测之前构建的树的数量。一般来说,树的数量越多,性能和预测的准确性越好,但这也意味着计算成本更高。

  • max_features: 此参数是随机森林允许在单个树中尝试的最大特征数。

  • min_sample_leaf: 此参数决定了分割内部节点所需的最小叶子数。

  • n_jobs: 此超参数告诉引擎在拟合模型和预测新实例时并行运行多少个作业。如果它的值为 None1,则只运行一个作业。-1 的值意味着它将使用所有处理器。

  • random_state: 此参数将在 random_state 有确定的值时始终产生相同的结果,并且如果它已经给出了相同的超参数和相同的训练数据。

  • oob_score: 此参数也称为 袋外抽样,是一种随机森林交叉验证方法。在此抽样方法中,大约三分之一的 数据未用于训练模型,可用于评估其性能。这些样本称为 袋外样本

准备工作

在这个例子中,我们使用了来自 UCI ML 存储库的信用卡违约数据集。此数据集包含以下信息:

  • 违约支付

  • 人口统计因素

  • 信用数据

  • 付款历史

  • 信用卡客户的账单

数据和数据描述提供在 GitHub 文件夹中:

我们将首先加载所需的库并读取我们的数据集:

import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns

我们将工作文件夹设置为以下内容:

# Set your working directory according to your requirement
os.chdir(".../Chapter 6/Random Forest")
os.getcwd()

让我们现在读取我们的数据。我们将 DataFrame 名称前缀为 df_,这样我们就可以轻松理解它:

df_creditcarddata = pd.read_csv("UCI_Credit_Card.csv")

我们检查数据集的形状:

df_creditcarddata.shape

我们检查数据类型:

df_creditcarddata.dtypes

我们删除了 ID 列,因为这不是必需的:

df_creditcarddata = df_creditcarddata.drop("ID", axis= 1) 

我们可以用各种方式探索我们的数据。让我们看看几种不同的方法:

selected_columns = df_creditcarddata[['AGE','BILL_AMT1','BILL_AMT2','BILL_AMT3','BILL_AMT4','BILL_AMT5','BILL_AMT6', 'LIMIT_BAL']]

selected_columns.hist(figsize=(16, 20), bins=50, xlabelsize=8, ylabelsize=8);

注意,在前面的代码块中,我们使用了分号。分号有助于隐藏 Matplotlib 生成的冗长信息。xlabelsizeylabelsize 用于调整 x 轴和 y 轴的字体大小。

以下图表显示了数值变量的分布:

图片

现在,我们将按年龄组探索支付违约情况。我们将 age 变量分桶,并将分桶的值存储在 df_creditcarddata 中的新变量 age_group 中:

df_creditcarddata['agegroup'] = pd.cut(df_creditcarddata['AGE'], range(0, 100, 10), right=False)
df_creditcarddata.head()

然后,我们使用新的 age_group 变量来绘制每个年龄组的违约数量:

# Default vs Age
pd.crosstab(df_creditcarddata.age_group, \
           df_creditcarddata["default.payment.next.month"]).plot(kind='bar',stacked=False, grid=True) 

plt.title('Count of Defaults by AGE')
plt.xlabel('AGE')
plt.ylabel('# of Default')
plt.legend(loc='upper left')

以下截图显示了每个年龄的违约金额:

图片

由于我们不再需要它,我们可以从 df_creditcarddata 中删除 age_group 变量:

df_creditcarddata = df_creditcarddata.drop(columns = ['age_group'])
df_creditcarddata.head()

现在,我们将根据账户持有者的信用额度查看支付违约情况:

fig_facetgrid = sns.FacetGrid(df_creditcarddata, hue='default.payment.next.month', aspect=4)
fig_facetgrid.map(sns.kdeplot, 'LIMIT_BAL', shade=True)
max_limit_bal = df_creditcarddata['LIMIT_BAL'].max()
fig_facetgrid.set(xlim=(0,max_limit_bal));
fig_facetgrid.set(ylim=(0.0,0.000007));
fig_facetgrid.set(title='Distribution of limit balance by default.payment')
fig_facetgrid.add_legend()

上述代码给出了以下图表:

图片

我们还可以为一些变量分配标签以使解释更好。我们为 GenderMarriageEducation 变量分配标签。

我们还将pay变量的数据类型更改为字符串:

GenderMap = {2:'female', 1:'male'}
MarriageMap = {1:'married', 2:'single', 3:'other', 0: 'other'}
EducationMap = {1:'graduate school', 2:'university', 3:'high school', 4:'others', 5:'unknown', 6:'unknown', 0:'unknown'}

df_creditcarddata['SEX'] = df_creditcarddata.SEX.map(GenderMap)
df_creditcarddata['MARRIAGE'] = df_creditcarddata.MARRIAGE.map(MarriageMap) 
df_creditcarddata['EDUCATION'] = df_creditcarddata.EDUCATION.map(EducationMap)
df_creditcarddata['PAY_0'] = df_creditcarddata['PAY_0'].astype(str) 
df_creditcarddata['PAY_2'] = df_creditcarddata['PAY_2'].astype(str) 
df_creditcarddata['PAY_3'] = df_creditcarddata['PAY_3'].astype(str) 
df_creditcarddata['PAY_4'] = df_creditcarddata['PAY_4'].astype(str) 
df_creditcarddata['PAY_5'] = df_creditcarddata['PAY_5'].astype(str) 
df_creditcarddata['PAY_6'] = df_creditcarddata['PAY_6'].astype(str) 

在本书提供的代码包中还有更多的探索。我们现在继续训练我们的随机森林模型。

如何做到这一点...

现在我们将探讨如何使用随机森林来训练我们的模型:

  1. 我们首先将目标和特征变量分开:
predictor= df_creditcarddata.iloc[:, df_creditcarddata.columns != 'default.payment.next.month']
target= df_creditcarddata.iloc[:, df_creditcarddata.columns == 'default.payment.next.month']
  1. 我们在我们的特征集中将数值变量和非数值变量分开:
# save all categorical columns in list
categorical_columns = [col for col in predictor.columns.values if predictor[col].dtype == 'object']

# dataframe with categorical features
df_categorical = predictor[categorical_columns]

# dataframe with numerical features
df_numeric = predictor.drop(categorical_columns, axis=1)
  1. 我们对分类变量进行虚拟编码:
dummy_code_cat_vars = pd.get_dummies(df_categorical,drop_first=True)
  1. 我们将虚拟编码变量连接到我们的 DataFrame:
df_predictor = pd.concat([df_numeric, dummy_code_cat_vars], axis=1)
df_predictor.head()
  1. 我们将数据集分为训练集和测试集:
from sklearn.model_selection import train_test_split
X_train,X_test, y_train, y_test = train_test_split(df_predictor, target, test_size = 0.30, random_state=0)
print("x_train ",X_train.shape)
print("x_test ",X_test.shape)
print("y_train ",y_train.shape)
print("y_test ",y_test.shape)
  1. 我们使用StandardScaler()对特征进行缩放:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
  1. 我们可能会注意到列名已被更改为数字。我们将列名和索引值赋回缩放后的 DataFrame:
X_train_scaled.columns = X_train.columns.values
X_test_scaled.columns = X_test.columns.values
X_train_scaled.index = X_train.index.values
X_test_scaled.index = X_test.index.values

X_train = X_train_scaled
X_test = X_test_scaled
  1. 我们从sklearn.ensemble导入RandomForestClassifier()。然后我们将构建我们的随机森林分类器模型:
from sklearn.ensemble import RandomForestClassifier

classifier = RandomForestClassifier(random_state = 0, n_estimators = 100,\
 criterion = 'entropy', max_leaf_nodes= 20,oob_score = True, n_jobs = -1 )

# fit the model
model_RF = classifier.fit(X_train, y_train)
  1. 之后,我们计算训练模型的准确率:
acc_random_forest = round(classifier.score(X_train, y_train) * 100, 2)
print(round(acc_random_forest,2,), "%")
  1. 通过将y_testy_pred_proba传递给roc_curve(),我们得到假阳性率FPR)和真阳性率TPR)。我们还可以使用roc_auc_score()得到auc值。使用 FPR、TPR 和 AUC 值,我们在图表上绘制 ROC 曲线,并在图表上标注 AUC 值:
from sklearn import metrics

y_pred_proba = model_RF.predict_proba(X_test)[::,1]
fpr, tpr, _ = metrics.roc_curve(y_test, y_pred_proba)
auc = metrics.roc_auc_score(y_test, y_pred_proba)
plt.plot(fpr,tpr,label="AUC="+str(auc))
plt.legend(loc=4)
plt.show()

以下图表显示了带有标注 AUC 值的 ROC 曲线:

  1. 我们还可以评估其他分数,如下所示:
# predict the model
y_pred_RF = model_RF.predict(X_test)

# evaluate other scores
evaluation_scores = pd.Series({'Model': " Random Forest Classifier ",
'ROC Score' : metrics.roc_auc_score(y_test, y_pred_RF),
'Precision Score': metrics.precision_score(y_test, y_pred_RF),
'Recall Score': metrics.recall_score(y_test, y_pred_RF),
'Accuracy Score': metrics.accuracy_score(y_test, y_pred_RF),
'Kappa Score':metrics.cohen_kappa_score(y_test, y_pred_RF)})

print(evaluation_scores)

上述代码产生了以下评估分数:

  1. 我们还可以根据目标变量的类别评估一些统计信息,在这种情况下是01
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred_RF))

sklearn.metrics中的classification_report根据目标变量的每个类别给出以下分数:

  1. 我们可以通过特征重要性绘制前 10 个变量,以查看哪些变量对模型很重要:
feature_importances = pd.Series(classifier.feature_importances_, index=X_train.columns)
feature_importances.nlargest(10).plot(kind='barh') #top 10 features

以下截图显示了前 10 个变量及其相对重要性:

我们可以更改超参数以查看模型如何表现更好。我们还可以对超参数值的组合进行网格搜索以微调我们的模型。

它是如何工作的...

步骤 1中,我们将目标和特征变量分开。在步骤 2中,在我们的特征集中,我们将数值变量和非数值变量分开。在步骤 3步骤 4中,我们将非数值变量转换为虚拟编码变量,并将它们添加回 DataFrame。在步骤 5中,我们将数据集分为训练集和测试集,在步骤 6中,我们从sklearn.preprocessing导入StandardScaler()并将相同的缩放应用于我们的特征。

执行步骤 6中的命令后,我们注意到列名已更改为顺序号。因此,在步骤 7中,我们将列名和索引值重新分配给缩放后的 DataFrame。在步骤 8中,我们从sklearn.ensemble中导入RandomForestClassifier()并构建了我们第一个随机森林分类器模型。之后,在步骤 9步骤 10中,我们使用我们的模型计算训练模型的准确度并绘制 ROC 曲线。我们还用 AUC 值标注了 ROC 曲线。

步骤 11中,我们评估了其他分数,包括 kappa 值、精确度、召回率和准确度。

步骤 12中,我们也根据目标变量的每个类别(在这种情况下是01)使用sklearn.metrics中的classification_report对这些分数进行了评估。在那里,classification_report()为我们提供了每个类别的精确度、召回率和 f1 分数等指标,以及每个指标的均值。

classification_report()报告平均值,包括平均总真实阳性、假阴性、假阳性,平均每个标签的无权均值,以及平均每个标签的支持加权均值。它还报告多标签分类的样本平均值。

最后,在步骤 13中,我们研究了前 10 个特征的相对变量重要性。这有助于在特征选择中构建具有正确特征的模型。

有各种特征选择方法可用,例如平均变量重要性、Boruta、递归特征选择以及使用 RF 进行变量选择。

还有更多...

隔离森林是另一种基于决策树的算法,用于异常值和异常检测。该算法基于异常数据点稀少的假设。

该算法的工作方式与随机森林略有不同。它创建了一组决策树,然后计算在树中隔离一个观察所需的路径长度。其想法是孤立观察值或异常值更容易分离,因为区分它们与正常情况所需的条件较少。因此,异常值将比正常观察值有更短的路径,并且因此将更靠近树的根部。当创建了多个决策树时,分数会被平均,这让我们对哪些观察值真正是异常值有一个很好的了解。因此,隔离森林被用于异常值和异常检测。

此外,隔离森林不利用任何距离或密度度量来检测异常。与基于距离和密度的方法相比,这显著降低了计算成本。

在 scikit-learn 中,sklearn.ensemble.IsolationForest提供了隔离森林算法的实现。

参见

  • 隔离森林算法的 scikit-learn 实现可以在这里找到:bit.ly/2DCjGGF

使用 H2O 实现预测信用卡违约的随机森林

H2O 是一个开源的分布式机器学习平台,允许您在大型数据集上构建机器学习模型。H2O 支持监督和非监督算法,并且非常快速、可扩展且易于实现。H2O 的 REST API 允许我们从外部程序(如 R 和 Python)访问其所有功能。在编写本书时,H2O 的最新版本是 H2O v3。

H2O 将闪电般的机器学习带给企业的原因如下所述:

"H2O 的核心代码是用 Java 编写的。在 H2O 中,使用分布式键/值存储来访问和引用数据、模型、对象等,跨越所有节点和机器。算法是在 H2O 的分布式 Map/Reduce 框架上实现的,并利用 Java fork/join 框架进行多线程处理。数据并行读取并分布在整个集群中,以压缩的列格式存储在内存中。H2O 的数据解析器具有内置的智能来猜测传入数据集的模式,并支持从多种格式的多个来源进行数据摄取"

  • 来自 h2o.ai

H2O 为我们提供了分布式随机森林,这是一种用于分类和回归任务的有力工具。它生成多个树,而不是单个树。在分布式随机森林中,我们使用分类和回归模型的平均预测来得出最终结果。

准备工作

Java 对于 H2O 运行是绝对必要的。请确保您已安装 Java,并在 Jupyter 中使用以下命令:

! apt-get install default-jre
! java -version

现在,您需要安装 H2O。要从 Jupyter 安装,请使用以下命令:

! pip install h2o

导入所需的库:

import h2o
import seaborn as sns
import numpy as np
import pandas as pd
import seaborn
import matplotlib.pyplot as plt
%matplotlib inline

from h2o.estimators.random_forest import H2ORandomForestEstimator
from sklearn import metrics

要使用 H2O,我们需要初始化一个实例并将其连接。我们可以这样做:

h2o.init()

默认情况下,前面的命令会尝试连接到一个实例。如果它无法这样做,它将尝试启动一个实例然后连接到它。一旦连接到实例,我们将看到该实例的详细信息,如下所示:

图片

我们将数据读入一个 pandas DataFrame:

df_creditcarddata = pd.read_csv("UCI_Credit_Card.csv")

我们使用 h2o.H2OFrame() 将我们的 pandas DataFrame 转换为 H2O DataFrame。我们将 df_creditcarddata H2O DataFrame 命名:

hf_creditcarddata = h2o.H2OFrame(df_creditcarddata)

检查 H2O DataFrame 中的数据是否已正确加载,如下所示:

hf_creditcarddata.head()

我们可以使用 describe() 方法查看摘要统计信息:

hf_creditcarddata.describe()

我们删除 ID 列,因为这对于我们的模型构建练习不是必需的:

hf_creditcarddata = hf_creditcarddata.drop(["ID"], axis = 1) 

我们现在将进入探索数据和构建模型的过程。

如何做到这一点...

在上一节中,我们对数据进行了各种探索。我们可以探索数据的方式没有限制。在本节中,我们将探讨一些更多技术:

  1. 我们检查每个特征变量与目标变量的相关性:
df_creditcarddata.drop(['default.payment.next.month'], \
     axis = 1).corrwith(df_creditcarddata['default.payment.next.month']).\
     plot.bar(figsize=(20,10), \
     title = 'Correlation with Response variable', \
     fontsize = 15, rot = 45, grid = True)

下面的图显示了每个特征与目标变量的相关性:

图片

  1. 我们检查 H2O DataFrame 中的数据类型。注意,对于pandas DataFrame,我们使用了dtypes。对于 H2O DataFrame,我们使用types
hf_creditcarddata.types
  1. 我们注意到它们都是整型数据类型。我们将它们转换为因子类型,这是分类性质的:
hf_creditcarddata['SEX'] = hf_creditcarddata['SEX'].asfactor()
hf_creditcarddata['EDUCATION'] = hf_creditcarddata['EDUCATION'].asfactor()
hf_creditcarddata['MARRIAGE'] = hf_creditcarddata['MARRIAGE'].asfactor()
hf_creditcarddata['PAY_0'] = hf_creditcarddata['PAY_0'].asfactor()
hf_creditcarddata['PAY_2'] = hf_creditcarddata['PAY_2'].asfactor()
hf_creditcarddata['PAY_3'] = hf_creditcarddata['PAY_3'].asfactor()
hf_creditcarddata['PAY_4'] = hf_creditcarddata['PAY_4'].asfactor()
hf_creditcarddata['PAY_5'] = hf_creditcarddata['PAY_5'].asfactor()
hf_creditcarddata['PAY_6'] = hf_creditcarddata['PAY_6'].asfactor()

我们可以使用hf_creditcarddata.types来检查数据类型,以查看数据类型转换是否已发生。

  1. 我们将二进制目标变量编码为因子类型变量:
hf_creditcarddata['default.payment.next.month'] = \
             hf_creditcarddata['default.payment.next.month'].asfactor() 
hf_creditcarddata['default.payment.next.month'].levels() 
  1. 我们选择特征和target变量:
predictors = ['LIMIT_BAL','SEX','EDUCATION','MARRIAGE','AGE','PAY_0','PAY_2','PAY_3','PAY_4','PAY_5','PAY_6','BILL_AMT1','BILL_AMT2','BILL_AMT3','BILL_AMT4','BILL_AMT5','BILL_AMT6','PAY_AMT1','PAY_AMT2','PAY_AMT3','PAY_AMT4','PAY_AMT5','PAY_AMT6']

target = 'default.payment.next.month'
  1. 现在,我们将 H2O DataFrame 拆分为训练集和测试集。我们使用 70%的数据来训练模型,剩余的 30%用于验证:
splits = hf_creditcarddata.split_frame(ratios=[0.7], seed=123) 
train = splits[0]
test = splits[1] 
  1. 我们使用默认设置构建了随机森林模型。您可以使用以下命令检查测试数据上的模型性能:
from h2o.estimators.random_forest import H2ORandomForestEstimator

RF_D = H2ORandomForestEstimator(model_id = 'RF_D',seed = 123)
RF_D.train(x = predictors, y = target, training_frame = train)

print(RF_D.model_performance(test))

这给我们以下性能指标:

图片

它是如何工作的...

准备就绪部分,我们安装了 JRE 和 H2O。我们使用h2o.init()初始化并连接到一个 H2O 实例。然后我们使用pandas读取我们的数据并将其转换为 H2O DataFrame。我们在 H2O DataFrame 上使用了head()describe()方法,就像我们在pandas DataFrame 上使用它们一样。然后我们从 H2O DataFrame 中删除了ID列。

准备就绪部分进行这些数据探索之后,我们继续下一步。在步骤 1中,我们检查了每个特征与target变量的相关性。在步骤 2中,我们使用了h2o DataFrame 并检查了数据类型。

注意,对于pandas DataFrame,我们使用了dtypes,而对于h2o DataFrame,我们使用了types

步骤 3中,我们使用了asfactor()函数将数值变量转换为分类类型。我们对那些本应为分类类型但显示为数值的变量执行了此操作。

在前面的例子中,我们在pandas DataFrame 上使用了astype()方法。对于 H2O DataFrame,我们使用了asfactor()方法。

步骤 4中,我们在target变量上使用了asfactor()将其转换为分类变量。

步骤 5中,我们将特征和target变量分开。在步骤 6中,我们使用split_frame()在 H2O DataFrame 上拆分了 H2O DataFrame,将数据集分为训练集和测试集。我们使用ratios参数,并将其设置为ratios=[0.7],以便split_frame()将 70%的数据分配给训练集,30%的数据分配给测试集。

步骤 7中,我们从h2o.estimators.random_forest导入了H2ORandomForestEstimator。我们传递了model_id,然后引用它来调用train()函数并传递预测变量和target变量。然后我们通过传递测试子集到model_performance()来查看性能指标。

还有更多...

在我们前面的例子中,我们有 AUC 为0.76和 log 损失为0.44

  1. 我们可以通过将nfolds作为参数传递给H2ORandomForestEstimator()来应用交叉验证:
RF_cv = H2ORandomForestEstimator(model_id = 'RF_cv', 
                                 seed = 12345, 
                                 ntrees = 500, 
                                 sample_rate = 0.9, 
                                 col_sample_rate_per_tree = 0.9, 
                                 nfolds = 10)

RF_cv.train(x = predictors, y = target, training_frame = train)
print(RF_cv.model_performance(test))

我们注意到 AUC 略有提高至0.77,而 log 损失降至0.43

图片

  1. 我们还可以应用网格搜索来从给定选项中提取最佳模型。我们设置选项如下:
search_criteria = {'strategy': "RandomDiscrete"}

hyper_params = {'sample_rate': [0.5, 0.6, 0.7],\
                'col_sample_rate_per_tree': [0.7, 0.8, 0.9],\
                'max_depth': [3, 5, 7]}
  1. 我们使用前面的搜索参数构建模型:
from h2o.grid.grid_search import H2OGridSearch

RF_Grid = H2OGridSearch(
                    H2ORandomForestEstimator(
                        model_id = 'RF_Grid', 
                        ntrees = 200, 
                        nfolds = 10,
                        stopping_metric = 'AUC', 
                        stopping_rounds = 25), 
                    search_criteria = search_criteria, # full grid search
                    hyper_params = hyper_params)
RF_Grid.train(x = predictors, y = target, training_frame = train)
  1. 我们现在按 AUC 降序对所有模型进行排序,然后选择第一个具有最高 AUC 的模型:
RF_Grid_sorted = RF_Grid.get_grid(sort_by='auc',decreasing=True)
print(RF_Grid_sorted)

best_RF_model = RF_Grid_sorted.model_ids[0]
best_RF_from_RF_Grid = h2o.get_model(best_RF_model)
  1. 我们应用最佳模型来测试我们的数据:
best_RF_from_RF_Grid.model_performance(test)
  1. 我们可以绘制到目前为止我们达到的最佳模型的变量重要性:
best_RF_from_RF_G
rid.varimp_plot()

这给出了以下图表:

图片

参见

你可能想了解一下极随机树,它们的实现方式略有不同,但有时可能比随机森林表现得更好。

在集成方法中,每个模型在数据集的子集和用于训练的特征向量子集方面以不同的方式学习。这些子集是随机选取的。极随机树在计算分裂和选择特征子集的方式上具有很高的随机性因素。与随机森林不同,在随机森林中分裂阈值是随机选择的,而在极随机树中,使用判别阈值作为分裂规则。因此,集成整体的方差降低,整体性能可能更好。

在以下链接中可以找到 scikit-learn 对极随机树的实现:bit.ly/2zWsNNS. H2O 也支持极随机树。

第七章:使用提升算法提升模型性能

在本章中,我们将涵盖以下食谱:

  • 提升算法简介

  • 使用 scikit-learn 实现 AdaBoost 进行疾病风险预测

  • 使用 scikit-learn 实现梯度提升进行疾病风险预测

  • 使用 XGBoost 和 scikit-learn 实现极端梯度提升进行玻璃识别

提升算法简介

提升算法是一种集成技术,通过将一组弱学习器组合起来形成一个强学习器,从而帮助提高模型性能和准确性。提升背后的理念是预测器应该从先前预测器所犯的错误中学习。

提升算法有两个关键特性:

  • 首先,它们经历多次迭代

  • 第二,每次迭代都专注于先前迭代错误分类的实例

当一个输入被假设错误分类时,其权重将在下一次迭代中改变,以便下一个假设可以正确分类它。将更多的权重给予在训练数据上提供更好性能的那些。通过多次迭代,这个过程将弱学习器转换为一组强学习器,从而提高模型性能。

在袋装法中,没有自助样本依赖于任何其他自助样本,因此它们都并行运行。提升算法以顺序方式进行,不涉及自助采样。袋装法和提升法都通过将不同模型中的多个估计组合成一个单一估计来减少单个估计的方差。然而,需要注意的是,如果单个模型过拟合,提升算法并不能显著帮助。如果模型过拟合,袋装法可能是一个更好的选择。另一方面,提升算法试图减少偏差,而袋装法很少能改善偏差。

在本章中,我们将介绍不同的提升算法,例如自适应提升AdaBoost)、梯度提升和极端梯度提升XGBoost)。

使用 scikit-learn 实现 AdaBoost 进行疾病风险预测

AdaBoost 是用于二元分类的最早提升算法之一。它由 Freund 和 Schapire 于 1996 年提出。此后,基于 AdaBoost 的许多其他提升算法已被开发出来。

另一种自适应提升的变体被称为AdaBoost-abstain。AdaBoost-abstain 允许每个基线分类器在其相关特征缺失时放弃投票。

AdaBoost 专注于将一组弱学习器组合成一个强学习器。AdaBoost 分类器的过程如下:

  1. 初始时,将一个短决策树分类器拟合到数据上。决策树可以只有一个分割,这被称为决策树桩。评估整体误差。这是第一次迭代。

  2. 在第二次迭代中,正确分类的数据将被赋予较低的权重,而错误分类的类别将被赋予较高的权重。

  3. 在第三次迭代中,将再次对数据进行拟合,并在下一次迭代中更改权重。

  4. 一旦这些迭代完成,每个分类器在每个迭代中都会根据错误率自动计算权重,以得出一个强分类器。

以下截图显示了 AdaBoost 的工作原理:

图片

该算法背后的概念是将权重分配给训练示例,并选择具有最低加权错误的分类器。最后,它通过这些弱学习者的线性组合构建一个强分类器。

AdaBoost 的一般公式如下:

图片

在这里,F(x) 代表一个强分类器,图片 代表权重,而 f(x) 代表一个弱分类器。

AdaBoost 分类器接受各种参数。以下解释了重要的参数:

  • base_estimator:用于训练模型的算法。如果未提供此参数的值,则基本估计器为 DecisionTreeClassifier (max_depth=1)

  • n_estimators:迭代训练的模型数量。

  • learning_rate:每个模型对权重的贡献。默认情况下,learning_rate 的值为 1。较低的 learning_rate 值会使模型训练得更慢,但可能会得到更好的性能分数。

准备工作

首先,导入 ospandas 包,并根据您的需求设置工作目录:

# import required packages
import os
import pandas as pd
import numpy as np

from sklearn.ensemble import AdaBoostClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

from sklearn.metrics import roc_auc_score, roc_curve, auc
from sklearn.model_selection import train_test_split

# Set working directory as per your need
os.chdir(".../.../Chapter 8")
os.getcwd()

从 GitHub 下载 breastcancer.csv 数据集并将其复制到您的当前工作目录。读取数据集:

df_breastcancer = pd.read_csv("breastcancer.csv")

使用 head() 函数查看前几行:

df_breastcancer.head(5)

注意,diagnosis 变量具有 M 和 B 等值,分别代表恶性和良性。我们将对 diagnosis 变量进行标签编码,以便将 M 和 B 值转换为数值。

我们使用 head() 来查看变化:

# import LabelEncoder from sklearn.preprocessing
from sklearn.preprocessing import LabelEncoder

lb = LabelEncoder()
df_breastcancer['diagnosis'] =lb.fit_transform(df_breastcancer['diagnosis']) 
df_breastcancer.head(5)

然后,我们检查数据集是否有任何空值:

df_breastcancer.isnull().sum()

我们使用 shape() 检查数据集的形状:

df_breastcancer.shape

现在,我们将我们的目标集和特征集分开。我们还把数据集分成训练集和测试集:

# Create feature & response variables
# Drop the response var and id column as it'll not make any sense to the analysis
X = df_breastcancer.iloc[:,2:31]

# Target
Y = df_breastcancer.iloc[:,0]

# Create train & test sets
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.30, random_state=0, stratify= Y)

现在,我们将继续使用 AdaBoost 算法构建我们的模型。

重要的是要注意,准确率和 AUC 分数可能因随机分割和其他随机因素而不同。

如何做到这一点...

现在我们将探讨如何使用 AdaBoost 训练我们的模型:

  1. 在我们构建第一个 AdaBoost 模型之前,让我们使用 DecisionTreeClassifier 训练我们的模型:
dtree = DecisionTreeClassifier(max_depth=3, random_state=0)
dtree.fit(X_train, Y_train)
  1. 我们可以通过以下代码看到我们的准确率和 曲线下面积AUC):
# Mean accuracy
print('The mean accuracy is: ',(dtree.score(X_test,Y_test))*100,'%')

#AUC score
y_pred_dtree = dtree.predict_proba(X_test)
fpr_dtree, tpr_dtree, thresholds = roc_curve(Y_test, y_pred_dtree[:,1])
auc_dtree = auc(fpr_dtree, tpr_dtree)
print ('AUC Value: ', auc_dtree)

我们得到了准确率分数和 AUC 值分别为 91.81% 和 0.91。请注意,由于随机性,这些值可能因用户而异。

  1. 现在,我们将使用 scikit-learn 库构建我们的 AdaBoost 模型。我们将使用AdaBoostClassifier构建我们的AdaBoost模型。AdaBoost默认使用dtree作为基础分类器:
AdaBoost = AdaBoostClassifier(n_estimators=100, base_estimator=dtree, learning_rate=0.1, random_state=0)
AdaBoost.fit(X_train, Y_train)
  1. 我们检查了模型在测试数据上的准确率和 AUC 值:
# Mean accuracy
print('The mean accuracy is: ',(AdaBoost.score(X_test,Y_test))*100,'%')

#AUC score
y_pred_adaboost = AdaBoost.predict_proba(X_test)
fpr_ab, tpr_ab, thresholds = roc_curve(Y_test, y_pred_adaboost[:,1])
auc_adaboost = auc(fpr_ab, tpr_ab)
print ('AUC Value: ', auc_adaboost)

我们注意到我们得到了 92.82%的准确率分数和 0.97 的 AUC 值。这两个指标都高于我们在步骤 1中构建的决策树模型。

  1. 然后,我们必须微调我们的超参数。我们将n_estimators设置为100,将learning_rate设置为0.4
# Tuning the hyperparams
AdaBoost_with_tuning = AdaBoostClassifier(n_estimators=100, base_estimator=dtree, learning_rate=0.4, random_state=0)
AdaBoost_with_tuning.fit(X_train, Y_train)
  1. 现在,我们将检查我们的新模型在测试数据上的准确率和 AUC 值:
# Mean accuracy
print('The mean accuracy is: ',(AdaBoost_with_tuning.score(X_test,Y_test))*100,'%')

#AUC score
y_pred_adaboost_tune = AdaBoost.predict_proba(X_test)
fpr_ab_tune, tpr_ab_tune, thresholds = roc_curve(Y_test, y_pred_adaboost_tune[:,1])
auc_adaboost_tune = auc(fpr_ab_tune, tpr_ab_tune)
print ('AUC Value: ', auc_adaboost_tune)

我们注意到准确率下降到 92.39%,但我们得到了改进的 AUC 值,为 0.98。

它是如何工作的...

步骤 1中,我们使用DecisionTreeClassifier构建了我们的模型。在步骤 2中,我们注意到我们的平均准确率和 AUC 分数分别为 91.81%和 0.91。我们希望通过使用AdaBoost算法来提高这一点。

注意,AdaBoost算法默认使用决策树作为基础分类器。在步骤 3中,我们使用默认的基础学习器AdaBoost训练了我们的模型。我们将n_estimators设置为100,将learning_rate设置为0.1。我们在步骤 4中检查了我们的平均准确率和 AUC 值。我们注意到平均准确率和 AUC 值分别提高了 93.57%和 0.977。

步骤 5中,我们微调了AdaBoost算法的一些超参数,该算法使用决策树作为基础分类器。我们将n_estimators设置为100,将learning_rate设置为0.4步骤 6给出了我们在步骤 5中构建的模型的准确率和 AUC 值。我们看到准确率下降到 93.56%,而 AUC 值保持在 0.981 左右。

更多内容...

在这里,我们将展示如何使用 AdaBoost 训练一个模型,其中基础学习器为支持向量机SVM):

默认情况下,AdaBoost 使用决策树作为基础学习器。我们也可以使用不同的基础学习器。在以下示例中,我们使用 SVM 作为我们的基础学习器,并使用AdaBoost算法。我们使用SVC并使用rbf作为核:

from sklearn.svm import SVC

Adaboost_with_svc_rbf = AdaBoostClassifier(n_estimators=100, base_estimator=SVC(probability=True, kernel='rbf'), learning_rate=1, random_state=0)
Adaboost_with_svc_rbf.fit(X_train, Y_train)

我们可以使用支持向量分类器SVC)作为基础学习器来检查我们的 AdaBoost 模型的准确率和 AUC 值:

# Mean accuracy
print('The mean accuracy is: ',(Adaboost_with_svc_rbf.score(X_test,Y_test))*100,'%') 

#AUC score
y_pred_svc_rbf = Adaboost_with_svc_rbf.predict_proba(X_test)
fpr_svc_rbf, tpr_svc_rbf, thresholds = roc_curve(Y_test, y_pred_svc_rbf[:,1])
auc_svc_rbf = auc(fpr_svc_rbf, tpr_svc_rbf)
print ('AUC Value: ', auc_svc_rbf)

我们注意到准确率和 AUC 值分别下降到 62.57 和 0.92。

现在,我们将使用 SVC 重新构建我们的 AdaBoost 模型。这次,我们将使用线性核:

Adaboost_with_svc_linear =AdaBoostClassifier(n_estimators=100, base_estimator=SVC(probability=True, kernel='linear'), learning_rate=1, random_state=0)
Adaboost_with_svc_linear.fit(X_train, Y_train)

现在,我们得到了 90.64%的平均准确率和 0.96 的合理 AUC 值。

我们现在将使用以下代码绘制一个图表来比较每个模型的 AUC 值:

import matplotlib.pyplot as plt
% matplotlib inline
plt.figure(figsize=(8,8))

plt.plot(fpr_dtree, tpr_dtree,label="Model1: Dtree, auc="+str(auc_dtree))
plt.plot(fpr_ab, tpr_ab,label="Model2: Adaboost, auc="+str(auc_adaboost))
plt.plot(fpr_ab_tune,tpr_ab_tune,label="Model3: Adaboost with Tuning, auc="+str(auc_adaboost_tune))
plt.plot(fpr_svc_rbf, tpr_svc_rbf, label="Model4: Adaboost with SVC (RBF Kernel), auc="+str(auc_svc_rbf))
plt.plot(fpr_svc_lin, tpr_svc_lin, label="Model5: Adaboost with SVC (Linear Kernel), auc="+str(auc_svc_linear))

plt.legend(loc=5)
plt.show()

这给出了以下图表:

我们也可以使用以下代码绘制所有模型的准确率:

import matplotlib.pyplot as plt
% matplotlib inline
plt.figure(figsize=(8,8))

label = ['Decison Tree', 'Adaboost', 'Adaboost with Tuning', 'Adaboost with SVC (RBF)', 'Adaboost with SVC (Linear)']

values = [dtree.score(X_test,Y_test),
        AdaBoost.score(X_test,Y_test),
        AdaBoost_with_tuning.score(X_test,Y_test),
        Adaboost_with_svc_rbf.score(X_test,Y_test),
        Adaboost_with_svc_linear.score(X_test,Y_test)]

def plot_bar_accuracy():
    # this is for plotting purpose
    index = np.arange(len(label))
    plt.bar(index, values)
    plt.xlabel('Algorithms', fontsize=10)
    plt.ylabel('Accuracy', fontsize=10)
    plt.xticks(index, label, fontsize=10, rotation=90)
    plt.title('Model Accuracies')
    plt.show()

plot_bar_accuracy()

这给出了以下输出:

参见

我们也可以使用网格搜索与 AdaBoost:

#grid search using svm
Adaboost_with_svc = AdaBoostClassifier(n_estimators=100, base_estimator=SVC(probability=True, kernel='linear'), learning_rate=1, algorithm= 'SAMME')

Ada_Grid = {'n_estimators': [10,30,40,100],
           'learning_rate': [0.1, 0.2, 0.3]}

estimator = Adaboost_with_svc
Adaboost_with_grid_search = GridSearchCV(estimator,Ada_Grid).fit(X_train, Y_train)
print(Adaboost_with_grid_search.best_params_)
print(Adaboost_with_grid_search.best_score_)

在前面的代码中,我们进行了网格搜索,将n_estimators设置为103040100,将learning_rate设置为0.10.20.3

使用 scikit-learn 实现梯度提升机进行疾病风险预测

梯度提升是一种机器学习技术,它基于提升原理,其中弱学习器迭代地将注意力转向在先前迭代中难以预测的错误观测值,并创建一个弱学习者的集成,通常是决策树。

梯度提升以顺序方式训练模型,并涉及以下步骤:

  1. 将模型拟合到数据中

  2. 将模型拟合到残差中

  3. 创建一个新的模型

虽然 AdaBoost 模型通过使用分配给数据点的权重来识别错误,但梯度提升通过在损失函数中计算梯度来完成同样的工作。损失函数是衡量模型能够拟合其训练数据的程度的一个指标,通常取决于所解决的问题的类型。如果我们谈论回归问题,可能使用均方误差,而在分类问题中,可以使用对数损失。梯度下降过程用于在逐个添加树时最小化损失。模型中现有的树保持不变。

有一些超参数可以调整:

    • N_estimators:这表示模型中的树的数量。通常,它越高,模型学习数据的能力越好。

    • max_depth:这表示我们的树有多深。它用于控制过拟合。

    • min_samples_split:这是分割内部节点所需的最小样本数。过高的值可能会阻止模型学习关系。

    • learning_rate:这控制估计值的变化幅度。通常,较低值与较高的树的数量更受青睐。

    • loss:这指的是在每次分割中最小化的损失函数。算法中默认参数使用deviance,另一个是exponential

    • max_features:这表示在寻找最佳分割时需要考虑的特征数量。

    • criterion:这个函数衡量分割的质量,并支持friedman_msemae来评估模型的性能。

    • subsample:这表示用于拟合单个基学习者的样本的分数。选择小于 1.0 的子样本会导致方差减少和偏差增加。

    • min_impurity_split:这表示一个阈值,用于提前停止树的生长。

准备工作

我们将使用与训练我们的 AdaBoost 模型相同的数据集。在这个例子中,我们将看到如何使用梯度提升机来训练我们的模型。我们还将查看一些可以调整以改进模型性能的超参数。

首先,我们必须导入所有必需的库:

import os
import pandas as pd
import numpy as np

from sklearn.model_selection import train_test_split

from sklearn.ensemble import GradientBoostingClassifier 
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score, roc_auc_score
from sklearn.preprocessing import MinMaxScaler

import matplotlib.pyplot as plt
import itertools

然后,我们读取我们的数据并将目标变量编码为 1 和 0:

# Read the Dataset
df_breastcancer = pd.read_csv("breastcancer.csv")

from sklearn.preprocessing import LabelEncoder
lb = LabelEncoder()
df_breastcancer['diagnosis'] = lb.fit_transform(df_breastcancer['diagnosis']) 
df_breastcancer.head(5)

然后,将我们的目标变量和特征变量分开。我们将数据分为训练集和测试集:

# create feature & response variables
# drop the response var and id column as it'll not make any sense to the analysis
X = df_breastcancer.iloc[:,2:31]

# Target variable
Y = df_breastcancer.iloc[:,0]

# Create train & test sets
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.20, random_state=0, stratify= Y)

这与我们在AdaBoost示例的准备就绪部分中使用的代码相同。

如何操作...

现在,我们将探讨如何使用梯度提升机来训练我们的模型:

  1. 在上一节准备就绪中,我们导入了GradientBoostingClassifiersklearn.ensemble。我们使用GradieBoostingClassfier训练我们的模型:
GBM_model = GradientBoostingClassifier() 
GBM_model.fit(X_train, Y_train)
  1. 在这里,我们必须将我们的测试数据传递给predict()函数,使用我们在步骤 1中构建的模型进行预测:
Y_pred_gbm = GBM_model.predict(X_test)
  1. 现在,我们使用classification_report查看以下指标:
print(classification_report(Y_test, Y_pred_gbm))

classification_report提供了以下输出:

  1. 我们将使用confusion_matrix()生成混淆矩阵。然后,我们将confusion_matrix的输出传递给我们的预定义函数,即plot_confusion_matrix(),以绘制矩阵:

  1. 我们可以使用accuracy_score()roc_auc_score()来检查测试准确率和 AUC 值。

注意,accuracy_scoreroc_auc_score已从sklearn.metrics导入:

它是如何工作的...

步骤 1中,我们训练了一个梯度提升分类器模型。在步骤 2中,我们使用predict()方法对我们的测试数据进行预测。

步骤 3中,我们使用了classification_report()来查看每个类别的各种指标,如precisionrecallf1-score,以及每个指标的均值。classification_report()报告了总真实正例、假负例、假正例、未加权的每个标签的平均值和支持加权的每个标签的平均值。它还报告了多标签分类的样本平均值。

精度指的是分类器不将负例标记为正例的能力,而召回率指的是分类器找到所有正例的能力。f[1]分数是精度和召回率的加权调和平均值。最佳的f[1]分数是 1.0,最差的是 0.0。支持是每个类别的观测数。

步骤 4中,我们使用confusion_matrix()生成混淆矩阵,以查看真实正例、真实负例、假正例和假负例。

步骤 5中,我们使用accuracy_score()roc_auc_score()函数查看了测试数据的准确率和 AUC 值。

在下一节中,我们将使用网格搜索调整超参数,以找到最佳模型。

更多内容...

现在,我们将探讨如何微调梯度提升机的超参数:

  1. 首先,我们从sklearn.model_selection导入GridSearchCV
from sklearn.model_selection import GridSearchCV
  1. 我们将网格参数设置为一个变量:
parameters = {
    "n_estimators":[100,150,200],
    "loss":["deviance"],
    "learning_rate": [0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
    "min_samples_split":np.linspace(0.1, 0.5, 4),
    "min_samples_leaf": np.linspace(0.1, 0.5, 4),
    "max_depth":[3, 5, 8],
    "max_features":["log2","sqrt"],
    "criterion": ["friedman_mse", "mae"],
    "subsample":[0.3, 0.6, 1.0]
    }
  1. 我们使用GridSeacrhCV,它允许我们将估计量与网格搜索相结合以调整超参数。GridSeacrhCV方法从网格值中选择最佳参数,并将其与估计量一起使用:
grid = GridSearchCV(GradientBoostingClassifier(), parameters, cv=3, n_jobs=-1) 
grid.fit(X_train, Y_train)
  1. 然后,我们可以查看最佳参数:
grid.best_estimator_

看看下面的截图:

图片

  1. 我们将测试数据传递给predict方法以获取预测结果:
grid_predictions = grid.predict(X_test)
  1. 再次,我们可以看到classification_report提供的指标:
print(classification_report(Y_test, grid_predictions))

这给我们以下输出。我们注意到平均precisionf1-score比之前的案例有所提高:

图片

  1. 现在,我们将查看混淆矩阵并绘制它,就像我们之前做的那样:
cnf_matrix = confusion_matrix(Y_test, grid_predictions)
plot_confusion_matrix(cnf_matrix,classes=[0,1])

从前面的代码中,我们得到以下图表:

图片

  1. 现在,我们再次查看准确率和 AUC 值:
print("Accuracy score = {:0.2f}".format(accuracy_score(Y_test, grid_predictions)))
print("Area under ROC curve = {:0.2f}".format(roc_auc_score(Y_test, grid_predictions)))

我们注意到准确率保持不变,但 AUC 从 0.96 提高到 0.97:

图片

使用 scikit-learn 和 XGBoost 实现玻璃识别的极端梯度提升方法

XGBoost 代表极端梯度提升。它是梯度提升机的变体,旨在提高性能和速度。Python 中的 XGBoost 库实现了梯度提升决策树算法。梯度提升的名字来源于它在添加新模型时使用梯度下降算法来最小化损失。XGBoost 可以处理回归和分类任务。

由于在困难的机器学习问题中性能和执行速度出色,XGBoost 成为了 Kaggle 竞赛中参赛者的首选算法。

在 XGBoost 中使用的一些重要参数如下:

  • n_estimators/ntrees:这指定了要构建的树的数量。默认值是 50。

  • max_depth:这指定了最大树深度。默认值是 6。更高的值会使模型更加复杂,可能会导致过拟合。将此值设置为 0 表示没有限制。

  • min_rows:这指定了叶子的最小观测数。默认值是 1。

  • learn_rate:这指定了用于缩小特征权重的学习率。在每次提升步骤之后缩小特征权重可以使提升过程更加保守,并防止过拟合。范围是 0.0 到 1.0。默认值是 0.3。

  • sample_rate:这指定了训练实例(x轴)的行采样比率。例如,将此值设置为 0.5 表示 XGBoost 随机收集一半的数据实例来生长树。默认值是 1,范围是 0.0 到 1.0。更高的值可能会提高训练准确率。

  • col_sample_rate:这指定了每个级别的每个分割的列采样率(y 轴)。默认值是 1.0,范围是从 0 到 1.0。更高的值可能会提高训练准确率。

准备中...

您需要安装XGBoost库才能继续此食谱。您可以使用以下pip命令安装XGBoost库:

!pip install xgboost

导入所需的库:

# Import required libraries
import os
import pandas as pd
import numpy as np

from numpy import sort

from xgboost import XGBClassifier
from xgboost import plot_tree
from xgboost import plot_importance

from sklearn.feature_selection import SelectFromModel
from sklearn.model_selection import train_test_split, KFold, cross_val_score, StratifiedKFold

import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score, confusion_matrix

import itertools

设置您的当前工作文件夹并读取您的数据:

os.chdir("/.../Chapter 7")
os.getcwd()

df_glassdata = pd.read_csv('glassdata.csv')
df_glassdata.shape

此数据来自 UCI ML 存储库。列名已根据以下链接提供的数据描述进行更改:bit.ly/2EZX6IC

我们来看看数据:

df_glassdata.head()

我们将数据分为目标和特征集,并验证它。请注意,我们忽略了 ID 列:

# split data into X and Y
X = df_glassdata.iloc[:,1:10]
Y = df_glassdata.iloc[:,10]

print(X.shape)
print(Y.shape)

我们确认没有缺失值:

df_glassdata.isnull().sum()

我们将数据集分为训练集和测试集:

# Create train & test sets
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.30, random_state=0)

如何做到这一点...

现在,我们将继续构建我们的第一个 XGBoost 模型:

  1. 首先,我们将训练数据拟合到 XGBoost 分类器:
xg_model = XGBClassifier()
xg_model.fit(X_train, Y_train)
  1. 我们可以可视化训练模型中的单个 XGBoost 决策树。可视化决策树可以提供梯度提升过程的洞察:
plot_tree(xg_model, num_trees=0, rankdir='LR')
fig = pyplot.gcf()
fig.set_size_inches(30, 30)

这给我们以下输出:

num_trees=0时,我们得到第一个提升树。我们可以通过将索引值设置为num_trees参数来查看其他提升树。

  1. 在以下示例中,我们将num_trees设置为5
plot_tree(xg_model, num_trees=5, rankdir='LR')
fig = pyplot.gcf()
fig.set_size_inches(30, 30)

以下截图显示了第 6 个提升树:

您需要在您的系统上安装graphviz库来绘制提升树。

  1. 我们现在将在测试数据上使用predict()来获取预测值。我们可以使用accuracy_score()看到我们的测试准确率:
test_predictions = xg_model.predict(X_test)
test_accuracy = accuracy_score(Y_test, test_predictions)

print("Test Accuracy: %.2f%%" % (test_accuracy * 100.0))

通过执行此代码,我们可以看到测试准确率为 69.23%。

  1. 我们可以通过以下代码查看我们的混淆矩阵:
confusion_matrix(Y_test, predictions)
  1. 然后,我们可以使用预定义的函数plot_confusion_matrix(),该函数来自scikit-learn.org
def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.tight_layout()
  1. 然后,我们查看目标变量的unique值以设置目标变量每个级别的名称:
Y.unique()

在以下代码块中,我们可以看到target_names的值为123567。我们相应地为目标变量的每个级别设置名称:

# Set names to each level of our target variable
target_names = [ '1', '2', '3', '5', '6', '7']

# Pass Actual & Predicted values to confusion_matrix()
cm = confusion_matrix(Y_test, predictions)

plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()

我们现在可以可视化混淆矩阵,如下面的截图所示:

它是如何工作的...

步骤 1中,我们将XGBoostClassfier拟合到我们的训练数据。在步骤 2步骤 3中,我们可视化了单个提升树。为此,我们使用了plot_tree()函数。我们将我们的XGBoost模型传递给plot_tree(),并通过设置num_trees参数来设置树的索引。rankdir='LR'参数从左到右绘制树。将rankdir设置为 UT 将绘制垂直树。

步骤 4 中,我们将测试子集传递给 predict() 以获取测试准确率。步骤 5 给出了混淆矩阵。在 步骤 6 中,我们从 scikit-learn.org 中获取了一个预定义的函数,plot_confusion_matrix()。我们使用此函数来绘制我们的混淆矩阵。在 步骤 7 中,我们查看目标变量的唯一值,以便我们可以为混淆矩阵图中的每个类别设置名称。然后我们绘制了混淆矩阵以评估我们的模型。

更多...

在本节中,我们将探讨如何检查特征重要性并根据该重要性进行特征选择。我们还将探讨如何使用交叉验证评估我们的 XGBoost 模型的性能。

我们可以使用 model.feature_importances_ 检查特征重要性:

print(xg_model.feature_importances_)

我们还可以使用 plot_importance() 可视化特征重要性:

注意,我们已经从 xgboost 库中导入了 plot_importance

plot_importance(xg_model)

执行前面的代码后,我们可以看到以下图表,它显示了按重要性降序排列的特征重要性:

可以使用 SelectFromModel 进行特征选择:

SelectFromModel 类是从 sklearn.feature_selection 导入的。

在以下示例中,SelectFromModel 使用预训练的 XGBoost 模型,并从我们的数据集中提供具有选定特征的子集。它根据阈值值决定选定的特征。

重要性大于或等于阈值值的特征将被保留,而其他任何特征都将被丢弃:

# The threshold value to use for feature selection. 
feature_importance = sort(xg_model.feature_importances_)

# select features using threshold
for each_threshold in feature_importance:
    selection = SelectFromModel(xg_model, threshold=each_threshold, prefit=True)

    # Reduce X_train only to the selected feature
    selected_feature_X_train = selection.transform(X_train)

    # Train the model
    selection_model = XGBClassifier()
    selection_model.fit(selected_feature_X_train, Y_train)

    # Reduce X_test only to the selected feature
    selected_feature_X_test = selection.transform(X_test)

    # Predict using the test value of the selected feature
    predictions = selection_model.predict(selected_feature_X_test)

    accuracy = accuracy_score(Y_test, predictions)
    print("Threshold=%.5f, Number of Features=%d, Model Accuracy: %.2f%%" % (each_threshold, selected_feature_X_train.shape[1],accuracy*100))

从前面的代码中,我们可以看到以下输出:

我们注意到模型的性能随着选定特征数量的增加而波动。根据前面的输出,我们决定选择五个特征,这些特征给我们带来了 72% 的准确率。此外,如果我们使用奥卡姆剃刀原则,我们可能可以选择一个具有四个特征且略微降低的 71% 准确率的更简单模型。

我们还可以使用交叉验证来评估我们的模型。要执行 k 折交叉验证,我们必须从 sklearn.model_selection 中导入 KFold 类。

首先,我们创建 KFold 对象并说明我们希望拥有的拆分数量:

kfold = KFold(n_splits=40, random_state=0)
xg_model_with_kfold = XGBClassifier()

cv_results = cross_val_score(xg_model_with_kfold, X_train, Y_train, cv=kfold, verbose=True)
print("Mean Accuracy: %.2f%% Standard Deviation %.2f%%" % (cv_results.mean()*100, cv_results.std()*100))

使用 cross_val_score(),我们评估我们的模型,它给出了平均和标准差分类准确率。我们注意到我们得到了 77.92% 的平均准确率和 22.33% 的标准差。

在我们的情况下,我们有一个具有六个类别的目标变量。

如果对于多类分类任务有多个类别,在执行交叉验证时,您可以使用分层折:

Stratfold = StratifiedKFold(n_splits=40, random_state=0)
xg_model_with_stratfold = XGBClassifier()

sf_results = cross_val_score(xg_model_with_stratfold, X_train, Y_train, cv=Stratfold, verbose=True)
print("Mean Accuracy: %.2f%% Standard Deviation %.2f%%" % (sf_results.mean()*100, sf_results.std()*100))

使用 StratifiedKFold(),我们得到了改进的平均准确率 81.18% 和降低的标准差 21.37%。

注意,n_splits 不能大于每个类别中的成员数量。

参见

  • LightGBM 是由微软开发的开源软件,用于梯度提升框架。它使用基于树的算法,与其他 梯度提升机 (GBMs) 不同:bit.ly/2QW53jH

第八章:与堆叠结合

在本章中,我们将涵盖以下食谱:

  • 理解堆叠泛化

  • 通过结合预测实现堆叠泛化

  • 使用 H2O 实现营销活动结果预测的堆叠泛化

技术要求

本章的技术要求与我们在早期章节中详细说明的要求相同。

访问 GitHub 仓库以查找数据集和代码。数据集和代码文件按章节编号和主题名称排列。

理解堆叠泛化

堆叠泛化是一组多样化的模型的集成,引入了元学习器的概念。元学习器是一个第二级机器学习算法,它从基础学习器的最优组合中学习:

"堆叠泛化是一种非线性组合泛化器以创建一个新的泛化器的方法,试图最优地整合每个原始泛化器对学习集的看法。每个泛化器有更多的话要说(这不会在其他泛化器的话中重复),结果堆叠泛化就越好。"

- Wolpert (1992), 堆叠泛化

堆叠的步骤如下:

  1. 将您的数据集分为训练集和测试集。

  2. 在训练集上训练几个基础学习器。

  3. 将基础学习器应用于测试集进行预测。

  4. 使用预测作为输入,实际响应作为输出来训练一个高级学习器。

由于基础学习器的预测被混合在一起,堆叠也被称为混合。

以下图表为我们提供了堆叠的概念表示:

图片

对于堆叠泛化来说,基础学习器的预测之间不相关是很重要的。为了从基础学习器中获得不相关的预测,可以使用内部采用不同方法的算法来训练基础学习器。堆叠泛化主要用于最小化基础学习器的泛化误差,可以看作是交叉验证的改进版本。它使用比交叉验证的赢家通吃方法更复杂的策略来结合基础学习器的预测。

通过结合预测实现堆叠泛化

在本节中,我们将探讨如何从头实现堆叠泛化。

我们将执行以下步骤以开始:

  1. 为堆叠构建三个基础学习器。

  2. 结合每个基础学习器的预测。

  3. 使用另一种算法构建元学习器。

准备中...

在这个例子中,我们使用 UCI ML 存储库中的信用卡违约数据集。该数据集包含关于违约支付、人口统计因素、信用数据、支付历史和信用卡客户的账单陈述的信息。数据和数据描述在 GitHub 上提供。

我们将首先加载所需的库并读取我们的数据集:

import os
import numpy as np
import pandas as pd
from sklearn.metrics import accuracy_score

我们将工作文件夹设置为以下内容:

# Set your working directory according to your requirement
os.chdir(".../Chapter 8/")
os.getcwd()

现在我们读取我们的数据。我们将以df_作为 DataFrame 名称的前缀,这样我们就可以轻松理解它:

df_creditcarddata = pd.read_csv("UCI_Credit_Card.csv")

我们删除了ID列,因为这个列不是必需的:

df_creditcarddata = df_creditcarddata.drop("ID", axis= 1) 

我们检查数据集的形状:

df_creditcarddata.shape

我们注意到数据集现在有 30,000 个观测值和 24 列。现在让我们继续训练我们的模型。

如何做到这一点...

  1. 我们分割目标和特征变量:
from sklearn.model_selection import train_test_split

X = df_creditdata.iloc[:,0:23]
Y = df_creditdata['default.payment.next.month']
  1. 将数据分割为训练、验证和测试子集:
# We first split the dataset into train and test subset
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.1, random_state=1)

# Then we take the train subset and carve out a validation set from the same
X_train, X_val, Y_train, Y_val = train_test_split(X_train, Y_train, test_size=0.2, random_state=1)
  1. 检查每个子集的维度以确保我们的分割是正确的:
# Dimensions for train subsets
print(X_train.shape)
print(Y_train.shape)

# Dimensions for validation subsets
print(X_val.shape)
print(Y_val.shape)

# Dimensions for test subsets
print(X_test.shape)
print(Y_test.shape)
  1. 导入基础学习器和元学习器所需的库:
# for the base learners
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier

# for the meta learner
from sklearn.linear_model import LogisticRegression
  1. 创建基础学习器的实例并在我们的训练数据上拟合模型:
# The base learners
model_1 = GaussianNB()
model_2 = KNeighborsClassifier(n_neighbors=1)
model_3 = DecisionTreeClassifier()

# Now we train a list of models
base_learner_1 = model_1.fit(X_train, Y_train)
base_learner_2 = model_2.fit(X_train, Y_train)
base_learner_3 = model_3.fit(X_train, Y_train)
  1. 使用我们的验证子集上的基础学习器进行预测:
# We then use the models to make predictions on validation data
val_prediction_base_learner_1 = base_learner_1.predict(X_val)
val_prediction_base_learner_2 = base_learner_2.predict(X_val)
val_prediction_base_learner_3 = base_learner_3.predict(X_val)
  1. 我们从三个基础学习器获得了三组预测结果。我们使用它们来创建堆叠数组:
# And then use the predictions to create a new stacked dataset
import numpy as np
prediction_test_stack = np.dstack([val_prediction_base_learner_1, val_prediction_base_learner_2, val_prediction_base_learner_3])

# Now we stack the actual outcomes i.e. Y_Test with the prediction_stack
final_train_stack = np.dstack([prediction_test_stack, Y_val])
  1. 我们将final_train_stack堆叠数组转换为 DataFrame 并为每个列添加列名。验证维度并查看前几行:
stacked_train_dataframe = pd.DataFrame(final_train_stack[0,0:5400], columns='NB_VAL KNN_VAL DT_VAL Y_VAL'.split())

print(stacked_train_dataframe.shape)
print(stacked_train_dataframe.head(5))

在以下图像中,我们看到堆叠数组现在有 5,400 个观测值和 4 列:

  1. 使用我们在步骤 8中创建的堆叠数组来训练元学习器:
# Build the Mata-learner
meta_learner = LogisticRegression()
meta_learner_model = meta_learner.fit(stacked_train_dataframe.iloc[:,0:3], stacked_train_dataframe['Y_VAL'])
  1. 使用测试子集创建堆叠测试集:
# Take the test data (new data)
# Apply the base learners on this new data to make predictions

# We now use the models to make predictions on the test data and create a new stacked dataset
test_prediction_base_learner_1 = base_learner_1.predict(X_test)
test_prediction_base_learner_2 = base_learner_2.predict(X_test)
test_prediction_base_learner_3 = base_learner_3.predict(X_test)

# Create the stacked data
final_test_stack = np.dstack([test_prediction_base_learner_1, test_prediction_base_learner_2, test_prediction_base_learner_3])
  1. final_test_stack堆叠数组转换为 DataFrame 并为每个列添加列名。验证维度并查看前几行:
stacked_test_dataframe = pd.DataFrame(final_test_stack[0,0:3000], columns='NB_TEST KNN_TEST DT_TEST'.split())
print(stacked_test_dataframe.shape)
print(stacked_test_dataframe.head(5))

我们看到stacked_test_dataframe中的堆叠数组现在有 3,000 个观测值和 3 列:

  1. 检查base_learner在我们原始测试数据上的准确率:
test_prediction_base_learner_1 = base_learner_1.predict(X_test)
test_prediction_base_learner_2 = base_learner_2.predict(X_test)
test_prediction_base_learner_3 = base_learner_3.predict(X_test)

print("Accuracy from GaussianNB:", accuracy_score(Y_test, test_prediction_base_learner_1))
print("Accuracy from KNN:", accuracy_score(Y_test, test_prediction_base_learner_2))
print("Accuracy from Decision Tree:", accuracy_score(Y_test, test_prediction_base_learner_3))

我们注意到准确率如下。请注意,根据采样策略和超参数,结果可能会有所不同:

  1. 在堆叠测试数据上使用元学习器并检查准确率:
test_predictions_meta_learner = meta_learner_model.predict(stacked_test_dataframe)
print("Accuracy from Meta Learner:", accuracy_score(Y_test, test_predictions_meta_learner))

我们看到元学习器在堆叠测试数据上应用后返回的以下输出。这个准确率高于单个基础学习器:

它是如何工作的...

步骤 1中,我们将数据集分为目标和特征集。在步骤 2中,我们创建了我们的训练、验证和测试子集。在步骤 3中,我们检查了每个子集的维度,以验证分割是否正确。

然后我们继续构建基础学习器和元学习器。在步骤 4中,我们导入了用于基础学习器和元学习器的必需库。对于基础学习器,我们使用了高斯朴素贝叶斯、KNN 和决策树,而对于元学习器,我们使用了逻辑回归。

步骤 5中,我们将基础学习器拟合到我们的训练数据集。包括高斯朴素贝叶斯、KNN 和决策树在内的单一模型在 0 层空间中建立。然后我们有了三个基础模型。

步骤 6中,我们使用这三个基础模型在我们的验证子集中预测目标变量。然后我们得到了基础学习器给出的三组预测。

现在将通过堆叠泛化在第一层空间中将基础学习器通过逻辑回归进行集成。在步骤 7中,我们将三组预测值堆叠起来创建了一个数组。我们还把训练数据集的实际目标变量也堆叠到数组中。然后我们的数组中有四列:三列来自基础学习器的三组预测值,以及一列来自训练数据集的目标变量。我们称之为final_train_stack,也称为stacked_train_dataframe,并且根据用于基础学习器的算法命名列。在我们的例子中,我们使用了NB_VALKNN_VALDT_VAL这些名称,因为我们分别使用了高斯朴素贝叶斯、KNN 和决策树分类器。因为基础学习器被拟合到我们的验证子集中,所以我们给列名加上_VAL后缀,以便更容易理解。

步骤 9中,我们使用逻辑回归构建了元学习器并将其拟合到我们的堆叠数据集stacked_train_dataframe。请注意,我们离开了原始数据集,转向了一个包含基础学习器预测值的堆叠数据集。

步骤 10中,我们使用基础模型在我们的测试子集中获取预测结果。我们称之为final_test_stack。在步骤 11中,我们将final_test_stack数组转换为名为stacked_test_dataframe的 DataFrame。请注意,在我们的stacked_test_dataframe中,我们只有三列,这些列包含了在测试子集上应用基础学习器返回的预测值。这三列以使用的算法命名,后缀为_TEST,因此stacked_test_dataframe中的三列是NB_TESTKNN_TESTDT_TEST

步骤 12中,我们检查了基础模型在我们原始测试子集中的准确性。高斯朴素贝叶斯、KNN 和决策树分类器模型分别给出了 0.39、0.69 和 0.73 的准确性评分。

步骤 13中,我们检查了通过在堆叠测试数据上应用元学习器模型所获得的准确性。这给出了 0.77 的准确性,我们可以看到这比单个基础学习器的准确性要高。然而,请记住,仅仅在堆叠算法中添加更多基础学习器并不能保证你会得到更好的准确性。

还有更多...

创建堆叠模型可能很繁琐。mlxtend库提供了简化堆叠模型构建的工具。它提供了StackingClassifier,这是堆叠的集成学习元分类器,并且它还提供了StackingCVClassifier,它使用交叉验证为第二级元学习器准备输入,以防止过拟合。

您可以从pypi.org/project/mlxtend/下载库,或者使用pip install mlxtend命令进行安装。您可以在rasbt.github.io/mlxtend/user_guide/classifier/StackingClassifier/找到一些简单的堆叠分类和带有网格搜索的堆叠分类的优秀示例。

相关内容

您还可以查看ML-Ensemble库。要了解更多关于ML-Ensemble的信息,请访问ml-ensemble.com/ML-Ensemble的使用指南可在bit.ly/2GFsxJN找到。

使用 H2O 实现针对活动结果预测的堆叠泛化

H2O 是一个开源平台,用于构建机器学习和预测分析模型。算法是写在 H2O 的分布式 map-reduce 框架上的。使用 H2O,数据在节点间分布式,并行读取,并以压缩方式存储在内存中。这使得 H2O 非常快。

H2O 的堆叠集成方法是一个用于监督问题的集成机器学习算法,它通过堆叠找到一组预测算法的最佳组合。H2O 的堆叠集成支持回归、二分类和多分类。

在本例中,我们将探讨如何使用 H2O 的堆叠集成构建堆叠模型。我们将使用可在 GitHub 上找到的银行营销数据集。

准备中...

首先,导入h2o库和其他 H2O 模块:

import h2o
from h2o.estimators.random_forest import H2ORandomForestEstimator
from h2o.estimators.gbm import H2OGradientBoostingEstimator
from h2o.estimators.glm import H2OGeneralizedLinearEstimator
from h2o.estimators.stackedensemble import H2OStackedEnsembleEstimator
from h2o.grid.grid_search import H2OGridSearch

使用init()函数初始化h2o实例:

h2o.init()

一旦运行前面的代码,h2o实例将被初始化,我们将看到以下输出:

图片

现在我们已经实例化了H2O实例,我们将继续读取我们的数据集并构建堆叠模型。

如何操作...

  1. 我们使用h2o.import_file()函数读取数据。我们将文件名作为参数传递给函数:
df_bankdata = h2o.import_file("bank-full.csv")
  1. 我们将数据分为训练集和测试集:
# split into train and validation sets
train, test = df_bankdata.split_frame(ratios = [.8], seed = 1234)
  1. 我们检查训练集和测试集的维度,以验证分割是否正确:
train.shape, test.shape
  1. 我们查看前几行以确保数据正确加载:
df_bankdata.head()
  1. 我们将目标列和预测列的名称分别命名为responsepredictors
# Set the predictor names 
predictors = train.columns

# Set the response column name
response = "y"

# Remove the 'y' variable from the predictors
predictors.remove(response)

print(predictors)
  1. 我们使用asfactor()函数将response变量转换为分类类型:
train[response] = train[response].asfactor()
test[response] = test[response].asfactor()
  1. 我们将使用交叉验证来训练我们的基本学习器。我们将nfolds值设置为5。我们还设置了一个变量encodingOneHotExplicit。我们将使用此变量来对分类变量进行编码。
# Number of CV folds
nfolds = 5

# Using the `categorical_encoding` parameter
encoding = "OneHotExplicit"
  1. 我们开始训练我们的基本学习器。我们选择梯度提升机算法来构建我们的第一个基本学习器:
# Train and cross-validate a GBM
base_learner_gbm = H2OGradientBoostingEstimator(distribution="bernoulli",\
                                                ntrees=100,\
                                                max_depth=5,\
                                                min_rows=2,\
                                                learn_rate=0.01,\
                                                nfolds=nfolds,\
                                                fold_assignment="Modulo",\
                                                categorical_encoding = encoding,\
                                                keep_cross_validation_predictions=True)

base_learner_gbm.train(x=predictors, y=response, training_frame=train)
  1. 对于我们的第二个基本学习器,我们使用随机森林:
# Train and cross-validate a RF
base_learner_rf = H2ORandomForestEstimator(ntrees=250,\
                                           nfolds=nfolds,\
                                           fold_assignment="Modulo",\
                                           categorical_encoding = encoding,\
                                           keep_cross_validation_predictions=True)
base_learner_rf.train(x=predictors, y=response, training_frame=train)
  1. 对于我们的第三个基本学习器,我们实现了一个广义线性模型GLM):
# Train and cross-validate a GLM
base_learner_glm = H2OGeneralizedLinearEstimator(family="binomial",\
                                                 model_id="GLM",\
                                                 lambda_search=True,\
                                                 nfolds = nfolds,\
                                                 fold_assignment = "Modulo",\
                                                 keep_cross_validation_predictions = True)

base_learner_glm.train(x = predictors, y = response,training_frame = train)
  1. 在测试集上,根据test AUC获取最佳性能的基本学习器。将其与堆叠集成模型的test AUC进行比较:
# Compare to base learner performance on the test set
gbm_test_performance = base_learner_gbm.model_performance(test)
rf_test_performance = base_learner_rf.model_performance(test)
glm_test_performance = base_learner_glm.model_performance(test)

print("Best AUC from the GBM", gbm_test_performance.auc())
print("Best AUC from the Random Forest", rf_test_performance.auc())
print("Best AUC from the GLM", glm_test_performance.auc())

baselearner_best_auc_test = max(gbm_test_performance.auc(), rf_test_performance.auc(), glm_test_performance.auc())
print("Best AUC from the base learners", baselearner_best_auc_test)

stack_auc_test = perf_stack_test.auc()
print("Best Base-learner Test AUC: ", baselearner_best_auc_test)
print("Ensemble Test AUC: ", stack_auc_test)
  1. 我们使用前面步骤中构建的基本学习器训练一个堆叠集成:
all_models = [base_learner_glm, base_learner_gbm, base_learner_rf]

# Set up Stacked Ensemble. Using Deep Learning as the meta learner
ensemble_deep = H2OStackedEnsembleEstimator(model_id ="stack_model_d", base_models = all_models, metalearner_algorithm = 'deeplearning')

ensemble_deep.train(y = response, training_frame = train)

# Eval ensemble performance on the test data
perf_stack_test = ensemble_deep.model_performance(test)
stack_auc_test = perf_stack_test.auc()
print("Ensemble_deep Test AUC: {0}".format(stack_auc_test))

它是如何工作的...

步骤 1中,我们使用了h2o.import_file()函数来读取我们的数据集。

h2o.import_file()函数返回一个H2OFrame实例。

步骤 2中,我们将H2OFrame拆分为训练集和测试集。在步骤 3中,我们检查了这些子集的维度,以验证我们的拆分是否满足我们的要求。

步骤 4中,我们查看了一些前几行数据,以检查数据是否正确加载。在步骤 5中,我们分离出响应变量和预测变量的列名,并在步骤 6中,我们使用asfactor()函数将响应变量转换为分类类型。

步骤 7中,我们定义了一个名为nfolds的变量,我们使用它进行交叉验证。我们还定义了一个名为encoding的变量,我们在后续步骤中使用它来指示 H2O 对分类变量使用独热编码。在步骤 8步骤 10中,我们构建了我们的基本学习器。

步骤 11中,我们训练了一个梯度提升机模型。我们向一些超参数传递了一些值,如下所示:

  • nfolds:K 折交叉验证的折数。

  • fold_assignment:此选项指定用于交叉验证折分配的方案。此选项仅在指定了nfolds值且未指定fold_column时适用。

  • distribution:指定分布。在我们的情况下,由于响应变量有两个类别,我们将distribution设置为"bernoulli"

  • ntrees:树的数量。

  • max_depth:表示最大树深度。

  • min_rows:叶子节点中允许的最少观测值。

  • learn_rate:学习率取值范围从0.01.0

注意,对于所有基本学习器,交叉验证折数必须相同,并且keep_cross_validation_predictions必须设置为True

步骤 9中,我们使用以下超参数训练了一个随机森林基本学习器:ntreesnfoldsfold_assignment

步骤 10中,我们使用 GLM 训练了我们的算法。请注意,我们尚未对 GLM 中的分类变量进行编码。

H2O 建议用户允许 GLM 处理分类列,因为它可以利用分类列以获得更好的性能和高效的内存利用。

来自 H2o.ai 的建议:"我们强烈建议避免将具有任何级别的分类列进行 one-hot 编码成多个二进制列,因为这非常低效。这对于习惯手动扩展其分类变量以适应其他框架的 Python 用户来说尤其如此"。

步骤 11中,我们为每个基础学习者生成了测试 AUC 值,并打印了最佳的 AUC。

步骤 12中,我们通过使用H2OStackedEnsembleEstimator结合基础学习者的输出,训练了一个堆叠集成模型。我们在测试子集上使用了训练好的集成模型。请注意,默认情况下,GLM 被用作H2OStackedEnsembleEstimator的元学习器。然而,在我们的示例中,我们使用了深度学习作为元学习器。

注意,我们已经为我们的元学习器使用了默认的超参数值。我们可以使用metalearner_params指定超参数值。metalearner_params选项允许您传递一个字典/超参数列表,用于作为元学习器的算法。

微调超参数可以带来更好的结果。

还有更多...

您也可以以不同的方式组装一个模型列表以堆叠。在前面的示例中,我们训练了单个模型并将它们放入列表中进行集成。我们也可以训练一个模型网格:

  1. 我们指定网格的随机森林超参数:
hyper_params = {"max_depth": [3, 4, 5, 8, 10],
                "min_rows": [3,4,5,6,7,8,9,10],
                "mtries": [10,15, 20],
                "ntrees": [100,250,500, 750],
                "sample_rate": [0.7, 0.8, 0.9, 1.0],
                "col_sample_rate_per_tree": [0.5, 0.6, 0.7, 0.8, 0.9, 1.0]}

search_criteria = {"strategy": "RandomDiscrete", "max_models": 3, "seed": 1}
  1. 我们使用前面代码中定义的超参数进行网格训练:
# Train the grid
grid = H2OGridSearch(model=H2ORandomForestEstimator(nfolds=nfolds,\
                                                    fold_assignment="Modulo",\
                                                    keep_cross_validation_predictions=True),\
                     hyper_params=hyper_params,\
                     search_criteria=search_criteria,\
                     grid_id="rf_grid_binomial")

grid.train(x=predictors, y=response, training_frame=train)
  1. 我们使用随机森林网格进行集成训练:
# Train a stacked ensemble using the RF grid
ensemble = H2OStackedEnsembleEstimator(model_id="ensemble_rf_grid_binomial_9", base_models=grid.model_ids)

ensemble.train(x=predictors, y=response, training_frame=train)

# Evaluate ensemble performance on the test data
perf_stack_test = ensemble.model_performance(test)

# Compare to base learner performance on the test set
baselearner_best_auc_test = max([h2o.get_model(model).model_performance(test_data=test).auc() for model in grid.model_ids])

stack_auc_test = perf_stack_test.auc()

print("Best Base-learner Test AUC: ", baselearner_best_auc_test)
print("Ensemble Test AUC: ", stack_auc_test)

上述代码将给出最佳基础学习器测试 AUC,并测试集成模型的 AUC。如果响应变量高度不平衡,考虑微调以下超参数以控制过采样和欠采样:

  • balance_classes:此选项可用于平衡类分布。当启用时,H2O 将减少多数类的样本量或增加少数类的样本量。如果此选项被启用,您还可以指定class_sampling_factorsmax_after_balance_size选项的值。

  • class_sampling_factors:默认情况下,采样因子将在训练期间自动计算以获得类平衡。此行为可以通过class_sampling_factors参数进行更改。此选项为每个类设置过采样或欠采样比率,并需要balance_classes=true

  • max_after_balance_size:在大多数情况下,将balance_classes设置为 true 会增加 DataFrame 的大小。为了减少 DataFrame 的大小,您可以使用max_after_balance_size参数。此参数指定平衡类计数后的训练数据的最大相对大小,默认为5.0

参见

看一看由 Marios Michailidis 在其博士论文中开发的StackNetStackNet在 MIT 许可下可用。它是一个可扩展的分析框架,类似于前馈神经网络,并使用 Wolpert 的堆叠泛化概念来提高机器学习预测任务的准确性。它使用元学习者的概念,即它使用某些算法的预测作为其他算法的特征。StackNet 还可以在多个级别上进行泛化堆叠。然而,它计算密集。最初是用 Java 开发的,但现在也提供了一种较轻的 Python 版本,名为pystacknet

让我们思考一下 StackNet 是如何工作的。在神经网络的情况下,某一层的输出被插入到下一层作为输入,并应用激活函数,如 sigmoid、tanh 或 relu。同样,在 StackNet 的情况下,激活函数可以被任何监督机器学习算法所替代。

堆叠元素可以在两种模式下运行:正常堆叠模式和重新堆叠模式。在正常堆叠模式下,每一层使用前一层的结果进行预测。在重新堆叠模式下,每一层使用前几层的神经元和激活。

使用 StackNet 的示例代码将包括以下步骤:

  1. 导入所需的库(请注意,我们已经从pystacknet库中导入了StackNetClassifierStackNetRegressor):
import numpy as np

# import required libraries from sklearn
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression

from sklearn.metrics import roc_auc_score, log_loss
from sklearn.model_selection import StratifiedKFold

# import StackNetClassifier and StackNetRegressor from pystacknet
from pystacknet.pystacknet import StackNetClassifier,StackNetRegressor
from pystacknet.metrics import rmse,mae
  1. 我们读取数据,删除ID列,并检查数据集的维度:
df_creditcarddata = pd.read_csv("UCI_Credit_Card.csv")

#dropping the ID column, as it would not be required
df_creditcarddata.drop(["ID"],axis=1,inplace=True)

# Check the shape of the data
df_creditcarddata.shape
  1. 我们将目标变量和预测变量分开。同时,我们将数据分为训练集和测试集:
#create the predictor & target set
X = df_creditcarddata.iloc[:,0:23]
Y = df_creditcarddata['default.payment.next.month']

# Create train & test sets
X_train, X_test, Y_train, Y_test = \
train_test_split(X, Y, test_size=0.20, random_state=1)
  1. 我们定义了基学习器和元学习器的模型:
models=[[DecisionTreeClassifier(criterion="entropy", max_depth=5, max_features=0.5, random_state=1),
GradientBoostingClassifier(n_estimators=100, learning_rate=0.1, max_depth=5, max_features=0.5, random_state=1),
LogisticRegression(random_state=1)],
[RandomForestClassifier (n_estimators=500, criterion="entropy", max_depth=5, max_features=0.5, random_state=1)]]
  1. 现在我们使用StackNetClassifier构建堆叠集成。但是请注意,我们使用restacking=False,这意味着它使用正常堆叠模式:
model=StackNetClassifier(models, metric="accuracy", folds=4, restacking=False, use_retraining=True, use_proba=True, random_state=12345, n_jobs=1, verbose=1)

model.fit(X_train,Y_train )

# Uses the meta-learner model to predict the outcome
preds=model.predict_proba(X_test)[:,1]
print ("TEST ACCURACY without RESTACKING, auc %f " % (roc_auc_score(Y_test,preds)))

使用restacking=True时,StackNetClassifier将使用重新堆叠模式来构建模型。

在 Kaggle 竞赛中,StackNet 被用于赢得各种案例研究。关于如何使用StackNet的示例可以在bit.ly/2T7339y找到。