前言
在机器学习项目的数据集中,特征间的高相关、特征与标签的低相关或不相关、特征本身的信息量以及特征数量等因素都会对模型的效果产生影响,特征筛选的目的是保留对预测有贡献的特征,删除冗余或无用特征。特征选择方法分为三大类,分别为过滤法(Filter)、包裹法(Wrapper)、嵌入法(Embedding);本文仅研究过滤法,过滤法由可以分为两种,直接使用某个标准对每个特征分别打分,然后根据打分直接用阈值过滤特征;和衡量每个特征与响应变量之间的关系,再根据得分扔掉不好的特征。
本文基于实践流程的思路,分三个步骤对数据集进行筛选,其中每一步都基于前一步的结果进行。
第一步:根据特征自身统计特性筛选
是一个特征的初筛,目的是剔除信息量过小的特征。其中连续型特征通过方差来筛选,方差过小的特征过于平稳,对模型预测的贡献度微乎其微;类别型特征通过异众比率来筛选,剔除绝大多数值都属于同一类别的特征。表中阈值仅供参考。
数据类型 | 筛选方法 | 阈值 |
---|---|---|
连续性数据 | 方差 | 大于0.01 |
类别型数据 | 异众比率 | 大于0.05 |
第二步:根据特征与标签的相关性筛选
数据集中的特征都是为预测标签而存在,因此特征与标签的相关性就很重要,也可以作为特征筛选的一种方法。根据数据类型的不同,可以将特征与标签的相关性检验分为四种方法,见下表,其中阈值仅供参考:
数据一类型 | 数据二类型 | 计算方法 | 衡量指标 | 选择阈值 |
---|---|---|---|---|
连续型 | 连续型 | 皮尔森相关系数 | r | 大于|0.3| |
连续型 | 二分类 | 独立样本t检验 | p | 小于0.05 |
连续型 | 多分类 | 单因素方差分析 | p | 小于0.05 |
类别型 | 类别型 | 卡方检验 | p | 小于0.05 |
第二步:根据特征与标签的相关性筛选
1 分类数据VS分类数据:卡方检验
当我们要检验的变量都是分类变量时,我们可以用列联表结合卡方检验来分析分类变量间的相关性。列联表形如:
体重<=50kg | 体重>50kg | |
---|---|---|
年龄<=15 | 10 | 20 |
年龄>15 | 30 | 40 |
其中数值表示对应行列分类下的频数,如数值“10”代表年龄<=15且体重<=50kg的人数。
卡方检验的思想在于比较期望频数和实际频数的吻合程度,实际频数就是上边表格里的数字,而期望频数则是指行列变量相互独立的时候期望的频数。
接下来我们用上表演示一下如何生成期望频数:
原表
每个单元格所在的行之和乘以列之和
每个单元格除以列联表中总频数100,得到期望频率
现在我们有了实际频数(第一张表)和期望频率(最后一张表),接下来就可以进行卡方检验了;卡方检验的原假设是期望频数等于实际频数,即二者相互独立,备择假设是期望频数不等于实际频数,即二者相关;卡方的计算公式为:
其中Turefrequency是真实频率,Expectedfrequency是期望频率;现在我们计算得到一个卡方值,那怎么来衡量这个值到底是接受原假设(即两变量相互独立)、还是拒绝原假设(两变量相关)呢?这就需要一个阈值:自由度,当卡方值大于自由度对应的阈值(阈值通过自由度表差得),我们认为拒绝原假设;当卡方值小于自由度对应的阈值,我们认为接受原假设。自由度=(行数-1)*(列数-1)。
自由度/概率 | 0.95 | 0.9 | 0.8 | 0.7 | 0.5 | 0.3 | 0.2 | 0.1 | 0.05 | 0.01 | 0.001 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0.004 | 0.02 | 0.06 | 0.15 | 0.46 | 1.07 | 1.64 | 2.71 | 3.84 | 6.64 | 10.83 |
2 | 0.1 | 0.21 | 0.45 | 0.71 | 1.39 | 2.41 | 3.22 | 4.6 | 5.99 | 9.21 | 13.82 |
3 | 0.35 | 0.58 | 1.01 | 1.42 | 2.37 | 3.66 | 4.64 | 6.25 | 7.82 | 11.34 | 16.27 |
4 | 0.71 | 1.06 | 1.65 | 2.2 | 3.36 | 4.88 | 5.99 | 7.78 | 9.49 | 13.28 | 18.47 |
5 | 1.14 | 1.61 | 2.34 | 3 | 4.35 | 6.06 | 7.29 | 9.24 | 11.07 | 15.09 | 20.52 |
6 | 1.63 | 2.2 | 3.07 | 3.83 | 5.35 | 7.23 | 8.56 | 10.64 | 12.59 | 16.81 | 22.46 |
7 | 2.17 | 2.83 | 3.82 | 4.67 | 6.35 | 8.38 | 9.8 | 12.02 | 14.07 | 18.48 | 24.32 |
8 | 2.73 | 3.49 | 4.59 | 5.53 | 7.34 | 9.52 | 11.03 | 13.36 | 15.51 | 20.09 | 26.12 |
9 | 3.32 | 4.17 | 5.38 | 6.39 | 8.34 | 10.66 | 12.24 | 14.68 | 16.92 | 21.67 | 27.88 |
10 | 3.94 | 4.86 | 6.18 | 7.27 | 9.34 | 11.78 | 13.44 | 15.99 | 18.31 | 23.21 | 19.59 |
卡方检验对数据量有一定的要求,一般认为卡方检验其单元格最小频数应大于1,且至少应有4/5的单元格频数大于5,此时使用卡方检验才是有意义的。
####卡方检验
def chi_square(col1,col2):
"""
卡方检验函数
:param col1: series,一列分类数据,用作列联表的行
:param col2: series,一列分类数据,用作列联表的列
:return: 输出接受原假设的概率值
"""
cross_table =pd.crosstab(index=col1, columns=col2, margins=False) ##对两列生成列联表
kf = chi2_contingency(cross_table)
p_value = kf[1] #p值
return p_value
2 数值数据VS数值数据:皮尔逊相关系数
使用皮尔森相关系数只能检验数据的线性相关性,当数据不是线性相关时,皮尔森相关系数没有意义,可以通过散点图直观的判断数据直接的关系。皮尔森相关系数的取值范围为-1--1,0表示无线性相关性,当皮尔森系数为正时,数值越大正线性相关性越强,当皮尔森系数为负时,数值越小,负线性相关性越强。下面是相关系数公式:上半部分表示x,y的协方差,下半部分表示x,y的标准差。
####两个变量间的皮尔森相关系数矩阵与p值
def Biva_Pearson(col1,col2):
"""
两个变量的相关系数矩阵与p值
:param col1: 变量1,seris或list
:param col2: 变量2,seris或list
:return:
"""
coef_matrix = np.corrcoef(col1, col2) ##相关性矩阵
(_, P_value) = ss.pearsonr(col1, col2) ##相关系数和p值
# Cor_coef = col1.corr(col2) ##相关系数
return coef_matrix,P_value
####多变量间的皮尔森相关系数矩阵和p值
def Mult_Pearson(df):
"""
多变量间的相关性矩阵、p值
:param df:
:return:
"""
coef_matrix = df.corr()
P_value_list = []
for i in df.columns.tolist()[:-1]:
(_, P_value) = ss.pearsonr(df[i],df[df.columns.tolist()[-1]])
P_value_list.append(P_value)
return coef_matrix,P_value_list
####画多变量散点图矩阵
def Scatter_plot_maxtrix(df,hue=None):
"""
绘制多维散点图矩阵
:param df: 绘图数据,dataframe
:param hue: 按哪列进行分类,默认是none
:return:
"""
sns.set(style="ticks", color_codes=True) ##画图设置
sns.pairplot(df , hue =hue) #散点图按hue列的分布矩阵
plt.show()
####画热力图
def Ther_diagram(df):
"""
画热力图矩阵
:param df:输入绘图数据,dataframe
:return:
"""
sns.set(style="ticks", color_codes=True) ##画图设置
figure, ax = plt.subplots(figsize=Cor_analysis.figsize)
sns.heatmap(df.corr(), square=True, annot=True, ax=ax)
plt.show()
3 二分类数据与数值数据:独立样本t检验
独立样本t检验,衡量二分类数据中,两个类别下连续型数据均值的差异是否显著,当差异显著时,认为二分类数据对连续型数据有影响,否则没有。
def t_test(name_x,name_y,df):
"""
独立样本t检验,二值类别变量与连续型变量间的相关性,原假设是两类别对应的值均值相等,即两列相关独立不相关,
:param name_x:dataframe中一个列名,二值变量
:param name_y:dataframe中一个列名,连续型变量
:param df:数据集dataframe
:return: p_t:t检验的p值,当p <0.05时拒绝原假设,即两变量相关
"""
from scipy.stats import ttest_ind, levene
namex_list = df[name_x].tolist()
namey_list = df[name_y].tolist()
type_one = [];type_two = []
for i in range(len(namex_list)):
if namex_list[i] == list(set(df[name_x].tolist()))[0]:
type_one.append(namey_list[i])
else:
type_two.append(namey_list[i])
# 方差齐性检验 当检验结果为p>0.05所以,可以认为方差是相等的。
p_s = levene(type_one, type_two)
# print("方差齐性检验:",p_s,p_s[1])
if p_s[1] >0.05: ##当方差齐
# 独立样本T检验,默认方差齐性 当p值>0.05, 接受原假设, 认为两台机床的加工精度无显著差异。
p_t = ttest_ind(type_one, type_two)
else: ###当方差不齐
###如果方差不齐性,则equal_var=False
p_t = ttest_ind(type_one, type_two, equal_var=False)
return p_t[1]
4 多分类数据与数值数据:单因素方差分析
与独立样本t检验思想类似,验证每个类别下连续型数据均值的显著差异
def covariance(name_x,name_y,df):
"""
单因素方差分析,类别型变量与连续型变量关系分析
:param name_x:dataframe中一个类别型变量的列名
:param name_y:dataframe中一个连续型变量的列名
:param df:数据集dataframe
:return:
p:p值,拒绝原假设(自变量对因变量没有显著影响,即两个变量相互独立)的最小显著性水平
f: F值,组间误差均方MSA除组内误差均方MSE,自由度F(K-1,N-K),其中k是类别变量的类别数,N是样本量
"""
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
formula = '{} ~ {}'.format(name_x, name_y)
model = ols(formula, df).fit()
anovat = anova_lm(model)
# f = anovat["F"][name_y]
p = anovat["PR(>F)"][name_y]
# df1 = len(df[name_x].drop_duplicates().tolist())-1 ##F值分子自由度
# print("df1:",df1)
# df2 = len(df[name_x].tolist())-df1+1 #F值分母自由度
return p
第二步:根据特征与特征的相关性筛选(多重共线性)
待补充
参考文献
用 Python 对数据进行相关性分析用 Python 对数据进行相关性分析
sql联表分类统计_分类变量的相关性:五分钟掌握卡方检验「详细解析,附代码」...sql联表分类统计_分类变量的相关性:五分钟掌握卡方检验「详细解析,附代码」..._weixin_39736606的博客-CSDN博客