YeoJohnsonTransformer#
Yeo-Johnson 变换是 Box-Cox 变换的扩展,除了正数值外,还支持对包含零和负值的变量进行幂变换。
另一方面,Box-Cox 变换适用于严格为正的数值变量。当变量包含负值时,我们有两个选择:
通过添加一个常数,将分布向正值方向移动
使用 Yeo-Johnson 变换
Yeo-Johnson 变换定义为:
其中 Y 是自变量,λ 是变换参数。
Yeo-Johnson 和 Box-Cox 变换的用途#
Yeo-Johnson 和 Box-Cox 变换都自动化了识别最优幂变换以近似高斯分布的过程。它们评估了各种幂变换,包括对数和倒数函数,通过最大似然估计变换参数。
这些转换通常在数据预处理期间应用,特别是在使用参数统计检验或回归的线性模型时。这些检验和模型通常对数据有潜在的假设,这些假设可能无法自然满足,因此这些转换对于满足这些假设是必不可少的。
Yeo-Johnson 与 Box-Cox 变换#
Yeo-Johnson 变换与 Box-Cox 变换有何关联?
Yeo-Johnson 变换扩展了 Box-Cox 变换,以处理具有零、负值和正值的变量。
对于严格正值:Yeo-Johnson 变换等同于应用于 (X + 1) 的 Box-Cox 变换。
对于严格负值:Yeo-Johnson 变换对应于应用于 (-X + 1) 的 Box-Cox 变换,其幂为 (2 — λ),其中 λ 是变换参数。
对于同时具有正值和负值的变量:Yeo-Johnson 变换结合了这两种方法,对变量的正值和负值部分使用不同的幂次。
要在 Python 中应用 Yeo-Johnson 变换,可以使用 scipy.stats.yeojohnson
,它可以一次变换一个变量。对于同时变换多个变量,像 scikit-klearn 和 Feature-engine 这样的库更为合适。
YeoJohnsonTransformer#
Feature-engine 的 YeoJohnsonTransformer()
将 Yeo-Johnson 变换应用于数值变量。
在底层,YeoJohnsonTransformer()
使用 scipy.stats.yeojohnson 对每个变量应用变换。
Python 实现#
在本节中,我们将对Ames房价数据集中的几个变量应用Yeo-Johnson变换。执行变换后,我们将进行数据分析,以了解其对变量分布的影响。
首先,我们导入必要的库和转换器,加载数据集,并将其分割为训练集和测试集。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from feature_engine.transformation import YeoJohnsonTransformer
# Load dataset
data = fetch_openml(name='house_prices', as_frame=True)
data = data.frame
# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
data.drop(['Id', 'SalePrice'], axis=1),
data['SalePrice'], test_size=0.3, random_state=0)
X_train.head()
在以下输出中,我们看到了房价数据集的预测变量:
MSSubClass MSZoning LotFrontage LotArea Street Alley LotShape \
254 20 RL 70.0 8400 Pave NaN Reg
1066 60 RL 59.0 7837 Pave NaN IR1
638 30 RL 67.0 8777 Pave NaN Reg
799 50 RL 60.0 7200 Pave NaN Reg
380 50 RL 50.0 5000 Pave Pave Reg
LandContour Utilities LotConfig ... ScreenPorch PoolArea PoolQC Fence \
254 Lvl AllPub Inside ... 0 0 NaN NaN
1066 Lvl AllPub Inside ... 0 0 NaN NaN
638 Lvl AllPub Inside ... 0 0 NaN MnPrv
799 Lvl AllPub Corner ... 0 0 NaN MnPrv
380 Lvl AllPub Inside ... 0 0 NaN NaN
MiscFeature MiscVal MoSold YrSold SaleType SaleCondition
254 NaN 0 6 2010 WD Normal
1066 NaN 0 5 2009 WD Normal
638 NaN 0 5 2008 WD Normal
799 NaN 0 6 2007 WD Normal
380 NaN 0 5 2010 WD Normal
[5 rows x 79 columns]
现在让我们设置转换器,将 Yeo-Johnson 变换应用于两个变量;LotArea
和 GrLivArea
:
tf = YeoJohnsonTransformer(variables = ['LotArea', 'GrLivArea'])
tf.fit(X_train)
通过 fit()
,YeoJohnsonTransformer()
学习了 Yeo-Johnson 幂变换的最佳 lambda 值。我们可以如下检查这些值:
tf.lambda_dict_
我们在下面看到最佳的 lambda 值:
{'LotArea': 0.02258978732751055, 'GrLivArea': 0.06781061353154169}
我们现在可以继续应用数据转换,以更接近正态分布。
train_t = tf.transform(X_train)
test_t = tf.transform(X_test)
我们将在下一节中检查变换的效果。
变量分布的变换效果#
让我们对变换进行分析。我们将探讨在应用Yeo和Johnson描述的变换前后变量的分布情况。
让我们为原始数据制作直方图,以检查原始变量的分布:
X_train[['LotArea', 'GrLivArea']].hist(bins=50, figsize=(10,4))
plt.show()
在下图中,我们可以观察到原始数据中 ‘LotArea’ 和 ‘GrLivArea’ 分布的偏斜:
现在,让我们绘制变换后的变量的直方图:
train_t[['LotArea', 'GrLivArea']].hist(bins=50, figsize=(10,4))
plt.show()
我们看到,在转换后的数据中,两个变量都具有更加对称、类似高斯分布的特征。
恢复原始数据#
应用 Yeo-Johnson 变换后,我们可以使用 inverse_transform
方法恢复原始数据表示,即原始变量值。
train_unt = tf.inverse_transform(train_t)
test_unt = tf.inverse_transform(test_t)
其他资源#
你可以在以下位置找到更多关于 YeoJohnsonTransformer()
的详细信息:
有关此方法和其他特征工程方法的更多详细信息,请查看以下资源:
或者阅读我们的书:
我们的书籍和课程都适合初学者和更高级的数据科学家。通过购买它们,您正在支持 Feature-engine 的主要开发者 Sole。