基于流水线的工作流
scikit-learn 中的 Pipeline 类。它使得我们可以拟合包含任意多个处理步骤的模型,并模型用于新数据的预测。
案例1:威斯康星乳腺癌数据集
使用Breast Cancer Wisconsin 数据集,此数据集共包含569个恶性或良性肿瘤细胞样本。数据集的前两列分别存储了样本唯一的ID以及对样本的诊断结果(M代表恶性,B代表良性)。数据集的3~32列包含了30个从细胞核照片中提取、用实数值标识的特征,它们可以用于构建判定模型,对肿瘤是良性还是恶性做出预测。
1.数据加载
import pandas as pd
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-\
databases/breast-cancer-wisconsin/wdbc.data', header=None)
from sklearn.preprocessing import LabelEncoder
X = df.loc[:, 2:].values
y = df.loc[:, 1].values
le = LabelEncoder()
y = le.fit_transform(y)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
random_state=1)
使用 scikit-learn 中的 LabelEncoder 类,可以将类标从原始字符串表示(M 或 B)转换为整数。
2.在pipeline中集成数据转换及评估操作
通过 Pipeline 类将 StandardScaler、PCA、LogisticRegression 对象串联起来,无需在训练数据集和测试数据集上分别进行模型拟合。
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
pipe_lr = Pipeline([
('sc1', StandardScaler()),
('pca', PCA(n_components=2)),
('clf', LogisticRegression(random_state=1)),
])
pipe_lr.fit(X_train, y_train)
print('Test Accuracy: %.3f' % (pip_lr.score(X_test, y_test)))
执行结果如下:
Test Accuracy: 0.947
Pipeline 对象采用元组的序列作为输入,其中每个元组中的第一个值为一个字符串,可以是任意的标识符,我们通过它来访问 pipeline 中的元素,而元组的第二个值则为 scikit-learn 中的一个转换器或分类器。
注意:pipeline 中没有设定中间步骤的数量。pipeline 的工作方式可用下图来描述:
k-fold 交叉验证评估模型性能
构建机器学习模型的一个关键步骤就是在新数据上对模型性能进行评估。如果一个模型过于简单,将会面临欠拟合(高偏差)的问题,而模型基于训练数据构造得过于复杂,则会到时过拟合(高方差)问题。为了在偏差和方差之间找到可接受的折中方案,需要对模型惊醒评估。目前,常用的交叉验证技术有:holdout 交叉验证和k-fold交叉验证。
holdout法
通过 holdout 将原始数据集划分为训练数据集和测试数据集,为进一步提高模型在预测未知数据上的性能,需要对不同参数设置进行调优和比较。
但是,如果再模型选择过程中不断重复使用相同的测试数据,它们可看作训练数据的一部分,模型更易于过拟合。
使用 holdout 进行模型选择更好的方法是将数据划分为三个部分:训练数据集、验证数据集和测试数据集。训练数据集用于不同模型的拟合,模型在验证数据集上的性能表现作为模型选择的标准。交叉验证中,在使用不同参数值对模型进行训练后,使用验证数据集反复进行模型性能的评估。一旦参数优化获得较为满意的结果,就可以在测试数据集上对模型的泛化误差进行评估。
holdout 法的一个缺点在于:模型性能的评估对训练数据集划分为训练及验证子集的方法是敏感的,评价结果会随着样本的不同而发生变化。
k-fold交叉验证法
在 k-fold 交叉验证中,将训练数据集划分为 k 个,其中 k - 1 个用于模型的训练,剩余1个用于测试。重复此过程 k 次,就得到了 k 个模型及对模型性能的评价。
与 holdout 方法相比,k-fold 得到的结果对数据划分方法的敏感性相对较低。通过情况下,将 k-fold 交叉验证用于模型的调优,一旦找到了满意的超参值,就可以在全部的训练数据上重新训练模型,并使用独立的测试数据集对模型性能做出最终评价。
由于 k-fold 交叉验证使用了无重复抽样技术,该方法的优势在于(每次迭代过程中)每个样本点只有一次被划入训练数据集或测试数据集的机会,与 holdout 法相比,这将使得模型性能的评估具有较小的方差。
k-fold 交叉验证法的一个特例就是留一交叉验证法(leave-one-out, LOO),LOO将训练数据集划分为等同于样本数的子集,这样每次只有一个样本用于测试,当数据集非常小时,建议使用此方法进行验证。
分层 k-fold 交叉验证法对标准 k-fold 交叉验证法进行了改进,它可以获得偏差和方差都较低的评价,特别是类别比例相差较大时。在分层交叉验证中,类别比列在每一个分块中得以保持,这使得每个分块中的类别比例与训练数据的整体比例一致。
from sklearn.cross_validation import StratifiedKFold
import numpy as np
kfold = StratifiedKFold(y=y_train, n_folds=10, random_state=1)
scores = []
for k, (train, test) in enumerate(kfold):
pipe_lr.fit(X_train[train], y_train[train])
score = pipe_lr.score(X_train[test], y_train[test])
scores.append(score)
print('Fold: %s, Class dist: %s, Acc: %.3f' % (k + 1, np.bincount(y_train[train]), score))
print('CV accuracy: %.3f +/- %.3f' % (np.mean(sc