特征工程(五)—(2)特征选择_基于统计的特征选择

基于统计的特征选择

基于统计的特征选择,可以使用皮尔逊相关系数、假设检验来帮助我们进行特征选择。

1、基于皮尔逊系数

皮尔逊相关系数会测量列和列之间的线性关系,该系数在-1~1之间变化,0代表没有线性关系,-1和1 代表线性关系很强。
注意:
皮尔逊相关系数要求每列是正态分布的,如果数据集很大(超过500阈值),根据中心极限定理,很大程度上也可以忽略这个要求。

"""
基于统计的特征选择

可以使用皮尔逊相关系数、假设检验来帮助我们进行特征选择。

皮尔逊相关系数会测量列和列之间的线性关系,该系数在-1~1之间变化,0代表没有线性关系,-1和1 代表线性关系很强。
注意:
  皮尔逊相关系数要求每列是正态分布的,如果数据集很大(超过500阈值),根据中心极限定理,很大程度上也可以忽略这个要求。
"""

import pandas as pd
import numpy as np


# 利用pandas读取信用卡逾期数据集
credit_card_default = pd.read_csv("../data/credit_card_default.csv")


# 相关系数的计算
credit_card_default.corr()

特征工程(五)—(2)特征选择_基于统计的特征选择_第1张图片

# pandas的corr方法会为所有的列计算相关系数,不过这个矩阵很难读,用热图进行优化
import seaborn as sns
import matplotlib.style as style


style.use('fivethirtyeight')
sns.heatmap(credit_card_default.corr())

# 注意,heatmap会自动选择最相关的特征显示

特征工程(五)—(2)特征选择_基于统计的特征选择_第2张图片

# 特征和响应的相关性
credit_card_default.corr()['default payment next month']

特征工程(五)—(2)特征选择_基于统计的特征选择_第3张图片

# 利用pandas过滤出相关系数超过正负0.2的特征

highly_corr_features = credit_card_default.columns[
    credit_card_default.corr()['default payment next month'].abs() > 0.2
].drop('default payment next month')

highly_corr_features

在这里插入图片描述

# 构建特征矩阵和响应变量
X = credit_card_default.drop('default payment next month', axis=1)
y = credit_card_default['default payment next month']

# 从sklearn中导入网格搜索模块
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier

# 创建一个函数,用来评估模型
def get_best_model_and_accuracy(model, params, X, y):

    grid = GridSearchCV(model, # 要搜索的模型
                        params, # 要尝试的参数
                        error_score=0.0 # 如果报错,结果为0
                        )

    # 拟合模型和参数
    grid.fit(X, y)
    # 经典的性能指标
    print('最佳的准确率为:{}'.format(grid.best_score_))
    # 得到最佳准确率的最佳参数
    print('得到最佳准确率的最佳参数:{}'.format(grid.best_params_))
    # 拟合的平均时间
    print('拟合的平均时间:{} 秒'.format(round(grid.cv_results_['mean_fit_time'].mean(), 3)))
    # 预测的平均时间
    print('预测的平均时间:{} 秒'.format(round(grid.cv_results_['mean_score_time'].mean(), 3)))



# 只留下,原始数据集的5个特征,用于预测响应的变量
X_sub = X[highly_corr_features]

# 决策树
tree_params = {
    'max_depth':[None, 1, 3, 5, 7]
}
d_tree = DecisionTreeClassifier()

# 决策树
get_best_model_and_accuracy(d_tree, tree_params, X_sub, y)

# 准确率为0.8213  比 之前0.8206高,拟合时间比之前0.154秒低,预测时间比之前0.002秒低。
# 模型只需要5个特征就可以学习整个数据集,而且速度快得多。

特征工程(五)—(2)特征选择_基于统计的特征选择_第4张图片
自定义一个转换器,来完成上面的逻辑

'''
将特征的相关性选择作为预处理的一部分,自定义一个转换器,来完成上面的逻辑
'''

import pandas as pd
from sklearn.base import TransformerMixin, BaseEstimator
from sklearn.pipeline import  Pipeline
# 从sklearn中导入网格搜索模块
from sklearn.model_selection import GridSearchCV


# 创建一个函数,用来评估模型
def get_best_model_and_accuracy(model, params, X, y):

    grid = GridSearchCV(model, # 要搜索的模型
                        params, # 要尝试的参数
                        error_score=0.0 # 如果报错,结果为0
                        )

    # 拟合模型和参数
    grid.fit(X, y)
    # 经典的性能指标
    print('最佳的准确率为:{}'.format(grid.best_score_))
    # 得到最佳准确率的最佳参数
    print('得到最佳准确率的最佳参数:{}'.format(grid.best_params_))
    # 拟合的平均时间
    print('拟合的平均时间:{} 秒'.format(round(grid.cv_results_['mean_fit_time'].mean(), 3)))
    # 预测的平均时间
    print('预测的平均时间:{} 秒'.format(round(grid.cv_results_['mean_score_time'].mean(), 3)))


class MyCorrFeaturesChooser(TransformerMixin, BaseEstimator):

    def __init__(self, response, cols_to_keep=[], threshold=None):
        # 保存响应变量
        self.response = response
        # 保存阈值
        self.threshold = threshold
        # 初始化一个变量,保存要保留的特征
        self.cols_to_keep = cols_to_keep

    def transform(self, X):
        # 转换会选择合适的列
        return X[self.cols_to_keep]


    def fit(self, X, *_):
        # 创建新的DF,存放特征和响应
        df = pd.concat([X, self.response], axis=1)
        # 保存高于阈值的列的名称
        self.cols_to_keep = df.columns[
            df.corr()[df.columns[-1]].abs() > self.threshold
        ]
        # 只保留X,去掉response
        self.cols_to_keep = [c for c in self.cols_to_keep if c in X.columns]
        return self


'''
在流水线中将一切都组装起来
'''

# 利用pandas读取信用卡逾期数据集
credit_card_default = pd.read_csv("../data/credit_card_default.csv")
# 构建特征矩阵和响应变量
X = credit_card_default.drop('default payment next month', axis=1)
y = credit_card_default['default payment next month']


ccc = MyCorrFeaturesChooser(response=y)
from sklearn.tree import DecisionTreeClassifier
# 决策树
d_tree = DecisionTreeClassifier()
# 流水线
ccc_pipe = Pipeline(
    [
        ('ccc_select', ccc),
        ('classifier', d_tree)
    ]
)

# 决策树参数
tree_pipe_params = {
    'ccc_select__threshold':[0.0, 0.1, 0.2, 0.3],
    'classifier__max_depth':[None, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
}


get_best_model_and_accuracy(ccc_pipe, tree_pipe_params, X, y)

'''
特征选择前:
最佳的准确率为:0.8206333333333333
得到最佳准确率的最佳参数:{'max_depth': 3}
拟合的平均时间:0.154 秒
预测的平均时间:0.002 秒


特征选择后:
最佳的准确率为:0.8207333333333333
得到最佳准确率的最佳参数:{'ccc_select__threshold': 0.2, 'classifier__max_depth': 3}
拟合的平均时间:0.105 秒
预测的平均时间:0.002 秒


流水线显示,如果把阈值设置为0.2,就可以消除噪声提高准确性,并且缩短拟合时间
'''

2、基于假设检验

假设检验是一种统计学方法,可以对单个特征进行复杂的统计检验。
p值是介于0到1之间的小数,代表在假设检验下,给定数据偶然出现的概率。p值越低,拒绝零假设的概率越大。

换句话说,p值越低,说明这个特征与响应变量有关联的概率就越大,我们就应该保留这个特征。

"""
基于统计的特征选择

可以使用皮尔逊相关系数、假设检验来帮助我们进行特征选择。


假设检验是一种统计学方法,可以对单个特征进行复杂的统计检验。
p值是介于0到1之间的小数,代表在假设检验下,给定数据偶然出现的概率。p值越低,拒绝零假设的概率越大。

换句话说,p值越低,说明这个特征与响应变量有关联的概率就越大,我们就应该保留这个特征。
"""

# 给定目标函数后,选择K个最高分
from sklearn.feature_selection import SelectKBest
# ANOVA测试
from sklearn.feature_selection import f_classif

# 需要注意的是,f_classif函数在每个特征上单独执行一次ANOVA测试(一种假设检验的类型),并且分配一个p值。
# SelectKBest会将特征按照p值排列(越小越好),只保留我们指定的k个最佳特征


# 实例化一个SelectKBest,设置k=5,代表希望保留5个最佳特征
k_best = SelectKBest(f_classif, k=5)

# 选择最佳特征后的矩阵
k_best.fit_transform(X, y)

特征工程(五)—(2)特征选择_基于统计的特征选择_第5张图片

# 特征和p值组成df
p_values = pd.DataFrame(
    {
        'column':X.columns,
        'p_value':k_best.pvalues_
    }
).sort_values('p_value')

# 前5个特征
p_values.head()

特征工程(五)—(2)特征选择_基于统计的特征选择_第6张图片

# p值常见的阈值是0.05,意思是可以认为p小于0.05的特征是显著的

# 查看p<0.05的特征
p_values[
    p_values['p_value'] < 0.05
]

特征工程(五)—(2)特征选择_基于统计的特征选择_第7张图片

# 可以看到大部分特征的p值都很低,但不是全部。
# 查看那些列的p值较高
p_values[
    p_values['p_value'] >= 0.05
]

特征工程(五)—(2)特征选择_基于统计的特征选择_第8张图片
在流水线应用SelectBest

import pandas as pd
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif
from sklearn.pipeline import Pipeline
from sklearn.tree import DecisionTreeClassifier
# 从sklearn中导入网格搜索模块
from sklearn.model_selection import GridSearchCV

# 创建一个函数,用来评估模型
def get_best_model_and_accuracy(model, params, X, y):

    grid = GridSearchCV(model, # 要搜索的模型
                        params, # 要尝试的参数
                        error_score=0.0 # 如果报错,结果为0
                        )

    # 拟合模型和参数
    grid.fit(X, y)
    # 经典的性能指标
    print('最佳的准确率为:{}'.format(grid.best_score_))
    # 得到最佳准确率的最佳参数
    print('得到最佳准确率的最佳参数:{}'.format(grid.best_params_))
    # 拟合的平均时间
    print('拟合的平均时间:{} 秒'.format(round(grid.cv_results_['mean_fit_time'].mean(), 3)))
    # 预测的平均时间
    print('预测的平均时间:{} 秒'.format(round(grid.cv_results_['mean_score_time'].mean(), 3)))

# 利用pandas读取信用卡逾期数据集
credit_card_default = pd.read_csv("../data/credit_card_default.csv")
# 构建特征矩阵和响应变量
X = credit_card_default.drop('default payment next month', axis=1)
y = credit_card_default['default payment next month']

# 决策树
d_tree = DecisionTreeClassifier()


k_best = SelectKBest(f_classif)

# 建立流水线
select_k_pipe = Pipeline(
    [
        ('k_best', k_best),
        ('classifier', d_tree)
    ]
)

# 决策树参数
tree_pipe_params = {
    'k_best__k':list(range(1, 23)) + ['all'],
    'classifier__max_depth':[None, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
}
'''
{
   'k_best__k': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 'all'], 
   'classifier__max_depth': [None, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
}
'''

get_best_model_and_accuracy(select_k_pipe, tree_pipe_params, X, y)

'''

最佳的准确率为:0.8213333333333332
得到最佳准确率的最佳参数:{'classifier__max_depth': 3, 'k_best__k': 5}
拟合的平均时间:0.101 秒
预测的平均时间:0.002 秒

和自定义的转换器相比,准确率差不多,不够快了一点。
'''


你可能感兴趣的:(#,特征工程,python,pandas,数据分析)