热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

机器学习系列(4)_特征工程02特征提取

文章目录一、Filter过滤法1、方差过滤(1)使用KNN进行考察(2)使用随机森林(RFC)进行考察2、相关性过滤


文章目录

  • 一、Filter过滤法
    • 1、方差过滤
      • (1)使用KNN进行考察
      • (2)使用随机森林(RFC)进行考察
    • 2、相关性过滤
      • (1)卡方过滤
      • (2) 用随机森林进行比较特征选择
      • (3)选取超参数
      • (4)F检验
      • (5)互信息法
  • 二、Embedded嵌入法
  • 三、Wrapper包装法



数据预处理,特征选择的目的是改善数据质量,体现数据的本质特征,降低计算成本,提升模型的表现。

特征选择–主要分为三个模块:


  1. 特征提取(Features Extraction):如从文本型数据提取日期型数据;从非结构化数据(文本,视频,音频等)提取数据。如:Web爬取等;
  2. 特征创建(Features Creation):通过组合,计算等方法,得到原本不存在的特征(必须是合理的),比如:使用(数量*单价-折扣)得到销售额字段;
  3. 特征选择(Features Selection):从所有特征中,选择对当前模型有价值的特征,但必须要经过验证。
    特征选择是独立于任何机器学习算法的,往往是根据各种统计检验的分值以及相关性指标来选择特征。
  4. 特征选择与模型应用的基本流程:
    全部特征有哪些–》通过统计检验获取最佳特征子集(无创造新特征)–》通过算法进行训练–》模型评估–》模型应用

创造新特征:在数据整理的时候,

import pandas as pd
data=pd.read_csv("digit recognizor.csv")# 手写体数字特征提取

在这里插入图片描述

X=data.iloc[:,1:] # 前面的标签不要

在这里插入图片描述

y=data.iloc[:,0]
y.unique() # 想要知道每个数据上有多少数据

在这里插入图片描述

# 体现0-9共十个数字每个数字有多少个样本
a=data.groupby("label").count()

一、Filter过滤法


1、方差过滤

方差过滤:消除方差为0的数据。

为什么使用方差过滤?


  1. 方差用来衡量随机变量或数据的离散程度(统计),或者衡量随机变量与数学期望(如均值)之间的偏离程度。
  2. 方差小,表示样本在特征上基本无差异,这种情况对于样本区分的价值不高
  3. 消除方差为0的特征是特征工程的重要任务。使用threshold来进行筛选,默认为0。

在机器学习的数据预处理的过程中常常会是使用到过滤法,而方差过滤是过滤法之一。所谓的方差过滤就是过滤掉那些特征方差较小的特征。

比如一个特征本身的方差很小,就表示样本在这个特征上基本没有差异,可能特征中的大多数值都一样,甚至整个特征的取值都相同,那这个特征对于样本区分没有什么作用。

所以可以设置一个过滤的阈值,过滤掉那些方差小的特征,从而达到特征筛选的目的。
在 sklearn中可以调用from sklearn.feature_selection import VarianceThreshold 类实现方差过滤。



以手写识别为例子:
在这里插入图片描述

from sklearn.feature_selection import VarianceThreshold
selector=VarianceThreshold() # 实例化,默认方差为0
X_var0=selector.fit_transform(X) # 获取具有特定价值的新特征矩阵
X_var0.shape # 使用方差进行过滤时,过滤掉了80+的数据

在这里插入图片描述
在这里插入图片描述

import numpy as np
np.median(X.var().values)

# 以特征方差中位数为阈值,考察特征选择结果
X_fsvar=VarianceThreshold(np.median(X.var().values)).fit_transform(X)

在这里插入图片描述

# 若特征是伯努利的随机变量,假设p=0.8 :表示如果某一种分类站到80%以上时,要删除特征
X_bvar=VarianceThreshold(.8*(1-0.8)).fit_transform(X)
X_bvar.shape # (42000, 685) 大概消除了100个特征

from sklearn.feature_selection import VarianceThreshold
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.neighbors import KNeighborsClassifier as KNN
from sklearn.model_selection import cross_val_score # 交叉验证

利用KNN和随机森林对全部特征,和以方差中位数为阈值的特征进行比较:
在这里插入图片描述


(1)使用KNN进行考察

过滤:特征选择。
比较KNN在方差过滤前后的准确度:

# KNN在方差过滤之前
cross_val_score(KNN(),X,y,cv=5).mean() # 0.9658%%timeit # 计算运行时间
cross_val_score(KNN(),X,y,cv=5).mean()

# KNN在方差过滤之后
cross_val_score(KNN(),X_fsvar,y,cv=5).mean() # 0.966%%timeit # 计算运行时间
cross_val_score(KNN(),X_fsvar,y,cv=5).mean()

(2)使用随机森林(RFC)进行考察

# 随机森林考察特征选择效果
%%timeit
cross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()%%timeit
cross_val_score(RFC(n_estimators=10,random_state=0),X_fsvar,y,cv=5).mean()

使用方差过滤后的特征对KNN和RFC的影响:


  1. 对两种算法的检测结果,可看出其模型精度是上升的,说明方差过滤是有效的,即将随机模式设置为random——state=0之后大部分噪声都被过滤掉了。
  2. 阈值较小被过滤的特征也会更少,模型表现不同会受影响,运行时间总体会少,但有时不明显。
  3. 阈值较大被过滤的特征相对较多,模型表现可能会更好,因为噪声在某些算法下可能被过滤了,但也有可能是相反的,在运行时间方面肯定会降低。

tempdf=pd.DataFrame(X,y)
tempdf.reset_index(inplace=True)
tempdf

在这里插入图片描述
自定义函数:使用自定义函数提炼数据中两个特征之间的相关系数

#参考 自定义函数
import mathdef PearsonFirst(X,Y):'''公式一'''XY = X*YEX = X.mean()EY = Y.mean()EX2 = (X**2).mean()EY2 = (Y**2).mean()EXY = XY.mean()numerator = EXY - EX*EY # 分子denominator = math.sqrt(EX2-EX**2)*math.sqrt(EY2-EY**2) # 分母if denominator == 0:return 'NaN'rhoXY = numerator/denominatorreturn rhoXYdef PearsonSecond(X,Y):'''公式二'''XY = X*YX2 = X**2Y2 = Y**2n = len(XY)numerator = n*XY.sum() - X.sum()*Y.sum() # 分子denominator = math.sqrt(n*X2.sum() - X.sum()**2)*math.sqrt(n*Y2.sum() - Y.sum()**2) # 分母if denominator == 0:return 'NaN'rhoXY = numerator/denominatorreturn rhoXY

r1=PearsonFirst(tempdf['label'],tempdfempdf['pixel400']) # 使用公式一计算X与Y的相关系数
r2=PearsonFirst(tempdf['label'],tempdfempdf['pixel400']) # 使用公式二计算X与Y的相关系数
tempdf.corr(method="pearson") # 耗时太长,了解即可



2、相关性过滤

选出与标签相关且有意义的特征。


(1)卡方过滤


  1. 专门针对离散型的标签(分类问题,如0,1,2…),使用sklearn.feature_selection.chi2计算每个非负特征(标准化,归一化过程)和标签之间的卡方统计量。根据统计量进行排名,并结合sklearn.feature_selection.chi2输入评选标准来选择K个特征。
  2. 卡方检测中若检测到某特征中所有值都相同,会提示使用方差过滤法进行先行处理。
  3. 卡方过滤一般使用经过中位数参数方差过滤后的特征数据进行,但若模型表现下降,则使用无过滤的原数据。

from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.model_selection import cross_val_score #交叉验证
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2 #卡方

# 假设需要300个特征
X_fschi = SelectKBest(chi2, k=300).fit_transform(X_fsvar, y)
# 从使用中位数方差过滤后的特征中选择
X_fschi.shape

在这里插入图片描述
在这里插入图片描述


(2) 用随机森林进行比较特征选择

# 用随机森林进行比较特征选择
cross_val_score(RFC(n_estimators=20,random_state=0),X_fschi,y,cv=10).mean()

在这里插入图片描述
计算时间:
在这里插入图片描述


(3)选取超参数

k到底选择多大最合适?利用算法+学习曲线进行判断

# 选取超参数
%matplotlib inline
import matplotlib.pylab as plt
score=[]
for i in range(390,200,-10):X_fschi=SelectKBest(chi2,k=i).fit_transform(X_fsvar,y)once=cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()score.append(once)
plt.plot(range(390,200,-10),score)
plt.show()

如下图,最高大约在94%,因此K值大约选在380位置处。
在这里插入图片描述
对应score如下:
在这里插入图片描述

从特征工程的角度,选取卡方值较大,P值小于0.05的特征 ,即与标签有较大相关性。返回k值进行检验

chivalue,pyvalues_chi=chi2(X_fsvar,y) # 输入特征矩阵与标签
k=chivalue.shape[0]-(pyvalues_chi>0.05).sum() # 去除与标签无关的相关值
X_fschi=SelectKBest(chi2,k=k).fit_transform(X_fsvar,y)
cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean
# n_estimators=10 选取10颗树,使用RFC来进行交叉验证

k=chivalue.shape[0]-(pvalues_chi>0.05).sum() # 去除与标签无关的相关值
# 大于0.05表示与标签无关

在这里插入图片描述
求出K值,就可以用在下面的代码中:

X_fschi=SelectKBest(chi2,k=k).fit_transform(X_fsvar,y)
cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()

在这里插入图片描述
如果使用全特征呢?

# 如果使用全特征呢?
chivalue,pvalues_chi=chi2(X,y) # 输入特征矩阵和标签
k=chivalue.shape[0]-(pvalues_chi>0.05).sum() # 去除与标签无关的相关值
k

在这里插入图片描述
可以看到全特征计算出的K值更多:↑
在这里插入图片描述
但是准确度小于中位数特征值处理后的准确度:↑

总结卡方检验的作用:

推测两组数据之间的差异,原假设是:两组数据之间是相互独立的。返回卡方值和P值这两个统计量。


P值<0.05或者0.01>0.05或者0.01
数据差异差异不是自然形成的差异是自然形成的
相关性两组数据是相关的两组数据是相互独立的
原假设拒绝原假设接受原假设

从特征工程的角度&#xff0c;选取卡方值较大&#xff0c;P值小于0.05的特征&#xff0c;即与标签有较大相关性。返回K值进行检验。

调用SelectKBest之前&#xff0c;直接从chi2实例化后的模型中获得各个特征所对应的卡方值和P值。


&#xff08;4&#xff09;F检验


  1. F检验是用来捕捉每个特征与标签之间的线性关系的过滤方法。
  2. 可回归&#xff0c;可分类&#xff0c;故包含&#xff08;离散型变量feature_selection.f_classif&#xff09;和&#xff08;连续型变量feature_selection.f_regression&#xff09;两类。
  3. 需要与SelectKBest联合使用&#xff0c;即也需要有超参数
  4. 正态分布情况下效果稳定
  5. 原假设&#xff1a;数据之间不存在显著的线性关系。返回F和P值。小于0。05或者0.01代表显著性相关

from sklearn.feature_selection import f_classif
F,pvalues_f&#61;f_classif(X_fsvar,y)
F

在这里插入图片描述
P值当中存在大量的0&#xff1a;↓
在这里插入图片描述
接着求出K值后&#xff0c;代入随机森林当中做计算&#xff1a;
在这里插入图片描述

X_fsF&#61;SelectKBest(f_classif,k&#61;k).fit_transform(X_fsvar,y)
cross_val_score(RFC(n_estimators&#61;10,random_state&#61;0),X_fschi,y,cv&#61;5).mean()

在这里插入图片描述


&#xff08;5&#xff09;互信息法


  1. 两个随机变量的互信息&#xff08;mutual information&#xff09;是变量之间相互依赖性的量度
  2. 互信息度量是两个随机变量共享的信息——知道随机变量x,对随机变量Y的不确定性减少的程度&#xff08;或者知道随机变量Y&#xff0c;对随机变量X的不确定性减少的程度&#xff09;&#xff0c;用I&#xff08;X&#xff1a;Y&#xff09;表示
  3. 特征与标签之间可能存在任意关系&#xff08;线性和非线性&#xff09;
  4. 可回归&#xff0c;可分类&#xff0c;feature_selection.mutual_info_classif&#xff08;互信息分类&#xff09;和feature_selection.mutual_info_regression&#xff08;互信息回归&#xff09;
  5. 不返回P或者F&#xff0c;返回的是每个特征与目标特征之间互信息量的估计值&#xff0c;【0,1】之间取值

#X_fsvar 利用中位数取的特征&#xff0c;使用的是互信息法的方式
from sklearn.feature_selection import mutual_info_classif as MIC
result &#61; MIC(X_fsvar,y)
result

在这里插入图片描述

k &#61; result.shape[0] - sum(result <&#61; 0)
k

在这里插入图片描述
根据算出的K值&#xff0c;计算交叉验证得到的准确度&#xff1a;

X_fsmic &#61; SelectKBest(MIC, k&#61;k).fit_transform(X_fsvar, y)
cross_val_score(RFC(n_estimators&#61;10,random_state&#61;0),X_fsmic,y,cv&#61;5).mean()

在这里插入图片描述


二、Embedded嵌入法


  1. 嵌入法是一种让算法自己决定使用哪些特征的方法&#xff0c;即特征选择和算法训练同时进行。
  2. 先使用某些机器学习的算法和模型进行训练
  3. 得到各个特征的权值系数&#xff0c;根据权值系数从大到小选择特征
  4. 有别于过滤法的 “ 手工 ” 操作方式&#xff1a;过滤法使用统计量&#xff08;如P值&#xff09;&#xff0c;但嵌入法的权值系数没有参考临界值
  5. 应用feature_selection.SelectFromModel元变换器。可以与任何在拟合之后有coef_&#xff08;回归系数&#xff09;&#xff0c;feature_importances_属性或参数中可选惩罚项的评估器一起使用&#xff0c;如随机森林和树模型

在这里插入图片描述

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier as RFC
RFC_ &#61; RFC(n_estimators &#61;10,random_state&#61;0)
X_embedded &#61; SelectFromModel(RFC_,threshold&#61;0.005).fit_transform(X,y)
X_embedded.shape

在这里插入图片描述
在这里插入图片描述

# 模型的维度有没有降低&#xff1f;
#学习曲线来找最佳阈值import numpy as np
import matplotlib.pyplot as pltRFC_.fit(X,y).feature_importances_
threshold &#61; np.linspace(0,(RFC_.fit(X,y).feature_importances_).max(),20)
score &#61; []
for i in threshold:X_embedded &#61; SelectFromModel(RFC_,threshold&#61;i).fit_transform(X,y)once &#61; cross_val_score(RFC_,X_embedded,y,cv&#61;5).mean()score.append(once)
plt.plot(threshold,score)
plt.show()

在这里插入图片描述

将最高部分的学习曲线进行放大&#xff1a;

score2 &#61; []
for i in np.linspace(0,0.004,20):X_embedded &#61; SelectFromModel(RFC_,threshold&#61;i).fit_transform(X,y)once &#61; cross_val_score(RFC_,X_embedded,y,cv&#61;5).mean()score2.append(once)
plt.figure(figsize&#61;[20,5])
plt.plot(np.linspace(0,0.004,20),score2)
plt.xticks(np.linspace(0,0.004,20))
plt.show()

在这里插入图片描述


三、Wrapper包装法


  1. 特征选择与算法&#xff08;并非随机森林等&#xff09;训练同时进行&#xff0c;类似嵌入法
  2. 不同&#xff1a;使用目标函数作为黑盒帮助选取特征&#xff0c;而非自己输入某个评估指标或者统计量的阈值
  3. coef_或者feature_importances_属性获取每个特征的重要性
  4. 修建当前特征组中最不重要的特征&#xff0c;在修建的集合上递归重复该过程&#xff0c;直到最终达到所需数量的特征
  5. 要使用特征子集进行多次训练&#xff0c;计算成本较高&#xff0c;但其所选的特征是最有利于提升模型表现的

# 使用包装法
from sklearn.feature_selection import RFE
RFC_ &#61; RFC(n_estimators &#61;10,random_state&#61;0)
selector &#61; RFE(RFC_,n_features_to_select&#61;340,step&#61;50).fit(X,y)
selector.support_.sum()

selector.ranking_

在这里插入图片描述

X_wrapper&#61;selector.transform(X)
cross_val_score(RFC_,X_wrapper,y,cv&#61;5).mean()
# 使用sklearn的cross_val_score进行交叉验证

在这里插入图片描述

#调参 100
from sklearn.feature_selection import RFE
RFC_ &#61; RFC(n_estimators &#61;100,random_state&#61;0)
selector &#61; RFE(RFC_, n_features_to_select&#61;340, step&#61;50).fit(X, y) # 特征选择340个&#xff0c;每个步骤做50个参数的调整
selector.support_.sum()
selector.ranking_
X_wrapper &#61; selector.transform(X) # 通过包装法得到最优结果
cross_val_score(RFC_,X_wrapper,y,cv&#61;5).mean() # 使用交叉验证计算准确性

在这里插入图片描述

在这里插入图片描述


推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
author-avatar
无梗啦_671
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有