橘智橘智
FakeOrange
预计阅读时间:8分钟3秒

数据分析2.3 —— 更好的模型之Stacking(模型集大成者)

Stacking是机器学习中一种集成学习的技巧

0
0

概述


Stacking是一种集成学习技术,它通过组合多个不同的模型来提高整体预测性能。在机器学习中,单个模型可能会在某些情况下表现不佳,而通过组合多个模型的预测结果,Stacking可以有效减小单个模型的偏差和方差,从而提高预测准确性。


Stacking的原理


Stacking的核心思想是通过多层模型的结合,来提高模型的泛化能力。具体步骤如下:

  1. 第一层(基础模型层):我们训练多个不同的基础模型(例如:决策树、支持向量机、KNN等)来预测数据集的输出。每个基础模型独立训练并产生预测结果。
  2. 第二层(元模型层):将第一层的模型预测结果作为新的特征输入,训练一个元模型。元模型通常是简单的回归模型或分类模型,它基于第一层模型的输出进行最终的预测。

通过这种方法,Stacking能结合多个模型的优点,并通过元模型纠正各个基础模型的预测误差,从而提高整体模型的性能。通常来说,差异性较大的算法结合会有更好的结果,不过单模型本身的性能也不能太差。最好性能相近,算法差异模型:例如KNN与SVG


Stacking的优势


  1. 提高预测性能:通过组合多个不同类型的模型,Stacking可以集成各个模型的优点,提高整体模型的性能和泛化能力。
  2. 减少过拟合:多个模型共同参与决策,能够减小单个模型可能带来的过拟合风险。
  3. 灵活性强:可以选择不同的基础模型和元模型组合,不拘泥于某种特定的模型类型。
  4. 平衡偏差和方差:Stacking通过组合多个模型的输出结果,平衡了模型的偏差和方差,提升了模型的稳定性。


Stacking的挑战


  • 训练复杂度较高:训练多个模型需要较大的计算开销,尤其在数据量较大的情况下。
  • 模型选择困难:需要仔细选择基础模型和元模型的组合,以获得最优性能。


代码演示(原理及示范):


使用泰坦尼克数据集进行Stacking


1. 导入必要的库


import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_predict
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.model_selection import KFold

2. 加载和预处理数据


# 加载Titanic数据集
df = pd.read_csv('titanic.csv')

# 简单预处理:处理缺失值和分类特征
df['Age'].fillna(df['Age'].median(), inplace=True)
df['Embarked'].fillna('S', inplace=True)
df = pd.get_dummies(df, columns=['Sex', 'Embarked'], drop_first=True)

# 特征和标签
X = df.drop(columns=['Survived', 'PassengerId', 'Name', 'Ticket', 'Cabin'])
y = df['Survived']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

3. 定义Stacking模型


为了简化,我们可以实现一个自定义的Stacking类,用于管理基础模型和元模型的组合。

class StackingClassifier(BaseEstimator, ClassifierMixin):
    def __init__(self, base_models, meta_model, n_folds=5):
        self.base_models = base_models
        self.meta_model = meta_model
        self.n_folds = n_folds

    def fit(self, X, y):
        self.base_models_ = [list() for x in self.base_models]
        self.meta_X = np.zeros((X.shape[0], len(self.base_models)))
        kfold = KFold(n_splits=self.n_folds, shuffle=True, random_state=42)

        # 训练每个基础模型
        for i, model in enumerate(self.base_models):
            for train_idx, holdout_idx in kfold.split(X, y):
                instance = model
                instance.fit(X[train_idx], y[train_idx])
                self.base_models_[i].append(instance)
                self.meta_X[holdout_idx, i] = instance.predict(X[holdout_idx])

        # 训练元模型
        self.meta_model.fit(self.meta_X, y)
        return self

    def predict(self, X):
        meta_X_test = np.column_stack([np.column_stack([model.predict(X) for model in base_models]).mean(axis=1) 
                                        for base_models in self.base_models_])
        return self.meta_model.predict(meta_X_test)

4. 初始化模型并进行Stacking


我们将使用三个基础模型(随机森林、梯度提升和逻辑回归),然后使用逻辑回归作为元模型。

# 初始化基础模型
base_models = [RandomForestClassifier(n_estimators=100, random_state=42),
               GradientBoostingClassifier(n_estimators=100, random_state=42),
               LogisticRegression(random_state=42)]

# 初始化元模型
meta_model = LogisticRegression()

# 定义Stacking模型
stacking_clf = StackingClassifier(base_models=base_models, meta_model=meta_model, n_folds=5)

# 训练Stacking模型
stacking_clf.fit(X_train.values, y_train.values)

# 预测并评估模型性能
y_pred = stacking_clf.predict(X_test.values)
print("Stacking模型的准确率:", accuracy_score(y_test, y_pred))

5. 结果分析


通过Stacking,我们组合了多个模型,得到了最终的预测结果。通常情况下,Stacking的性能会优于单个基础模型,因为它综合了多种模型的优势,并通过元模型对基础模型的结果进行优化。你可以通过调整不同的基础模型和元模型,进一步提升模型的性能。

代码演示(高可用库mlxtend):


1. 安装必要的库


首先,确保你安装了mlxtend库。如果未安装,可以使用以下命令:

pip install mlxtend

2. 导入必要的库


import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from mlxtend.classifier import StackingClassifier
from sklearn.metrics import accuracy_score

3. 加载和预处理数据


我们使用Titanic数据集,并对其进行基本的预处理。

# 加载Titanic数据集
df = pd.read_csv('titanic.csv')

# 简单预处理:处理缺失值和分类特征
df['Age'].fillna(df['Age'].median(), inplace=True)
df['Embarked'].fillna('S', inplace=True)
df = pd.get_dummies(df, columns=['Sex', 'Embarked'], drop_first=True)

# 特征和标签
X = df.drop(columns=['Survived', 'PassengerId', 'Name', 'Ticket', 'Cabin'])
y = df['Survived']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

4. 定义基础模型和元模型


我们将使用三个基础模型:随机森林梯度提升,并将逻辑回归作为元模型。

# 定义基础模型
rf_clf = RandomForestClassifier(n_estimators=100, random_state=42)
gb_clf = GradientBoostingClassifier(n_estimators=100, random_state=42)

# 定义元模型
lr_meta = LogisticRegression(random_state=42)

5. 使用mlxtend实现Stacking


mlxtend库中的StackingClassifier可以轻松实现模型堆叠。我们将基础模型和元模型堆叠起来。

# 使用mlxtend实现Stacking
stacking_clf = StackingClassifier(classifiers=[rf_clf, gb_clf],
                                  meta_classifier=lr_meta)

# 训练Stacking模型
stacking_clf.fit(X_train, y_train)

# 在测试集上进行预测
y_pred = stacking_clf.predict(X_test)

# 打印准确率
print("Stacking模型的准确率:", accuracy_score(y_test, y_pred))

6. 结果分析


在模型训练完成后,我们会输出Stacking模型的准确率。通常,Stacking模型的表现会优于单个模型,尤其是在基础模型性能存在互补的情况下。


7. 完整代码总结


以下是完整的代码:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from mlxtend.classifier import StackingClassifier
from sklearn.metrics import accuracy_score

# 1. 加载数据集并预处理
df = pd.read_csv('titanic.csv')
df['Age'].fillna(df['Age'].median(), inplace=True)
df['Embarked'].fillna('S', inplace=True)
df = pd.get_dummies(df, columns=['Sex', 'Embarked'], drop_first=True)

X = df.drop(columns=['Survived', 'PassengerId', 'Name', 'Ticket', 'Cabin'])
y = df['Survived']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 2. 定义基础模型和元模型
rf_clf = RandomForestClassifier(n_estimators=100, random_state=42)
gb_clf = GradientBoostingClassifier(n_estimators=100, random_state=42)
lr_meta = LogisticRegression(random_state=42)

# 3. 创建Stacking模型
stacking_clf = StackingClassifier(classifiers=[rf_clf, gb_clf],
                                  meta_classifier=lr_meta)

# 4. 训练模型并进行预测
stacking_clf.fit(X_train, y_train)
y_pred = stacking_clf.predict(X_test)

# 5. 输出模型准确率
print("Stacking模型的准确率:", accuracy_score(y_test, y_pred))

总结


Stacking是一种强大的集成学习方法,能够通过组合多个模型来提高预测的准确性。在许多场景中,Stacking常被用作提升模型性能的有效手段。虽然Stacking模型的训练较为复杂,但它的灵活性和性能提升使其在实践中具有很高的应用价值。 通过使用mlxtend库,我们能够更方便地实现Stacking技术。这个库封装了很多常见的集成学习方法,简化了Stacking模型的创建过程。通过这个例子,我们可以看到Stacking如何通过多个模型的结合来提升预测性能。



评论