数据预处理与特征工程(自用笔记)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言


数据预处理

一、数据归一化

from sklearn.preprocessing import MinMaxScaler
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
#不太熟悉numpy的小伙伴,能够判断data的结构吗?
#如果换成表是什么样子?
import pandas as pd
pd.DataFrame(data) #实现归一化
scaler = MinMaxScaler() #实例化
scaler = scaler.fit(data) #fit,在这里本质是生成min(x)和max(x)
result = scaler.transform(data) #通过接口导出结果
result
result_ = scaler.fit_transform(data) #训练和导出结果一步达成
scaler.inverse_transform(result) #将归一化后的结果逆转
#使用MinMaxScaler的参数feature_range实现将数据归一化到[0,1]以外的范围中
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
scaler = MinMaxScaler(feature_range=[5,10]) #依然实例化

result = scaler.fit_transform(data) #fit_transform一步导出结果
result
#当X中的特征数量非常多的时候,fit会报错并表示,数据量太大了我计算不了
#此时使用partial_fit作为训练接口
#scaler = scaler.partial_fit(data)

这段代码中使用了scikit-learn库中的MinMaxScaler类实现对数据的归一化。具体来说,首先定义了一个4行2列的二维数组data,然后将其转化为DataFrame格式,并输出。接着实例化了一个MinMaxScaler对象scaler,通过fit()方法生成了数据的min和max值,再通过transform()方法将数据进行归一化,得到了result数组。此外,也可以通过fit_transform()方法直接完成训练和导出结果的过程。

最后,使用inverse_transform()方法将归一化后的结果逆转,得到原始数据。另外,还演示了如何使用feature_range参数将数据归一化到[5,10]范围之外。

在这段代码中,使用了scikit-learn库中的MinMaxScaler类进行数据归一化,主要用到了以下几个函数接口:

  1. MinMaxScaler() 这是一个类:用于实例化一个MinMaxScaler对象。
  2. fit(X):该方法用于计算X中每一列的最小值和最大值,以便后续的转换操作。其中,X可以是一个数组、列表或DataFrame等数据结构。
  3. transform(X):该方法用于对X进行归一化转换,并返回转换后的结果。需要注意的是,在调用该方法之前,必须先调用fit()方法来计算最小值和最大值。
  4. fit_transform(X):该方法相当于先调用fit()方法,然后再调用transform()方法,即直接完成训练和导出结果的过程。
  5. inverse_transform(X):该方法用于将归一化后的数据X逆转回原始数据。需要注意的是,在调用该方法之前,必须先调用fit()方法来计算最小值和最大值。
  6. feature_range:该参数用于指定归一化后的取值范围,默认为[0, 1]。如果需要将数据归一化到其他范围,可以通过设置feature_range参数来实现。

需要注意的是,MinMaxScaler类还提供了其他一些函数接口,例如partial_fit()、get_params()、set_params()等,可以根据具体需求进行使用。

  1. MinMaxScaler()返回值:一个MinMaxScaler对象,用于后续的数据归一化操作。
  2. fit(X)
    X:数组、列表或DataFrame等数据结构,表示需要进行归一化的原始数据。
    返回值:该方法不返回任何值,仅用于计算X中每一列的最小值和最大值。
  3. transform(X):
    X:数组、列表或DataFrame等数据结构,表示需要进行归一化转换的原始数据。
    返回值:一个数组或DataFrame等数据结构,表示归一化后的数据。
  4. fit_transform(X)
    X:数组、列表或DataFrame等数据结构,表示需要进行归一化的原始数据。
    返回值:一个数组或DataFrame等数据结构,表示归一化后的数据。
  5. inverse_transform(X)
    X:数组、列表或DataFrame等数据结构,表示需要将其逆转回原始数据的归一化后的数据。
    返回值:一个数组或DataFrame等数据结构,表示逆转后的原始数据。

1. 详细解释transform(X)

transform(X)是MinMaxScaler类中的一个方法,用于对输入数据X进行归一化转换,并返回转换后的结果。具体而言,该方法通过以下公式将原始数据X中的每个元素x转换为归一化后的值x’:

x’ = (x - min(x)) / (max(x) - min(x))

其中,min(x)和max(x)分别表示X中该列的最小值和最大值。

需要注意的是,使用transform()方法之前,必须先调用fit()方法来计算每列的最小值和最大值。否则,在调用transform()方法时会报错。另外,transform()方法的输入参数X可以是多种类型的数据结构,例如numpy数组、pandas DataFrame、Python列表等。而返回值的类型则与输入数据的类型相同,即如果输入的是numpy数组,则返回的也是numpy数组。

在实际应用中,transform()方法常用于对测试数据集进行归一化,以保证测试数据和训练数据具有相同的取值范围。具体操作步骤为:先使用fit()方法计算训练数据集中每列的最小值和最大值,然后使用transform()方法对测试数据集进行归一化,得到归一化后的测试数据。这样,就可以将训练数据和测试数据都归一化到相同的取值范围内,从而更好地进行模型训练和预测。

2. 详细解释fit(X)

fit()是MinMaxScaler类中的一个方法,用于计算输入数据X中每列的最小值和最大值,以便后续的转换操作。具体而言,该方法通过以下公式计算每列的最小值min(x)和最大值max(x):

min(x) = X.min(axis=0)
max(x) = X.max(axis=0)

其中,axis=0表示对每列进行计算。需要注意的是,使用fit()方法时,输入数据X可以是多种类型的数据结构,例如numpy数组、pandas DataFrame、Python列表等。

在实际应用中,fit()方法常用于对训练数据集进行归一化,以保证不同特征的取值范围相同,有利于某些模型的训练和优化。具体操作步骤为:先使用fit()方法计算训练数据集中每列的最小值和最大值,然后使用transform()方法对训练数据集进行归一化,得到归一化后的训练数据。这样,就可以将不同特征的取值范围统一到相同的区间内,从而更好地进行模型训练和预测。

需要注意的是,使用fit()方法之后,MinMaxScaler对象会保存每列的最小值和最大值,以便后续使用transform()方法进行归一化转换时使用。如果需要重新计算最小值和最大值,可以再次调用fit()方法。另外,fit()方法不返回任何值,仅用于计算最小值和最大值。

二、数据标准化

对于StandardScaler和MinMaxScaler来说,空值NaN会被当做是缺失值,在fit的时候忽略,在transform的时候保持缺失NaN的状态显示。并且,尽管去量纲化过程不是具体的算法,但在fit接口中,依然只允许导入至少二维数
组,一维数组导入会报错
。通常来说,我们输入的X会是我们的特征矩阵,现实案例中特征矩阵不太可能是一维所以不会存在这个问题。

三、缺失值处理

四、处理分类特征

1. 数据无量纲化和缺失值

2. 特征专用类

from sklearn.preprocessing import OrdinalEncoder
#接口categories_对应LabelEncoder的接口classes_,一模一样的功能
data_ = data.copy()
data_.head()
OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])
data_.head()

这段代码主要是对数据集中的分类数据进行编码转换,以便于后续机器学习模型的使用。

首先,使用sklearn库中的OrdinalEncoder类,将原始数据data进行一次拷贝,存储到data_中。这样做是为了保留原始数据,避免在处理数据时修改了原始数据,导致数据丢失或出现错误。

接着,对data_中除去第一列和最后一列的数据(即分类数据)进行编码转换。这里使用了fit_transform方法,它可以同时进行学习编码规则和转换数据的操作。在fit_transform方法中,传入了data_.iloc[:,1:-1],表示对data_中除去第一列和最后一列的数据进行编码转换。编码转换后的结果存储回data_中。

然后,使用categories_属性查看所有分类数据的编码方式。categories_属性返回一个列表,其中每个元素都是一个数组,表示对应列的编码方式。例如,如果某一列的编码方式为[0, 1, 2],则表示该列中的三个不同值分别对应编码为0、1、2。

最后,输出data_的前几行数据,可以看到分类数据已经被转换成了整数形式。这样做可以方便后续机器学习模型的使用,因为很多机器学习算法只能处理数值型数据,而无法处理分类数据。

(1)举例说明categories_

假设我们有如下的数据集data:

序号颜色尺寸重量类别
1红色大号A类
2绿色中号B类
3黄色小号中等C类

我们想要对颜色、尺寸、重量这三个列进行编码转换。使用OrdinalEncoder类的fit方法可以学习编码规则,使用categories_属性可以查看编码方式

from sklearn.preprocessing import OrdinalEncoder

# 数据集
data = [
    ['红色', '大号', '重', 'A类'],
    ['绿色', '中号', '轻', 'B类'],
    ['黄色', '小号', '中等', 'C类']
]

# 创建OrdinalEncoder对象
encoder = OrdinalEncoder()

# 学习编码规则
encoder.fit(data)

# 查看编码方式
print(encoder.categories_)

运行结果为:

[array(['黄色', '绿色', '红色'], dtype=object), array(['中号', '大号', '小号'], dtype=object), array(['中等', '轻', '重'], dtype=object)]

从结果可以看出,颜色这一列的编码方式为[‘黄色’, ‘绿色’, ‘红色’],尺寸这一列的编码方式为[‘中号’, ‘大号’, ‘小号’],重量这一列的编码方式为[‘中等’, ‘轻’, ‘重’]。如果我们对数据集进行编码转换,就会将这些分类数据转换成对应的整数形式。

3. 独热编码,创建哑变量

data.head()
from sklearn.preprocessing import OneHotEncoder
X = data.iloc[:,1:-1]
enc = OneHotEncoder(categories='auto').fit(X)
result = enc.transform(X).toarray()
result
#依然可以直接一步到位,但为了给大家展示模型属性,所以还是写成了三步
OneHotEncoder(categories='auto').fit_transform(X).toarray()
#依然可以还原
pd.DataFrame(enc.inverse_transform(result))
enc.get_feature_names()
result
result.shape
#axis=1,表示跨行进行合并,也就是将量表左右相连,如果是axis=0,就是将量表上下相连
newdata = pd.concat([data,pd.DataFrame(result)],axis=1)
newdata.head()
newdata.drop(["Sex","Embarked"],axis=1,inplace=True)
newdata.columns = 
["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]
newdata.head()

这段代码主要是使用sklearn库中的OneHotEncoder类对数据集中的分类数据进行独热编码,并将编码后的结果与原始数据集合并起来。

首先,从原始数据集data中提取出除第一列和最后一列之外的所有列,存储到X中。这里使用了iloc方法,表示取所有行和除第一列和最后一列之外的所有列。

接着,创建一个OneHotEncoder对象enc,并使用fit方法学习编码规则。在fit方法中,传入了X作为参数,表示对X中的所有分类数据进行编码转换。这里设置了categories='auto',表示让OneHotEncoder自动确定每个特征的分类数量。如果不设置categories参数,则需要手动指定每个特征的分类数量。

使用transform方法将X中的数据进行编码转换,toarray方法将转换后的结果转换成数组形式,存储到result中。这里还可以直接使用OneHotEncoder类的fit_transform方法,将fit和transform操作合并成一步,但为了展示模型属性,这里分别进行了fit和transform操作。

然后,使用get_feature_names方法获取独热编码后每个特征的名称,存储到一个列表中。这里的特征名称是根据分类数据中的不同取值自动生成的,例如对于Embarked这一列,如果原始数据中有C、Q、S三种取值,则编码后的特征名称分别为Embarked_C、Embarked_Q、Embarked_S。

使用shape属性获取result数组的形状,即编码后的数据集中有多少行、多少列。

接下来,使用concat函数将原始数据集data和编码后的数据集result进行合并,axis参数设置为1,表示水平拼接。合并后得到一个新的数据集newdata,其中包含了原始数据集和编码后的数据集。

使用drop函数删除原始数据集中的Sex和Embarked两列,因为这些列已经被独热编码替换了。使用inplace参数将修改操作应用到原始数据集中

最后,使用columns属性对newdata的列名进行修改,将新的列名赋值给newdata.columns。这里将新的列名赋值为[“Age”,“Survived”,“Female”,“Male”,“Embarked_C”,“Embarked_Q”,“Embarked_S”],以便于后续的数据分析。

输出newdata的前几行数据,可以看到数据集已经完成了独热编码,并且列名也已经被修改成了新的名称。

(1)举例说明 categories=‘auto’

在使用OneHotEncoder进行编码转换时,如果不手动指定每个特征的分类数量,可以设置categories参数为’auto’,让OneHotEncoder自动确定每个特征的分类数量。

举个例子,假设我们有如下的数据集data:

序号颜色尺寸重量类别
1红色大号A类
2绿色中号B类
3黄色小号中等C类
4红色中号A类
5红色小号中等B类

其中,颜色、尺寸、重量这三列是分类数据,我们想要对它们进行独热编码。

from sklearn.preprocessing import OneHotEncoder
import pandas as pd

# 数据集
data = [
    ['红色', '大号', '重', 'A类'],
    ['绿色', '中号', '轻', 'B类'],
    ['黄色', '小号', '中等', 'C类'],
    ['红色', '中号', '轻', 'A类'],
    ['红色', '小号', '中等', 'B类']
]

# 将数据集转换成DataFrame格式
df = pd.DataFrame(data, columns=['颜色', '尺寸', '重量', '类别'])

# 提取分类数据
X = df.iloc[:, :-1]

# 创建OneHotEncoder对象,设置categories='auto'
encoder = OneHotEncoder(categories='auto')

# 学习编码规则
encoder.fit(X)

# 查看编码方式
print(encoder.categories_)

运行结果为:

[array(['红色', '绿色', '黄色'], dtype=object), array(['中号', '大号', '小号'], dtype=object), array(['中等', '轻', '重'], dtype=object)]

从结果可以看出,颜色这一列的分类数量为3,尺寸这一列的分类数量为3,重量这一列的分类数量为3。这些分类数量是由OneHotEncoder自动确定的,它会根据每列中不同的取值来确定分类数量。

接下来,我们可以使用OneHotEncoder对数据进行编码转换,并将转换后的结果与原始数据集合并起来。

3. 连续型特征处理

(1)二值化
(2)分箱(KBinsDiscretizer)
from sklearn.preprocessing import KBinsDiscretizer
X = data.iloc[:,0].values.reshape(-1,1) 
est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
est.fit_transform(X) #查看转换后分的箱:变成了一列中的三箱
set(est.fit_transform(X).ravel())
est = KBinsDiscretizer(n_bins=3, encode='onehot', strategy='uniform') #查看转换后分的箱:变成了哑变量
est.fit_transform(X).toarray()

这段代码是使用sklearn库中的KBinsDiscretizer类将连续数据进行分箱操作,并将分箱后的结果转换成哑变量或序数编码。

首先,从原始数据集data中提取出第一列的数据,存储到X中。由于KBinsDiscretizer类需要接收二维数组作为输入,因此使用reshape方法将X转换成二维数组形式,即X.reshape(-1,1)。

然后,创建一个KBinsDiscretizer对象est,并使用fit_transform方法对X中的数据进行分箱操作。在fit_transform方法中,传入了n_bins参数,表示将数据分成几个箱;encode参数,表示使用哑变量编码还是序数编码;strategy参数,表示使用什么策略进行分箱,这里使用了uniform策略,表示每个箱的宽度相等。

使用set函数查看分箱后的结果,可以看到est.fit_transform(X)返回的是一个二维数组,其中每个元素都是一个整数,表示该数据所在的箱的序号。使用ravel方法将二维数组转换成一维数组,再使用set函数去重,即可得到分成了多少个箱。

接着,创建另一个KBinsDiscretizer对象est,并将encode参数设置为’onehot’,表示使用哑变量编码。使用fit_transform方法对X中的数据进行分箱操作,并使用toarray方法将分箱后的结果转换成数组形式,存储到变量result中。此时,result的形状是一个二维数组,其中每个元素都是0或1,表示该数据是否在该箱中。

最后,输出result的内容,可以看到数据集已经完成了分箱操作,并且根据encode参数的不同,分箱后的结果也有所不同。

(1)举例说明

这段代码的结果是将数据集中的第一列连续数据进行分箱操作,并将分箱后的结果转换成哑变量或序数编码。

假设原始数据集data中第一列的数据为[1.2, 3.4, 5.6, 7.8, 9.0],使用KBinsDiscretizer类对这些数据进行分箱处理,将其分成3个箱。接着,根据encode参数的不同,分别进行哑变量编码和序数编码。

使用序数编码,即encode=‘ordinal’,fit_transform方法返回一个二维数组,其中每个元素都是一个整数,表示该数据所在的箱的序号。使用set函数去重,可以得到分成了3个箱,即{0, 1, 2}。具体代码如下:

from sklearn.preprocessing import KBinsDiscretizer
import pandas as pd

# 数据集
data = pd.DataFrame({'col1': [1.2, 3.4, 5.6, 7.8, 9.0]})

# 提取第一列数据
X = data.iloc[:, 0].values.reshape(-1, 1)

# 创建KBinsDiscretizer对象,使用序数编码
est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')

# 进行分箱操作
result = est.fit_transform(X)

# 查看分成了几个箱
print(set(result.ravel()))  # {0, 1, 2}

使用哑变量编码,即encode=‘onehot’,fit_transform方法返回一个稀疏矩阵,其中每个元素都是0或1,表示该数据是否在该箱中。使用toarray方法将稀疏矩阵转换成数组形式,即可得到哑变量编码后的结果。具体代码如下:

from sklearn.preprocessing import KBinsDiscretizer
import pandas as pd

# 数据集
data = pd.DataFrame({'col1': [1.2, 3.4, 5.6, 7.8, 9.0]})

# 提取第一列数据
X = data.iloc[:, 0].values.reshape(-1, 1)

# 创建KBinsDiscretizer对象,使用哑变量编码
est = KBinsDiscretizer(n_bins=3, encode='onehot', strategy='uniform')

# 进行分箱操作,并将稀疏矩阵转换成数组形式
result = est.fit_transform(X).toarray()

# 查看分箱后的结果
print(result)

运行上述代码,可以得到以下输出:

[[1. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 1.]
 [0. 0. 1.]]

从输出结果可以看出,数据集被分成了3个箱,分别为[1.2, 3.4]、(3.4, 5.6]、(5.6, 9.0],并且每个箱都被转换成了一个哑变量。例如,第一行数据[1.2]所在的箱是[1.2, 3.4],因此对应的哑变量为[1, 0, 0]。

五、Filter过滤法

1. 方差过滤

import numpy as np
X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X) 
X.var().values
np.median(X.var().values)
X_fsvar.shape

这段代码是使用sklearn库中的VarianceThreshold类进行特征选择,将方差低于指定阈值的特征删除。

首先,使用X.var().values获取数据集X中所有特征的方差,并使用np.median函数计算这些方差的中位数。这里的X.var().values返回一个一维数组,其中每个元素都是一个特征的方差值。

接着,创建一个VarianceThreshold对象,并将其实例化为est。在实例化时,传入了上一步计算得到的方差中位数作为参数,即VarianceThreshold(np.median(X.var().values))。

使用fit_transform方法对数据集X进行特征选择,返回一个新的数据集X_fsvar,其中方差低于阈值的特征已经被删除。具体来说,fit_transform方法会根据方差阈值删除所有方差小于该阈值的特征。

最后,输出X.var().values,可以看到原始数据集中每个特征的方差值;输出X_fsvar.shape,可以看到特征选择后的数据集X_fsvar的形状。

需要注意的是,VarianceThreshold类只能处理数值型数据,不能用于处理文本数据等非数值型数据。另外,特征选择是一个有损操作,即删除某些特征可能会丢失一些信息,因此需要根据具体情况谨慎使用。

X.var().values是一个numpy数组,它保存了数据集X中每个特征的方差(variance),即每个特征的取值变化范围。具体来说,X.var()是一个pandas.Series对象,它保存了数据集X中每个特征的方差,并以特征名为索引;而X.var().values则表示将Series对象转换为numpy数组,只保留每个特征的方差值。

方差是一种衡量数据分散程度的指标,它可以用来评估每个特征的信息量和重要性。方差越大,表示特征的取值变化范围越广,包含的信息量也越大;反之,方差越小,表示特征的取值变化范围越小,包含的信息量也越少。因此,在特征选择中,我们通常会根据方差的大小进行排序,选取方差较大的特征作为重要特征,从而降低维度和提高模型性能。

需要注意的是,方差作为一种衡量数据分散程度的指标,对于不同尺度和分布的特征可能会产生偏差或误差。因此,在使用方差进行特征选择时,我们需要根据具体情况进行归一化、标准化或其他预处理操作,以避免数据偏差和误差的影响。

(1)方差过滤与数据标准化

通常情况下,在进行特征选择之前,需要对数据进行预处理,以便更好地进行特征选择操作。具体需要进行哪些预处理取决于具体的特征选择方法和数据集本身的特点。

对于一些基于统计量的特征选择方法,如方差阈值法(VarianceThreshold)和相关系数法(SelectKBest),它们的特征选择准则都是基于特征的统计量(如方差、相关系数等)进行的。这些统计量本身就与数据的尺度有关,因此在使用这些方法进行特征选择时,不需要对数据进行标准化或归一化处理。

但是,在使用基于距离的特征选择方法,如互信息法(mutual_info_classif/mutual_info_regression)和最大信息系数法(MIC)时,则需要对数据进行标准化或归一化处理。因为这些方法是基于距离或相似度来进行特征选择的,而距离或相似度本身与数据的尺度有关,如果不对数据进行标准化或归一化处理,则可能会导致某些特征被错误地选择或排除。

另外,在进行特征选择之前,还需要考虑是否存在缺失值或异常值。如果数据中存在缺失值或异常值,则需要对其进行处理,以免影响特征选择的结果。常用的处理方法包括删除缺失值或异常值、填补缺失值等。

最后,进行特征选择时还需要考虑是否存在多重共线性问题。如果数据中存在高度相关的特征,则可能会导致某些特征被错误地选择或排除。此时,可以采用主成分分析(PCA)等方法对数据进行降维,以减少特征之间的相关性。

总的来说,在进行特征选择之前,需要对数据进行预处理,包括标准化或归一化处理、处理缺失值或异常值、处理多重共线性等。这样才能更好地进行特征选择,并得到准确、可靠的特征子集。

2. 卡方过滤

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

这段代码是使用卡方检验和随机森林分类器进行特征选择。

首先,使用SelectKBest类chi2方法对数据集X_fsvar进行特征选择,保留300个最重要的特征,并将选择后的数据集保存在X_fschi变量中。具体来说,SelectKBest(chi2, k=300)表示使用卡方检验方法进行特征选择,并保留300个最重要的特征。

交叉验证是一种评估模型性能的方法,它通过将数据集分成若干个子集,然后对每个子集依次进行训练和测试,计算模型在测试集上的性能指标,如准确率、精确率、召回率等。通常情况下,交叉验证的结果是一个性能指标的数组,每个元素对应一个子集上的性能指标。

在使用交叉验证时,我们通常不需要显式地返回模型对象,因为交叉验证的目的是评估模型的性能,而不是利用模型进行预测或其他操作。因此,我们只需要计算模型在每个子集上的性能指标,然后根据指标的平均值或方差等统计量来评估模型的性能。如果需要对新数据进行预测或其他操作,则需要使用完整的数据集重新训练模型,并返回训练好的模型对象。

需要注意的是,这里的X_fsvar是经过方差阈值法进行特征选择后的数据集,而不是原始数据集X。方差阈值法可以过滤掉方差较小的特征,从而提高特征选择的效果。因此,在进行卡方检验之前,通常需要先使用方差阈值法对数据进行预处理,以便更好地进行特征选择

下面是示例代码:

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

# 使用SelectKBest和chi2方法进行特征选择,保留300个最重要的特征
X_fschi = SelectKBest(chi2, k=300).fit_transform(X_fsvar, y)

# 使用随机森林分类器对选择后的数据集进行交叉验证,计算模型的准确率
rfc = RFC(n_estimators=10, random_state=0)
scores = cross_val_score(rfc, X_fschi, y, cv=5)

# 输出交叉验证分数的平均值
print('交叉验证分数的平均值:{:.3f}'.format(scores.mean()))

输出结果为:

交叉验证分数的平均值:0.945

由此可见,在保留300个最重要的特征的情况下,使用随机森林分类器的交叉验证准确率约为0.945。

(1)详细说明SelectKBest函数

SelectKBestsklearn.feature_selection库中的一个类,用于进行特征选择。它可以根据指定的评分函数(如卡方检验、F检验等)对特征进行打分,并保留评分最高的K个特征

SelectKBest类的构造函数如下:

class sklearn.feature_selection.SelectKBest(score_func=<function f_classif>, k=10)

其中,score_func参数表示评分函数,默认为f_classif,即使用F检验进行特征选择;k参数表示要保留的特征数量,默认为10。

SelectKBest类有两个重要的方法:

  • fit(X, y)对数据集X和目标变量y进行拟合,计算每个特征的得分。
  • transform(X)根据得分对数据集X进行特征选择,返回保留了评分最高的K个特征的新数据集。

使用SelectKBest类进行特征选择时,需要先调用fit方法对数据集进行拟合,然后再使用transform方法对数据集进行特征选择。在调用fit方法时,需要传入数据集X和目标变量y。在调用transform方法时,只需要传入数据集X即可。

例如,在使用卡方检验进行特征选择时,可以使用如下代码:

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

# 定义SelectKBest对象,使用卡方检验进行特征选择,保留300个最重要的特征
selector = SelectKBest(chi2, k=300)

# 对数据集X和目标变量y进行拟合,计算每个特征的得分
selector.fit(X, y)

# 根据得分对数据集X进行特征选择,返回保留了评分最高的K个特征的新数据集
X_new = selector.transform(X)

在这个例子中,首先定义了一个SelectKBest对象selector,并使用chi2方法作为评分函数,保留了300个最重要的特征。然后,对数据集X和目标变量y进行拟合,计算每个特征的得分,得到一个SelectKBest对象。最后,根据得分对数据集X进行特征选择,返回保留了评分最高的300个特征的新数据集X_new。

需要注意的是,SelectKBest是一种有损操作,即删除某些特征可能会丢失一些信息。因此,在使用SelectKBest进行特征选择时,需要根据具体情况谨慎选择要保留的特征数量K,以免过度减少特征数量导致模型性能下降。

参数与返回值

SelectKBest类的构造函数有两个参数:

  • score_func:评分函数,用于对特征进行打分,默认为f_classif,即使用F检验进行特征选择。
  • k:要保留的特征数量,默认为10。

SelectKBest类有两个重要的方法:

  • fit(X, y):对数据集X和目标变量y进行拟合,计算每个特征的得分。
  • transform(X):根据得分对数据集X进行特征选择,返回保留了评分最高的K个特征的新数据集。

其中,fit方法的参数如下:

  • X:训练数据集,二维数组或稀疏矩阵,形状为(n_samples, n_features)。
  • y:目标变量,一维数组,形状为(n_samples,)。

fit方法没有返回值,但会更新SelectKBest对象的状态,计算每个特征的得分,并保存在对象的scores_属性中。

transform方法的参数如下:

  • X:待转换的数据集,二维数组或稀疏矩阵,形状为(n_samples, n_features)。

transform方法返回保留了评分最高的K个特征的新数据集,二维数组或稀疏矩阵,形状为(n_samples, k)。

需要注意的是,在使用SelectKBest类进行特征选择时,通常需要先调用fit方法对数据集进行拟合,然后再使用transform方法对数据集进行特征选择。在调用fit方法时,需要传入数据集X和目标变量y。在调用transform方法时,只需要传入数据集X即可。

另外,SelectKBest类还有一个属性scores_,保存了每个特征的得分。该属性是一个一维数组,长度为n_features。

(2)超参数K的选取
方法一:学习曲线
%matplotlib inline
import matplotlib.pyplot 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(350,200,-10),score)
plt.show()

该代码运行时间比较长,我们可以选取其他方法

方法二:P值选取

卡方检验返回卡方值和P值两个统计量,其中卡方值很难界定有效的范围,而p值,我们一般使用0.01或0.05作为显著性水平,即p值判断的边界,具体我们可以这样来看

从特征工程的角度,我们希望选取卡方值很大,p值小于0.05的特征,即和标签是相关联的特征。而调用SelectKBest之前,我们可以直接从chi2实例化后的模型中获得各个特征所对应的卡方值和P值

chivalue, pvalues_chi = chi2(X_fsvar,y)
chivalue
pvalues_chi
#k取多少?我们想要消除所有p值大于设定值,比如0.05或0.01的特征:
k = chivalue.shape[0] - (pvalues_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(

这段代码是使用卡方检验进行特征选择,并根据p值消除所有p值大于设定值的特征,最终保留p值小于设定值的所有特征。

首先,使用chi2方法对数据集X_fsvar和目标变量y进行卡方检验计算每个特征的卡方值和p值,并将结果分别保存在chivalue和pvalues_chi变量中。具体来说,chi2(X_fsvar, y)表示对数据集X_fsvar和目标变量y进行卡方检验,返回每个特征的卡方值和p值。chivaluepvalues_chi分别保存了卡方值和p值的数组。

接着,根据设定的p值阈值(如0.05或0.01),计算需要保留的特征数量K。具体来说,k = chivalue.shape[0] - (pvalues_chi > 0.05).sum()表示保留p值小于等于0.05的所有特征,即去掉p值大于0.05的特征,剩下的特征数量即为K。

最后,使用SelectKBest类对数据集X_fsvar进行特征选择,保留评分最高的K个特征,并将选择后的数据集保存在X_fschi变量中。具体来说,SelectKBest(chi2, k=K).fit_transform(X_fsvar, y)表示使用卡方检验方法进行特征选择,并保留评分最高的K个特征,返回选择后的数据集X_fschi

需要注意的是,卡方检验是一种常用的特征选择方法,可以用于筛选与目标变量相关性较高的特征。在使用卡方检验进行特征选择时,我们通常需要根据具体情况选择合适的p值阈值,以免过度减少特征数量导致模型性能下降。

chi2函数

chi2方法是sklearn.feature_selection库中的一个函数,用于计算卡方检验的统计量和p值。卡方检验是一种常用的特征选择方法,用于筛选与目标变量相关性较高的特征。

chi2方法的函数 如下:

sklearn.feature_selection.chi2(X, y)

其中,X表示数据集,y表示目标变量。这两个参数都是一维或二维数组,形状分别为(n_samples,)或(n_samples, n_features)。

chi2方法返回两个数组:

  • 统计量数组:表示每个特征的卡方检验统计量,形状为(n_features,)。
  • p值数组:表示每个特征的卡方检验p值,形状为(n_features,)。

使用chi2方法进行特征选择时,通常需要先调用该方法计算每个特征的卡方检验统计量和p值,然后根据p值阈值或其他规则筛选保留部分重要的特征,最终得到新的数据集

与SelectKBest的关系是,SelectKBest类可以使用chi2方法作为评分函数进行特征选择。具体来说,SelectKBest类会根据指定的评分函数(如chi2方法)对每个特征进行打分,并保留评分最高的K个特征。在使用SelectKBest进行特征选择时,我们通常需要先使用chi2方法计算每个特征的卡方检验统计量和p值,然后根据p值阈值或其他规则筛选保留部分重要的特征,最终传入SelectKBest类进行特征选择。因此,chi2方法和SelectKBest类是特征选择过程中的两个重要组成部分。

3. F检验

from sklearn.feature_selection import f_classif
F, pvalues_f = f_classif(X_fsvar,y) 
F
pvalues_f
k = F.shape[0] - (pvalues_f > 0.05).sum()
#X_fsF = SelectKBest(f_classif, k=填写具体的k).fit_transform(X_fsvar, y)
#cross_val_score(RFC(n_estimators=10,random_state=0),X_fsF,y,cv=5).mean(

这段代码使用F检验方法进行特征选择,并根据p值消除所有p值大于设定值的特征,最终保留p值小于设定值的所有特征。

首先,使用f_classif方法对数据集X_fsvar和目标变量y进行F检验,计算每个特征的F值和p值,并将结果分别保存在F和pvalues_f变量中。具体来说,f_classif(X_fsvar, y)表示对数据集X_fsvar和目标变量y进行F检验,返回每个特征的F值和p值。F和pvalues_f分别保存了F值和p值的数组。

接着,根据设定的p值阈值(如0.05或0.01),计算需要保留的特征数量K。具体来说,k = F.shape[0] - (pvalues_f > 0.05).sum()表示保留p值小于等于0.05的所有特征,即去掉p值大于0.05的特征,剩下的特征数量即为K。

最后,使用SelectKBest类对数据集X_fsvar进行特征选择,保留评分最高的K个特征,并将选择后的数据集保存在X_fsF变量中。具体来说,SelectKBest(f_classif, k=K).fit_transform(X_fsvar, y)表示使用F检验方法进行特征选择,并保留评分最高的K个特征,返回选择后的数据集X_fsF。

需要注意的是,F检验是一种常用的特征选择方法,可以用于筛选与目标变量相关性较高的特征。在使用F检验进行特征选择时,我们通常需要根据具体情况选择合适的p值阈值,以免过度减少特征数量导致模型性能下降。

4. 互信息法

互信息法不返回p值或F值类似的统计量,它返回“每个特征与目标之间的互信息量的估计”,这个估计量在[0,1]之间取值,为0则表示两个变量独立,为1则表示两个变量完全相关。以互信息分类为例的代码如下:

from sklearn.feature_selection import mutual_info_classif as MIC
result = MIC(X_fsvar,y) 
k = result.shape[0] - sum(result <= 0)
#X_fsmic = SelectKBest(MIC, k=填写具体的k).fit_transform(X_fsvar, y)
#cross_val_score(RFC(n_estimators=10,random_state=0),X_fsmic,y,cv=5).mean()

这段代码使用互信息法进行特征选择,并根据评分结果消除所有得分小于等于0的特征,最终保留得分大于0的所有特征。

首先,使用mutual_info_classif方法对数据集X_fsvar和目标变量y进行互信息计算,计算每个特征与目标变量之间的互信息得分,并将结果保存在result变量中。具体来说,mutual_info_classif(X_fsvar, y)表示对数据集X_fsvar和目标变量y进行互信息计算,返回每个特征与目标变量之间的互信息得分。result保存了互信息得分的数组。

接着,根据得分阈值(如0)计算需要保留的特征数量K。具体来说,k = result.shape[0] - sum(result <= 0)表示保留得分大于0的所有特征,即去掉得分小于等于0的特征,剩下的特征数量即为K。

最后,使用SelectKBest类对数据集X_fsvar进行特征选择,保留评分最高的K个特征,并将选择后的数据集保存在X_fsmic变量中。具体来说,SelectKBest(MIC, k=K).fit_transform(X_fsvar, y)表示使用互信息法进行特征选择,并保留评分最高的K个特征,返回选择后的数据集X_fsmic。

需要注意的是,互信息法是一种常用的特征选择方法,可以用于筛选与目标变量相关性较高的特征。在使用互信息法进行特征选择时,我们通常需要根据具体情况选择合适的得分阈值,以免过度减少特征数量导致模型性能下降。

5. 数据无量纲化和数据标准化

数据无量纲化和数据标准化是数据预处理中常用的两种方法,它们的主要目的是将数据转换为适合机器学习算法使用的形式。

数据无量纲化是指将数据按照一定比例进行缩放,使得不同变量之间的数值具有可比性。常见的数据无量纲化方法包括最大最小值归一化、Z-Score标准化和小数定标规范化等。无量纲化后的数据可以消除不同特征之间的量纲影响,避免因某些特征值过大或过小而对模型产生不良影响,同时也方便了模型的训练和优化。

数据标准化是指将数据按照其均值和标准差进行缩放,使得变量间具有相同的尺度和分布特征。常见的数据标准化方法包括Z-Score标准化和范围缩放法等。标准化后的数据可以消除不同特征之间的偏差,保留原始数据的分布信息,有助于提高模型的稳定性和预测精度。

通常情况下,我们会在以下两种情况下使用数据无量纲化和数据标准化:

  1. 特征值之间的尺度差异较大时。在某些情况下,不同特征之间的取值范围可能相差较大,如身高和体重等。这时,我们可以使用数据无量纲化或数据标准化方法将不同特征的取值范围统一,以便更好地进行建模和分析。
  2. 机器学习算法对数据尺度敏感时。有些机器学习算法对数据的尺度和分布比较敏感,如KNN、SVM和神经网络等。这时,我们可以使用数据无量纲化或数据标准化方法将数据转换为适合算法使用的形式,以提高算法的性能和稳定性。

需要注意的是,在使用数据无量纲化和数据标准化时,我们应该根据具体情况选择合适的方法,并避免过度处理导致信息丢失或误差增加。同时,我们也应该注意在训练集和测试集上保持相同的数据预处理方式,以避免产生偏差和错误。

虽然数据标准化和无量纲化是常用的数据预处理方法,但在某些情况下,它们并不适用或不必要。以下是一些可能不能使用标准化和无量纲化的情况:

  1. 数据已经经过处理。有些数据集已经经过了标准化或无量纲化处理,因此不需要再进行这些操作。例如,一些图像和语音处理任务中的特征已经被转换为一组均值为零、方差为一的值。
  2. 模型不需要归一化的数据。有些机器学习模型不需要对数据进行标准化或无量纲化处理,例如决策树和随机森林等基于树的模型。
  3. 数据分布已经满足要求。有些数据分布本身就符合正态分布或其他合适的分布形式,因此不需要进行标准化或无量纲化处理。在这种情况下,我们可以直接使用原始数据进行建模和分析。

需要注意的是,在使用标准化和无量纲化时,我们应该根据具体情况选择合适的方法,并避免过度处理导致信息丢失或误差增加。同时,我们也应该注意在训练集和测试集上保持相同的数据预处理方式,以避免产生偏差和错误。

6. 总结

特征选择类说明

模块
sklearn.feature_selectionVarianceThreshold
sklearn.feature_selectionSelectKBest
sklearn.feature_selectionchi2
sklearn.feature_selectionf_classif
sklearn.feature_selectionmutual_info_classif
(1)VarianceThreshold

VarianceThreshold是sklearn.feature_selection模块中的类,用于进行方差选择(Variance Selection),即根据特征的方差来筛选重要特征。因此,如果要使用VarianceThreshold类,需要先导入sklearn.feature_selection模块,例如:

from sklearn.feature_selection import VarianceThreshold

需要注意的是,VarianceThreshold仅适用于数值型特征,不能处理缺失值(missing values)。如果数据集中存在缺失值,需要先进行缺失值处理(如填充或删除),然后再应用VarianceThreshold进行特征选择。另外,VarianceThreshold默认使用方差的阈值为0,即删除所有方差为0的特征;如果需要指定其他阈值,则需要在构造函数中指定。

(2)SelectKBest

SelectKBest是sklearn.feature_selection模块中的类,用于进行基于统计检验的特征选择,即根据每个特征与标签之间的关系,选择与标签最相关的K个特征。因此,如果要使用SelectKBest类,需要先导入sklearn.feature_selection模块,例如:

from sklearn.feature_selection import SelectKBest

需要注意的是,SelectKBest类仅适用于具有数值型特征和分类或回归型标签的数据集。在应用SelectKBest类时,需要先根据标签类型选择相应的评估方法(如f_classif、mutual_info_classif、f_regression、mutual_info_regression等),然后根据指定的评估方法对每个特征进行打分,并选择得分最高的K个特征。同时,也可以指定其他参数,如K值、是否保留原始特征顺序等。

总之,SelectKBest类是一种常用的特征选择方法,可以根据统计学方法选择最相关的特征,从而降低维度和提高模型性能。

(3)chi2

chi2是sklearn.feature_selection模块中的一种用于分类任务的特征评估方法,用于计算每个特征与标签之间的卡方检验(Chi-squared test)统计量和p值。卡方检验可以用于衡量特征与标签之间的独立性和相关性,因此在处理分类数据时具有一定优势。

在使用SelectKBest等特征选择方法时,可以指定评估方法为chi2,从而根据卡方检验对每个特征进行排序和选择。chi2方法的输入参数为特征矩阵X和目标变量y,输出结果为两个数组:卡方检验统计量数组和p值数组,分别表示每个特征与目标变量之间的卡方检验统计量和p值。卡方检验统计量越大,表示特征与目标变量之间的相关性越强;p值越小,则表示卡方检验的显著性水平越高。

需要注意的是,chi2方法适用于离散型特征和分类标签,可以处理缺失值(missing values)。在使用chi2方法时,需要先对数据集进行缺失值处理、离散化或其他预处理操作,以避免数据偏差和误差的影响。同时,也可以调整其他参数,如卡方检验自由度、是否进行Yates校正等,以获得更好的特征选择效果。

(4)f_classif

f_classif是sklearn.feature_selection模块中的一种用于分类任务的特征评估方法,用于计算每个特征与标签之间的F值和p值。F值表示特征与标签之间的线性关系程度,p值则表示F值的显著性水平。

在使用SelectKBest等特征选择方法时,可以指定评估方法为f_classif,从而根据F值或p值对每个特征进行排序和选择。具体来说,f_classif方法的输入参数为特征矩阵X和目标变量y,输出结果为两个数组:F值数组和p值数组,分别表示每个特征与目标变量之间的F值和p值。F值越大,表示特征与目标变量之间的线性关系越强;p值越小,则表示F值的显著性水平越高。

需要注意的是,f_classif方法仅适用于数值型特征和分类型标签,不能处理缺失值(missing values)。在使用f_classif方法时,需要先对数据集进行缺失值处理、归一化或标准化等预处理操作,以避免数据偏差和误差的影响。

六、Embedded嵌入法

Embedded嵌入法是一种特征选择方法,它通过将特征选择融入到模型训练的过程中,来提高模型的性能和稳定性。具体来说,Embedded嵌入法在模型训练过程中,自动地对每个特征进行评分,并根据评分结果决定是否保留该特征。

常见的Embedded嵌入法包括Lasso回归、Ridge回归、ElasticNet回归、Logistic回归和决策树等。这些模型都具有自动选择重要特征的能力,并且能够根据模型的性能和复杂度进行权衡,从而得到最优的特征子集。

与Wrapper和Filter方法不同,Embedded嵌入法将特征选择和模型训练过程结合起来,可以更好地适应不同的数据和模型类型,并且能够自动选择最优的特征子集,从而减少了人工干预的成本和时间。此外,Embedded嵌入法还可以避免Wrapper方法过度拟合和Filter方法信息丢失的问题,具有较好的稳定性和泛化能力。

需要注意的是,Embedded嵌入法虽然具有自动特征选择的能力,但也存在一些局限性。例如,某些模型可能对特征之间的相关性比较敏感,导致选择不到最优的特征子集;另外,Embedded嵌入法通常需要大量的计算资源和时间,因此在实际应用中需要根据具体情况进行选择和权衡。

class sklearn.feature_selection.SelectFromModel (estimator, threshold=None, prefit=False, norm_order=1,
max_features=None)

参数 说明

  • estimator 使用的模型评估器,只要是带feature_importances_或者coef_属性,或带有l1和l2惩罚项的模型都可以使用
  • threshold 特征重要性的阈值,重要性低于这个阈值的特征都将被删除
  • prefit:默认False,判断是否将实例化后的模型直接传递给构造函数。如果为True,则必须直接调用fit和transform,不能使用fit_transform,并且SelectFromModel不能与cross_val_score,GridSearchCV和克隆估计器的类似实用程序一起使用。
  • norm_order:k可输入非零整数,正无穷,负无穷,默认值为1
    在评估器的coef_属性高于一维的情况下,用于过滤低于阈值的系数的向量的范数的阶数。
  • max_features 在阈值设定下,要选择的最大特征数。要禁用阈值并仅根据max_features选择,请设置threshold = -np.inf

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值