《特征工程入门与实践》 -特征选择
元指标
元指标是指不直接与模型预测性能相关的指标,它们试图衡量周遭的性能,包括:
-
模型拟合/训练所需的时间;
-
拟合后的模型预测新实例的时间;
-
需要持久化(永久保存)的数据大小。
为了跟踪这些指标,我们可以创建一个get_best_model_and_accuracy
函数以评估若干模型,同时精细到可以提供每个模型的指标。我们会利用函数,完成以下任务:
- 搜索所有给定的参数,优化机器学习流水线;
- 输出有助于评估流水线质量的指标。
# 导入网格搜索模块
from sklearn.model_selection import GridSearchCV
def get_best_model_and_accuracy(model, params, X, y):
grid = GridSearchCV(model, # 要搜索的模型
params, # 要尝试的参数
error_score=0.) # 如果报错,结果是0
grid.fit(X, y) # 拟合模型和参数
# 经典的性能指标
print("Best Accuracy: {}".format(grid.best_score_))
# 得到最佳准确率的最佳参数
print("Best Parameters: {}".format(grid.best_params_))
# 拟合的平均时间(秒)
print("Average Time to Fit (s):
{}".format(round(grid.cv_results_['mean_fit_time'].mean(), 3)))
# 预测的平均时间(秒)
# 从该指标可以看出模型在真实世界的性能
print("Average Time to Score (s):
{}".format(round(grid.cv_results_['mean_score_time'].mean(), 3)))
我们会用这个函数评估每个特征选择方法,带来一种标准化的感觉。
案例分析:信用卡逾期数据集
import pandas as pd
import numpy as np
# 用随机数种子保证随机数永远一致
np.random.seed(123)
# archive.ics.uci.edu/ml/datasets/default+of+credit+card+clients
# 导入数据集
credit_card_default = pd.read_csv('../data/credit_card_default.csv')
先进行基本的探索性数据分析。检查一下数据集的大小,代码如下:
# 30 000行,24列
credit_card_default.shape
# 描述性统计
# 调用.T方法进行转置,以便更好地观察
credit_card_default.describe().T
default payment next month(下个月逾期)
是响应,其他都是特征,特征的尺度迥异,是我们选择数据处理方法和模型时需要考虑的因素。
# 检查缺失值,本数据集中不存在
credit_card_default.isnull().sum()
LIMIT_BAL 0
SEX 0
EDUCATION 0
MARRIAGE 0
AGE 0
PAY_0 0
PAY_2 0
PAY_3 0
PAY_4 0
PAY_5 0
PAY_6 0
BILL_AMT1 0
BILL_AMT2 0
BILL_AMT3 0
BILL_AMT4 0
BILL_AMT5 0
BILL_AMT6 0
PAY_AMT1 0
PAY_AMT2 0
PAY_AMT3 0
PAY_AMT4 0
PAY_AMT5 0
PAY_AMT6 0
default payment next month 0
dtype: int64
没有缺失值。接下来设置变量,代码如下:
# 特征矩阵
X = credit_card_default.drop('default payment next month', axis=1)
# 响应变量
y = credit_card_default['default payment next month']
和往常一样创建 X X X 和 y y y 变量。 X X X 矩阵有30000行和23列,而 y y y 是长度为30000的Pandas Series。因为要执行分类任务,所以取一个空准确率,确保机器学习的性能比基准更好。代码如下:
# 取空准确率
y.value_counts(normalize=True)
0 0.7788
1 0.2212
本例需要击败77.88%这个准确率,也就是没有逾期者的比例(0代表没有逾期)。
创建基准机器学习流水线
# 导入4种模型
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
先建立一些变量,代码如下:
# 为网格搜索设置变量
# 先设置机器学习模型的参数
# 逻辑回归
lr_params = {'C':[1e-1, 1e0, 1e1, 1e2], 'penalty':['l1', 'l2']}
# KNN
knn_params = {'n_neighbors': [1, 3, 5, 7]}
# 决策树
tree_params = {'max_depth':[None, 1, 3, 5, 7]}
# 随机森林
forest_params = {'n_estimators': [10, 50, 100], 'max_depth': [None, 1, 3, 5, 7]}
导入后执行get_best_model_and_accuracy
函数,取得每个模型处理原始数据的基准。
因为我们通过函数设置模型,而这会调用一个网格搜索模型,所以只需要创建空白模型即可,代码如下:
# 实例化机器学习模型
lr = LogisticRegression()
knn = KNeighborsClassifier()
d_tree = DecisionTreeClassifier()
forest = RandomForestClassifier()
我们在所有的模型上运行评估函数,了解一下效果的好坏。记住,我们要击败的精确率是0.7788,也就是基线空准确率。运行模型的代码如下:
get_best_model_and_accuracy(lr, lr_params, X, y)
Best Accuracy: 0.809566666667
Best Parameters: {'penalty': 'l1', 'C': 0.1}
Average Time to Fit (s): 0.602
Average Time to Score (s): 0.002
在KNN上做同样的处理:
get_best_model_and_accuracy(knn, knn_params, X, y)
Best Accuracy: 0.760233333333
Best Parameters: {'n_neighbors': 7}
Average Time to Fit (s): 0.035
Average Time to Score (s): 0.88
KNN是按照欧几里得距离进行预测的,在非标准数据上可能会失效,但是其他3个算法不会受此影响.
KNN是基于距离的模型,使用空间的紧密度衡量,假定所有的特征尺度相同,但是我们知道数据并不是这样。因此对于KNN,我们需要更复杂的流水线,以更准确地评估基准性能。代码如下:
# 导入所需的包
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
# 为流水线设置KNN参数
knn_pipe_params = {'classifier__{}'.format(k): v for k, v in knn_params.items()}
# KNN需要标准化的参数
knn_pipe = Pipeline([('scale', StandardScaler()), ('classifier', knn)])
# 拟合快,预测慢
get_best_model_and_accuracy(knn_pipe, knn_pipe_params, X, y)
print(knn_pipe_params) # {'classifier__n_neighbors': [1, 3, 5, 7]}
Best Accuracy: 0.8008
Best Parameters: {'classifier__n_neighbors': 7}
Average Time to Fit (s): 0.035
Average Time to Score (s): 6.723
在用StandardScalar进行 z z z分数标准化处理后,这个流水线的准确率至少比空准确率要高,但是这也严重影响了预测时间,因为多了一个预处理步骤。
从更简单的决策树开始:
get_best_model_and_accuracy(d_tree, tree_params, X, y)
Best Accuracy: 0.820266666667
Best Parameters: {'max_depth': 3}
Average Time to Fit (s): 0.158
Average Time to Score (s): 0.002
决策树的拟合速度比逻辑回归快,预测速度比KNN快。最后测试一下随机森林,代码如下:
get_best_model_and_accuracy(forest, forest_params, X, y)
Best Accuracy: 0.819566666667
Best Parameters: {'n_estimators': 50, 'max_depth': 7}
Average Time to Fit (s): 1.107
Average Time to Score (s): 0.044
比逻辑回归和KNN好得多,但是没有决策树好。我们汇总一下结果,看看应该使用哪个模型。
决策树的准确率最高,并且预测时间和逻辑回归并列第一,而带缩放的KNN拟合最快。总体而言,决策树应该是最适合下一步采用的模型,因为它在两个最重要的指标上领先:
- 我们想要最高的准确率,以保证预测的准确性;
- 考虑到实时生产环境,预测时间低大有裨益。
特征选择的类型:
选择特征是为了提高预测能力,降低时间成本<