ML_3 简单的数据预处理和特征工程

学习目标有四个:

  • 无量纲化:最值归一化、均值方差归一化及sklearn中的Scaler

  • 缺失值处理

  • 处理分类型特征:编码与哑变量

  • 处理连续型特征:二值化与分段

一、数据归一化

  在量纲不同的情况下,以上的情况,不能反映样本中每一个特征的重要程度。这就需要数据归一化了。

  一般来说,我们的解决方案是:把所有的数据都映射到同一个尺度(量纲)上。

  一般来说,常用的数据归一化有两种

    最值归一化:映射到0-1之间,适用范围是特征分布具有明显边界的,受outlier影响比较大的x_scaler=(x-x_min)/(x_max-x_min)

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

    MaxAbs归一化:x'=x/|Max|

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

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

    均值方差归一化:归一到均值为0方差为1的分布中,适用于数据没有边界的,有个可能存在极端值的情况x_scaler=(x-x_mean)/S

#最值归一化的实现
#创建100个随机数,对其进行最值归一化
import numpy as np
#最值归一化
x=np.random.randint(0,100,size=100)
(x-np.min(x))/(np.max(x)-np.min(x))

x=np.random.randint(0,100,(50,2)) #矩阵
x=np.array(x,dtype=float) #浮点,对列进行归一化
x_1=(x[:,0]-np.min(x[:,0]))/(np.max(x[:,0])-np.min(x[:,0]))
x_2=(x[:,1]-np.min(x[:,1]))/(np.max(x[:,1])-np.min(x[:,1]))
    #循环
for i in range(0,x.shape(1)):
    X[:,i] = (X[:,i]-np.min(X[:,i])) / (np.max(X[:,i] - np.min(X[:,i])))

import matplotlib.pyplot as plt
    # 简单绘制样本,看横纵坐标
plt.scatter(x_1,x_2)
plt.show()

#均值方差归一化
X2 = np.array(np.random.randint(0,100,(50,2)),dtype=float)

    # 套用公式,对每一列做均值方差归一化
for i in range(0,2):
    X2[:,i]=(X2[:,i]-np.mean(X2[:,i])) / np.std(X2[:,i])
plt.scatter(X2[:,0],X2[:,1])
plt.show()
np.mean(X2[:,0])
np.std(X2[:,1])

#sklearn中的归一化

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
iris = datasets.load_iris()
X = iris.data
y = iris.target
X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,test_size=0.2,random_state=666)

from sklearn.preprocessing import StandardScaler
standardScaler=StandardScaler()
#归一化过程和训练模型一样
standardScaler.fit(X_train)
standardScaler.mean_
standardScaler.scale_ #std分布范围
#使用transform即为输出后的数据
X_train_standard = standardScaler.transform(X_train)
X_test_standard = standardScaler.transform(X_test)

#工程
import numpy as np

class StandardScaler:

    def __init__(self):
        self.mean_ = None
        self.scale_ = None

    def fit(self, X):
        """根据训练数据集X获得数据的均值和方差"""
        assert X.ndim == 2, "The dimension of X must be 2"

        # 求出每个列的均值
        self.mean_ = np.array([np.mean(X[:,i] for i in range(X.shape[1]))])
        self.scale_ = np.array([np.std(X[:, i] for i in range(X.shape[1]))])

        return self

    def tranform(self, X):
        """将X根据StandardScaler进行均值方差归一化处理"""
        assert X.ndim == 2, "The dimension of X must be 2"
        assert self.mean_ is not None and self.scale_ is not None, 
        "must fit before transform"
        assert X.shape[1] == len(self.mean_), 
        "the feature number of X must be equal to mean_ and std_"
        # 创建一个空的浮点型矩阵,大小和X相同
        resX = np.empty(shape=X.shape, dtype=float)
        # 对于每一列(维度)都计算
        for col in range(X.shape[1]):
            resX[:,col] = (X[:,col] - self.mean_[col]) / self.scale_[col]
        return resX

KNN优缺点

KNN的主要优点有:

  1. 理论成熟,思想简单,既可以用来做分类也可以用来做回归
  2. 天然解决多分类问题,也可用于回归问题
  3. 和朴素贝叶斯之类的算法比,对数据没有假设,准确度高,对异常点不敏感
  4. 由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合

KNN的主要缺点有:

  1. 计算量大,效率低。即使优化算法,效率也不高。
  2. 高度数据相关,样本不平衡的时候,对稀有类别的预测准确率低
  3. 相比决策树模型,KNN模型可解释性不强
  4. 维度灾难:随着维度的增加,“看似相近”的两个点之间的距离越来越大,而knn非常依赖距离(使用太多的特征导致了过拟合。分类器学习了很多异常特征(如噪声等),因此对于新的数据泛化性能不好。)

kd树

对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构,且kd树是一种二叉树,表示对k维空间的一个划分

常规的k-d tree的构建过程为:

  1. 循环依序取数据点的各维度来作为切分维度,
  2. 取数据点在该维度的中值作为切分超平面,
  3. 将中值左侧的数据点挂在其左子树,将中值右侧的数据点挂在其右子树,
  4. 递归处理其子树,直至所有数据点挂载完毕。

优化算法:选择切分维度:方差越大越分散,从方差大的维度开始切分,有较好的切分效果和平衡性

    确定中值点:预先对原始数据点在所有维度进行一次排序,存储下来,然后在后续的中值选择中,无须每次都对其子集进行排序,提升了性能。也可以从原始数据点中随机选择固定数目的点,然后对其进行排序,每次从这些样本点中取中值,来作为分割超平面。该方式在实践中被证明可以取得很好性能及很好的平衡性。

 kd树的检索

kd树的检索是KNN算法至关重要的一步,给定点p,查询数据集中与其距离最近点的过程即为最近邻搜索。

(1)将查询数据Q从根结点开始,按照Q与各个结点的比较结果向下访问Kd-Tree,直至达到叶子结点。

其中Q与结点的比较指的是将Q对应于结点中的k维度上的值与m进行比较,若Q(k) < m,则访问左子树,否则访问右子树。达到叶子结点时,计算Q与叶子结点上保存的数据之间的距离,记录下最小距离对应的数据点,记为当前“最近邻点”Pcur和最小距离Dcur。

(2)进行回溯(Backtracking)操作,该操作是为了找到离Q更近的“最近邻点”。即判断未被访问过的分支里是否还有离Q更近的点,它们之间的距离小于Dcur。

如果Q与其父结点下的未被访问过的分支之间的距离小于Dcur,则认为该分支中存在离P更近的数据,进入该结点,进行(1)步骤一样的查找过程,如果找到更近的数据点,则更新为当前的“最近邻点”Pcur,并更新Dcur。

如果Q与其父结点下的未被访问过的分支之间的距离大于Dcur,则说明该分支内不存在与Q更近的点。

回溯的判断过程是从下往上进行的,直到回溯到根结点时已经不存在与P更近的分支为止。

#%%knn中的kd树
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Circle
from sklearn.neighbors import KDTree
np.random.seed(0)
points=np.random.random((100,2))  #100个2维数据
tree=KDTree(points)
point=points[0]   #第一个点的knn近邻
dists,indices=tree.query([point],k=3)
print(dists,indices) #找到最近的三个距离以及编号
indices=tree.query_radius([point],r=0.2)
print(indices)
fig=plt.figure()#
    #主要讲一个参数num:相当于给画布定义一个id,如果给出了num,之前没有使用,则创建一个新的画布;如果之前使用了这个num,那么返回那个画布的引用,在之前的画布上继续作图。如果没有给出num, 则每次创建一块新的画布。
ax=fig.add_subplot(111,aspect='equal')
    #add_subplot(*args, **kwargs)
    #向图中加入子图的轴。返回子图的坐标轴axes
ax.add_patch(Circle(point,0.2,color='r',fill=False))
    #作为背景的Rectangle对象
X,Y=[[p[0] for p in points],[p[1] for p in points]]
plt.scatter(X,Y)
plt.scatter([point[0]],[point[1]],c='r')
plt.show()

二、特征工程

特征工程是利用数据领域的相关知识来创建能够使机器学习算法达到最佳性能的特征的过程。

特征工程又包含了Data PreProcessing(数据预处理)、Feature Extraction(特征提取)、Feature Selection(特征选择)和Feature construction(特征构造)等子问题,而数据预处理又包括了数据清洗和特征预处理等子问题

 (一)数值型特征无量纲化

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

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

数据标准化的原因:

  • 某些算法要求样本具有零均值和单位方差;

  • 需要消除样本不同属性具有不同量级时的影响。

    • 归一化有可能提高精度;

      数量级的差异将导致量级较大的属性占据主导地位,从而与实际情况相悖(比如这时实际情况是值域范围小的特征更重要);

    • 数量级的差异将导致迭代收敛速度减慢;

      当使用梯度下降法寻求最优解时,很有可能走“之字型”路线(垂直等高线走),从而导致需要迭代很多次才能收敛;

    • 依赖于样本距离的算法对于数据的数量级非常敏感。

1.数据标准化:前提是特征值服从正态分布,标准化后,其转化成正态分布

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

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

Z—score:

  优点:简单,容易计算,能够应用于数值型的数据,并且不受数据量级的影响

  缺点:需要总体的平均值和方差,实际运算中用样本代替

     对数据分布有一定要求,正态分布最有利

     消除了数据具有的实际意义,A的Z-Score与B的Z-Score与他们各自的分数不再有关系,因此Z-Score的结果只能用于比较数据间的结果,数据的真实意义还需要还原原值

     存在异常值的时候无法保证平衡的特征尺度

2.归一化

    最值归一化:映射到0-1之间,适用范围是特征分布具有明显边界的,受outlier影响比较大的x_scaler=(x-x_min)/(x_max-x_min)

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

    MaxAbs归一化:x'=x/|Max|

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

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

3.正态分布化(Normalization)

1)定义

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

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

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

#%%数据标准化
from sklearn.preprocessing import StandardScaler
standardScaler=StandardScaler().fit(X_train)
standardScaler.transform(X_train)

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

from sklearn.preprocessing import MaxAbsScaler
maxAbsScaler =MaxAbsScaler().fit(X_train)
maxAbsScaler.transform(X_train)

from sklearn.preprocessing import Normalizer
normalizer=Normalizer(norm='l2').fit(X_train)
normalizer.transform(X_train)

4.标准化和归一化的对比

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

不同点:目的不同:归一化是为了消除量纲,压缩到【0,1】区间

         标准化是为了调整特征整体的分布

    归一化运算与最大值最小值有关,标准化与均值标准差有关

    归一化输出在【0,1】之间,标准化无限制

适用场景:

  • 如果对输出结果范围有要求,用归一化;

  • 如果数据较为稳定,不存在极端的最大最小值,用归一化;

  • 如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响。

归一化与标准化的应用场景

  • 在分类、聚类算法中,需要使用距离来度量相似性的时候(如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 。这里只考虑边界,每个等份里面的实例数量可能不等。

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

3)等频分箱

将数据分成几等份,每等份数据里面的个数是一样的。

区间的边界值要经过选择,使得每个区间包含大致相等的实例数量。比如说 N=10 ,每个区间应该包含大约10%的实例。

4)聚类分箱

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

    对预处理后的数据进行归一化处理;

  • Step 1:

    将归一化处理过的数据,应用k-means聚类算法,划分为多个区间:

    采用等距法设定k-means聚类算法的初始中心,得到聚类中心;

  • Step 2:

    在得到聚类中心后将相邻的聚类中心的中点作为分类的划分点,将各个对象加入到距离最近的类中,从而将数据划分为多个区间;

  • Step 3:

    重新计算每个聚类中心,然后重新划分数据,直到每个聚类中心不再变化,得到最终的聚类结果。

5)二值化(Binarization)

二值化可以将数值型(numerical)的feature进行阀值化得到boolean型数据。这对于下游的概率估计来说可能很有用(比如:数据分布为Bernoulli分布时)。
定量特征二值化的核心在于设定一个阈值,大于阈值的赋值为1,小于等于阈值的赋值为0,公式如下:

#%%分箱
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'])
#cut将根据值本身来选择箱子均匀间隔,即每个箱子的间距都是相同的
df['age_bin_2'] = pd.cut(df['age'],3)  #新增一列存储等距划分的分箱特征
display(df)
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'])
#qcut是根据这些值的频率来选择箱子的均匀间隔,即每个箱子中含有的数的数量是相同的
df['age_bin_1'] = pd.qcut(df['age'],3) #新增一列存储等频划分的分箱特征
display(df)
#聚类分箱
from sklearn.cluster import KMeans
k=3
kmodel=KMeans(n_clusters=k) #k类
data=np.array([22,13,33,52,16,42,53,39,26,66])
kmodel.fit(data.reshape(-1,1))#训练模型
c=pd.DataFrame(kmodel.cluster_centers_)
c=c.sort_values(by=0)
w=c.rolling(2).mean().iloc[1:] #用滑动窗口求均值的方法求相邻两项求中点,作为边界点
w=[0] +list(w[0] + [ data.max() ])  #把首末边界点加上
d3= pd.cut(data,w,labels=range(k)) #cut函数

#二值化
from sklearn.preprocessing import Binarizer
binarizer=Binarizer(threshold=0.0).fit(X_train)
binarizer.transform(X_train)

2.有监督分箱法

1)卡方分箱法

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

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

实现步骤
    • Step 0:

      预先定义一个卡方的阈值;

    • Step 1:

      初始化;


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

    • Step 2:

      合并区间;

      • 计算每一对相邻区间的卡方值;

      • 将卡方值最小的一对区间合并;

Aij:第i区间第j类的实例的数量;Eij:Aij的期望频率(=(Ni*Cj)/N),N是总样本数,Ni是第i组的样本数,Cj是第j类样本在全体中的比例;
阈值的意义

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

注意
  • ChiMerge算法推荐使用0.90、0.95、0.99置信度,最大区间数取10到15之间;

  • 也可以不考虑卡方阈值,此时可以考虑最小区间数或者最大区间数。

    指定区间数量的上限和下限,最多几个区间,最少几个区间;

  • 对于类别型变量,需要分箱时需要按照某种方式进行排序。

2)最小熵法分箱

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

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

首先对某个特征所有值进行排序,通过遍历该特征所有的值(离散值,连续值需要处理成离散值)。计算信息增益,选择信息增益大的值作为一个分断点,然后这个断点将数据分成两部分,然后分别对分割的两部分依次进行上面的操作,直到达到停止条件。

一般来说,停止准则是当得到的每个区间中的类标签都是一样。这样将导致到的分割点太多,过拟合。我们可以设置一些停止阈值,比如当信息增益小于阈值就停止等。
二、缺失值

机器学习和数据挖掘中所使用的数据,永远不可能是完美的。很多特征,对于分析和建模来说意义非凡

class sklearn.impute.SimpleImputer(missing_values=nanstrategy=’mean’fill_value=Noneverbose=0copy=True)

#%%缺失值_tancnic_data
data = pd.read_excel('missing.xlsx')   #通过索引顺序获取
age = data.loc[:,"Age"].values.reshape(-1,1)            #sklearn当中特征矩阵必须是二维
age[:20]

from sklearn.impute import SimpleImputer
imp_mean=SimpleImputer()
imp_median=SimpleImputer(strategy="median")
imp_0=SimpleImputer(strategy='constant',fill_value=0)
imp_mean = imp_mean.fit_transform(age)
imp_median=imp_median.fit_transform(age)
imp_0=imp_0.fit_transform(age)
imp_mean[:20]
imp_median[:20]
imp_0[:20]
data.info()
#用pandas和numpy填补更加简单
data = pd.read_excel('missing.xlsx')   #通过索引顺序获取
age = data.loc[:,"Age"].values.reshape(-1,1)            #sklearn当中特征矩阵必须是二维
data.head()

# =============================================================================
# loc:通过行标签索引数据

#iloc:通过行号索引行数据

#ix:通过行标签或行号索引数据(基于loc和iloc的混合)
# =============================================================================
data.loc[:,'Age']=data.loc[:,'Age'].fillna(data.loc[:,'Age'].median())
data.dropna(axis=0,inplace=True)
#.dropna(axis=0)删除所有有缺失值的行,.dropna(axis=1)删除所有有缺失值的列
#参数inplace,为True表示在原数据集上进行修改,为False表示生成一个复制对象,不修改原数据,默认False

 三、处理分类型特征:编码与哑变量

  在机器学习中,大多数算法,譬如逻辑回归,支持向量机SVM,k近邻算法等都只能够处理数值型数据,不能处理文字,在sklearn当中,除了专用来处理文字的算法,其他算法在fit的时候全部要求输入数组或矩阵,也不能够导入文字型数据(其实手写决策树和普斯贝叶斯可以处理文字,但是sklearn中规定必须导入数值型)。然而在现实中,许多标签和特征在数据收集完毕的时候,都不是以数字来表现的。比如说,学历的取值可以是["小学",“初中”,“高中”,"大学"],付费方式可能包含["支付宝",“现金”,“微信”]等等。在这种情况下,为了让数据适应算法和库,我们必须将数据进行编码,即是说,将文字型数据转换为数值型

 

  • preprocessing.LabelEncoder:标签专用,能够将分类转换为分类数值

  • preprocessing.OrdinalEncoder:特征专用,能够将分类特征转换为分类数值
  • preprocessing.OneHotEncoder:独热编码,创建哑变量

我们刚才已经用OrdinalEncoder把分类变量Sex和Embarked都转换成数字对应的类别了。在舱门Embarked这一列中,我们使用[0,1,2]代表了三个不同的舱门,然而这种转换是正确的吗?

我们来思考三种不同性质的分类数据:

1) 舱门(S,C,Q)

  三种取值S,C,Q是相互独立的,彼此之间完全没有联系,表达的是S≠C≠Q的概念。这是名义变量。

2) 学历(小学,初中,高中)

  三种取值不是完全独立的,我们可以明显看出,在性质上可以有高中>初中>小学这样的联系,学历有高低,但是学历取值之间却不是可以计算的,我们不能说小学 + 某个取值 = 初中。这是有序变量。

3) 体重(>45kg,>90kg,>135kg)

  各个取值之间有联系,且是可以互相计算的,比如120kg - 45kg = 90kg,分类之间可以通过数学计算互相转换。这是有距变量。

  然而在对特征进行编码的时候,这三种分类数据都会被我们转换为[0,1,2],这三个数字在算法看来,是连续且可以计算的,这三个数字相互不等,有大小,并且有着可以相加相乘的联系。所以算法会把舱门,学历这样的分类特征,都误会成是体重这样的分类特征。这是说,我们把分类转换成数字的时候,忽略了数字中自带的数学性质,所以给算法传达了一些不准确的信息,而这会影响我们的建模。

  类别OrdinalEncoder可以用来处理有序变量,但对于名义变量,我们只有使用哑变量的方式来处理,才能够尽量向算法传达最准确的信息:

 这样的变化,让算法能够彻底领悟,原来三个取值是没有可计算性质的,是“有你就没有我”的不等概念。在我们的数据中,性别和舱门,都是这样的名义变量。因此我们需要使用独热编码,将两个特征都转换为哑变量。

四、 处理连续型特征:二值化与分段

  • sklearn.preprocessing.Binarizer

  根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈值的值映射为0。默认阈值为0时,特征中所有的正值都映射到1。二值化是对文本计数数据的常见操作,分析人员可以决定仅考虑某种现象的存在与否。它还可以用作考虑布尔随机变量的估计器的预处理步骤(例如,使用贝叶斯设置中的伯努利分布建模)。

  • preprocessing.KBinsDiscretizer

  这是将连续型变量划分为分类变量的类,能够将连续型变量排序后按顺序分箱后编码。总共包含三个重要参数

原文地址:https://www.cnblogs.com/wjAllison/p/12501035.html