Python sklearn学习之数据预处理——非线性转换
文章目录
1. 两种常见的非线性转换
1.1 分位数转换
- 基本公式
- 公式说明
- x:特征
- F:特征的累积分布函数
- G^(-1):期望输出值分布G的分位数函数
- 目的:将所有特征置于相同的期望分布中
- 公式成立的事实说明
- 如果X是具有连续累积分布函数F的随机变量,那么F(X)均匀分布在[0,1]
- 如果U是在[0,1]上的随机分布,那么G^(-1)(U)有分布G.
累积分布函数:是概率密度函数的积分
概率密度函数:表示瞬时幅值落在某指定范围内的概率
设累积分布函数为F,概率密度函数为f,则可表示如下:
- 分位数转换优势:平滑了异常分布,并且比缩放方法受异常值的影响更小
- 分位数转换缺点:使特征间及特征内的关联和距离失真了
1.2 幂变换
本质是一组参数变换,其目的是将数据从任意分布映射到接近高斯分布的位置
2. sklearn中非线性变换的实现
2.1 映射到均匀分布
sklearn 将数据集映射到均匀分布的方式主要是通过分位数转换的方式实现,通过类QuantileTransformer 类以及quantile_transform 函数实现。
2.1.1QuantileTransformer类
- 类定义
def __init__(self, n_quantiles=1000, output_distribution='uniform',
ignore_implicit_zeros=False, subsample=int(1e5),
random_state=None, copy=True):
-
参数说明
- n_quantiles : int,optional(默认值= 1000或n_samples)
- 要计算的分位数。它对应于用于离散累积分布函数的标记的数量。如果n_quantiles大于样本数,则n_quantiles被设置为样本数,因为较大数量的分位数不能给出累积分布函数估计器的更好近似。
- output_distribution :str,optional(default =‘uniform’)
- 转换数据的边际分布。选择是“uniform”(默认)或“normal”
- ignore_implicit_zeros :boolean,optional(默认值= False)
- 仅适用于稀疏矩阵。如果为True,则丢弃矩阵的稀疏条目以计算分位数统计。如果为False,则将这些条目视为零
- subsample : int,optional(default = 1e5)
- 用于估计计算效率的分位数的最大样本数。注意,对于值相同的稀疏矩阵和密集矩阵,子采样过程可能不同
- random_state : int,RandomState实例或None,可选(默认=None)
- 如果是int,则random_state是随机数生成器使用的种子; 如果是RandomState实例,则random_state是随机数生成器; 如果为None,则随机数生成器是np.random使用的RandomState实例。请注意,这通过二次采样和平滑噪声来使用。
- copy :略
- n_quantiles : int,optional(默认值= 1000或n_samples)
-
对象属性
-
n_quantiles_ : 用于离散累积分布函数的实际分位数
-
quantiles_: 值与参考对应之间的分位数矩阵
-
references_:
n_samples = X.shape[0] # 数组维度元组,或者说是样本数 self.n_quantiles_ = max(1, min(self.n_quantiles, n_samples)) # 得到样本数与分数数较小的值,为了防止传入空数组,所以需保证大于1 self.references_ = np.linspace(0, 1, self.n_quantiles_,endpoint=True)
-
-
例子
X_train_trans = preprocessing.QuantileTransformer(random_state=0).fit_transform(X_train)
- quantile_transform 函数
一如既往,quantile_transform 函数只是本质上也是创建QuantileTransformer 转换器
n = QuantileTransformer(n_quantiles=n_quantiles,
output_distribution=output_distribution,
subsample=subsample,
ignore_implicit_zeros=ignore_implicit_zeros,
random_state=random_state,
copy=copy)
if axis == 0:
return n.fit_transform(X)
elif axis == 1:
return n.fit_transform(X.T).T
else:
raise ValueError("axis should be either equal to 0 or 1. Got"
" axis={}".format(axis))
2.2 映射到高斯分布
幂变换是一类参数化的单调变换, 其目的是将数据从任何分布映射到尽可能接近高斯分布,以便稳定方差和最小化偏斜。
PowerTransformer 类提供了两种幂变换,Yeo-Johnson transform 和 the Box-Cox transform
2.2.1 Yeo-Johnson transform变换
2.2.2 the Box-Cox transform变换
2.2.3 类说明
def __init__(self, method='yeo-johnson', standardize=True, copy=True):
-
参数说明
- method :可选,接受一个字符串值,默认是 ‘yeo-johnson’ ,
- ’yeo-johnson’ :指明幂变换方式以 Yeo-Johnson transform 方式实现,此种方式下数据集可以含有正负值
- the Box-Cox transform :指明幂变换方式以the Box-Cox transform 方式实现,此种方式下数据集只能是正值,不允许有负值
- standardize :可选,接受一个boolean值,默认是 ‘True’ ,设置为True可将零均值单位方差归一化应用于变换后的输出
- copy :略
- method :可选,接受一个字符串值,默认是 ‘yeo-johnson’ ,
-
属性
- lambdas_ : 得到一个浮点数组,转换过程中所选择的参数
self.lambdas_ = np.array([optim_function(col) for col in X.T])
-
例子
power = preprocessing.PowerTransformer(method='box-cox', standardize=False, copy=True)
X_lognormal = np.random.RandomState(616).lognormal(size=(3, 3))
power.fit_transform(X_lognormal)
# 注意没有下面这种使用方式
# power.fit(X_lognormal).transform(X_lognormal)
- power_transform 函数
本质上是构造 PowerTransformer 对象并调用 fit_transform 实现
pt = PowerTransformer(method=method, standardize=standardize, copy=copy)
return pt.fit_transform(X)
2.2.4 拓展
实际上,利用2.1.1中的 QuantileTransformer 类也可以讲数据集转换为正态分布(通过设置 output_distribution
=‘normal’)。