数据预处理

数据无量纲化

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

特征预处理API

sklearn.preprocessing

sklearn.preprocessing 模块包括缩放、居中、归一化、二值化方法。

归一化

对数值类型的特征做归一化可以将所有的特征都统一到一个大致相同的数值
区间内。最常用的方法主要有以下两种。

线性函数归一化(Min-Max Scaling)。它对原始数据进行线性变换,使结果映射到[0, 1]的范围,实现对原始数据的等比缩放。归一化公式如下

​其中X为原始数据,$X_$、$X_$分别为数据最大值和最小值,$X^{''}$为最终结果

API

  • sklearn.preprocessing.MinMaxScaler(feature_range=0, 1, *, copy=True, clip=False)
    
       fit_transform(X, y=None, **fit_params)
    

注意最大值最小值是变化的,另外,最大值与最小值非常容易受异常点影响,所以这种方法鲁棒性较差,只适合传统精确小数据场景。

标准化

零均值归一化(Z-Score Normalization)。它会将原始数据映射到均值为0、标准差为1的分布上。具体来说,假设原始特征的均值为μ、标准差为σ,那么归一化公式定义为
$$
X^{''} = \frac{x-\mu}{\sigma}
$$

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

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

  • sklearn.preprocessing.StandardScaler(*, copy=True, with_mean=True, with_std=True)
    
    • fit_transform(X, y=None, **fit_params)
      

示例代码

import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import StandardScaler

def minmax_demo():
    """
    归一化演示
    :return: None
    """
    data = pd.read_csv("../data/dating.txt")
    print(data)
    # 1、实例化一个转换器类
    transfer = MinMaxScaler(feature_range=(2, 3))
    # 2、调用fit_transform
    data = transfer.fit_transform(data[['milage','Liters','Consumtime']])
    print("最小值最大值归一化处理的结果:\n", data)

    return None

def stand_demo():
    """
    标准化演示
    :return: None
    """
    data = pd.read_csv("../data/dating.txt")
    print(data)
    # 1、实例化一个转换器类
    transfer = StandardScaler()
    # 2、调用fit_transform
    data = transfer.fit_transform(data[['milage','Liters','Consumtime']])
    print("标准化的结果:\n", data)
    print("每一列特征的平均值:\n", transfer.mean_)
    print("每一列特征的方差:\n", transfer.var_)

    return None

minmax_demo()
print('\n==================================================\n')
stand_demo()

示例数据

milage,Liters,Consumtime,target
40920,8.326976,0.953952,3
14488,7.153469,1.673904,2
26052,1.441871,0.805124,1
75136,13.147394,0.428964,1
38344,1.669788,0.134296,1
72993,10.141740,1.032955,1
35948,6.830792,1.213192,3
42666,13.276369,0.543880,3
67497,8.631577,0.749278,1
35483,12.273169,1.508053,3
50242,3.723498,0.831917,1
63275,8.385879,1.669485,1
5569,4.875435,0.728658,2
51052,4.680098,0.625224,1
77372,15.299570,0.331351,1
43673,1.889461,0.191283,1
61364,7.516754,1.269164,1
69673,14.239195,0.261333,1
15669,0.000000,1.250185,2
28488,10.528555,1.304844,3
6487,3.540265,0.822483,2
......

缺失值处理

机器学习和数据挖掘中所使用的数据,永远不可能是完美的。很多特征,对于分析和建模来说意义非凡,但对于实际收集数据的人却不是如此,因此数据挖掘之中,常常会有重要的字段缺失值很多,但又不能舍弃字段的情况。因此,数据预处理中非常重要的一项就是处理缺失值。

缺失值处理的方法说起来也很简单。要么直接把确实的那些数据删除(一般不这样做);要么采用一定得策略对这些缺失值进行填充。

数据长这样

image-20210708151148872

使用sklearn处理缺失值

class sklearn.impute.SimpleImputer(*, missing_values=nan, strategy='mean', fill_value=None, verbose=0, copy=True, add_indicator=False)
参数含义&输入
missing_values告诉SimpleImputer,数据中的缺失值长什么样,默认空值np.nan
strategy我们填补缺失值的策略,默认均值。
输入“mean”使用均值填补(仅对数值型特征可用)
输入“median"用中值填补(仅对数值型特征可用)
输入"most_frequent”用众数填补(对数值型和字符型特征都可用)
输入“constant"表示请参考参数“fill_value"中的值(对数值型和字符型特征都可用)
fill_value当参数startegy为”constant"的时候可用,可输入字符串或数字表示要填充的值,常用0
copy默认为True,将创建特征矩阵的副本,反之则会将缺失值填补到原本的特征矩阵中去。
import pandas as pd
from sklearn.impute import SimpleImputer
data = pd.read_csv(r"./Narrativedata.csv",
                   index_col=0) #index_col=0将第0列作为索引,不写则认为第0列为特征
 
data.head()
data.info()
#填补年龄
Age = data.loc[:,"Age"].values.reshape(-1,1)            #sklearn当中特征矩阵必须是二维
Age[:20] 

imp_mean = SimpleImputer()                              #实例化,默认均值填补
imp_median = SimpleImputer(strategy="median")           #用中位数填补
imp_0 = SimpleImputer(strategy="constant",fill_value=0) #用0填补
 
imp_mean = imp_mean.fit_transform(Age)                  #fit_transform一步完成调取结果
imp_median = imp_median.fit_transform(Age)
imp_0 = imp_0.fit_transform(Age)
 
imp_mean[:20]
imp_median[:20]
imp_0[:20]
 
#在这里我们使用中位数填补Age
data.loc[:,"Age"] = imp_median
 
data.info()
 
#使用众数填补Embarked
Embarked = data.loc[:,"Embarked"].values.reshape(-1,1)
imp_mode = SimpleImputer(strategy = "most_frequent")
data.loc[:,"Embarked"] = imp_mode.fit_transform(Embarked)
 
data.info()

使用Pandas和Numpy填补缺失值

import pandas as pd
data_ = pd.read_csv(r"./Narrativedata.csv"
                   ,index_col=0
                  )#index_col=0将第0列作为索引,不写则认为第0列为特征

data_.head()
 
data_.loc[:,"Age"] = data_.loc[:,"Age"].fillna(data_.loc[:,"Age"].median())
#.fillna 在DataFrame里面直接进行填补
 
data_.dropna(axis=0,inplace=True)
#.dropna(axis=0)删除所有有缺失值的行,.dropna(axis=1)删除所有有缺失值的列
#参数inplace,为True表示在原数据集上进行修改,为False表示生成一个复制对象,不修改原数据,默认False
# _data_ = data_.drop(axis=0,inplace=False)

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

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

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

from sklearn.preprocessing import LabelEncoder
import pandas as pd

data_ = pd.read_csv(r"./Narrativedata.csv"
                   ,index_col=0
                  )#index_col=0将第0列作为索引,不写则认为第0列为特征

data_.head()
 
y = data.iloc[:,-1]                         #要输入的是标签,不是特征矩阵,所以允许一维
 
le = LabelEncoder()                         #实例化
le = le.fit(y)                              #导入数据
label = le.transform(y)                     #transform接口调取结果
 
le.classes_                                 #属性.classes_查看标签中究竟有多少类别
label                                       #查看获取的结果label
 
le.fit_transform(y)                         #也可以直接fit_transform一步到位
 
le.inverse_transform(label)                 #使用inverse_transform可以逆转

data.iloc[:,-1] = label                     #让标签等于我们运行出来的结果
 
data.head()

preprocessing.OrdinalEncoder:特征专用,能够将分类特征转换为分类数值

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()

preprocessing.OneHotEncoder:独热编码,创建哑变量

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.preprocessing.Binarizer

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

#将年龄二值化

data_2 = data.copy()

from sklearn.preprocessing import Binarizer

X = data_2.iloc[:, 0].values.reshape(-1, 1)  #类为特征专用,所以不能使用一维数组
transformer = Binarizer(threshold=30).fit_transform(X)

data_2.iloc[:, 0] = transformer
data_2.head()

preprocessing.KBinsDiscretizer

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

from sklearn.preprocessing import KBinsDiscretizer
import pandas as np

data_ = pd.read_csv(r"./Narrativedata.csv"
                   ,index_col=0
                  )#index_col=0将第0列作为索引,不写则认为第0列为特征
 
X = data.iloc[:,0].values.reshape(-1,1) 
est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
est.fit_transform(X)