YeoJohnsonTransformer#

Yeo-Johnson 变换是 Box-Cox 变换的扩展,除了正数值外,还支持对包含零和负值的变量进行幂变换。

另一方面,Box-Cox 变换适用于严格为正的数值变量。当变量包含负值时,我们有两个选择:

  • 通过添加一个常数,将分布向正值方向移动

  • 使用 Yeo-Johnson 变换

Yeo-Johnson 变换定义为:


../../_images/yeojohnsonformula.png

其中 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 变换应用于两个变量;LotAreaGrLivArea

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’ 分布的偏斜:

../../_images/untransformedcoupleYJ.png


现在,让我们绘制变换后的变量的直方图:

train_t[['LotArea', 'GrLivArea']].hist(bins=50, figsize=(10,4))
plt.show()

我们看到,在转换后的数据中,两个变量都具有更加对称、类似高斯分布的特征。

../../_images/transformedcoupleYJ.png


恢复原始数据#

应用 Yeo-Johnson 变换后,我们可以使用 inverse_transform 方法恢复原始数据表示,即原始变量值。

train_unt = tf.inverse_transform(train_t)
test_unt = tf.inverse_transform(test_t)

其他资源#

你可以在以下位置找到更多关于 YeoJohnsonTransformer() 的详细信息:

有关此方法和其他特征工程方法的更多详细信息,请查看以下资源:

../../_images/feml.png

机器学习的特征工程#











或者阅读我们的书:

../../_images/cookbook.png

Python 特征工程手册#














我们的书籍和课程都适合初学者和更高级的数据科学家。通过购买它们,您正在支持 Feature-engine 的主要开发者 Sole。