码迷,mamicode.com
首页 > 其他好文 > 详细

【机器学习】scikit-learn中的数据预处理小结

时间:2020-12-09 11:58:12      阅读:5      评论:0      收藏:0      [点我收藏+]

标签:默认   str   pca   most   int   float   逻辑回归   数据转换   删除   

一.概述

1. 数据预处理

数据预处理是从数据中检测,修改或删除不准确或不适用于模型的记录的过程
可能面对的问题有:数据类型不同,比如有的是文字,有的是数字,有的含时间序列,有的连续,有的间断。 也可能,数据的质量不行,有噪声,有异常,有缺失,数据出错,量纲不一,有重复,数据是偏态,数据量太大或太小 。
数据预处理的目的:让数据适应模型,匹配模型的需求 。

2.sklearn中的数据预处理

sklearn中包含众多数据预处理相关的模块,包括:

  • 模块preprocessing:几乎包含数据预处理的所有内容
  • 模块Impute:填补缺失值专用

二 . 数据预处理

1.归一化

在机器学习算法实践中,我们往往有着将不同规格的数据转换到同一规格,或不同分布的数据转换到某个特定分布 的需求,这种需求统称为将数据“无量纲化”。
譬如梯度和矩阵为核心的算法中,譬如逻辑回归,支持向量机,神经 网络,无量纲化可以加快求解速度;而在距离类模型,譬如K近邻,K-Means聚类中,无量纲化可以帮我们提升模型精度,避免某一个取值范围特别大的特征对距离计算造成影响。

(1)preprocessing.MinMaxScaler

当数据(x)按照最小值中心化后,再按极差(最大值 - 最小值)缩放,数据移动了最小值个单位,并且会被收敛到 [0,1]之间,而这个过程,就叫做数据归一化(Normalization,又称Min-Max Scaling)。
归一化之后的数据服从正态分 布,公式如下:

\[x^{*} = \frac{x-min(x)}{max(x)-min(x)} \]

在sklearn当中,我们使用preprocessing.MinMaxScaler来实现这个功能。

  • MinMaxScaler有一个重要参数, feature_range,控制我们希望把数据压缩到的范围,默认是[0,1].
from sklearn.preprocessing import MinMaxScaler
 
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
#实现归一化 
scaler = MinMaxScaler(feature_range=[5,10])         #实例化,feature_range默认是[0,1]
# scaler = scaler.fit(data)                         #fit,在这里本质是生成min(x)和max(x) 
# result = scaler.transform(data)                   #通过接口导出结果 result
result_ = scaler.fit_transform(data)                #训练和导出结果一步达成,可以替代上两行数据
result_
array([[ 5.  ,  5.  ],
       [ 6.25,  6.25],
       [ 7.5 ,  7.5 ],
       [10.  , 10.  ]])

(2) preprocessing.StandardScale

当数据(x)按均值(μ)中心化后,再按标准差(σ)缩放,数据就会服从为均值为0,方差为1的正态分布(即标准正态分 布),而这个过程,就叫做数据标准化(Standardization,又称Z-score normalization),公式如下:

\[x^{*} = \frac{x-μ}{σ} \]

from sklearn.preprocessing import StandardScaler 
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
 
scaler = StandardScaler()                           #实例化 
# scaler = scaler.fit(data)                                    #fit,本质是生成均值和方差
# result = scaler.transform(data)                      #通过接口导出结果
 
result_ = scaler.fit_transform(data)                #使用fit_transform(data)一步达成结果
result_
array([[-1.18321596, -1.18321596],
       [-0.50709255, -0.50709255],
       [ 0.16903085,  0.16903085],
       [ 1.52127766,  1.52127766]])

(3) StandardScaler和MinMaxScaler选哪个?

看情况。大多数机器学习算法中,会选择StandardScaler来进行特征缩放,因为MinMaxScaler对异常值非常敏 感。在PCA,聚类,逻辑回归,支持向量机,神经网络这些算法中,StandardScaler往往是最好的选择。
MinMaxScaler在不涉及距离度量、梯度、协方差计算以及数据需要被压缩到特定区间时使用广泛,比如数字图像 处理中量化像素强度时,都会使用MinMaxScaler将数据压缩于[0,1]区间之中。

2.缺失值

数据预处理中非常重要的一项就是处理缺失值。

  • 对于连续值,常常使用均值或者中位数去填充缺失值;
  • 对于离散值,常常使用众数填充,或者把缺失值当作一个单独的类别。
  • 对于缺失率超过一定阈值的特征,可以考虑直接舍弃。
import pandas as pd 
data = pd.read_csv(r"./../Narrativedata.csv",index_col=0)
data.info()
<class ‘pandas.core.frame.DataFrame‘>
Int64Index: 891 entries, 0 to 890
Data columns (total 4 columns):
Age         714 non-null float64
Sex         891 non-null object
Embarked    889 non-null object
Survived    891 non-null object
dtypes: float64(1), object(3)
memory usage: 34.8+ KB

以Titanic数据为例,可以看到其中Age和Embarked两列有缺失值,且分别为连续值和离散值。

(1) impute.SimpleImputer

技术图片
from sklearn.impute import SimpleImputer 
# 对连续值Age进行填充    
Age = data.loc[:,"Age"].values.reshape(-1,1)            #sklearn当中特征矩阵必须是二维 
# 实例化
age_median = SimpleImputer(strategy="median")           #用中位数填补 (默认均值填补) 
age_0 = SimpleImputer(strategy="constant",fill_value=0) #使用具体值填补,用fill_value指定
# 转化
age_median = age_median.fit_transform(Age)    #fit_transform一步完成调取结果 
age_0 = age_0.fit_transform(Age)
#把填补后的列赋值回原来的矩阵里
data.loc[:,"Age"] = age_median
data.info()
<class ‘pandas.core.frame.DataFrame‘>
Int64Index: 891 entries, 0 to 890
Data columns (total 4 columns):
Age         891 non-null float64
Sex         891 non-null object
Embarked    889 non-null object
Survived    891 non-null object
dtypes: float64(1), object(3)
memory usage: 34.8+ KB
# 对离散值Embarked进行填充 
Embarked = data.loc[:,"Embarked"].values.reshape(-1,1) 
Embarked_most = SimpleImputer(strategy = "most_frequent")   #使用众数填补
data.loc[:,"Embarked"] = Embarked_most.fit_transform(Embarked)
data.info()
<class ‘pandas.core.frame.DataFrame‘>
Int64Index: 891 entries, 0 to 890
Data columns (total 4 columns):
Age         891 non-null float64
Sex         891 non-null object
Embarked    891 non-null object
Survived    891 non-null object
dtypes: float64(1), object(3)
memory usage: 34.8+ KB

(2) 用Pandas和Numpy进行填补

  • pd.fillna() 使用特定的值填充
  • pd.dropna(axis=0)删除所有有缺失值的行/列
import pandas as pd 
data1 = pd.read_csv(r"./../Narrativedata.csv",index_col=0)
 
data1.loc[:,"Age"] = data1.loc[:,"Age"].fillna(data1.loc[:,"Age"].median()) #.fillna 在data1Frame里面直接进行填补
 
data1.dropna(axis=0,inplace=True) #.dropna(axis=0)删除所有有缺失值的行,.dropna(axis=1)删除所有有缺失值的列
data1.info()
<class ‘pandas.core.frame.DataFrame‘>
Int64Index: 889 entries, 0 to 890
Data columns (total 4 columns):
Age         889 non-null float64
Sex         889 non-null object
Embarked    889 non-null object
Survived    889 non-null object
dtypes: float64(1), object(3)
memory usage: 34.7+ KB

3.处理离散特征:编码和哑变量

在sklearn当中,除了专用来处理文字的算法,其他算法在?t的时候全部要求输入数组或矩阵,也不能够导 入文字型数据。
为了让数据适 应算法和库,我们必须将数据进行编码,即是说,将文字型数据转换为数值型。

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

from sklearn.preprocessing import LabelEncoder 
y = data.iloc[:,-1]                         #要输入的是标签,不是特征矩阵,所以允许一维
print(y[:10])
le = LabelEncoder()                         #实例化 
label = le.fit_transform(y)                 # 匹配加转化一步到位
# le = le.fit(y)                            
# label = le.transform(y)                  
print(label[:10])
print(le.classes_)                           # 查看有多少类
data.iloc[:,-1] =label
0     No
1    Yes
2    Yes
3    Yes
4     No
5     No
6     No
7     No
8    Yes
9    Yes
Name: Survived, dtype: object
[0 2 2 2 0 0 0 0 2 2]
[‘No‘ ‘Unknown‘ ‘Yes‘]

(2)preprocessing.OrdinalEncoder:特征专用,能够将分类特征转换为分类数 (一般用于有序变量)

data_ =data.copy()
# 观察特征的原样式
data_.iloc[:,1:-1][:10]
Sex Embarked
0 male S
1 female C
2 female S
3 female S
4 male S
5 male Q
6 male S
7 male S
8 female S
9 female C
from sklearn.preprocessing import OrdinalEncoder
# 类似的,把实例化,匹配,转化和赋值写在一条语句上
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])
#接口categories_对应LabelEncoder的接口classes_,一模一样的功能 
print(OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_)
#查看数据,
data_.head() 
[array([0., 1.]), array([0., 1., 2.])]
Age Sex Embarked Survived
0 22.0 1.0 2.0 0
1 38.0 0.0 0.0 2
2 26.0 0.0 2.0 2
3 35.0 0.0 2.0 2
4 35.0 1.0 2.0 0
data_.info() 
<class ‘pandas.core.frame.DataFrame‘>
Int64Index: 891 entries, 0 to 890
Data columns (total 4 columns):
Age         891 non-null float64
Sex         891 non-null float64
Embarked    891 non-null float64
Survived    891 non-null int32
dtypes: float64(3), int32(1)
memory usage: 31.3 KB

由以上的数据情况可以看出,Age和Embarked的缺失值已被填充,特征Sex和Embarked等分类特征已转化为分类数值,标签Survived也已转化为分类数值。

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

由上面的处理可以看到OrdinalEncoder会把类别变量变成数值,比如转化为[0,1,2],这三个数字在算法看来,是连续且可以计算的,可能有大小并且有着可以相加相乘的联系。但是有的类别变量各类别是独立的,如果转化成数值会给算法传达了一些不准确的信息,而这会影响我们的建模。

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

# 同样的,观察下原数据样式
data.iloc[:,1:-1][:10]
Sex Embarked
0 male S
1 female C
2 female S
3 female S
4 male S
5 male Q
6 male S
7 male S
8 female S
9 female C
from sklearn.preprocessing import OneHotEncoder 
X = data.iloc[:,1:-1]
 
#可以直接一步到位
result = OneHotEncoder(categories=‘auto‘).fit_transform(X).toarray()
# # 也可以分开成两步计算
# enc = OneHotEncoder(categories=‘auto‘).fit(X) 
# result = enc.transform(X).toarray() 
# 把独热编码拼接到原数据上
newdata = pd.concat([data,pd.DataFrame(result)],axis=1)
newdata.drop(["Sex","Embarked"],axis=1,inplace=True) 
newdata.columns = ["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]
newdata.head() 
Age Survived Female Male Embarked_C Embarked_Q Embarked_S
0 22.0 0 0.0 1.0 0.0 0.0 1.0
1 38.0 2 1.0 0.0 1.0 0.0 0.0
2 26.0 2 1.0 0.0 0.0 0.0 1.0
3 35.0 2 1.0 0.0 0.0 0.0 1.0
4 35.0 0 0.0 1.0 0.0 0.0 1.0

(4) 使用pandas的.get_dummies函数 实现独热编码

dummies_Sex = pd.get_dummies(data.Sex,prefix=‘Sex‘)                    #ptefix 是前缀,因子化之后的字段名为 前缀_类名
dummies_Embarked = pd.get_dummies(data.Embarked,prefix=‘Embarked‘)    
newdata = pd.concat([data, dummies_Sex, dummies_Embarked], axis=1)         #将哑编码的内容拼接到data后
newdata.drop([ ‘Sex‘, ‘Embarked‘], axis=1, inplace=True)                # 把编码前的字段删除
newdata.head() 
Age Survived Sex_female Sex_male Embarked_C Embarked_Q Embarked_S
0 22.0 0 0 1 0 0 1
1 38.0 2 1 0 1 0 0
2 26.0 2 1 0 0 0 1
3 35.0 2 1 0 0 0 1
4 35.0 0 0 1 0 0 1

4.处理连续特征:二值化和分段

(1) sklearn.preprocessing.Binarize 用于处理连续变量的二值化

根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈值的值映射为0。默认阈值为0。

# 将年龄二值化
data_2 = data.copy()
from sklearn.preprocessing import Binarizer 
X = data_2.iloc[:,0].values.reshape(-1,1)               #类为特征专用,所以不能使用一维数组 
Age = Binarizer(threshold=30).fit_transform(X)          # 以30为阈值,>30为1,<30为0
Age[:10]
array([[0.],
       [1.],
       [0.],
       [1.],
       [1.],
       [0.],
       [1.],
       [0.],
       [0.],
       [0.]])

(2) sklearn.preprocessing.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)[:5]
array([[0.],
       [1.],
       [0.],
       [1.],
       [1.]])
est = KBinsDiscretizer(n_bins=3, encode=‘onehot‘, strategy=‘uniform‘) #查看转换后分的箱:变成了哑变量 
est.fit_transform(X).toarray()
array([[1., 0., 0.],
       [0., 1., 0.],
       [1., 0., 0.],
       ...,
       [0., 1., 0.],
       [1., 0., 0.],
       [0., 1., 0.]])

【机器学习】scikit-learn中的数据预处理小结

标签:默认   str   pca   most   int   float   逻辑回归   数据转换   删除   

原文地址:https://www.cnblogs.com/laiyaling/p/14087014.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!