【超全】一文详解机器学习特征工程(附代码)

特征工程是使用专业背景知识和技巧处理数据,使得特征值(自变量)能在机器学习算法上发挥更好的作用的过程。python的sklearn库,对于特征工程的处理提供了强大的接口。

在本文中,我将详细介绍特征工程相关内容,喜欢记得收藏、关注、点赞。

【注】完整代码、数据、技术交流,文末见

内容目录

  • 特征抽取/提取:将任意数据(文本、图像等)转化为可以用作机器学习的数字特征。文本类型–>数值型;分类型数据(字符串)–>数值型;

  • 特征预处理

  • 特征降维

  • 数据探索

  • 数据集的划分

  • 训练集:70%-80%

  • 测试集:20%-30%

图片

1 特征抽取/提取

1.1 字典特征提取-类别->one-hot编码

sklearn.feature_extraction.DictVectorizer(sparse=True/False…)

  • sparse=True将输出从稀疏矩阵更改为numpy稠密矩阵

  • DictVectorizer.fit_transform(X) X:字典或者包含字典的迭代器返回值;返回sparse矩阵

  • DictVectorizer.inverse_transform(X) X:array数组或者sparse矩阵返回值;转换之前数据格式

  • DictVectorizer.get_feature_names() 返回类别名称

'''字典特征抽取取'''
from sklearn.feature_extraction import DictVectorizer
# 1、数据:字典或字典迭代器形式
data=[{
    
    "city":"北京","housing_price":250},
        {
    
    "city":"上海","housing_price":260},
        {
    
    "city":"广州","housing_price":200}]  #字典迭代器
# 2、实例化一个转换器类
transfer = DictVectorizer(sparse=True)
# 3、调用fit_transform()
data_new = transfer.fit_transform(data)
print(data_new)  #非0值的坐标,值
'''
  (0, 1) 1.0
  (0, 3) 250.0
  (1, 0) 1.0
  (1, 3) 260.0
  (2, 2) 1.0
  (2, 3) 200.0
'''
print(transfer.get_feature_names()) #返回类别名称
#['city=上海', 'city=北京', 'city=广州', 'housing_price']
# 2、实例化一个转换器类
transfer = DictVectorizer(sparse=False)
# 3、调用fit_transform()
data_new = transfer.fit_transform(data)
print(data_new)  #二维数组
'''
[[  0.   1.   0.  250.]
 [  1.   0.   0.  260.]
 [  0.   0.   1.  200.]]
'''
print(transfer.get_feature_names()) #返回类别名称
#['city=上海', 'city=北京', 'city=广州', 'housing_price']
print(transfer.inverse_transform(transfer.fit_transform(data))) 
#转化前的数据格式
'''
[{'city=北京': 1.0, 'housing_price': 250.0}, 
{'city=上海': 1.0, 'housing_price': 260.0}, 
{'city=广州': 1.0, 'housing_price': 200.0}]
'''

1.2 文本特征提取

单词、词语:作为特征值

方法1 CountVectorizer()、jieba分词库–统计出现次数

  • sklearn.feature_extraction.text.CountVectorizer(stop_words=[]),返回词语出现的次数,返回词频矩阵,stop_words=[]停用词列表

  • 中文文本的分词:需要借助jieba分词库

  • CountVectorizer.fit_transform(X)X:文本或者包含文本字符串的可迭代对象返回值:返回sparse矩降

  • CountVectorizer.inverse_transform(X)Xarray数组或者sparse矩阵返回值;转换之前数据格

  • CountVectorizer.get_feature_names() 返回值;单词列表

'''中文非严格的分词'''
import pandas as pd
import numpy as np
from  sklearn.feature_extraction.text import CountVectorizer
data=["Maybe it was better to just really enjoy life. this is the life",
      "享受生活,顺其自然。这就是生活"]
transfer = CountVectorizer() 
#实例化一个转换器类
data_new = transfer.fit_transform(data) 
#调用fit_transform()
#print(data_new)
print(transfer.get_feature_names())
#返回标题(即词语)
print(data_new.toarray())
#转化为数组
data=pd.DataFrame(data_new.toarray(),columns=transfer.get_feature_names())
#构建成一个二维表
display(data)
#输出二维表,行转列data.T
#其实发现中文的分词效果并不好,
#原因:分词原理,根据空格、标点符号等特殊字符切分

图片

'''借助jieba分词库的分词'''
import pandas as pd
import numpy as np
from  sklearn.feature_extraction.text import CountVectorizer
import jieba  #(jieba 分词,安装:pip install jieba)
 
data=[u'今年国庆节打算去海南岛度假',
      "享受生活,顺其自然。这就是美好的生活!",
     "Maybe it was better to just really enjoy life."]
#数据

'''jieba分词'''
cut_data=[]
for s in data:
    cut_s=jieba.cut(s)
    l_cut_s=' '.join(list(cut_s))
    cut_data.append(l_cut_s)
print(cut_data)
 
'''统计特征词出现次数'''
transfer = CountVectorizer(stop_words=["打算","就是"]) 
#实例化一个转换器类,
# stop_words=["打算","就是"],去除不想要的词
data_new = transfer.fit_transform(cut_data) 
#调用fit_transform()
#print(data_new)
print(transfer.get_feature_names())
print(data_new.toarray())
#构建成一个二维表:
data=pd.DataFrame(data_new.toarray(),columns=transfer.get_feature_names())
display(data)
# 优点1:自动去除单个字的连接词,如:去、的
# 优点2:自动去除标点符号
# 优点3:英文同样处理

图片

方法2 TfidfVectorizer()分词—统计词频*逆文档频率

  • TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。返回的值越高,找到这篇文章更为关键的词。

  • TF-IDF作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。图片

import pandas as pd
import numpy as np
from  sklearn.feature_extraction.text import TfidfVectorizer
import jieba  #(jieba 分词,安装:pip install jieba)
 
#数据
data=["移动共享,共享汽车,共享经济,共享单车",
      "财经栏目,财经政策,经济政策,共享经济"]
 
#分词
cut_data=[]
for s in data:
    cut_s=jieba.cut(s)
    l_cut_s=' '.join(list(cut_s))
    cut_data.append(l_cut_s)
print(cut_data)
 
#TF-IDF
transfer = TfidfVectorizer() 
#实例化一个转换器类
data_new = transfer.fit_transform(cut_data) 
#调用fit_transform()
#print(data_new)
print(transfer.get_feature_names())
print(data_new.toarray())
 
#构建成一个二维表:
data=pd.DataFrame(data_new.toarray(),columns=transfer.get_feature_names())
display(data) 

图片

2 特征预处理

通过一些转换函数将特征数据转换成更加适合算法模型的特征数据。包含内容:

  • 数值型数据的无量钢化:

  • 归一化:

  • 标准化:均值标准差

  • 为什么我们要进行归一化/标准化?

  • 特征的单位或大小相差较大,或某特征的方差相比其他的特征要大出几个数量级,容易影响(支配)目标结果,使得一些算法无法学习到其它的特征。

  • 异常值的影响(归一化先处理异常值):

  • 对于归一化来说:如果出现异常点,影响了最大值和最小值,那么结果显然会发生改变。

  • 对于标准化来说:如果出现异常点,由于具有一定数据量,少量的异常点对于平均值的影响并不大,从而方差改变较小。

  • 特征预处理API:

  • sklearn.preprocessing

2.1 归一化

归一化缺点:异常值(缺失等),如果最大值和最小值异常时不能处理图片

# 归一化处理
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler  
#归一化库
 
# 1.获取数据
df = pd.read_excel(r"D:\Case_data/data01.xlsx",sheel=0,encoding="utf-8")
# display(df.sample(3))
x = df.iloc[:,2:6]
display(x.head(3))
 
#2.实例化一个转换器类
transfer = MinMaxScaler(feature_range=(10,20)) #实例化一个转换器类
# feature_range=(10,20),设置归一化后的数据取值范围
 
#3.#调用fit_transform()
xi = transfer.fit_transform(x) 
#调用fit_transform()
print(xi)
 
#4、转化为二维表
data = pd.DataFrame(xi,columns=x.columns)
data["y"] = df['是否已婚']
display(data)

图片

2.2 标准化

标准化有效地避免了归一化的缺点(最大值和最小值带来的影响)

  • 标准化定义:通过对原始数据进行变换到均值为0,标准差为1的范围内。

  • 公式:均值标准差,作用于每列。

  • 特征预处理API:from sklearn.preprocessing import StandardScaler

# 标准化处理(转化为均值为0,标准差为1 附近的值)
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler  
#标准化库
 
# 1.获取数据
df = pd.read_excel(r"D:\Case_data/data01.xlsx",sheel=0,encoding="utf-8")
# display(df.sample(3))
x = df.iloc[:,2:6]
display(x.head(3))
 
#2.实例化一个转换器类
transfer = StandardScaler() #实例化一个转换器类
 
#3.#调用fit_transform()
xi = transfer.fit_transform(x) #调用fit_transform()
print(xi)
 
#4、转化为二维表
data = pd.DataFrame(xi,columns=x.columns)
data["y"] = df['是否已婚']
display(data.tail(10))

图片

3 特征降维处理

  • 概念:降维是指在某些限定条件下,降低随机变量(特征变量、自变量)个数,得到一组“不相关”主变量的过程。

  • 目的:降维得到的特征变量之间是不相关的,去除冗余特征变量。

  • 方法:特征选择、主成分分析

3.1 特征选择

数据中包含冗余或相关变量(或称特征、属性、指标等),旨在从原有特征中找出主要特征。

方法:

  • Filter(过滤式):主要探究特征本身特点、特征与特征、特征与目标值之间的关联

  • 方差选择法:低方差特征过滤,删除低方差的一些特征。特征方差小:某个特征多样本的值比较相近;特征方差大:某个特征很多样本的值都有差别。再结合方差的大小来考虑这个方式的角度。

  • 相关系数法:相关性高的特征变量进行降维,可以去除不重要特征变量或者从新构造新的特征变量(如:加权求和主成分分析降维度)

  • Embedded(嵌入式):算法自动选择特征(特征与目标值之间的关联)

  • 决策树:信息熵、信息增益

  • 正则化:L1、L2

  • 深度学习:卷积等

方差选择法的python模块:sklearn.feature_selection

#构造一组特征值数据
import numpy as np
import pandas as dp
from scipy import stats
np.random.seed(10)
# 先生成一个种子生成器,以后生成的随机数就是一样的,参数为任意数字
x1 = stats.norm.rvs(loc=5,scale=0.0,size=500) 
#均值为5,标准差为0.0的正态分布,随机随机生成500个样本
x2 = stats.t.rvs(10, size=500) 
#生成服从t分布,自由度为10的500个随机数(rvs生成随机数)
x3 = stats.norm.rvs(loc=1,scale=0.5,size=500) 
#均值为1,标准差为0.5的正态分布,随机随机生成500个样本
x4 = np.random.rand(500)
x5 = 10*x4+5 + stats.norm.rvs(loc=0,scale=0.0,size=500)  
#stats.norm.rvs(loc=0,scale=0.0,size=500)用来构造残差
x6 = -5*x2 +1 + stats.norm.rvs(loc=0,scale=0.0,size=500)
#暂时不构造目标值y
data = pd.DataFrame({
    
    "x1":x1,"x2":x2,"x3":x3,"x4":x4,"x5":x5,"x6":x6})
display(data.sample(5))

图片

from sklearn.feature_selection import VarianceThreshold
# 低方差特征过滤
data = data
#1、获取数据,上段代码构造的一组特征值数据data 

transfer = VarianceThreshold(threshold=0.25) 
#2.实例化一个转换器类
   #threshold=0.25:用来设置方差的阀值,这里<=0.25的返回False,
   # 方差的阈值根据实际业务需求设定,默认为0.0
xi = transfer.fit_transform(data) 
#3.#调用fit_transform()
print(xi,"\n",transfer.get_support())
#4.输出过滤后的特征变量
data01=data.iloc[:,transfer.get_support()]
display(data01.head(5))
#虽然x4是一组随机数,但方差<0.25,所以也被过滤掉了

图片

相关性选择

相关系数(-1,1)。相关性高的特征变量进行降维,可以去除不重要特征变量或者从新构造新的特征变量(如:加权求和主成分分析降维度) 方法:pearson、spearman、Kendall’s Tau。详细的在探索变量间关系时说过,直接看两个例子。

# pearson只能检验两组数据的相关性
from scipy.stats import pearsonr
import pandas as pd
 
#1.数据使用上段代码生成的data01
print("x2-->x3:",stats.pearsonr(data01['x2'],data01['x3']))
print("x2-->x5:",stats.pearsonr(data01['x2'],data01['x5']))
print("x2-->x6:",stats.pearsonr(data01['x2'],data01['x6']))
print("x3-->x5:",stats.pearsonr(data01['x3'],data01['x5']))
print("x3-->x6:",stats.pearsonr(data01['x3'],data01['x6']))
print("x5-->x6:",stats.pearsonr(data01['x5'],data01['x6']))
#返回线性相关度和P值,是不是感觉非常麻烦
'''
结果
x2-->x3: (-0.01, 0.79)  #不相关
x2-->x5: (0.045, 0.31)  #不相关
x2-->x6: (-1.0, 0.0)    #相关
x3-->x5: (-0.07, 0.085) #不相关
x3-->x6: (0.011, 0.791) #不相关
x5-->x6: (-0.045, 0.31) #不相关
'''
# spearman:等级相关系数(Ranked data)检验
from scipy.stats import spearmanr
import pandas as pd
correlation,pvalue=spearmanr(data01) 
#可以直接传入二维表

correlation= pd.DataFrame(correlation,index=data01.columns,columns=data01.columns)
#方便看可以构造为二维表
pvalue= pd.DataFrame(pvalue,index=data01.columns,columns=data01.columns)
display(correlation,pvalue)

图片

3.2 主成分分析

应用PCA实现特征的降维

  • 定义:高维数据转化为低维数据的过程,在此过程中可能会舍弃原有数据、创造新的变量。

  • 作用:使数据维散压缩,尽可能降低原数据的维数(复杂度),损失少量信息。

  • 应用:回归分析或者聚类分析当中。

APA:sklearn.decomposition.PCA(n_components=None),将数据分解为较低维数空间

  • n_components:

  • 小数:表示保留百分之多少的信息

  • 整数:减少到多少特征

  • PCA.fit_transform(X)X:numpy array格式的数据[n_samples,n_features]

  • 返回值:转换后指定维度的array

# 主成分分析,保留n.n% 的信息
from sklearn.decomposition import PCA
import pandas as pd
import numpy as np
 
# 1、数据:使用上面代码生成的data01
display(data01.head(3))

#2.实例化一个转换器类
transfer = PCA(n_components=0.9) #实例化一个转换器类
    # n_components: ·小数:表示保留百分之多少的信息 ·整数:减少到多少特征

#3.#调用fit_transform()
xi = transfer.fit_transform(data01) 
#调用fit_transform()
#查看构成新的几个变量,查看单个变量的方差贡献率
print(xi.shape,transfer.explained_variance_ratio_)  

#4.输出新构造出来的主成分变量
Fi=[ ]
for i in range(1,xi.shape[1]+1):
    F="F" + str(i)
    Fi.append(F)
data02 = pd.DataFrame(xi,columns=Fi)
display(data02.sample(5))

图片

4 特征工程之数据探索

数据探索的目的就是为了,在建立模型之前更好的理解数据结构,数据探索方法,可以看之前的文章

5 数据集的划分

  • 训练集:70%-80%

  • 测试集:20%-30%

  • 语法:x_train,x_test,y_train,y_test = model_selection.train_test_split(x,y,test_size=n,random_state=m)

  • 解释:x_train训练的特征值(自变量);x_test测试的特征值;y_train训练的目标值,y_test测试的目标值 = 划分函数(x特征值,y目标值,test_size=测试集比例,随机种子)

import numpy as np
import pandas as pd
import sklearn
#机器学习库
from sklearn import model_selection
#机器学习模型训练库
from sklearn import datasets 
#机器学习数据集库
df = sklearn.datasets.load_iris()
#iris:花的数据集
x_train,x_test,y_train,y_test=sklearn.model_selection.train_test_split(
        df.data, df.target,
        test_size=0.2, random_state=11)
print(x_train.shape,x_test.shape,y_train.shape,y_test.shape)

#二维表DataFrame数据类,先构建二维表
data=pd.DataFrame(df.data,columns=list(df["feature_names"]))
data["y"] = df.target
display(data.sample(5))
x=data[df["feature_names"]]
y=data["y"]
x_train,x_test,y_train,y_test=model_selection.train_test_split(
    x,y,test_size=0.2,random_state=11)
print(x_train.shape,x_test.shape,y_train.shape,y_test.shape)

图片特征工程做完以后才能有效地发现样本是否适合做建模(机器学习),然后选择机器学习合适的算法,及不断评估和调优。

推荐文章

技术交流

欢迎转载、收藏、有所收获点赞支持一下!

在这里插入图片描述

目前开通了技术交流群,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友

  • 方式①、发送如下图片至微信,长按识别,后台回复:加群;
  • 方式②、添加微信号:dkl88191,备注:来自CSDN
  • 方式③、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

长按关注

猜你喜欢

转载自blog.csdn.net/weixin_38037405/article/details/124232732