一、数据的标准化、归一化、正则化
1、标准化
将数据转化为均值为0方差为1的数据,即标准正态分布。标准化可以规范数据,但不适用于稀疏数据,因为会破坏其数据结果。标准化的过程为两步:去均值的中心化(均值变为0);方差的规模化(方差变为1)。即每一列减去该列的均值再除以该列的方差。
在分类、聚类算法中,需要使用距离来度量相似性的时候、或者使用PCA技术进行降维的时候,StandardScaler表现更好。
对应函数:
sklearn.preprocessing.scale(X, axis=0, with_mean=True, with_std=True, copy=True)
- x:需要标准化标准化的数据。
- axis:需要标准化的方向,0为列,1为行。
- with_mean:是否去均值的中心化,默认为True。
- with_std:是否方差规模化,默认为True。
- copy:是否要copy数据。
代码示例:
import numpy as np
from sklearn.preprocessing import scale
a=np.random.normal(4,5,[5,2]) #创造数据
a_s=scale(a) #标准化
print('a:\n',a)
print('\na_s:\n',a_s)
print('\na_s的均值:',a_s.mean(axis=0))
print('\na_s的方差:',a_s.std(axis=0))
'''
结果:
a:
[[ 3.89399029 5.72996121]
[ 7.38088249 9.73803222]
[ 5.8379103 -5.40880669]
[ 3.29479806 -7.79727102]
[-0.68205516 -5.71899267]]
a_s:
[[-0.01873374 0.91171731]
[ 1.25922106 1.48078964]
[ 0.69371785 -0.66978276]
[-0.23833921 -1.00890074]
[-1.69586596 -0.71382346]]
a_s的均值: [-6.66133815e-17 0.00000000e+00]
a_s的方差: [1. 1.]
'''
2、归一化
归一化可以将稀疏的数据进行规范化,而且不会破坏其数据结构。归一化有两种,一种是归一化到[0,1]区间,另一种是归一化到[-1,1]区间内,这样是为了对付那些标准差相当小的特征并且保留下稀疏数据中的0值。
在不涉及距离度量、协方差计算、数据不符合正太分布的时候,可以使用MinMaxScaler。比如图像处理中,将RGB图像转换为灰度图像后将其值限定在[0 255]的范围。
[0,1]归一化:
对应的类:
sklearn.preprocessing.MinMaxScaler(feature_range=(0, 1), copy=True)
- feature_range:要归一化的范围。
- copy:是否拷贝数据。
类的方法:
- fit_transform(self, X, y=None, **fit_params) 将数据传入并转化,一般传入特征数据X即可,目标数据Y不需要转化。
inverse_transform(self, X) 将数据的归一化去除,变回原来的数据。
计算公式:
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min
其中max、min为sklearn.preprocessing.MinMaxScaler中参数feature的参数范围,一般默认是0、1。X.min(axis=0)表示列最小值。
[-1,1]归一化
对应的类:
sklearn.preprocessing.MaxAbsScaler(copy=True)
类的方法:
- fit_transform(self, X[, y])
代码示例:
import numpy as np
from sklearn.preprocessing import MinMaxScaler
x=np.arange(0,10).reshape(10,1) #创建10*1数组
scale=MinMaxScaler() #创建传化器
x_trans=scale.fit_transform(x) #传入数据并转化
print(x_trans)
'''
结果为:
[[0. ]
[0.11111111]
[0.22222222]
[0.33333333]
[0.44444444]
[0.55555556]
[0.66666667]
[0.77777778]
[0.88888889]
[1. ]]
'''
3、分位数标准化
当含有较多的异常值的时候,普通的标准化不能很好的规范数据,所以要可以用分位数标准化,即用范围在第一分位数,第三分位数之间的数据的均值与方差来标准化数据,而不是所有的数据。
对应的类:
sklearn.preprocessing.RobustScaler(with_centering=True, with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
- with_centering:是否去中心化。
- with_scaling:是否方差化。
- quantile_range:分位数的范围,值为0-100之间。
- copy:是否copy数据。
类的方法:
- fit_transform(self, X[, y]) 传入数据并标准化。
代码示例:
import numpy as np
from sklearn.preprocessing import RobustScaler
x = np.random.normal(0, 1, [10, 1]) # 创建数据
x[0, 0] = 3 # 创建异常值
x_trans = RobustScaler().fit_transform(x) # 标准化
print('x为:\n', x)
print('x_trans为:\n', x_trans)
'''
结果为:
x为:
[[ 3. ]
[ 0.57042561]
[ 1.15972829]
[ 0.26299752]
[-1.48938259]
[-2.11549533]
[ 0.43788961]
[-1.87936541]
[ 0.01614399]
[ 0.44674289]]
x_trans为:
[[ 1.60335674]
[ 0.13312028]
[ 0.48973183]
[-0.05291724]
[-1.11335529]
[-1.49224213]
[ 0.05291724]
[-1.3493501 ]
[-0.20229857]
[ 0.05827473]]
'''
关于规范化的选择:
1、在分类、聚类算法中,需要使用距离来度量相似性的时候、或者使用PCA技术进行降维的时候,StandardScaler表现更好。
2、在不涉及距离度量、协方差计算、数据不符合正太分布的时候,可以使用MinMaxScaler。比如图像处理中,将RGB图像转换为灰度图像后将其值限定在[0 255]的范围。
二、连续特征二值化与离散特征编码(哑变量)
对变量进行哑变量处理的原因是,有的模型不能够处理分类变量只能处理连续性变量,例如线性回归,所吧变量转化为用01编码的方式来表示有利于建模。
one-hot用在GBDT、XGBoost这些模型里面都挺好的,但是用在逻辑回归里不行。因为逻辑回归要求变量间相互独立,如果你只有一个属性需要做one-hot编码还好,如果你有多个属性需要做one-ont编码,那么当某个样本的多个one-hot属性同时为1时,这两个属性就完全相关了,必然会导致singular error,也就是非奇异矩阵不能求解唯一解,得不出唯一的模型,但是你又不可能把同一个属性的某一个one-hot延伸变量删除。
如果在逻辑回归中入模标称属性,可以直接替换成数值,然后做woe变换,用每个类别的woe值来代替原来的数值,这样既能够避免生成相关性强的变量,又能避开类别间大小无法比较的问题。
1、连续特征二值化
将数据二值化,当数据小于等于某个值转化为0,大于某个值转化为1,可以将数据简化。
对应的类:
sklearn.preprocessing.Binarizer(threshold=0.0, copy=True)
- threshold:二值化阈值,<=threshold转化为0,>threshold转化为1
- copy:是否拷贝数据。
类的方法:
- fit_transform(self, X, y=None, **fit_params) 传入数据并二值化。
代码示例:
import numpy as np
from sklearn.preprocessing import Binarizer
x = np.random.normal(0,1,[5,1]) # 创建数据
x_trans = Binarizer().fit_transform(x) # 二值化
print('x为:\n', x)
print('x_trans为:\n', x_trans)
'''
结果为:
x为:
[[-1.61958613e+00]
[-9.19743271e-04]
[-1.08147857e+00]
[-1.06551634e+00]
[ 7.29322079e-01]]
x_trans为:
[[0.]
[0.]
[0.]
[0.]
[1.]]
'''
2、离散特征二值化
这个相当于哑变量编码。
对应的类:
sklearn.preprocessing.LabelBinarizer(neg_label=0, pos_label=1, sparse_output=False)
- neg_label:不属于该类的标签,默认为0。
- pos_label:属于该类的标签,默认为1。
- sparse_output:是否用稀疏矩阵格式输出,即索引加值的形式。
类的方法:
- fit_transform(self, X, y=None, **fit_params) 传入数据并二值化。
类的属性:
- LabelBinarizer().classes_ 用于查看二值化前离散特征原始值。
代码示例:
import numpy as np
from sklearn.preprocessing import Binarizer,LabelBinarizer
x = ['a','b','a','c'] # 创建数据
transor=LabelBinarizer() #创建转化器具
x_trans = transor.fit_transform(x) # 二值化
print('x为:\n', x)
print('转化的类别为:\n',transor.classes_)
print('x_trans为:\n', x_trans)
'''
结果为:
x为:
['a', 'b', 'a', 'c']
转化的类别为:
['a' 'b' 'c']
x_trans为:
[[1 0 0]
[0 1 0]
[1 0 0]
[0 0 1]]
'''
3、哑变量on-hot编码
将离散型数据转化为哑变量。
对应的类:
sklearn.preprocessing.OneHotEncoder(n_values=None, categorical_features=None, categories=None, drop=None, sparse=True, dtype=<class ‘numpy.float64’>, handle_unknown=’error’)
- **n_values:可选值[None,'auto',int],用几个值(即几列0、1编码)来表示特征的离散值,默认是对单个特征,有几个离散值就有几个值对应。自己指定,如果学历分为[高,中,低],但是样本只有[高,低],为了把学历中也表示出来,就需要传入3。
- **categorical_features:指定了对哪些训练特征(即那些列)进行编码,默认对所有训练特征都进行编码。也可以自己指定选择哪些特征,通过索引或者 bool 值来指定,例如对列[a,b,c]中的列[a,b]编码,则传入[a,b]。
- categories:可选值['auto',list]。'auto'默认将特征的所有离散值转化。如果是list,则将保留categories[list]对应的离散值。一般默认就好。
- drop:可选值[None,'first',list]。默认None表示将所有的离散值转化;'first',去掉第一个特征再将离散值转化,编码后全为0的表示第一个离散值;list:指定去除的离散值。建议默认就好。
- **sparse:True返回稀疏矩阵,索引加值的矩阵。
- dtype:数据类型。
- handle_unknown:对空值怎么处理,‘error’ 表示报错,‘ignore’表示忽略。
类的方法:
- fit_transform(self, X, y=None, **fit_params) 传入数据并二值化。
- get_feature_names() 返回编码后的列的名字,形式为:特证名_离散值。
代码示例:
import numpy as np
from sklearn.preprocessing import OneHotEncoder
x = np.array([['a'],['b'],['a'],['c']]) # 创建数据
transor=OneHotEncoder(sparse=False) #创建转化器具
x_trans = transor.fit_transform(x) # 二值化
print('x为:\n', x)
print('编码的后的列为:\n',transor.get_feature_names())
print('x_trans为:\n', x_trans)
'''
结果为:
x为:
[['a']
['b']
['a']
['c']]
编码的后的列为:
['x0_a' 'x0_b' 'x0_c']
x_trans为:
[[1. 0. 0.]
[0. 1. 0.]
[1. 0. 0.]
[0. 0. 1.]]
'''
4、pandas中的哑变量编码
对应函数:
pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)
- data:传入的数据,数组、Series类或者dataframe类。
- prefix:编码后列名的前缀,默认用特征名做为前缀,例如性别特征,编码后的列为[性别_男,性别_女]。如果要传入,长度要和特征数相同。
- prefix_sep:编码后列名的间隔符,默认就好。
- dummy_na:是否对NaNs类的数据进行单独的编码,否的话忽略NaNs数据。
- sparse:是否输出稀疏矩阵,即index+值。
- drop_first:是否去除第一个离散值再编码。
- dtype:数据类型。
代码示例:
import pandas as pd
df=pd.DataFrame(data=[['a'],['b'],['c'],['a']],columns=['grade'])
df_dum=pd.get_dummies(df)
print(df_dum)
'''
结果为:
grade_a grade_b grade_c
0 1 0 0
1 0 1 0
2 0 0 1
3 1 0 0
'''
三、缺失值插补
1、单变量插补
即只根据特征自身来进行缺失值的补充。
对应的类:
sklearn.impute.SimpleImputer(missing_values=nan, strategy=’mean’, fill_value=None, verbose=0, copy=True, add_indicator=False)
- missing_values:缺失值,用什么表示缺失值。默认是np.nan
- 'strategy:插补缺失值的方法,'mean':均值;'median':中位数;'most_frequent':频数最高的数;'constant':用蚕食fill_value的值代替。
- fill_value:参数strategy='constant'时用来替换缺失值的值。
- add_indicator:若为True则替换后对数据添加是否插补缺失值的标签。
类的方法:
- fit_transform(self, X, y=None, **fit_params) 传入数据补充缺失值。
代码示例:
from sklearn.impute import SimpleImputer
import numpy as np
x=np.array([1,2,3,4,5,6,7,8,np.nan,10]).reshape(10,1)
imp=SimpleImputer(np.nan)
x_imp=imp.fit_transform(x)
print(x_imp)
'''
结果为:
[[ 1. ]
[ 2. ]
[ 3. ]
[ 4. ]
[ 5. ]
[ 6. ]
[ 7. ]
[ 8. ]
[ 5.11111111]
[10. ]]
'''
2、多变量插补法
缺失值的插补也可以通过利用多变量建模的方式来插补,例如用knn、随机森林、贝叶斯估计等,可以用不同的插补法,在建模后通过不通的模型效果来选择最合适的。
sklearn这里允许我们自己选择建模的方式,使用迭代器 IterativeImputer
类(这个类还在试验阶段),该类将每个 missing value 的特征建模为其他特征的函数,并使用该估计进行插补。它是以循环的方式实现的:在每个步骤中,一个特征列被指定为输出 y,而其他特征列被视为输入 X 。对于已知 y,回归量适合(X,y)。然后,回归量用于预测 y 的缺失值。对于 n 迭代方式,然后对 max-iter 插补轮进行重复。最后一轮插补的结果被返回。
对应的类:
sklearn.impute.IterativeImputer(estimator=None, missing_values=nan, sample_posterior=False, max_iter=10, tol=0.001, n_nearest_features=None, initial_strategy=’mean’, imputation_order=’ascending’, min_value=None, max_value=None, verbose=0, random_state=None, add_indicator=False)
- estimator :estimator对象,默认= BayesianRidge()。循环法插补的每一步使用的估算器。如果sample_posterior为True,则估算器必须支持 return_std其predict方法。
- missing_values :指定何种占位符表示缺失值,可选 number ,string ,np.nan(default) ,None
- sample_posterior :布尔值,默认为False,是否从每个插补的拟合估计的(高斯)预测后验进行采样。如果设置为True,Estimator 必须支持return_std 其predict 方法。True如果IterativeImputer用于多个插补,则设置为 。
- max_iter :输入为int型数据,默认值是10。在返回最后一轮计算的估算值之前要执行的最大插补轮次数。
- tol :容忍停止条件
- n_nearest_features :用于估计每个要素列的缺失值的其他要素数。使用每个特征对之间的绝对相关系数(在初始插补之后)测量特征之间的接近度。为了确保在整个插补过程中覆盖特征,邻居特征不一定是最接近的,而是以与每个插补目标特征的相关性成比例的概率绘制。当功能数量巨大时,可以提供显着的加速。如果None,将使用所有功能。
- initial_strategy :使用哪种策略初始化缺失值。与 SimpleImputer 中的strategy参数相同
- imputation_order :排序规则
- ascending :从缺失值最少的功能到最多
- descending :从具有最多缺失值的功能到最少
- roman :左到右
- arabic :右到左
- random :随机顺序
- min_value :最小可能的估算值。默认值None将最小值设置为负无穷大。
- max_value :最大可能的估算值。默认值None将最大值设置为正无穷大。
- verbose :详细程度标志控制在评估函数时发出的调试消息。越高越详细。可以是0,1或2。
- random_state :伪随机数生成器的种子使用。如果 n_nearest_features不是None,imputation_order则随机选择估计器特征, if random和后验if的采样sample_posterior为True。
- add_indicator :如果为True,则MissingIndicator变换将堆叠到imputer的变换的输出上。这允许预测估计器尽管插补而解释缺失。如果某个要素在拟合/训练时没有缺失值,即使在变换/测试时缺少值,该要素也不会出现在缺失的指示符上。
类的方法:
- fit_transform(self, X, y=None) 用来插补缺失值
代码示例:
from sklearn.experimental import enable_iterative_imputer #要先导入这个才能正常使用
from sklearn.impute import IterativeImputer
import numpy as np
imp = IterativeImputer(max_iter=10, random_state=0)
imp.fit([[1, 2], [3, 6], [4, 8], [np.nan, 3], [7, np.nan]])
X_test = [[np.nan, 2], [6, np.nan], [np.nan, 6]]
print(np.round(imp.transform(X_test)))
'''
结果为:
[[ 1. 2.]
[ 6. 12.]
[ 3. 6.]]
'''
3、impyute一个多变量缺失值插补包
除了sklearn之外,还有两个常用的缺失值插补的包impytue和fancyimpute,除了简单的单变量之外,还支持多变量插补。由于 fancyimpute由于包安装不成功,所以这里不做介绍,impyute包,这里只列出相关的缺失值插补方法与一个简单示例。
fast_knn | 快速knn算法 |
mice | mice算法 |
mean | 均值填充 |
代码示例:
这里有三种方法的实现,分别用三个函数:fast_knn, mice, mean,然后计算拟合缺失值的误差,然后计算出那个算法的误差最大,循环100次,最后输出各个算法误差最大的次数。
这里每次结果都不一样,但是knn和mice的算法的误差比mean的误差大的次数要少,所以一般建议可以使用knn或者mice算法。
from impyute.imputation.cs import fast_knn, mice, mean
from sklearn.datasets import load_iris
import numpy as np
iris = load_iris()
x = iris.data
#记录三种方法误差最大的次数,初始为0
knn_cnt = 0
mice_cnt = 0
mean_cnt = 0
for i in range(99):
#第2列的数据随机添加缺失值
rand_x = np.random.randint(0, 150, 10)
x_copy = np.copy(x)
x_copy[rand_x, 1] = np.nan
#用三种方法插补缺失值
x1 = fast_knn(x_copy, 4)
x2 = mice(x_copy)
x3 = mean(x_copy)
knn_error = np.abs(np.sum(x1[rand_x, 1] - x[rand_x, 1])) # knn误差
mice_error = np.abs(np.sum(x2[rand_x, 1] - x[rand_x, 1])) # mice误差
mean_error = np.abs(np.sum(x3[rand_x, 1] - x[rand_x, 1])) # mean误差
#如果误差最大,则算法次数加1
if knn_error == max(knn_error, mice_error, mean_error):
knn_cnt += 1
elif mice_error == max(knn_error, mice_error, mean_error):
mice_cnt += 1
else:
mean_cnt += 1
#输出误差最大的次数
print(knn_cnt, mice_cnt, mean_cnt)
4、github上基于sklearn的一个多变量缺失值插补包
这个包在github上可以找到,叫MissingImputer,这个包可以通过利用knn, randomforest, xgboost, lightgbm的方法来填补缺失值,数据的训练和拟合方法和sklearn一样,所以很推荐使用,需要注意的时它需要额外的包xgboost和lightgbm,可以通过pip进行安装即可。
对应的类:
MissingImputer(max_iter=10, ini_fill = True, ini_strategy_reg = 'mean', ini_strategy_clf = 'most_frequent', with_cat = False, cat_index = None, tol = 1e-3, model_reg = "knn", model_clf = "knn")
- max_iter:迭代次数,模型一开始用简单数据填充缺失,然后训练模型并拟合缺失,然后用拟合了缺失的数据继续训练拟合,重复直到迭代结束。
- ini_fill:是否要进行简单填补(False仅对xgb和lgb有效)。
- ini_strategy_reg:连续变量简单填补规则, mean or median。
- ini_strategy_clf:离散变量简单填补规则, only most_frequent。
- cat_index:离散变量索引(int)。
- tol:阈值。
- model_reg:连续变量采用的预测缺失值模型, be xgboost,lightgbm, randomforest, knn。
- model_clf:离散变量采用的预测缺失值模型
类的方法:
MissingImputer.fit()训练,MissingImputer. transform()拟合缺失值。
示例代码:
from MissingImputer.ModelBasedImputer.MissingImputer import MissingImputer
from sklearn.datasets import load_iris
import numpy as np
iris = load_iris()
x = iris.data
rand_x = np.random.randint(0, 150, 10) # 0-150取10个随机数作为随机航
x_copy = np.copy(x)
x_copy[rand_x, 1] = np.nan # 这10个随机行添加缺失值
model=MissingImputer()
model.fit(x) # 训练
x=model.transform(x) # 拟合
来源:oschina
链接:https://my.oschina.net/u/4302374/blog/3383213