scikit-learnで正規分布へ変換

スポンサーリンク

はじめに

scikit-learnを使って、データを正規分布のように変換する方法を紹介します。

PowerTransformer

PowerTransformerでは、Yoe-JohnsonBox-Coxでの変換が可能です。

sklearn.preprocessing.PowerTransformer
Examples using sklearn.preprocessing.PowerTransformer: Compare the effect of different scalers on data with outliers Compare the effect of different scalers on ...

Yeo-Johnson

pt = PowerTransformer(method='yeo-johnson')
pt.fit(df[cols].values)
df[cols] = pt.transform(df[cols].values)

Box-Cox

こちらは負の値が扱えないことに注意してください。

pt = PowerTransformer(method='box-cox')
pt.fit(df[cols].values)
df[cols] = pt.transform(df[cols].values)

QuantileTransformer

QuantileTransformerは分位数を使って正規分布に変換します。

sklearn.preprocessing.QuantileTransformer
Examples using sklearn.preprocessing.QuantileTransformer: Partial Dependence and Individual Conditional Expectation Plots Partial Dependence and Individual Cond...

n_quantilesで分位数の数を設定できます。

qt =  QuantileTransformer(n_quantiles=100, output_distribution='normal', random_state=42)
qt.fit(df[cols].values)
df[cols] = qt.transform(df[cols].values)

実際にやってみる

Kaggleのtitanicデータを使って実際にそれぞれ変換してみます。

Titanic - Machine Learning from Disaster | Kaggle
Start here! Predict survival on the Titanic and get familiar with ML basics

今回は、AgeFareのデータを変換してみます。

まずデータを読み込んで、今回は試してみるだけなので欠損データと負の値のデータを削除してしまいます。

from sklearn.preprocessing import PowerTransformer, QuantileTransformer
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

df = pd.read_csv('../input/titanic/train.csv')
df = df.dropna(subset=cols)
df = df[df['Fare']>0]

cols = ['Age', 'Fare']

df = df.dropna(subset=cols)
df = df[df['Fare']>0]

元の分布

元のデータの分布はそれぞれ下記の通りになります。

fig, axes = plt.subplots(1, 2, figsize=(20, 10))
axes = axes.ravel()

for col, ax in zip(cols, axes):
    sns.histplot(df[col], ax=ax)

plt.show()

PowerTransformer(Yeo-Johnson)

PowerTransformer(Yeo-Johnson)で変換します。

yj_cols = ['Age_yj', 'Fare_yj']
pt = PowerTransformer(method='yeo-johnson')
pt.fit(df[cols].values)
df[yj_cols] = pt.transform(df[cols].values)

変換した後の分布は下記のようになります。

fig, axes = plt.subplots(1, 2, figsize=(20, 10))
axes = axes.ravel()

for col, ax in zip(yj_cols, axes):
    sns.histplot(df[col], ax=ax)

plt.show()

PowerTransformer(Box-Cox)

PowerTransformer(Box-Cox)で変換します。

bc_cols = ['Age_bc', 'Fare_bc']
pt = PowerTransformer(method='box-cox')
pt.fit(df[cols].values)
df[bc_cols] = pt.transform(df[cols].values)

変換した後の分布は下記のようになります。

fig, axes = plt.subplots(1, 2, figsize=(20, 10))
axes = axes.ravel()

for col, ax in zip(bc_cols, axes):
    sns.histplot(df[col], ax=ax)

plt.show()

QuantileTransformer

QuantileTransformerで変換します。

qt_cols = ['Age_qt', 'Fare_qt']
qt =  QuantileTransformer(n_quantiles=100, output_distribution='normal', random_state=42)
qt.fit(df[cols].values)
df[qt_cols] = qt.transform(df[cols].values)

変換した後の分布は下記のようになります。

fig, axes = plt.subplots(1, 2, figsize=(20, 10))
axes = axes.ravel()

for col, ax in zip(qt_cols, axes):
    sns.histplot(df[col], ax=ax)

plt.show()

参考

タイトルとURLをコピーしました