百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

Pandas/Sklearn进行机器学习之特征筛选,有效提升模型性能

liuian 2024-12-20 17:19 38 浏览

作者:俊欣

来源:关于数据分析与可视化

今天小编来说说如何通过pandas以及sklearn这两个模块来对数据集进行特征筛选,毕竟有时候我们拿到手的数据集是非常庞大的,有着非常多的特征,减少这些特征的数量会带来许多的好处,例如

  • 提高预测的精准度
  • 降低过拟合的风险
  • 加快模型的训练速度
  • 增加模型的可解释性

事实上,很多时候也并非是特征数量越多训练出来的模型越好,当添加的特征多到一定程度的时候,模型的性能就会下降,从下图中我们可以看出,

因此我们需要找到哪些特征是最佳的使用特征,当然我们这里分连续型的变量以及离散型的变量来讨论,毕竟不同数据类型的变量处理的方式不同,我们先来看一下对于连续型的变量而言,特征选择到底是怎么来进行的。

计算一下各个变量之间的相关性

我们先导入所需要用到的模块以及导入数据集,并且用pandas模块来读取

from sklearn.datasets import load_boston
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import RFE
from sklearn.linear_model import RidgeCV, LassoCV, Ridge, Lasso

这次用到的数据集是机器学习中尤其是初学者经常碰到的,波士顿房价的数据集,其中我们要预测的这个对象是MEDV这一列

x = load_boston()
df = pd.DataFrame(x.data, columns = x.feature_names)
df["MEDV"] = x.target
X = df.drop("MEDV",1)   #将模型当中要用到的特征变量保留下来
y = df["MEDV"]          #最后要预测的对象
df.head()

output

      CRIM    ZN  INDUS  CHAS    NOX  ...    TAX  PTRATIO       B  LSTAT  MEDV
0  0.00632  18.0   2.31   0.0  0.538  ...  296.0     15.3  396.90   4.98  24.0
1  0.02731   0.0   7.07   0.0  0.469  ...  242.0     17.8  396.90   9.14  21.6
2  0.02729   0.0   7.07   0.0  0.469  ...  242.0     17.8  392.83   4.03  34.7
3  0.03237   0.0   2.18   0.0  0.458  ...  222.0     18.7  394.63   2.94  33.4
4  0.06905   0.0   2.18   0.0  0.458  ...  222.0     18.7  396.90   5.33  36.2

我们可以来看一下特征变量的数据类型

df.dtypes

output

CRIM       float64
ZN         float64
INDUS      float64
CHAS       float64
NOX        float64
RM         float64
AGE        float64
DIS        float64
RAD        float64
TAX        float64
PTRATIO    float64
B          float64
LSTAT      float64
MEDV       float64
dtype: object

我们看到都是清一色的连续型的变量,我们来计算一下自变量和因变量之间的相关性,通过seaborn模块当中的热力图来展示,代码如下

plt.figure(figsize=(10,8))
cor = df.corr()
sns.heatmap(cor, annot=True, cmap=plt.cm.Reds)
plt.show()

相关系数的值一般是在-1到1这个区间内波动的

  • 相关系数要是接近于0意味着变量之间的相关性并不强
  • 接近于-1意味着变量之间呈负相关的关系
  • 接近于1意味着变量之间呈正相关的关系

我们来看一下对于因变量而言,相关性比较高的自变量有哪些

# 筛选出于因变量之间的相关性
cor_target = abs(cor["MEDV"])
# 挑选于大于0.5的相关性系数
relevant_features = cor_target[cor_target>0.5]
relevant_features

output

RM         0.695360
PTRATIO    0.507787
LSTAT      0.737663
MEDV       1.000000
Name: MEDV, dtype: float64

筛选出3个相关性比较大的自变量来,然后我们来看一下自变量之间的相关性如何,要是自变量之间的相关性非常强的话,我们也只需要保留其中的一个就行,

print(df[["LSTAT","PTRATIO"]].corr())
print("=" * 50)
print(df[["RM","LSTAT"]].corr())
print("=" * 50)
print(df[["PTRATIO","RM"]].corr())

output

            LSTAT   PTRATIO
LSTAT    1.000000  0.374044
PTRATIO  0.374044  1.000000
==================================================
             RM     LSTAT
RM     1.000000 -0.613808
LSTAT -0.613808  1.000000
==================================================
          PTRATIO        RM
PTRATIO  1.000000 -0.355501
RM      -0.355501  1.000000

从上面的结果中我们可以看到,RM变量和LSTAT这个变量是相关性是比较高的,我们只需要保留其中一个就可以了,我们选择保留LSTAT这个变量,因为它与因变量之间的相关性更加高一些

递归消除法

我们可以尝试这么一种策略,我们选择一个基准模型,起初将所有的特征变量传进去,我们再确认模型性能的同时通过对特征变量的重要性进行排序,去掉不重要的特征变量,然后不断地重复上面的过程直到达到所需数量的要选择的特征变量。

LR= LinearRegression()
# 挑选出7个相关的变量
rfe_model = RFE(model, 7)
# 交给模型去进行拟合
X_rfe = rfe_model.fit_transform(X,y)  
LR.fit(X_rfe,y)
# 输出各个变量是否是相关的,并且对其进行排序
print(rfe_model.support_)
print(rfe_model.ranking_)

output

[False False False  True  True  True False  True  True False  True False
  True]
[2 4 3 1 1 1 7 1 1 5 1 6 1]

第一行的输出包含TrueFalse,其中True代表的是相关的变量对应下一行的输出中的1,而False包含的是不相关的变量,然后我们需要所需要多少个特征变量,才能够使得模型的性能达到最优

#将13个特征变量都依次遍历一遍
feature_num_list=np.arange(1,13)
# 定义一个准确率
high_score=0
# 最优需要多少个特征变量
num_of_features=0           
score_list =[]
for n in range(len(feature_num_list)):
    X_train, X_test, y_train, y_test = train_test_split(X,y, test_size = 0.3, random_state = 0)
    model = LinearRegression()
    rfe_model = RFE(model,feature_num_list[n])
    X_train_rfe_model = rfe_model.fit_transform(X_train,y_train)
    X_test_rfe_model = rfe_model.transform(X_test)
    model.fit(X_train_rfe_model,y_train)
    score = model.score(X_test_rfe_model,y_test)
    score_list.append(score)
    if(score>high_score):
        high_score = score
        num_of_features = feature_num_list[n]
print("最优的变量是: %d个" %num_of_features)
print("%d个变量的准确率为: %f" % (num_of_features, high_score))

output

最优的变量是: 10个
10个变量的准确率为: 0.663581

从上面的结果可以看出10个变量对于整个模型来说是最优的,然后我们来看一下到底是哪10个特征变量

cols = list(X.columns)
model = LinearRegression()
# 初始化RFE模型,筛选出10个变量
rfe_model = RFE(model, 10)             
X_rfe = rfe.fit_transform(X,y)  
# 拟合训练模型
model.fit(X_rfe,y)              
df = pd.Series(rfe.support_,index = cols)
selected_features = df[df==True].index
print(selected_features)

output

Index(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'DIS', 'RAD', 'PTRATIO',
       'LSTAT'],
      dtype='object')

正则化

例如对于Lasso的正则化而言,对于不相关的特征而言,该算法会让其相关系数变为0,因此不相关的特征变量很快就会被排除掉了,只剩下相关的特征变量

lasso = LassoCV()
lasso.fit(X, y)
coef = pd.Series(lasso.coef_, index = X.columns)

然后我们看一下哪些变量的相关系数是0

print("Lasso算法挑选了 " + str(sum(coef != 0)) + " 个变量,然后去除掉了" +  str(sum(coef == 0)) + "个变量")

output

Lasso算法挑选了10个变量,然后去除掉了3个变量

我们来对计算出来的相关性系数排个序并且做一个可视化

imp_coef = coef.sort_values()
matplotlib.rcParams['figure.figsize'] = (8, 6)
imp_coef.plot(kind = "barh")
plt.title("Lasso Model Feature Importance")

output

可以看到当中有3个特征,‘NOX’、'CHAS'、'INDUS'的相关性为0

根据缺失值来进行判断

下面我们来看一下如何针对离散型的特征变量来做处理,首先我们可以根据缺失值的比重来进行判断,要是对于一个离散型的特征变量而言,绝大部分的值都是缺失的,那这个特征变量也就没有存在的必要了,我们可以针对这个思路在进行判断。

首先导入所需要用到的数据集

train = pd.read_csv("credit_example.csv")
train_labels = train['TARGET']
train = train.drop(columns = ['TARGET'])

我们可以先来计算一下数据集当中每个特征变量缺失值的比重

missing_series = train.isnull().sum() / train.shape[0]
df = pd.DataFrame(missing_series).rename(columns = {'index': '特征变量', 0: '缺失值比重'})
df.sort_values("缺失值比重", ascending = False).head()

output

                           缺失值比重
COMMONAREA_AVG            0.6953
COMMONAREA_MODE           0.6953
COMMONAREA_MEDI           0.6953
NONLIVINGAPARTMENTS_AVG   0.6945
NONLIVINGAPARTMENTS_MODE  0.6945

我们可以看到缺失值最高的比重将近有70%,我们也可以用可视化的根据来绘制一下缺失值比重的分布图

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.figure(figsize = (7, 5))
plt.hist(df['缺失值比重'], bins = np.linspace(0, 1, 11), edgecolor = 'k', color = 'blue', linewidth = 2)
plt.xticks(np.linspace(0, 1, 11));
plt.xlabel('缺失值的比重', size = 14); 
plt.ylabel('特征变量的数量', size = 14); 
plt.title("缺失值分布图", size = 14);

output

我们可以看到有一部分特征变量,它们缺失值的比重在50%以上,有一些还在60%以上,我们可以去除掉当中的部分特征变量

计算特征的重要性

在基于树的众多模型当中,会去计算每个特征变量的重要性,也就是feature_importances_属性,得出各个特征变量的重要性程度之后再进行特征的筛选

from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier()
# 模型拟合数据
clf.fit(X,Y)
feat_importances = pd.Series(clf.feature_importances_, index=X.columns)
# 筛选出特征的重要性程度最大的10个特征
feat_importances.nlargest(10)

我们同时也可以对特征的重要性程度进行可视化,

feat_importances.nlargest(10).plot(kind='barh', figsize = (8, 6))

output

除了随机森林之外,基于树的算法模型还有很多,如LightGBMXGBoost等等,大家也都可以通过对特征重要性的计算来进行特征的筛选

Select_K_Best算法

Sklearn模块当中还提供了SelectKBest的API,针对回归问题或者是分类问题,我们挑选合适的模型评估指标,然后设定K值也就是既定的特征变量的数量,进行特征的筛选。

假定我们要处理的是分类问题的特征筛选,我们用到的是iris数据集

iris_data = load_iris()
x = iris_data.data
y = iris_data.target
 
print("数据集的行与列的数量: ", x.shape) 

output

数据集的行与列的数量:  (150, 4)

对于分类问题,我们采用的评估指标是卡方,假设我们要挑选出3个对于模型最佳性能而言的特征变量,因此我们将K设置成3

select = SelectKBest(score_func=chi2, k=3)
# 拟合数据
z = select.fit_transform(x,y)
filter_1 = select.get_support()
features = array(iris.feature_names)
print("所有的特征: ", features)
print("筛选出来最优的特征是: ", features[filter_1])

output

所有的特征:  ['sepal length (cm)' 'sepal width (cm)' 'petal length (cm)'
 'petal width (cm)']
筛选出来最优的特征是:  ['sepal length (cm)' 'petal length (cm)' 'petal width (cm)']

那么对于回归的问题而言,我们可以选择上面波士顿房价的例子,同理我们想要筛选出对于模型最佳的性能而言的7个特征变量,同时对于回归问题的评估指标用的是f_regression

boston_data = load_boston()
x = boston_data.data
y = boston_data.target

然后我们将拟合数据,并且进行特征变量的筛选

select_regression = SelectKBest(score_func=f_regression, k=7)
z = select_regression.fit_transform(x, y)

filter_2 = select_regression.get_support()
features_regression = array(boston_data.feature_names)
 
print("所有的特征变量有:")
print(features_regression)
 
print("筛选出来的7个特征变量则是:")
print(features_regression[filter_2])

output

所有的特征变量有:
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']
筛选出来的7个特征变量则是:
['CRIM' 'INDUS' 'NOX' 'RM' 'TAX' 'PTRATIO' 'LSTAT']

相关推荐

赶紧收藏!编程python基础知识,本文给你全部整理好了

想一起学习编程Python的同学,趁我粉丝少,可以留言、私信领编程资料~Python基础入门既然学习Python,那么至少得了解下这门编程语言,知道Python代码执行过程吧。Python的历...

创建绩效改进计划 (PIP) 的6个步骤

每个经理都必须与未能达到期望的员工抗衡,也许他们的表现下降了,他们被分配了新的任务并且无法处理它们,或者他们处理了自己的任务,但他们的行为对他人造成了破坏。许多公司转向警告系统,然后在这些情况下终止。...

PI3K/AKT信号通路全解析:核心分子、上游激活与下游效应分子

PI3K/AKT/mTOR(PAM)信号通路是真核细胞中高度保守的信号转导网络,作用于促进细胞存活、生长和细胞周期进程。PAM轴上生长因子向转录因子的信号传导受到与其他多条信号通路的多重交叉相互作用的...

互联网公司要求签PIP,裁员连N+1都没了?

2021年刚画上句号,令无数互联网公司从业者闻风丧胆的绩效公布时间就到了,脉脉上已然炸了锅。阿里3.25、腾讯二星、百度四挡、美团绩效C,虽然名称五花八门,实际上都代表了差绩效。拿到差绩效,非但不能晋...

Python自动化办公应用学习笔记3—— pip工具安装

3.1pip工具安装最常用且最高效的Python第三方库安装方式是采用pip工具安装。pip是Python包管理工具,提供了对Python包的查找、下载、安装、卸载的功能。pip是Python官方提...

单片机都是相通的_单片机是串行还是并行

作为一个七年的从业者,单片机对于我个人而言它是一种可编程的器件,现在长见到的电子产品中几乎都有单片机的身影,它们是以单片机为核心,根据不同的功能需求,搭建不同的电路,从8位的单片机到32位的单片机,甚...

STM32F0单片机快速入门八 聊聊 Coolie DMA

1.苦力DMA世上本没有路,走的人多了,便成了路。世上本没有DMA,需要搬运的数据多了,便有了DMA。大多数同学应该没有在项目中用过这个东西,因为一般情况下也真不需要这个东西。在早期的单片机中...

放弃51单片机,直接学习STM32开发可能会面临的问题

学习51单片机并非仅仅是为了学习51本身,而是通过它学习一种方法,即如何仅仅依靠Datasheet和例程来学习一种新的芯片。51单片机相对较简单,是这个过程中最容易上手的选择,而AVR单片机则更为复杂...

STM32串口通信基本原理_stm32串口原理图

通信接口背景知识设备之间通信的方式一般情况下,设备之间的通信方式可以分成并行通信和串行通信两种。并行与串行通信的区别如下表所示。串行通信的分类1、按照数据传送方向,分为:单工:数据传输只支持数据在一个...

单片机的程序有多大?_单片机的程序有多大内存

之前一直很奇怪一个问题,每次写好单片机程序之后,用烧录软件进行烧录时,能看到烧录文件也就是hex的文件大小:我用的单片机芯片是STM32F103C8T6,程序储存器(flash)只有64K。从...

解析STM32单片机定时器编码器模式及其应用场景

本文将对STM32单片机定时器编码器模式进行详细解析,包括介绍不同的编码器模式、各自的优缺点以及相同点和不同点的应用场景。通过阅读本文,读者将对STM32单片机定时器编码器模式有全面的了解。一、引言...

两STM32单片机串口通讯实验_两个32单片机间串口通信

一、实验思路连接两个STM32单片机的串口引脚,单片机A进行发送,单片机B进行接收。单片机B根据接收到单片机A的指令来点亮或熄灭板载LED灯,通过实验现象来验证是否通讯成功。二、实验器材两套STM32...

基于单片机的智能考勤机设计_基于51单片机的指纹考勤机

一、设计背景随着科技水平的不断发展,在这么一个信息化的时代,智能化信息处理已是提高效率、规范管理和客观审查的最有效途径。近几年来,国内很多公司都在加强对企业人员的管理,考勤作为企业的基础管理,是公司...

STM32单片机详细教学(二):STM32系列单片机的介绍

大家好,今天给大家介绍STM32系列单片机,文章末尾附有本毕业设计的论文和源码的获取方式,可进群免费领取。前言STM32系列芯片是为要求高性能、低成本、低功耗的嵌入式应用设计的ARMCortexM...

STM32单片机的 Hard-Fault 硬件错误问题追踪与分析

有过单片机开发经验的人应该都会遇到过硬件错误(Hard-Fault)的问题,对于这样的问题,有些问题比较容易查找,有些就查找起来很麻烦,甚至可能很久都找不到问题到底是出在哪里。特别是有时候出现一次,后...