当前位置:   article > 正文

特征预处理_分位数变换

分位数变换

数值型特征无量纲

我们的数据一般都是有单位的,比如身高的单位有m,cm,这个无量纲化并不是说把m变成cm,而是说,无论是m还是cm,最后都会变成1,也就是没有了单位。

无量纲化使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化和归一化。

数据标准化的原因:

  • 某些算法要求样本具有零均值和单位方差;
  • 需要消除样本不同属性具有不同量级时的影响。
    • 归一化有可能提高精度;
      数量级的差异将导致量级较大的属性占据主导地位,从而与实际情况相悖(比如这时实际情况是值域范围小的特征更重要);
    • 数量级的差异将导致迭代收敛速度减慢;
      当使用梯度下降法寻求最优解时,很有可能走“之字型”路线(垂直等高线走),从而导致需要迭代很多次才能收敛;
    • 依赖于样本距离的算法对于数据的数量级非常敏感。

1.数据标准化(Standardization)

标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。

1)定义

基于原始数据的均值(mean)和标准差(standarddeviation)进行数据的标准化。将A的原始值x使用z-score标准化到x’。z-score标准化方法适用于属性A的最大值和最小值未知的情况,或有超出取值范围的离群数据的情况。

均值和标准差都是在样本集上定义的,而不是在单个样本上定义的。标准化是针对某个属性的,需要用到所有样本在该属性上的值。

2)优缺点

优点:

  • Z-Score最大的优点就是简单,容易计算,Z-Score能够应用于数值型的数据,并且不受数据量级的影响,因为它本身的作用就是消除量级给分析带来的不便。

缺点:

  • 估算Z-Score需要总体的平均值与方差,但是这一值在真实的分析与挖掘中很难得到,大多数情况下是用样本的均值与标准差替代;
  • Z-Score对于数据的分布有一定的要求,正态分布是最有利于Z-Score计算的;
  • Z-Score消除了数据具有的实际意义,A的Z-Score与B的Z-Score与他们各自的分数不再有关系,因此Z-Score的结果只能用于比较数据间的结果,数据的真实意义还需要还原原值;
  • 在存在异常值时无法保证平衡的特征尺度。
3)实现代码:
from sklearn.preprocessing import StandardScaler
#标准化,返回值为标准化后的数据
standardScaler  = StandardScaler().fit(X_train)
standardScaler.transform(X_train)
  • 1
  • 2
  • 3
  • 4

2.归一化

1)MinMax归一化

区间缩放法利用了边界值信息,将属性缩放到[0,1]。
实现代码

from sklearn.preprocessing import MinMaxScaler
#区间缩放,返回值为缩放到[0, 1]区间的数据
minMaxScaler  = MinMaxScaler().fit(X_train)
minMaxScaler.transform(X_train)
  • 1
  • 2
  • 3
  • 4

缺点:

  • 这种方法有一个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义;
  • MinMaxScaler对异常值的存在非常敏感。
2)MaxAbs归一化

单独地缩放和转换每个特征,使得训练集中的每个特征的最大绝对值将为1.0,将属性缩放到[-1,1]。它不会移动/居中数据,因此不会破坏任何稀疏性。

缺点:

  • 这种方法有一个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义;
  • MaxAbsScaler与先前的缩放器不同,绝对值映射在[0,1]范围内。
    在仅有正数据时,该缩放器的行为MinMaxScaler与此类似,因此也存在大的异常值。

实现代码

from sklearn.preprocessing import MaxAbsScaler
maxAbsScaler  = MaxAbsScaler().fit(X_train)
maxAbsScaler.transform(X_train)
  • 1
  • 2
  • 3

3.正态分布化(Normalization)

1)定义

正则化的过程是将每个样本缩放到单位范数(每个样本的范数为1),如果要使用如二次型(点积)或者其它核方法计算两个样本之间的相似性这个方法会很有用。

该方法是文本分类和聚类分析中经常使用的向量空间模型(Vector Space Model)的基础。

Normalization主要思想是对每个样本计算其p-范数,然后对该样本中每个元素除以该范数,这样处理的结果是使得每个处理后样本的p-范数(l1-norm,l2-norm)等于1。
实现代码

from sklearn.preprocessing import Normalizer
#归一化,返回值为归一化后的数据
normalizer  = Normalizer(norm='l2').fit(X_train)
normalizer.transform(X_train)
  • 1
  • 2
  • 3
  • 4

4.标准化与归一化对比

1)标准化与归一化的异同

相同点:
它们的相同点在于都能取消由于量纲不同引起的误差;都是一种线性变换,都是对向量X按照比例压缩再进行平移。

不同点:

  • 目的不同,归一化是为了消除纲量压缩到[0,1]区间;
    标准化只是调整特征整体的分布;
  • 归一化与最大,最小值有关;
    标准化与均值,标准差有关;
  • 归一化输出在[0,1]之间;
    标准化无限制。
2)什么时候用归一化?什么时候用标准化?
  • 如果对输出结果范围有要求,用归一化;
  • 如果数据较为稳定,不存在极端的最大最小值,用归一化;
  • 如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响。
3)归一化与标准化的应用场景
  • 在分类、聚类算法中,需要使用距离来度量相似性的时候(如SVM、KNN)、或者使用PCA技术进行降维的时候,标准化(Z-score standardization)表现更好;
  • 在不涉及距离度量、协方差计算、数据不符合正太分布的时候,可以使用第一种方法或其他归一化方法。
    比如图像处理中,将RGB图像转换为灰度图像后将其值限定在[0 255]的范围;
  • 基于树的方法不需要进行特征的归一化。
    例如随机森林,bagging与boosting等方法。
    如果是基于参数的模型或者基于距离的模型,因为需要对参数或者距离进行计算,都需要进行归一化。

一般来说,建议优先使用标准化。对于输出有要求时再尝试别的方法,如归一化或者更加复杂的方法。很多方法都可以将输出范围调整到[0, 1],如果我们对于数据的分布有假设的话,更加有效的方法是使用相对应的概率密度函数来转换。

除了上面介绍的方法外,还有一些相对没这么常用的处理方法:RobustScaler、PowerTransformer、QuantileTransformer和QuantileTransformer等。

数值型特征特征分箱(数据离散化)

离散化是数值型特征非常重要的一个处理,其实就是要将数值型数据转化成类别型数据。连续值的取值空间可能是无穷的,为了便于表示和在模型中处理,需要对连续值特征进行离散化处理。

分箱的重要性及其优势:

  • 离散特征的增加和减少都很容易,易于模型的快速迭代;
  • 稀疏向量内积乘法运算速度快,计算结果方便存储,容易扩展;
  • 离散化后的特征对异常数据有很强的鲁棒性;
    比如一个特征是年龄>30是1,否则0。
    如果特征没有离散化,一个异常数据“年龄300岁”会给模型造成很大的干扰;
  • 对于线性模型,表达能力受限;
    单变量离散化为N个后,每个变量有单独的权重,相当于模型引入了非线性,能够提升模型表达能力,加大拟合;
  • 离散化后可以进行特征交叉,由M+N个变量变为M*N个变量,进一步引入非线性,提升表达能力;
  • 特征离散化后,模型会更稳定;
    比如如果对用户年龄离散化,20-30作为一个区间,不会因为一个用户年龄长了一岁就变成一个完全不同的人。
    当然处于区间相邻处的样本会刚好相反,所以怎么划分区间是门学问;
  • 特征离散化以后,起到了简化了逻辑回归模型的作用,降低了模型过拟合的风险;
    可以将缺失作为独立的一类带入模型;
  • 将所有变量变换到相似的尺度上。

1.无监督分箱法

1)自定义分箱

自定义分箱,是指根据业务经验或者常识等自行设定划分的区间,然后将原始数据归类到各个区间中。

2)等距分箱

定义

按照相同宽度将数据分成几等份。

从最小值到最大值之间,均分为 N 等份, 这样, 如果 A,B 为最小最大值, 则每个区间的长度为 W=(B−A)/N , 则区间边界值为A+W,A+2W,….A+(N−1)W 。这里只考虑边界,每个等份里面的实例数量可能不等。

缺点是受到异常值的影响比较大

import pandas as pd
df = pd.DataFrame([[22,1],[13,1],[33,1],[52,0],[16,0],[42,1],[53,1],[39,1],[26,0],[66,0]],columns=['age','Y'])
df['age_bin_2'] = pd.cut(df['age'],3)  #新增一列存储等距划分的分箱特征
display(df)
# 输出
    age    Y    age_bin
0    22    1    (12.947, 30.667]
1    13    1    (12.947, 30.667]
2    33    1    (30.667, 48.333]
3    52    0    (48.333, 66.0]
4    16    0    (12.947, 30.667]
5    42    1    (30.667, 48.333]
6    53    1    (48.333, 66.0]
7    39    1    (30.667, 48.333]
8    26    0    (12.947, 30.667]
9    66    0    (48.333, 66.0]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
3)等频分箱

定义

将数据分成几等份,每等份数据里面的个数是一样的。
区间的边界值要经过选择,使得每个区间包含大致相等的实例数量。比如说 N=10 ,每个区间应该包含大约10%的实例。
实现程序

import pandas as pd
df = pd.DataFrame([[22,1],[13,1],[33,1],[52,0],[16,0],[42,1],[53,1],[39,1],[26,0],[66,0]],columns=['age','Y'])
df['age_bin_1'] = pd.qcut(df['age'],3) #新增一列存储等频划分的分箱特征
display(df)
# 输出
    age    Y    age_bin
0    22    1    (12.999, 26.0]
1    13    1    (12.999, 26.0]
2    33    1    (26.0, 42.0]
3    52    0    (42.0, 66.0]
4    16    0    (12.999, 26.0]
5    42    1    (26.0, 42.0]
6    53    1    (42.0, 66.0]
7    39    1    (26.0, 42.0]
8    26    0    (12.999, 26.0]
9    66    0    (42.0, 66.0]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
4)聚类分箱

定义

基于k均值聚类的分箱:k均值聚类法将观测值聚为k类,但在聚类过程中需要保证分箱的有序性:第一个分箱中所有观测值都要小于第二个分箱中的观测值,第二个分箱中所有观测值都要小于第三个分箱中的观测值,等等。

实现步骤

  • Step 0:
    对预处理后的数据进行归一化处理;
  • Step 1:
    将归一化处理过的数据,应用k-means聚类算法,划分为多个区间:
    采用等距法设定k-means聚类算法的初始中心,得到聚类中心;
  • Step 2:
    在得到聚类中心后将相邻的聚类中心的中点作为分类的划分点,将各个对象加入到距离最近的类中,从而将数据划分为多个区间;
  • Step 3:
    重新计算每个聚类中心,然后重新划分数据,直到每个聚类中心不再变化,得到最终的聚类结果。
    实现代码
from sklearn.cluster import KMeans
kmodel=KMeans(n_clusters=k)  #k为聚成几类
kmodel.fit(data.reshape(len(data),1))) #训练模型
c=pd.DataFrame(kmodel.cluster_centers_) #求聚类中心
c=c.sort_values(by=’列索引') #排序  
w=pd.rolling_mean(c,2).iloc[1:] #用滑动窗口求均值的方法求相邻两项求中点,作为边界点
w=[0] +list(w[0] + [ data.max() ]  #把首末边界点加上
d3= pd.cut(data,w,labels=range(k)) #cut函数
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
5)二值化(Binarization)

定义

二值化可以将数值型(numerical)的feature进行阀值化得到boolean型数据。这对于下游的概率估计来说可能很有用(比如:数据分布为Bernoulli分布时)。
实现代码

from sklearn.preprocessing import Binarizer
# Binarizer函数也可以设定一个阈值,结果数据值大于阈值的为1,小于阈值的为0
binarizer = Binarizer(threshold=0.0).fit(X_train)
binarizer.transform(X_train)
  • 1
  • 2
  • 3
  • 4

2.有监督分箱法

1)卡方分箱法

定义

自底向上的(即基于合并的)数据离散化方法。它依赖于卡方检验:具有最小卡方值的相邻区间合并在一起,直到满足确定的停止准则。

基本思想

对于精确的离散化,相对类频率在一个区间内应当完全一致。因此,如果两个相邻的区间具有非常类似的类分布,则这两个区间可以合并;否则,它们应当保持分开。而低卡方值表明它们具有相似的类分布。

实现步骤

  • Step 0:
    预先定义一个卡方的阈值;
  • Step 1:
    初始化;

根据要离散的属性对实例进行排序,每个实例属于一个区间;

  • Step 2:
  • 合并区间;
    • 计算每一对相邻区间的卡方值;
    • 将卡方值最小的一对区间合并;

阈值的意义

类别和属性独立时,有90%的可能性,计算得到的卡方值会小于4.6。大于阈值4.6的卡方值就说明属性和类不是相互独立的,不能合并。如果阈值选的大,区间合并就会进行很多次,离散后的区间数量少、区间大。

注意

  • ChiMerge算法推荐使用0.90、0.95、0.99置信度,最大区间数取10到15之间;
  • 也可以不考虑卡方阈值,此时可以考虑最小区间数或者最大区间数。
    指定区间数量的上限和下限,最多几个区间,最少几个区间;
  • 对于类别型变量,需要分箱时需要按照某种方式进行排序。
    实现代码

2)最小熵法分箱

需要使总熵值达到最小,也就是使分箱能够最大限度地区分因变量的各类别。

熵是信息论中数据无序程度的度量标准,提出信息熵的基本目的是找出某种符号系统的信息量和冗余度之间的关系,以便能用最小的成本和消耗来实现最高效率的数据存储、管理和传递。
数据集的熵越低,说明数据之间的差异越小,最小熵划分就是为了使每箱中的数据具有最好的相似性。给定箱的个数,如果考虑所有可能的分箱情况,最小熵方法得到的箱应该是具有最小熵的分箱。

总结

  1. 特征预处理是数据预处理过程的重要步骤,是对数据的一个的标准的处理,几乎所有的数据处理过程都会涉及该步骤。
  2. 我们对特征进行分箱后,需要对分箱后的每组(箱)进行woe编码和IV值的计算,通过IV值进行变量筛选后,然后才能放进模型训练。
  3. 分箱后需要进行特征编码,如:
    LabelEncode、OneHotEncode或LabelBinarizer等。

统计变换

数据分布的倾斜有很多负面的影响。我们可以使用特征工程技巧,利用统计或数学变换来减轻数据分布倾斜的影响。使原本密集的区间的值尽可能的分散,原本分散的区间的值尽量的聚合。

这些变换函数都属于幂变换函数簇,通常用来创建单调的数据变换。它们的主要作用在于它能帮助稳定方差,始终保持分布接近于正态分布并使得数据与分布的平均值无关。

1.Log变换

1)定义

Log变换通常用来创建单调的数据变换。它的主要作用在于帮助稳定方差,始终保持分布接近于正态分布并使得数据与分布的平均值无关。

Log 变换属于幂变换函数簇。该函数用数学表达式表示为

y = \log_b(x)
  • 1

自然对数使用 b=e,e=2.71828,通常叫作欧拉常数。你可以使用通常在十进制系统中使用的 b=10 作为底数。

当应用于倾斜分布时 Log 变换是很有用的,因为Log变换倾向于拉伸那些落在较低的幅度范围内自变量值的范围,倾向于压缩或减少更高幅度范围内的自变量值的范围。从而使得倾斜分布尽可能的接近正态分布。

2)作用

针对一些数值连续特征的方差不稳定,特征值重尾分布我们需要采用Log化来调整整个数据分布的方差,属于方差稳定型数据转换。比如在词频统计中,有些介词的出现数量远远高于其他词,这种词频分布的特征就会现有些词频特征值极不协调的状况,拉大了整个数据分布的方差。这个时候,可以考虑Log化。尤其在分本分析领域,时间序列分析领域,Log化非常常见, 其目标是让方差稳定,把目标关注在其波动之上。

代码示例

numeric_subset['log_' + col] = np.log(numeric_subset[col])
  • 1

2.Box-Cox变换

1)定义

Box-Cox 变换是另一个流行的幂变换函数簇中的一个函数。该函数有一个前提条件,即数值型值必须先变换为正数(与 log 变换所要求的一样)。万一出现数值是负的,使用一个常数对数值进行偏移是有帮助的。

2)作用

Box-Cox变换是Box和Cox在1964年提出的一种广义幂变换方法,是统计建模中常用的一种数据变换,用于连续的响应变量不满足正态分布的情况。Box-Cox变换之后,可以一定程度上减小不可观测的误差和预测变量的相关性。Box-Cox变换的主要特点是引入一个参数,通过数据本身估计该参数进而确定应采取的数据变换形式,Box-Cox变换可以明显地改善数据的正态性、对称性和方差相等性,对许多实际数据都是行之有效的。
4)实现代码

import scipy.stats as spstats
# 从数据分布中移除非零值
income = np.array(fcc_survey_df['Income'])
income_clean = income[~np.isnan(income)]
# 计算最佳λ值
l, opt_lambda = spstats.boxcox(income_clean)
print('Optimal lambda value:', opt_lambda)

# 进行Box-Cox变换
fcc_survey_df['Income_boxcox_lambda_opt'] = spstats.boxcox(fcc_survey_df['Income'],lmbda=opt_lambda)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

from sklearn.preprocessing import PowerTransformer
bc = PowerTransformer(method='box-cox')
bc.fit(X_train).transform(X_test)
  • 1
  • 2
  • 3

Yeo-Johnson变换

Yeo-Johnson变换(Yeo-Johnson transformation)或“Yeo-Johnson幂变换(Yeo-Johnson power transformation)”是幂变换(power transformation)的方法之一,通过构建一组单调函数对随机变量进行数据变换 。

Yeo-Johnson变换具有幂变换的一般性质,能够减小随机变量的异方差性(heteroscedasticity)并放大其正态性(normality),使其概率密度函数的形态向正态分布靠近 。Yeo-Johnson变换的特点在于其可被应用于包含0值和负值的样本中,因此其也被认为是Box-Cox变换在实数域的推广

Yeo-Johnson变换作为数据标准化的方法之一被应用于数据挖掘和机器学习的数据预处理阶段。当随机变量正态性较差时,对其使用Yeo-Johnson变换进行预处理,有利于对该随机变量进行基于正态假设的统计分析

实现代码

from sklearn.preprocessing import PowerTransformer
yj = PowerTransformer(method='yeo-johnson')
yj.fit(X_train).transform(X_test)
  • 1
  • 2
  • 3

分位数变换

实现代码

from sklearn.preprocessing import QuantileTransformer
qt = QuantileTransformer(n_quantiles=500, output_distribution='normal',
                         random_state=rng)
qt.fit(X_train).transform(X_test)

  • 1
  • 2
  • 3
  • 4
  • 5

1

分类特征(类别特征)编码

在统计学中,分类特征是可以采用有限且通常固定数量的可能值之一的变量,基于某些定性属性将每个个体或其他观察单元分配给特定组或名义类别。

1.标签编码(LabelEncode)

1)定义

LabelEncoder是对不连续的数字或者文本进行编号,编码值介于0和n_classes-1之间的标签。

2)优缺点

优点:相对于OneHot编码,LabelEncoder编码占用内存空间小,并且支持文本特征编码。

缺点:它隐含了一个假设:不同的类别之间,存在一种顺序关系。在具体的代码实现里,LabelEncoder会对定性特征列中的所有独特数据进行一次排序,从而得出从原始输入到整数的映射。所以目前还没有发现标签编码的广泛使用,一般在树模型中可以使用。
例如:比如有[dog,cat,dog,mouse,cat],我们把其转换为[1,2,1,3,2]。这里就产生了一个奇怪的现象:dog和mouse的平均值是cat。

3)实现代码
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(["paris", "paris", "tokyo", "amsterdam"])

print('特征:{}'.format(list(le.classes_)))
# 输出 特征:['amsterdam', 'paris', 'tokyo']

print('转换标签值:{}'.format(le.transform(["tokyo", "tokyo", "paris"])))
# 输出 转换标签值:array([2, 2, 1]...)

print('特征标签值反转:{}'.format(list(le.inverse_transform([2, 2, 1]))))
# 输出 特征标签值反转:['tokyo', 'tokyo', 'paris']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.独热编码(OneHotEncode)

1)定义

OneHotEncoder用于将表示分类的数据扩维。最简单的理解就是与位图类似,设置一个个数与类型数量相同的全0数组,每一位对应一个类型,如该位为1,该数字表示该类型。

OneHotEncode只能对数值型变量二值化,无法直接对字符串型的类别变量编码。

2)为什么要使用独热编码

独热编码是因为大部分算法是基于向量空间中的度量来进行计算的,为了使非偏序关系的变量取值不具有偏序性,并且到圆点是等距的。使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用one-hot编码,会让特征之间的距离计算更加合理。

为什么特征向量要映射到欧式空间?
将离散特征通过one-hot编码映射到欧式空间,是因为,在回归、分类、聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算。

3)例子

假如有三种颜色特征:红、黄、蓝。

在利用机器学习的算法时一般需要进行向量化或者数字化。那么你可能想令 红=1,黄=2,蓝=3。那么这样其实实现了标签编码,即给不同类别以标签。然而这意味着机器可能会学习到“红<黄<蓝”,但这并不是我们的让机器学习的本意,只是想让机器区分它们,并无大小比较之意。

所以这时标签编码是不够的,需要进一步转换。因为有三种颜色状态,所以就有3个比特。即红色:1 0 0 ,黄色: 0 1 0,蓝色:0 0 1 。如此一来每两个向量之间的距离都是根号2,在向量空间距离都相等,所以这样不会出现偏序性,基本不会影响基于向量空间度量算法的效果。

4)优缺点

优点:独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。

缺点:当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA来减少维度。而且one hot encoding+PCA这种组合在实际中也非常有用。

5)实现代码

使用sklearn实现
注:当特征是字符串类型时,需要先用 LabelEncoder() 转换成连续的数值型变量,再用 OneHotEncoder() 二值化 。

from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])    # fit来学习编码
enc.transform([[0, 1, 3]]).toarray()    # 进行编码
# 输出:array([[ 1., 0., 0., 1., 0., 0., 0., 0., 1.]])
  • 1
  • 2
  • 3
  • 4
  • 5

使用pandas实现

import pandas as pd
import numpy as np

sex_list = ['MALE', 'FEMALE', np.NaN, 'FEMALE', ]
df = pd.DataFrame({'SEX': sex_list})
display(df)
# 输出
    SEX
0    MALE
1    FEMALE
2    NaN
3    FEMALE

df = pd.get_dummies(df['SEX'],prefix='IS_SEX')
display(df)
# 输出
    IS_SEX_FEMALE    IS_SEX_MALE
0    0               1
1    1               0
2    0               0
3    1               0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3.标签二值化(LabelBinarizer)

1)定义

功能与OneHotEncoder一样,但是OneHotEncode只能对数值型变量二值化,无法直接对字符串型的类别变量编码,而LabelBinarizer可以直接对字符型变量二值化。

2)实现代码
from sklearn.preprocessing import LabelBinarizer
lb = LabelBinarizer()
lb.fit([1, 2, 6, 4, 2])

print(lb.classes_)
# 输出 array([1, 2, 4, 6])

print(lb.transform([1, 6]))
# 输出 array([[1, 0, 0, 0],
             [0, 0, 0, 1]])

print(lb.fit_transform(['yes', 'no', 'no', 'yes']))
# 输出 array([[1],
             [0],
             [0],
             [1]])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

4.多标签二值化(MultiLabelBinarizer)

1)定义

用于label encoding,生成一个(n_examples * n_classes)大小的0~1矩阵,每个样本可能对应多个label。

2)适用情况
  • 每个特征中有多个文本单词;

用户兴趣特征(如特征值:
”健身 电影 音乐”)适合使用多标签二值化,因为每个用户可以同时存在多种兴趣爱好。

  • 多分类类别值编码的情况。
    电影分类标签中(如:
    [action, horror]和[romance, commedy])需要先进行多标签二值化,然后使用二值化后的值作为训练数据的标签值。
3)实现代码
from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()
print(mlb.fit_transform([(1, 2), (3,)]))
# 输出
array([[1, 1, 0],
       [0, 0, 1]])

print(mlb.classes_)
# 输出:array([1, 2, 3])

print(mlb.fit_transform([{'sci-fi', 'thriller'}, {'comedy'}]))
# 输出:array([[0, 1, 1],
       [1, 0, 0]])

print(list(mlb.classes_))
# 输出:['comedy', 'sci-fi', 'thriller']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

5.平均数编码(Mean Encoding)

1)定义

平均数编码(mean encoding),针对高基数类别特征的有监督编码。当一个类别特征列包括了极多不同类别时(如家庭地址,动辄上万)时,可以采用。

平均数编码(mean encoding)的编码方法,在贝叶斯的架构下,利用所要预测的应变量(target variable),有监督地确定最适合这个定性特征的编码方式。在Kaggle的数据竞赛中,这也是一种常见的提高分数的手段。

算法原理详情可参考:平均数编码:针对高基数定性特征(类别特征)的数据预处理/特征工程。

2)为什么要用平均数编码

如果某一个特征是定性的(categorical),而这个特征的可能值非常多(高基数),那么平均数编码(mean encoding)是一种高效的编码方式。在实际应用中,这类特征工程能极大提升模型的性能。

因为定性特征表示某个数据属于一个特定的类别,所以在数值上,定性特征值通常是从0到n的离散整数。例子:花瓣的颜色(红、黄、蓝)、性别(男、女)、地址、某一列特征是否存在缺失值(这种NA 指示列常常会提供有效的额外信息)。

一般情况下,针对定性特征,我们只需要使用sklearn的OneHotEncoder或LabelEncoder进行编码,这类简单的预处理能够满足大多数数据挖掘算法的需求。定性特征的基数(cardinality)指的是这个定性特征所有可能的不同值的数量。在高基数(high cardinality)的定性特征面前,这些数据预处理的方法往往得不到令人满意的结果。

3)优点

和独热编码相比,节省内存、减少算法计算时间、有效增强模型表现。

4)实现代码
MeanEnocodeFeature = ['item_city_id','item_brand_id'] #声明需要平均数编码的特征
ME = MeanEncoder(MeanEnocodeFeature) #声明平均数编码的类
trans_train = ME.fit_transform(X,y)#对训练数据集的X和y进行拟合
test_trans = ME.transform(X_test)#对测试集进行编码
  • 1
  • 2
  • 3
  • 4

MeanEncoder实现源码详情可参考:平均数编码:针对高基数定性特征(类别特征)的数据预处理/特征工程。

总结

  1. 特征预处理是数据预处理过程的重要步骤,是对数据的一个的标准的处理,几乎所有的数据处理过程都会涉及该步骤。
  2. 由于树模型(Random Forest、GBDT、xgboost等)对特征数值幅度不敏感,可以不进行无量纲化和统计变换处理;
    同时,由于树模型不依赖于样本距离来进行学习,所以也可以不进行类别特征编码(但字符型特征不能直接作为输入,所以需要至少要进行标签编码)。
  3. 依赖样本距离来学习的模型(如线性回归、SVM、深度学习等)
    • 对于数值型特征需要进行无量纲化处理;
    • 对于一些长尾分布的数据特征,可以做统计变换,使得模型能更好优化;
    • 对于线性模型,特征分箱可以提升模型表达能力;
  1. 对数值型特征进行特征分箱可以让模型对异常数据有很强的鲁棒性,模型也会更稳定。
    另外,分箱后需要进行特征编码。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/328482
推荐阅读
相关标签
  

闽ICP备14008679号