数据分析2.3 —— 更好的模型之Stacking(模型集大成者)
Stacking是机器学习中一种集成学习的技巧
概述
Stacking是一种集成学习技术,它通过组合多个不同的模型来提高整体预测性能。在机器学习中,单个模型可能会在某些情况下表现不佳,而通过组合多个模型的预测结果,Stacking可以有效减小单个模型的偏差和方差,从而提高预测准确性。
Stacking的原理
Stacking的核心思想是通过多层模型的结合,来提高模型的泛化能力。具体步骤如下:
- 第一层(基础模型层):我们训练多个不同的基础模型(例如:决策树、支持向量机、KNN等)来预测数据集的输出。每个基础模型独立训练并产生预测结果。
- 第二层(元模型层):将第一层的模型预测结果作为新的特征输入,训练一个元模型。元模型通常是简单的回归模型或分类模型,它基于第一层模型的输出进行最终的预测。
通过这种方法,Stacking能结合多个模型的优点,并通过元模型纠正各个基础模型的预测误差,从而提高整体模型的性能。通常来说,差异性较大的算法结合会有更好的结果,不过单模型本身的性能也不能太差。最好性能相近,算法差异模型:例如KNN与SVG
Stacking的优势
- 提高预测性能:通过组合多个不同类型的模型,Stacking可以集成各个模型的优点,提高整体模型的性能和泛化能力。
- 减少过拟合:多个模型共同参与决策,能够减小单个模型可能带来的过拟合风险。
- 灵活性强:可以选择不同的基础模型和元模型组合,不拘泥于某种特定的模型类型。
- 平衡偏差和方差: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如何通过多个模型的结合来提升预测性能。